Beispiel #1
0
func main() {
	name := os.Args[1]
	buf, err := ioutil.ReadFile(name)
	if err != nil {
		panic(err)
	}
	var schema Schema
	err = yaml.Unmarshal(buf, &schema)
	if err != nil {
		panic(err)
	}

	fmt.Printf("properties=%v\n", schema.Properties)

	fmt.Printf("\n\n/////\n")
	tag := strings.Split(schema.Tag, "/")
	tname := strings.Split(tag[len(tag)-1], "-")[0]
	fmt.Printf("type %s struct {\n", snaker.SnakeToCamel(tname))
	for k, prop := range schema.Properties {
		fmt.Printf("\t%s %v `yaml:\"%s\"` // %q\n",
			snaker.SnakeToCamel(k),
			prop.Type, k,
			strings.TrimSpace(prop.Description),
		)
		//fmt.Printf("// %#v\n", prop)
	}
	fmt.Printf("}\n")
}
Beispiel #2
0
func printer(cfg map[string]interface{}) (dst string) {
	for k, v := range cfg {
		switch v.(type) {
		case int64:
			dst += fmt.Sprintf("    %s int `toml:\"%s\"`\n", snaker.SnakeToCamel(k), k)
		case string:
			dst += fmt.Sprintf("    %s string `toml:\"%s\"`\n", snaker.SnakeToCamel(k), k)
		case bool:
			dst += fmt.Sprintf("    %s bool `toml:\"%s\"`\n", snaker.SnakeToCamel(k), k)
		case []map[string]interface{}:
			vv := v.([]map[string]interface{})
			if len(vv) > 0 {
				dst += fmt.Sprintf("  %s []struct {\n", snaker.SnakeToCamel(k))
				dst += printer(vv[0])
				dst += fmt.Sprintf("  }\n")
			}
		case map[string]interface{}:
			dst += fmt.Sprintf("  %s struct {\n", snaker.SnakeToCamel(k))
			dst += printer(v.(map[string]interface{}))
			dst += fmt.Sprintf("  }\n")
		default:
			panic(fmt.Sprintf("Unknown type: %T", v))
		}
	}
	return
}
Beispiel #3
0
// PgLoadTables loads the table definitions from the database, writing the
// resulting templates to typeMap and returning the created templates.TableTemplates.
func PgLoadTables(args *internal.ArgType, db *sql.DB, typeMap map[string]*bytes.Buffer) (map[string]*templates.TableTemplate, error) {
	var err error

	// load columns
	cols, err := models.ColumnsByRelkindSchema(db, "r", args.Schema)
	if err != nil {
		return nil, err
	}

	// process columns
	fieldMap := map[string]map[string]bool{}
	tableMap := map[string]*templates.TableTemplate{}
	for _, c := range cols {
		if _, ok := fieldMap[c.TableName]; !ok {
			fieldMap[c.TableName] = map[string]bool{}
		}

		// set col info
		c.Field = snaker.SnakeToCamel(c.ColumnName)
		c.Len, c.NilType, c.Type = PgParseType(args, c.DataType, c.IsNullable)

		// set value in table map if not present
		if _, ok := tableMap[c.TableName]; !ok {
			tableMap[c.TableName] = &templates.TableTemplate{
				Type:        inflector.Singularize(snaker.SnakeToCamel(c.TableName)),
				TableSchema: args.Schema,
				TableName:   c.TableName,
				Fields:      []*models.Column{},
			}
		}

		// set primary key
		if c.IsPrimaryKey {
			tableMap[c.TableName].PrimaryKey = c.ColumnName
			tableMap[c.TableName].PrimaryKeyField = c.Field
			tableMap[c.TableName].PrimaryKeyType = c.Type
		}

		// append col to template fields
		if _, ok := fieldMap[c.TableName][c.ColumnName]; !ok {
			tableMap[c.TableName].Fields = append(tableMap[c.TableName].Fields, c)
		}

		fieldMap[c.TableName][c.ColumnName] = true
	}

	// generate table templates
	for _, t := range tableMap {
		buf := GetBuf(typeMap, strings.ToLower(t.Type))
		err = templates.Tpls["postgres.model.go.tpl"].Execute(buf, t)
		if err != nil {
			return nil, err
		}
	}

	return tableMap, nil
}
Beispiel #4
0
// PgLoadEnums reads the enums from the database, writing the values to the
// typeMap and returning the created EnumTemplates.
func PgLoadEnums(args *internal.ArgType, db *sql.DB, typeMap map[string]*bytes.Buffer) (map[string]*templates.EnumTemplate, error) {
	var err error

	// load enums
	enums, err := models.EnumsBySchema(db, args.Schema)
	if err != nil {
		return nil, err
	}

	// process enums
	enumMap := map[string]*templates.EnumTemplate{}
	for _, e := range enums {
		// calc go type and add to known types
		goType := inflector.Singularize(snaker.SnakeToCamel(e.EnumType))
		templates.KnownTypeMap[goType] = true

		// calculate val, chopping off redundant type name if applicable
		val := snaker.SnakeToCamel(strings.ToLower(e.EnumValue))
		if strings.HasSuffix(strings.ToLower(val), strings.ToLower(goType)) {
			v := val[:len(val)-len(goType)]
			if len(v) > 0 {
				val = v
			}
		}

		// copy values back into model
		e.Value = val
		e.Type = goType

		// set value in enum map if not present
		typ := strings.ToLower(goType)
		if _, ok := enumMap[typ]; !ok {
			enumMap[typ] = &templates.EnumTemplate{
				Type:     goType,
				EnumType: e.EnumType,
				Values:   []*models.Enum{},
			}
		}

		// append enum to template vals
		enumMap[typ].Values = append(enumMap[typ].Values, e)
	}

	// generate enum templates
	for _, e := range enumMap {
		buf := GetBuf(typeMap, strings.ToLower(e.Type))
		err = templates.Tpls["postgres.enum.go.tpl"].Execute(buf, e)
		if err != nil {
			return nil, err
		}
	}

	return enumMap, nil
}
Beispiel #5
0
// PgLoadProcs reads the procs from the database, writing the values to the
// typeMap and returning the created ProcTemplates.
func PgLoadProcs(args *internal.ArgType, db *sql.DB, typeMap map[string]*bytes.Buffer) (map[string]*templates.ProcTemplate, error) {
	var err error

	// load procs
	procs, err := models.ProcsBySchema(db, args.Schema)
	if err != nil {
		return nil, err
	}

	// process procs
	procMap := map[string]*templates.ProcTemplate{}
	for _, p := range procs {
		// fix the name if it starts with underscore
		name := p.ProcName
		if name[0:1] == "_" {
			name = name[1:]
		}

		// create template
		procTpl := templates.ProcTemplate{
			Name:               snaker.SnakeToCamel(name),
			TableSchema:        args.Schema,
			ProcName:           p.ProcName,
			ProcParameterTypes: p.ParameterTypes,
			ProcReturnType:     p.ReturnType,
			Parameters:         []*models.Column{},
		}

		// parse return type into template
		_, procTpl.NilReturnType, procTpl.ReturnType = PgParseType(args, p.ReturnType, false)

		// split parameter types
		if len(p.ParameterTypes) > 0 {
			for i, paramType := range strings.Split(p.ParameterTypes, ", ") {
				// determine the go equivalent parameter types and add to parameters
				_, _, pt := PgParseType(args, paramType, false)
				procTpl.Parameters = append(procTpl.Parameters, &models.Column{
					Field: "v" + strconv.Itoa(i),
					Type:  pt,
				})
			}
		}

		procMap[p.ProcName] = &procTpl
	}

	// generate proc templates
	for _, p := range procMap {
		buf := GetBuf(typeMap, strings.ToLower("sp_"+p.Name))
		err = templates.Tpls["postgres.proc.go.tpl"].Execute(buf, p)
		if err != nil {
			return nil, err
		}
	}

	return procMap, nil
}
Beispiel #6
0
// fixFieldName changes field names like
//  'id' -> 'ID'
func fixFieldName(field *gogo.FieldDescriptorProto) {
	if gogoproto.IsCustomName(field) {
		return // Skip if a custom name is specified.
	}

	if field.Options == nil {
		field.Options = new(gogo.FieldOptions)
	}

	name := field.GetName()
	name = snaker.SnakeToCamel(name)
	name = lintName(name)

	// Use gogoproto.customname
	proto.SetExtension(field.Options, gogoproto.E_Customname, &name)
}
Beispiel #7
0
Datei: util.go Projekt: knq/xo
// SnakeToIdentifier wraps snaker.SnakeToCamel and adds logic specific for xo and go.
func SnakeToIdentifier(s string) string {
	// lowercase
	s = strings.ToLower(s)

	// replace bad chars with _
	s = replaceBadChars(s)

	// remove leading/trailing underscores
	s = strings.TrimLeft(s, "_")
	s = strings.TrimRight(s, "_")

	// fix 2 or more __
	s = underscoreRE.ReplaceAllString(s, "_")

	return snaker.SnakeToCamel(s)
}
Beispiel #8
0
func fillWithDetails(strukt interface{}, only []string, except []string) {
	elem := reflect.ValueOf(strukt).Elem()
	elemT := reflect.TypeOf(strukt).Elem()

	for i := 0; i < elem.NumField(); i++ {
		field := elem.Field(i)
		fieldt := elemT.Field(i)
		fakeType := fieldt.Tag.Get("fako")

		if fakeType != "" {
			fakeType = snaker.SnakeToCamel(fakeType)
			function := findFakeFunctionFor(fakeType)

			inOnly := len(only) == 0 || (len(only) > 0 && contains(only, fieldt.Name))
			notInExcept := len(except) == 0 || (len(except) > 0 && !contains(except, fieldt.Name))

			if field.CanSet() && fakeType != "" && inOnly && notInExcept {
				field.SetString(function())
			}
		}

	}
}
Beispiel #9
0
// PgParseQuery parses the query and generates a type for it.
func PgParseQuery(args *internal.ArgType, db *sql.DB, typeMap map[string]*bytes.Buffer) error {
	var err error

	// parse supplied query
	queryStr, params := parseQuery(args, args.Query, "$%d")
	inspectStr, _ := parseQuery(args, args.Query, "NULL")

	// strip out
	if args.QueryStrip {
		queryStr = queryStripRE.ReplaceAllString(queryStr, "")
	}

	// split up query and inspect based on lines
	query := strings.Split(queryStr, "\n")
	inspect := strings.Split(inspectStr, "\n")

	// build query comments with stripped values
	// FIXME: this is off by one, because of golang template syntax limitations
	queryComments := make([]string, len(query)+1)
	if args.QueryStrip {
		for i, l := range inspect {
			pos := queryStripRE.FindStringIndex(l)
			if pos != nil {
				queryComments[i+1] = l[pos[0]:pos[1]]
			} else {
				queryComments[i+1] = ""
			}
		}
	}

	// trim whitespace if applicable
	if args.QueryTrim {
		for n, l := range query {
			query[n] = strings.TrimSpace(l)
			if n < len(query)-1 {
				query[n] = query[n] + " "
			}
		}

		for n, l := range inspect {
			inspect[n] = strings.TrimSpace(l)
			if n < len(inspect)-1 {
				inspect[n] = inspect[n] + " "
			}
		}
	}

	// create temporary view xoid
	xoid := "_xo_" + genRandomID()
	viewq := `CREATE TEMPORARY VIEW ` + xoid + ` AS (` + strings.Join(inspect, "\n") + `)`
	_, err = db.Exec(viewq)
	if err != nil {
		return err
	}

	// determine schema name temporary view was created on
	// sql query
	var nspq = `SELECT n.nspname ` +
		`FROM pg_class c ` +
		`JOIN pg_namespace n ON n.oid = c.relnamespace ` +
		`WHERE n.nspname LIKE 'pg_temp%' AND c.relname = $1`

	// run schema query
	var schema string
	err = db.QueryRow(nspq, xoid).Scan(&schema)
	if err != nil {
		return err
	}

	// load column information ("v" == view)
	cols, err := models.ColumnsByRelkindSchema(db, "v", schema)
	if err != nil {
		return err
	}

	// create template for query type
	typeTpl := &templates.TableTemplate{
		Type:        args.QueryType,
		TableSchema: args.Schema,
		Fields:      []*models.Column{},
		Comment:     args.QueryTypeComment,
	}

	// process columns
	for _, c := range cols {
		c.Field = snaker.SnakeToCamel(c.ColumnName)
		c.Len, c.NilType, c.Type = PgParseType(args, c.DataType, false)
		typeTpl.Fields = append(typeTpl.Fields, c)
	}

	// generate query type template
	buf := GetBuf(typeMap, strings.ToLower(args.QueryType))
	err = templates.Tpls["postgres.model.go.tpl"].Execute(buf, typeTpl)
	if err != nil {
		return err
	}

	// build func name
	funcName := args.QueryFunc
	if funcName == "" {
		// no func name specified, so generate based on type
		if args.QueryOnlyOne {
			funcName = args.QueryType
		} else {
			funcName = inflector.Pluralize(args.QueryType)
		}

		// affix any params
		if len(params) == 0 {
			funcName = "Get" + funcName
		} else {
			funcName = funcName + "By"
			for _, p := range params {
				funcName = funcName + strings.ToUpper(p[0][:1]) + p[0][1:]
			}
		}
	}

	// create func template
	funcTpl := &templates.FuncTemplate{
		Name:          funcName,
		Type:          args.QueryType,
		Query:         query,
		QueryComments: queryComments,
		Parameters:    params,
		OnlyOne:       args.QueryOnlyOne,
		Comment:       args.QueryFuncComment,
		Table:         typeTpl,
	}

	// generate template
	err = templates.Tpls["postgres.func.go.tpl"].Execute(buf, funcTpl)
	if err != nil {
		return err
	}

	return nil
}
Beispiel #10
0
	var ep spec.Endpoint

	if err := json.NewDecoder(f).Decode(&ep); err != nil {
		return err
	}

	return cliTemplate.Execute(os.Stdout, map[string]interface{}{
		"spec": ep,
	})
}

