func formatEndpoint(v *registry.Value, r int) string { // default format is tabbed plus the value plus new line fparts := []string{"", "%s %s", "\n"} for i := 0; i < r+1; i++ { fparts[0] += "\t" } // its just a primitive of sorts so return if len(v.Values) == 0 { return fmt.Sprintf(strings.Join(fparts, ""), snaker.CamelToSnake(v.Name), v.Type) } // this thing has more things, it's complex fparts[1] += " {" vals := []interface{}{snaker.CamelToSnake(v.Name), v.Type} for _, val := range v.Values { fparts = append(fparts, "%s") vals = append(vals, formatEndpoint(val, r+1)) } // at the end l := len(fparts) - 1 for i := 0; i < r+1; i++ { fparts[l] += "\t" } fparts = append(fparts, "}\n") return fmt.Sprintf(strings.Join(fparts, ""), vals...) }
func ValidateUniquenessOf(resource Resource, attribute string) { reflected := reflect.ValueOf(resource).Elem() value := reflect.Indirect(reflected).FieldByName(attribute) field := snaker.CamelToSnake(attribute) var count int table := DB.NewScope(resource).TableName() query := DB.Table(table).Where("LOWER("+field+")=?", strings.ToLower(value.String())) id := reflect.Indirect(reflected).FieldByName("ID").Int() if id > 0 { query = query.Not("id", id) } query.Count(&count) if count > 0 { resource.Errors().Add(attribute, "already exists") } }
//Generate generates a migration on the migrations folder func Generate(c *cli.Context) { setupTestingEnv() base := os.Getenv("TRANS_TESTING_FOLDER") name := "migration" if c.App != nil && len(c.Args()) > 0 { name = c.Args().First() } name = snaker.CamelToSnake(name) identifier := time.Now().UnixNano() migration := MigrationData{ Identifier: identifier, Name: name, } buff := bytes.NewBufferString("") tmpl, _ := template.New("migration").Parse(utils.MigrationTemplate) _ = tmpl.Execute(buff, migration) fileName := strconv.FormatInt(identifier, 10) + "_" + name + ".go" path := filepath.Join(base, "db", "migrations", fileName) err := ioutil.WriteFile(path, buff.Bytes(), generatedFilePermissions) if err != nil { log.Println(err) log.Println("| Could not write migration file, please check db/migrations folder exists") } }
func (query Query) createQuery() (q *gorm.DB) { query.tableify() q = query.Context.Connection.Table(query.tableName) for _, ancestor := range query.Ancestors { filter_by_str := ancestor.primaryKey() + " = ?" q = q.Where(filter_by_str, ancestor.key()) } for filter_by, value := range query.Filters { filter_by = snaker.CamelToSnake(filter_by) filter_by_str := filter_by + " ?" q = q.Where(filter_by_str, value) } if query.Limit != 0 { q = q.Limit(query.Limit) } if query.Offset != 0 { q = q.Offset(query.Offset) } if query.Order != "" { direction, column := order_by(query.Order) order_str := column + " " + direction q = q.Order(order_str) } return q }
// pluralCamelNameType takes a type, and returns its type converted // to camel_case and pluralised. func pluralCamelNameType(typ reflect.Type) string { t := fmt.Sprintf("%v", typ) a := strings.Split(t, ".") t1 := a[len(a)-1] t2 := snaker.CamelToSnake(t1) t3 := inflector.Pluralize(t2) return t3 }
// pluralCamelName takes an interface, and returns its type converted // to camel_case and pluralised. eg. pluralCamelName(ImportantPerson{}) // should return "important_people" func pluralCamelName(i interface{}) string { t := fmt.Sprintf("%T", i) a := strings.Split(t, ".") t1 := a[len(a)-1] t2 := snaker.CamelToSnake(t1) t3 := inflector.Pluralize(t2) return t3 }
func (e Errors) MarshalJSON() ([]byte, error) { for key, value := range e.collection { delete(e.collection, key) e.collection[snaker.CamelToSnake(key)] = value } return json.Marshal(e.collection) }
func GenerateKey(s string) string { key := CustomKeys[s] if key != "" { return key } key = strings.Replace(s, " ", "", -1) key = strings.Replace(key, "-", "", -1) key = snaker.CamelToSnake(key) return key }
func (n *Node) Render(buf *bytes.Buffer, r Renderer, nodes map[string]*Node, index int) error { header := fmt.Sprintf(`--- title: %s note: Auto generated by tickdoc menu: kapacitor_02: name: %s identifier: %s weight: %d parent: tick --- `, n.Name, strings.Replace(n.Name, "Node", "", 1), snaker.CamelToSnake(n.Name), (index+1)*indexWidth, ) buf.Write([]byte(header)) renderDoc(buf, nodes, r, n.Doc) // Properties if len(n.Properties) > 0 { r.Header(buf, func() bool { buf.Write([]byte("Properties")); return true }, 2, "") r.Paragraph(buf, func() bool { buf.Write([]byte("Property methods modify state on the calling node. They do not add another node to the pipeline, and always return a reference to the calling node.")) return true }) renderProperties(buf, r, n.Properties, nodes, 3, "node") } // Methods if len(n.Methods) > 0 { r.Header(buf, func() bool { buf.Write([]byte("Chaining Methods")); return true }, 2, "") r.Paragraph(buf, func() bool { buf.Write([]byte("Chaining methods create a new node in the pipeline as a child of the calling node. They do not modify the calling node.")) return true }) methods := make([]string, len(n.Methods)) i := 0 for name, _ := range n.Methods { methods[i] = name i++ } sort.Strings(methods) for _, name := range methods { n.Methods[name].Render(buf, r, nodes) buf.Write([]byte("\n")) } } return nil }
// New generates a new engine and returns it as an engine pointer func New(driver string, dsn string) (*Engine, error) { conn, err := sqlx.Open(driver, dsn) if err != nil { return nil, err } // set name mapper function conn.MapperFunc(func(name string) string { return snaker.CamelToSnake(name) }) return &Engine{ dialect: NewDialect(driver), dsn: dsn, db: conn, logger: &DefaultLogger{LDefault, log.New(os.Stdout, "", -1)}, }, err }
// goparamlist converts a list of fields into their named Go parameters, // skipping any Field with Name contained in ignoreNames. addType will cause // the go Type to be added after each variable name. addPrefix will cause the // returned string to be prefixed with ", " if the generated string is not // empty. // // Any field name encountered will be checked against goReservedNames, and will // have its name substituted by its corresponding looked up value. // // Used to present a comma separated list of Go variable names for use with as // either a Go func parameter list, or in a call to another Go func. // (ie, ", a, b, c, ..." or ", a T1, b T2, c T3, ..."). func (a *ArgType) goparamlist(fields []*Field, addPrefix bool, addType bool, ignoreNames ...string) string { ignore := map[string]bool{} for _, n := range ignoreNames { ignore[n] = true } i := 0 vals := []string{} for _, f := range fields { if ignore[f.Name] { continue } s := "v" + strconv.Itoa(i) if len(f.Name) > 0 { n := strings.Split(snaker.CamelToSnake(f.Name), "_") s = strings.ToLower(n[0]) + f.Name[len(n[0]):] } // check go reserved names if r, ok := goReservedNames[strings.ToLower(s)]; ok { s = r } // add the go type if addType { s += " " + a.retype(f.Type) } // add to vals vals = append(vals, s) i++ } // concat generated values str := strings.Join(vals, ", ") if addPrefix && str != "" { return ", " + str } return str }
// shortname checks the passed type against the ShortNameTypeMap and returns // the value for it. If the type is not found, then the value is calculated and // stored in the ShortNameTypeMap for use in the future. func shortname(typ string) string { var v string var ok bool // check short name map if v, ok = ShortNameTypeMap[typ]; !ok { // calc the short name u := []string{} for _, s := range strings.Split(strings.ToLower(snaker.CamelToSnake(typ)), "_") { if len(s) > 0 && s != "id" { u = append(u, s[:1]) } } v = strings.Join(u, "") // store back in short name map ShortNameTypeMap[typ] = v } return v }
func main() { if len(os.Args) != 4 { fmt.Println("Usage: tickdoc absPath path/to/golang/package output/dir") fmt.Println() fmt.Println("absPath - the absolute path of rendered documentation, used to generate links.") os.Exit(1) } absPath = os.Args[1] dir := os.Args[2] out := os.Args[3] fset := token.NewFileSet() // positions are relative to fset skipTest := func(fi os.FileInfo) bool { return !strings.HasSuffix(fi.Name(), "_test.go") } pkgs, err := parser.ParseDir(fset, dir, skipTest, parser.ParseComments) if err != nil { log.Fatal(err) } nodes := make(map[string]*Node) for _, pkg := range pkgs { f := ast.MergePackageFiles(pkg, ast.FilterFuncDuplicates|ast.FilterUnassociatedComments|ast.FilterImportDuplicates) ast.Inspect(f, func(n ast.Node) bool { switch decl := n.(type) { case *ast.GenDecl: handleGenDecl(nodes, decl) case *ast.FuncDecl: handleFuncDecl(nodes, decl) } return true }) } ordered := make([]string, 0, len(nodes)) for name, node := range nodes { if name == "" || !ast.IsExported(name) { continue } if node.Embedded { err := node.Embed(nodes) if err != nil { log.Fatal(err) } } else { ordered = append(ordered, name) node.Flatten(nodes) } } sort.Strings(ordered) r := markdown.NewRenderer() for i, name := range ordered { var buf bytes.Buffer n := nodes[name] n.Render(&buf, r, nodes, i) filename := path.Join(out, snaker.CamelToSnake(name)+".md") log.Println("Writing file:", filename, i) f, err := os.Create(filename) if err != nil { log.Fatal(err) } defer f.Close() f.Write(buf.Bytes()) } }
func nodeNameToLink(name string) string { return fmt.Sprintf("%s/%s/", absPath, snaker.CamelToSnake(name)) }
func PropertyToField(s string) string { mediary := snaker.CamelToSnake(s) return snaker.SnakeToCamel(mediary) }
func PropertyToColumn(s string) string { return snaker.CamelToSnake(s) }
func underscore(s string) string { return snaker.CamelToSnake(s) + ".go" }
func nodeNameToLink(name string) string { return fmt.Sprintf("%s/%s/", config.Root, snaker.CamelToSnake(name)) }
func Snakecase(s string) string { return snaker.CamelToSnake(s) }
// Get the information for a struct field. // // The format is as follows: // // Field SomeType `form:"TYPE[,required][,autofocus][,.htmlClass][,#htmlID][,<int>][,<int>!]"` // // The integer tag expresses a field size. The integer tag with "!" expresses a maximum length. // // TYPE is the HTML field type. For non-<input/> types, use the tag name ("select", "textarea", etc.) // // Many HTML classes may be specified. // If the HTML ID is not specified, the struct field name is used as the field name and HTML ID. // Otherwise, the HTML ID is used as the field name and HTML ID. // // The following additional field tags are also supported: // // fmsg: Format message, shown on validation error. // pattern: Regexp to enforce on client and server. // placeholder: Placeholder string. // label: Label string. // set: <select> value set. // func GetFieldInfo(sf reflect.StructField) FieldInfo { fi := FieldInfo{ FName: sf.Name, } tags := strings.Split(sf.Tag.Get("form"), ",") fi.Type = tags[0] for _, v := range tags[1:] { switch { case v == "required": fi.Required = true case v == "autofocus": fi.Autofocus = true case v == "": case v[0] == '.': fi.Classes = append(fi.Classes, v[1:]) case v[0] == '#': fi.ID = v[1:] case v[0] >= '0' && v[0] <= '9': strict := false if v[len(v)-1] == '!' { strict = true v = v[0 : len(v)-1] } else if idx := strings.IndexByte(v, 'x'); idx >= 0 { v2 := v[idx+1:] n, err := strconv.ParseUint(v2, 10, 31) if err == nil { fi.VSize = int(n) } v = v[0:idx] } n, err := strconv.ParseUint(v, 10, 31) if err == nil { if strict { fi.MaxLength = int(n) } else { fi.Size = int(n) } } default: if fi.Type == "" { fi.Type = v } } } fi.FormatMessage = sf.Tag.Get("fmsg") fi.Pattern = sf.Tag.Get("pattern") fi.ValueSet = sf.Tag.Get("set") if fi.ID == "" { fi.Name = fi.FName fi.Name = snaker.CamelToSnake(fi.Name) fi.ID = fi.Name } else { fi.Name = fi.ID } fi.Label = sf.Tag.Get("label") if fi.Label == "-" { fi.Label = "" } else if fi.Label == "" { fi.Label = fi.FName } fi.Placeholder = sf.Tag.Get("placeholder") if fi.Placeholder == "-" { fi.Placeholder = "" } else if fi.Placeholder == "" { fi.Placeholder = fi.Label } return fi }
func main() { flag.Usage = usage flag.Parse() args := flag.Args() if len(args) != 2 { flag.Usage() os.Exit(1) } dir := args[0] out := args[1] // Decode config err := decodeConfig(*configPath) if err != nil { log.Fatal(err) } fset := token.NewFileSet() // positions are relative to fset skipTest := func(fi os.FileInfo) bool { return !strings.HasSuffix(fi.Name(), "_test.go") } pkgs, err := parser.ParseDir(fset, dir, skipTest, parser.ParseComments) if err != nil { log.Fatal(err) } nodes := make(map[string]*Node) for _, pkg := range pkgs { f := ast.MergePackageFiles(pkg, ast.FilterFuncDuplicates|ast.FilterUnassociatedComments|ast.FilterImportDuplicates) ast.Inspect(f, func(n ast.Node) bool { switch decl := n.(type) { case *ast.GenDecl: handleGenDecl(nodes, decl) case *ast.FuncDecl: handleFuncDecl(nodes, decl) } return true }) } ordered := make([]string, 0, len(nodes)) for name, node := range nodes { if name == "" || !ast.IsExported(name) || node.Name == "" { continue } if node.Embedded { err := node.Embed(nodes) if err != nil { log.Fatal(err) } } else { ordered = append(ordered, name) node.Flatten(nodes) } } sort.Strings(ordered) r := markdown.NewRenderer(nil) for i, name := range ordered { var buf bytes.Buffer n := nodes[name] weight := (i + 1) * config.IndexWidth if w, ok := config.Weights[name]; ok { weight = w } n.Render(&buf, r, nodes, weight) filename := path.Join(out, snaker.CamelToSnake(name)+".md") log.Println("Writing file:", filename, i) f, err := os.Create(filename) if err != nil { log.Fatal(err) } defer f.Close() f.Write(buf.Bytes()) } }
func (n *Node) Render(buf *bytes.Buffer, r Renderer, nodes map[string]*Node, weight int) error { info := headerInfo{ Title: n.Name, Name: strings.Replace(n.Name, "Node", "", 1), Identifier: snaker.CamelToSnake(n.Name), Weight: weight, } config.headerTemplate.Execute(buf, info) renderDoc(buf, nodes, r, n.Doc) properties := make([]string, len(n.Properties)) i := 0 for name := range n.Properties { properties[i] = name i++ } sort.Strings(properties) methods := make([]string, len(n.Methods)) i = 0 for name := range n.Methods { methods[i] = name i++ } sort.Strings(methods) // Index r.Header(buf, func() bool { buf.Write([]byte("Index")); return true }, 2, "") r.Header(buf, func() bool { buf.Write([]byte("Properties")); return true }, 3, "") r.List(buf, func() bool { for _, name := range properties { r.ListItem(buf, []byte(fmt.Sprintf("[%s](%s)", name, methodNameToLink(n.Name, name))), 1024) } return true }, 0) r.Header(buf, func() bool { buf.Write([]byte("Chaining Methods")); return true }, 3, "") r.List(buf, func() bool { for _, name := range methods { r.ListItem(buf, []byte(fmt.Sprintf("[%s](%s)", name, methodNameToLink(n.Name, name))), 1024) } return true }, 0) // Properties if len(n.Properties) > 0 { r.Header(buf, func() bool { buf.Write([]byte("Properties")); return true }, 2, "") r.Paragraph(buf, func() bool { buf.Write([]byte(config.PropertyMethodDesc)) return true }) renderProperties(buf, r, n.Properties, nodes, 3, "node", "") } // Methods if len(methods) > 0 { r.Header(buf, func() bool { buf.Write([]byte("Chaining Methods")); return true }, 2, "") r.Paragraph(buf, func() bool { buf.Write([]byte(config.ChainMethodDesc)) return true }) for _, name := range methods { n.Methods[name].Render(buf, r, nodes) buf.Write([]byte("\n")) } } return nil }
func (sd *SchemaDSL) Parse() (err error) { fset := token.NewFileSet() f, err := parser.ParseFile(fset, sd.config.SchemaFile, nil, parser.ParseComments) if err != nil { return err } ast.FileExports(f) SCHEMA_PARSE_LOOP: for _, decl := range f.Decls { table := "" fields := []*ast.Field{} if genDecl, ok := decl.(*ast.GenDecl); ok { for _, spec := range genDecl.Specs { if typeSpec, ok := spec.(*ast.TypeSpec); ok { table = snaker.CamelToSnake(typeSpec.Name.Name) if structType, ok := typeSpec.Type.(*ast.StructType); ok { fields = structType.Fields.List } } } if genDecl.Doc != nil { for _, doc := range genDecl.Doc.List { if strings.HasPrefix(doc.Text, COMMENT_IGNORE_PREFIX) { continue SCHEMA_PARSE_LOOP } if strings.HasPrefix(doc.Text, COMMENT_TABLE_PREFIX) { table = strings.TrimSpace(strings.TrimPrefix(doc.Text, COMMENT_TABLE_PREFIX)) } } } } sd.Tables = append(sd.Tables, &Table{Name: table, AstFields: fields}) } for _, table := range sd.Tables { var primaryKeys []string for _, field := range table.AstFields { if field.Tag == nil { continue } var typeName string tagMap := parseTag(field.Tag.Value) if t, ok := field.Type.(*ast.Ident); ok { typeName = t.Name } if t, ok := field.Type.(*ast.SelectorExpr); ok { x := t.X.(*ast.Ident).Name sel := t.Sel.Name typeName = fmt.Sprintf("%s.%s", x, sel) } columns, err := sd.Dialect.ConvertSql(typeName, tagMap) if err != nil { return err } table.Fields = append(table.Fields, &Field{ Name: tagMap["sql"], Attribute: strings.Join(columns, " "), }) if _, ok := tagMap["primary"]; ok { primaryKeys = append(primaryKeys, tagMap["sql"]) } if _, ok := tagMap["uniq"]; ok { name := tagMap["uniq"] if name == "" { name = fmt.Sprintf("`%s_%s`", table.Name, strings.Replace(tagMap["sql"], "`", "", -1)) } table.ParseIndex(&table.UniqueIndexes, name, tagMap["sql"]) } if _, ok := tagMap["index"]; ok { table.ParseIndex(&table.Indexes, tagMap["index"], tagMap["sql"]) } } table.PrimaryKey = strings.Join(primaryKeys, ", ") } return nil }
func FieldToColumn(s string) string { return snaker.CamelToSnake(s) }
// shortname generates a safe Go identifier for typ. typ is first checked // against ArgType.ShortNameTypeMap, and if not found, then the value is // calculated and stored in the ShortNameTypeMap for future use. // // A shortname is the concatentation of the lowercase of the first character in // the words comprising the name. For example, "MyCustomName" will have have // the shortname of "mcn". // // If a generated shortname conflicts with a Go reserved name, then the // corresponding value in goReservedNames map will be used. // // Generated shortnames that have conflicts with any scopeConflicts member will // have ArgType.NameConflictSuffix appended. // // Note: recognized types for scopeConflicts are string, []*Field, // []*QueryParam. func (a *ArgType) shortname(typ string, scopeConflicts ...interface{}) string { var v string var ok bool // check short name map if v, ok = a.ShortNameTypeMap[typ]; !ok { // calc the short name u := []string{} for _, s := range strings.Split(strings.ToLower(snaker.CamelToSnake(typ)), "_") { if len(s) > 0 && s != "id" { u = append(u, s[:1]) } } v = strings.Join(u, "") // check go reserved names if n, ok := goReservedNames[v]; ok { v = n } // store back to short name map a.ShortNameTypeMap[typ] = v } // initial conflicts are the default imported packages from // xo_package.go.tpl conflicts := map[string]bool{ "sql": true, "driver": true, "csv": true, "errors": true, "fmt": true, "regexp": true, "strings": true, "time": true, } // add scopeConflicts to conflicts for _, c := range scopeConflicts { switch k := c.(type) { case string: conflicts[k] = true case []*Field: for _, f := range k { conflicts[f.Name] = true } case []*QueryParam: for _, f := range k { conflicts[f.Name] = true } default: panic("not implemented") } } // append suffix if conflict exists if _, ok := conflicts[v]; ok { v = v + a.NameConflictSuffix } return v }
func generateModel(dbName, tName, structName string, schema drivers.TableSchema, config CodeConfig, tmpl *template.Template) error { snakeStructName := snaker.CamelToSnake(structName) file, err := os.Create(path.Join(config.packageName, snakeStructName+"_mq.go")) if err != nil { return err } w := bufio.NewWriter(file) defer func() { w.Flush() file.Close() }() model := ModelMeta{ I: string(strings.ToLower(tName)[0]), Name: toCapitalCase(structName), SnakeName: snakeStructName, DbName: dbName, TableName: tName, Fields: make([]ModelField, len(schema)), Uniques: make([]ModelField, 0, len(schema)), config: config, } needTime := false for i, col := range schema { name := toCapitalCase(col.ColumnName) field := ModelField{ Name: name, ColumnName: col.ColumnName, Type: col.DataType, JsonMeta: fmt.Sprintf("`json:\"%s\"`", snaker.CamelToSnake(col.ColumnName)), IsPrimaryKey: strings.ToUpper(col.ColumnKey) == "PRI", IsUniqueKey: strings.ToUpper(col.ColumnKey) == "UNI", IsAutoIncrement: strings.ToUpper(col.Extra) == "AUTO_INCREMENT", DefaultValue: col.DefaultValue, Extra: col.Extra, Comment: col.Comment, IsNullable: col.IsNullable, NullType: col.NullType, IsSuper: IsSuperField(name), } if field.Type == "time.Time" { needTime = true } if field.IsPrimaryKey { model.PrimaryFields = append(model.PrimaryFields, &field) } if field.IsUniqueKey { model.Uniques = append(model.Uniques, field) } model.Fields[i] = field } if err := model.GenHeader(w, tmpl, needTime); err != nil { return fmt.Errorf("[%s] Fail to gen model header, %s", tName, err) } if config.buildStuct { if err := model.GenStruct(w, tmpl); err != nil { return fmt.Errorf("[%s] Fail to gen model struct, %s", tName, err) } } if err := model.GenFindFetch(w, tmpl); err != nil { return fmt.Errorf("[%s] Fail to gen find fetch api, %s", tName, err) } // if err := model.GenObjectApi(w, tmpl); err != nil { // return fmt.Errorf("[%s] Fail to gen model object api, %s", tName, err) // } // if err := model.GenQueryApi(w, tmpl); err != nil { // return fmt.Errorf("[%s] Fail to gen model query api, %s", tName, err) // } // if err := model.GenManagedObjApi(w, tmpl); err != nil { // return fmt.Errorf("[%s] Fail to gen model managed objects api, %s", tName, err) // } return nil }
var genFileParam = GenFileParam{} var GenHandlerAction = func(c *cli.Context) { if len(c.Args()) == 0 { fmt.Println("| ERROR: Please specify a handler name.") return } genFileParam.Name = strings.Replace(c.Args()[0], " ", "", -1) if exists, _ := pathExists("handlers"); exists == false { fmt.Println("| ERROR: handlers folder does not exist in current workign directory.") return } fileName := snaker.CamelToSnake(genFileParam.Name) filePath := path.Join("handlers", fileName+".go") if exists, _ := pathExists(filePath); exists == true { fmt.Printf("| ERROR: '%s' already exists \n", filePath) return } file, err := os.Create(filePath) if err != nil { fmt.Println("| ERROR: Could not create file: ", err.Error()) return } err, dat := writeTemplatedFile(handlerGenTemplate, genFileParam) if err != nil {
// ParseQuery satisfies Loader's ParseQuery. func (tl TypeLoader) ParseQuery(args *ArgType) error { var err error // parse supplied query queryStr, params := args.ParseQuery(tl.Mask(), true) inspectStr, _ := args.ParseQuery("NULL", false) // split up query and inspect based on lines query := strings.Split(queryStr, "\n") inspect := strings.Split(inspectStr, "\n") // query comment placeholder queryComments := make([]string, len(query)+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] + " " } } } // query strip if args.QueryStrip && tl.QueryStrip != nil { tl.QueryStrip(query, queryComments) } // create template for query type typeTpl := &Type{ Name: args.QueryType, RelType: Table, Fields: []*Field{}, Table: &models.Table{ TableName: "[custom " + strings.ToLower(snaker.CamelToSnake(args.QueryType)) + "]", }, Comment: args.QueryTypeComment, } if args.QueryFields == "" { // if no query fields specified, then pass to inspector colList, err := tl.QueryColumnList(args, inspect) if err != nil { return err } // process columns for _, c := range colList { f := &Field{ Name: SnakeToIdentifier(c.ColumnName), Col: c, } f.Len, f.NilType, f.Type = tl.ParseType(args, c.DataType, false) typeTpl.Fields = append(typeTpl.Fields, f) } } else { // extract fields from query fields for _, qf := range strings.Split(args.QueryFields, ",") { qf = strings.TrimSpace(qf) colName := qf colType := "string" i := strings.Index(qf, " ") if i != -1 { colName = qf[:i] colType = qf[i+1:] } typeTpl.Fields = append(typeTpl.Fields, &Field{ Name: colName, Type: colType, Col: &models.Column{ ColumnName: snaker.CamelToSnake(colName), }, }) } } // generate query type template err = args.ExecuteTemplate(QueryTypeTemplate, args.QueryType, "", 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.Name[:1]) + p.Name[1:] } } } // create func template queryTpl := &Query{ Name: funcName, Query: query, QueryComments: queryComments, QueryParams: params, OnlyOne: args.QueryOnlyOne, Interpolate: args.QueryInterpolate, Type: typeTpl, Comment: args.QueryFuncComment, } // generate template err = args.ExecuteTemplate(QueryTemplate, args.QueryType, "", queryTpl) if err != nil { return err } return nil }