示例#1
0
func init() {
	testApp = app.New()
	testApp.Config().Secret = stringutil.Random(32)
	testApp.Handle("^/hello$", func(ctx *app.Context) {
		ctx.Header().Add("X-Hello", "World")
		ctx.Header().Add("X-Number", "42")
		ctx.WriteString("hello world")
	})
	testApp.Handle("^/empty$", func(ctx *app.Context) {})
	testApp.Handle("^/echo$", func(ctx *app.Context) {
		if ctx.R.Method == "POST" {
			data, err := ioutil.ReadAll(ctx.R.Body)
			if err != nil {
				panic(err)
			}
			ctx.Write(data)
		}
	})
	testApp.Handle("^/echo-form$", func(ctx *app.Context) {
		if err := ctx.R.ParseForm(); err != nil {
			panic(err)
		}
		var values url.Values
		if ctx.R.Method == "POST" || ctx.R.Method == "PUT" {
			values = ctx.R.PostForm
		} else {
			values = ctx.R.Form
		}
		keys := generic.Keys(values).([]string)
		sort.Strings(keys)
		for _, k := range keys {
			fmt.Fprintf(ctx, "%s=%s\n", k, values.Get(k))
		}
	})
	testApp.Handle("^/invalid-write-header$", func(ctx *app.Context) {
		ctx.WriteHeader(0)
	})
	testApp.Handle("^/multiple-write-header$", func(ctx *app.Context) {
		ctx.WriteHeader(200)
		ctx.WriteHeader(300)
	})
}
示例#2
0
func (b *SqlBackend) Inspect(db *DB, m driver.Model, schema string) (*Table, error) {
	var val int
	name := db.QuoteString(m.Table())
	s := db.QuoteString(schema)
	eq := fmt.Sprintf("SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE "+
		"TABLE_NAME = %s AND TABLE_SCHEMA = %s", name, s)
	err := db.QueryRow(eq).Scan(&val)
	if err != nil {
		if err == ErrNoRows {
			return nil, nil
		}
		return nil, err
	}
	// Select fields with their types
	iq := fmt.Sprintf("SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, "+
		"CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS "+
		"WHERE TABLE_NAME = %s AND TABLE_SCHEMA = %s", name, s)
	rows, err := db.Query(iq)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var fields []*Field
	fieldsByName := make(map[string]*Field)
	for rows.Next() {
		var f Field
		var nullable string
		var maxLength *int
		if err := rows.Scan(&f.Name, &nullable, &f.Type, &maxLength); err != nil {
			return nil, err
		}
		if maxLength != nil {
			f.Type = fmt.Sprintf("%s (%d)", f.Type, *maxLength)
		}
		f.Type = strings.ToUpper(f.Type)
		if nullable != "YES" {
			f.AddConstraint(ConstraintNotNull)
		}
		fields = append(fields, &f)
		fieldsByName[f.Name] = &f
	}
	// Field constraints
	cq := fmt.Sprintf("SELECT C.CONSTRAINT_NAME, CONSTRAINT_TYPE, COLUMN_NAME "+
		"FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS C JOIN "+
		"INFORMATION_SCHEMA.KEY_COLUMN_USAGE K ON C.CONSTRAINT_NAME = "+
		"K.CONSTRAINT_NAME WHERE C.TABLE_NAME = %s AND K.TABLE_NAME = %s "+
		"AND C.TABLE_SCHEMA = %s", name, name, s)
	rows, err = db.Query(cq)
	if err != nil {
		return nil, err
	}
	foreignKeys := make(map[string]string)
	defer rows.Close()
	for rows.Next() {
		var constraintName string
		var constraintType string
		var name string
		if err := rows.Scan(&constraintName, &constraintType, &name); err != nil {
			return nil, err
		}
		field := fieldsByName[name]
		if field == nil {
			return nil, fmt.Errorf("table %s has constraint on non-existing field %s", m.Table(), name)
		}
		switch strings.ToLower(constraintType) {
		case "primary key":
			field.AddConstraint(ConstraintPrimaryKey)
		case "foreign key":
			foreignKeys[constraintName] = name
		case "unique":
			field.AddConstraint(ConstraintUnique)
		default:
			return nil, fmt.Errorf("unknown constraint type %s on field %s in table %s", constraintType, name, m.Table())
		}
	}
	if len(foreignKeys) > 0 {
		// Resolve FKs
		fks := strings.Join(generic.Map(generic.Keys(foreignKeys).([]string), db.QuoteString).([]string), ", ")
		fq := fmt.Sprintf("SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE CONSTRAINT_NAME IN (%s)", fks)
		rows, err := db.Query(fq)
		if err != nil {
			return nil, err
		}
		defer rows.Close()
		for rows.Next() {
			var constraintName string
			var tableName string
			var columnName string
			if err := rows.Scan(&constraintName, &tableName, &columnName); err != nil {
				return nil, err
			}
			fieldName := foreignKeys[constraintName]
			// Field was validated previously, won't be nil
			field := fieldsByName[fieldName]
			field.Constraints = append(field.Constraints, &Constraint{Type: ConstraintForeignKey, References: MakeReference(tableName, columnName)})
		}
	}
	return &Table{Fields: fields}, nil
}