var funcs = template.FuncMap{
	"methodName": snaker.SnakeToCamel,
	"optionsName": func(str string) string {
		return snaker.SnakeToCamel(str) + "Options"
	},
	"flag": func(typ, name, setVar, varName string) string {
		switch typ {
		case "bool":
			return fmt.Sprintf(`%s.BoolVar(&%s, "%s", false, "")`, setVar, varName, name)
		case "string":
			return fmt.Sprintf(`%s.StringVar(&%s, "%s", "", "")`, setVar, varName, name)
		case "int":
			return fmt.Sprintf(`%s.IntVar(&%s, "%s", 0, "")`, setVar, varName, name)
		default:
			panic("Invalid type " + typ)
		}
	},
}
Beispiel #11
0
// PgParseType parse a postgres type into a Go type based on the column
// definition.
func PgParseType(args *internal.ArgType, dt string, nullable bool) (int, string, string) {
	precision := 0
	nilType := "nil"
	asSlice := false

	// handle SETOF
	if strings.HasPrefix(dt, "SETOF ") {
		_, _, t := PgParseType(args, dt[len("SETOF "):], false)
		return 0, "nil", "[]" + t
	}

	// determine if it's a slice
	if strings.HasSuffix(dt, "[]") {
		dt = dt[:len(dt)-2]
		asSlice = true
	}

	// extract length
	if loc := pgLenRE.FindStringIndex(dt); len(loc) != 0 {
		precision, _ = strconv.Atoi(dt[loc[0]+1 : loc[1]-1])
		dt = dt[:loc[0]]
	}

	var typ string
	switch dt {
	case "boolean":
		nilType = "false"
		typ = "bool"
		if nullable {
			nilType = "sql.NullBool{}"
			typ = "sql.NullBool"
		}

	case "character", "character varying", "text":
		nilType = `""`
		typ = "string"
		if nullable {
			nilType = "sql.NullString{}"
			typ = "sql.NullString"
		}

	case "smallint":
		nilType = "0"
		typ = "int16"
		if nullable {
			nilType = "sql.NullInt64{}"
			typ = "sql.NullInt64"
		}
	case "integer":
		nilType = "0"
		typ = args.Int32Type
		if nullable {
			nilType = "sql.NullInt64{}"
			typ = "sql.NullInt64"
		}
	case "bigint":
		nilType = "0"
		typ = "int64"
		if nullable {
			nilType = "sql.NullInt64{}"
			typ = "sql.NullInt64"
		}

	case "smallserial":
		nilType = "0"
		typ = "uint16"
		if nullable {
			nilType = "sql.NullInt64{}"
			typ = "sql.NullInt64"
		}
	case "serial":
		nilType = "0"
		typ = args.Uint32Type
		if nullable {
			nilType = "sql.NullInt64{}"
			typ = "sql.NullInt64"
		}
	case "bigserial":
		nilType = "0"
		typ = "uint64"
		if nullable {
			nilType = "sql.NullInt64{}"
			typ = "sql.NullInt64"
		}

	case "real":
		nilType = "0.0"
		typ = "float32"
		if nullable {
			nilType = "sql.NullFloat64{}"
			typ = "sql.NullFloat64"
		}
	case "double precision":
		nilType = "0.0"
		typ = "float64"
		if nullable {
			nilType = "sql.NullFloat64{}"
			typ = "sql.NullFloat64"
		}

	case "bytea":
		asSlice = true
		typ = "byte"

	case "timestamp with time zone":
		typ = "*time.Time"
		if nullable {
			nilType = "pq.NullTime{}"
			typ = "pq.NullTime"
		}

	case "time with time zone", "time without time zone", "timestamp without time zone":
		nilType = "0"
		typ = "int64"
		if nullable {
			nilType = "sql.NullInt64{}"
			typ = "sql.NullInt64"
		}

	case "interval":
		typ = "*time.Duration"

	case `"char"`, "bit":
		// FIXME: this needs to actually be tested ...
		// i think this should be 'rune' but I don't think database/sql
		// supports 'rune' as a type?
		//
		// this is mainly here because postgres's pg_catalog.* meta tables have
		// this as a type.
		//typ = "rune"
		nilType = `uint8(0)`
		typ = "uint8"

	case `"any"`, "bit varying":
		asSlice = true
		typ = "byte"

	default:
		if strings.HasPrefix(dt, args.Schema+".") {
			// in the same schema, so chop off
			typ = snaker.SnakeToCamel(dt[len(args.Schema)+1:])
			nilType = typ + "(0)"
		} else {
			typ = snaker.SnakeToCamel(dt)
			nilType = typ + "{}"
		}
	}

	// special case for []slice
	if typ == "string" && asSlice {
		return precision, "StringSlice{}", "StringSlice"
	}

	// correct type if slice
	if asSlice {
		typ = "[]" + typ
		nilType = "nil"
	}

	return precision, nilType, typ
}
Beispiel #12
0
// PgLoadIdx loads indexes from the database.
func PgLoadIdx(args *internal.ArgType, db *sql.DB, typeMap map[string]*bytes.Buffer, tableMap map[string]*templates.TableTemplate) (map[string]*templates.IdxTemplate, error) {
	var err error

	// load idx's
	idxMap := map[string]*templates.IdxTemplate{}
	for _, t := range tableMap {
		// find relevant columns
		fields := []*models.Column{}
		for _, f := range t.Fields {
			if f.IsIndex && !f.IsForeignKey {
				if _, ok := idxMap[f.IndexName]; !ok {
					i := &templates.IdxTemplate{
						Type:        t.Type,
						Name:        snaker.SnakeToCamel(f.IndexName),
						TableSchema: t.TableSchema,
						TableName:   f.TableName,
						IndexName:   f.IndexName,
						IsUnique:    f.IsUnique,
						Fields:      fields,
						Table:       t,
					}

					// non unique lookup
					if !f.IsUnique {
						idxName := i.IndexName

						// chop off tablename_
						if strings.HasPrefix(idxName, f.TableName+"_") {
							idxName = idxName[len(f.TableName)+1:]
						}

						// chop off _idx or _index
						switch {
						case strings.HasSuffix(idxName, "_idx"):
							idxName = idxName[:len(idxName)-len("_idx")]
						case strings.HasSuffix(idxName, "_index"):
							idxName = idxName[:len(idxName)-len("_index")]
						}

						i.Name = snaker.SnakeToCamel(idxName)
						i.Plural = inflector.Pluralize(t.Type)
					}

					idxMap[f.IndexName] = i
				}

				idxMap[f.IndexName].Fields = append(idxMap[f.IndexName].Fields, f)
			}
		}
	}

	// idx keys
	idxKeys := []string{}
	for k := range idxMap {
		idxKeys = append(idxKeys, k)
	}
	sort.Strings(idxKeys)

	// generate templates
	for _, k := range idxKeys {
		buf := GetBuf(typeMap, strings.ToLower(idxMap[k].Type))
		err = templates.Tpls["postgres.idx.go.tpl"].Execute(buf, idxMap[k])
		if err != nil {
			return nil, err
		}
	}

	return idxMap, nil
}
Beispiel #13
0
		return err
	}

	return apiTemplate.Execute(os.Stdout, map[string]interface{}{
		"spec": ep,
	})
}

func ucfirst(str string) string {
	f, i := utf8.DecodeRuneInString(str)
	return string(unicode.ToUpper(f)) + str[i:]
}

var funcs = template.FuncMap{
	"responseName": func(str string) string {
		return snaker.SnakeToCamel(str) + "Response"
	},
	"optionsName": func(str string) string {
		return snaker.SnakeToCamel(str) + "Options"
	},
	"methodName": snaker.SnakeToCamel,
	"rsName": func(sp, rs string) string {
		return snaker.SnakeToCamel(sp) + ucfirst(rs)
	},
	"encodeFunc": func(str string) string {
		return "encode" + ucfirst(str)
	},
	"fieldName": func(str string) string {
		return ucfirst(snaker.SnakeToCamel(str))
	},
	"fieldNameFromRS": func(str string) string {
Beispiel #14
0
func run() int {
	var (
		args = flag.Args()
		g    genex.Generator
	)

	// Print the header and package clause.
	g.Printf("// Code generated by gen-config.\n")
	// Run generate for each type.
	filename := []string{}
	config := map[string]interface{}{}
	for _, fp := range genex.MustParseGlobs(args[:]) {
		if strings.HasSuffix(fp, ".tml") {
			if _, err := toml.DecodeFile(fp, &config); err == nil {
				g.Printf("// %s\n", fp)
				filename = append(filename, fp)
			}
		}
	}
	g.Printf("// DO NOT EDIT\n")
	g.Printf("\npackage %s\n", *pkg)

	// Generate two source files.
	params := map[string]interface{}{}
	params["ConfigDir"] = *confDir
	params["TypeBody"] = printer(config)
	params["Filename"] = func() (ret []string) {
		for _, v := range filename {
			ret = append(ret, strings.Replace(v, *confDir+"/", "", -1))
		}
		return
	}()
	params["StructName"] = func(cfg map[string]interface{}) (ret []map[string]string) {
		for k, _ := range cfg {
			elm := map[string]string{}
			elm["Struct"] = snaker.SnakeToCamel(k)
			elm["Tag"] = fmt.Sprintf("`toml:\"%s\"`", k)
			ret = append(ret, elm)
		}
		return
	}(config)

	// Format the output.
	t := template.Must(template.New("").Parse(text))
	var buf bytes.Buffer
	t.Execute(&buf, params)
	g.Printf("%s", buf.String())
	src := g.Format()

	// Write to file.
	outputName := *output
	if outputName == "" {
		baseName := OUTPUT
		outputName = filepath.Join(*srcDir, strings.ToLower(baseName))
	}
	err := ioutil.WriteFile(outputName, src, 0644)
	if err != nil {
		log.Fatalf("writing output: %s", err)
	}

	return 0
}
Beispiel #15
0
// Register allows user to add his own data generators for special cases
// that we could not cover with the generators that fako includes by default.
func Register(identifier string, generator func() string) {
	fakeType := snaker.SnakeToCamel(identifier)
	customGenerators[fakeType] = generator
}
Beispiel #16
0
func ColumnToField(s string) string {
	return snaker.SnakeToCamel(s)
}
Beispiel #17
0
func PropertyToField(s string) string {
	mediary := snaker.CamelToSnake(s)

	return snaker.SnakeToCamel(mediary)
}