Improve database to golang name mapping.
This commit is contained in:
parent
3e7277015d
commit
950663dadb
19 changed files with 538 additions and 122 deletions
|
|
@ -28,7 +28,7 @@ jobs:
|
||||||
command: |
|
command: |
|
||||||
go get github.com/google/uuid
|
go get github.com/google/uuid
|
||||||
go get github.com/lib/pq
|
go get github.com/lib/pq
|
||||||
go get github.com/serenize/snaker
|
|
||||||
go get github.com/pkg/profile
|
go get github.com/pkg/profile
|
||||||
go get gotest.tools/assert
|
go get gotest.tools/assert
|
||||||
go get github.com/davecgh/go-spew/spew
|
go get github.com/davecgh/go-spew/spew
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ func (q *queryData) writeString(str string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *queryData) writeIdentifier(name string) {
|
func (q *queryData) writeIdentifier(name string) {
|
||||||
quoteWrap := name != strings.ToLower(name) || strings.Contains(name, ".")
|
quoteWrap := name != strings.ToLower(name) || strings.ContainsAny(name, ". -")
|
||||||
|
|
||||||
if quoteWrap {
|
if quoteWrap {
|
||||||
q.writeString(`"` + name + `"`)
|
q.writeString(`"` + name + `"`)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-jet/jet/execution/internal"
|
"github.com/go-jet/jet/execution/internal"
|
||||||
"github.com/serenize/snaker"
|
"github.com/go-jet/jet/internal/util"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -139,10 +139,7 @@ func mapRowToSlice(scanContext *scanContext, groupKey string, slicePtrValue refl
|
||||||
if isGoBaseType(sliceElemType) {
|
if isGoBaseType(sliceElemType) {
|
||||||
index := 0
|
index := 0
|
||||||
if structField != nil {
|
if structField != nil {
|
||||||
tableName, columnName := getRefAlias(structField)
|
if index = scanContext.aliasColumnIndex(structField.Tag.Get("alias")); index < 0 {
|
||||||
index = scanContext.columnIndex(tableName, columnName)
|
|
||||||
|
|
||||||
if index < 0 {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -293,28 +290,24 @@ func mapRowToDestinationValue(scanContext *scanContext, groupKey string, dest re
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapRowToStruct(scanContext *scanContext, groupKey string, structPtrValue reflect.Value, structField *reflect.StructField, onlySlices ...bool) (updated bool, err error) {
|
func mapRowToStruct(scanContext *scanContext, groupKey string, structPtrValue reflect.Value, parentField *reflect.StructField, onlySlices ...bool) (updated bool, err error) {
|
||||||
structType := structPtrValue.Type().Elem()
|
structType := structPtrValue.Type().Elem()
|
||||||
structValue := structPtrValue.Elem()
|
structValue := structPtrValue.Elem()
|
||||||
|
|
||||||
tableName, _ := getRefAlias(structField)
|
typeName := getTypeName(structType, parentField)
|
||||||
|
|
||||||
if tableName == "" {
|
|
||||||
tableName = structType.Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < structType.NumField(); i++ {
|
for i := 0; i < structType.NumField(); i++ {
|
||||||
field := structType.Field(i)
|
field := structType.Field(i)
|
||||||
|
|
||||||
fieldValue := structValue.Field(i)
|
fieldValue := structValue.Field(i)
|
||||||
columnName := field.Name
|
fieldName := field.Name
|
||||||
|
|
||||||
if scannerValue, ok := implementsScanner(fieldValue); ok {
|
if scannerValue, ok := implementsScanner(fieldValue); ok {
|
||||||
if len(onlySlices) > 0 {
|
if len(onlySlices) > 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
cellValue := scanContext.getCellValue(tableName, columnName)
|
cellValue := scanContext.getCellValue(typeName, fieldName)
|
||||||
|
|
||||||
if cellValue == nil {
|
if cellValue == nil {
|
||||||
continue
|
continue
|
||||||
|
|
@ -336,7 +329,7 @@ func mapRowToStruct(scanContext *scanContext, groupKey string, structPtrValue re
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
cellValue := scanContext.getCellValue(tableName, columnName)
|
cellValue := scanContext.getCellValue(typeName, fieldName)
|
||||||
|
|
||||||
if cellValue != nil {
|
if cellValue != nil {
|
||||||
updated = true
|
updated = true
|
||||||
|
|
@ -365,26 +358,20 @@ func mapRowToStruct(scanContext *scanContext, groupKey string, structPtrValue re
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRefAlias(structField *reflect.StructField) (table, column string) {
|
func getTypeName(structType reflect.Type, parentField *reflect.StructField) string {
|
||||||
if structField == nil {
|
if parentField == nil {
|
||||||
return
|
return structType.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
aliasTag := structField.Tag.Get("alias")
|
aliasTag := parentField.Tag.Get("alias")
|
||||||
|
|
||||||
if aliasTag == "" {
|
if aliasTag == "" {
|
||||||
return
|
return structType.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
aliasParts := strings.Split(aliasTag, ".")
|
aliasParts := strings.Split(aliasTag, ".")
|
||||||
|
|
||||||
table = aliasParts[0]
|
return aliasParts[0]
|
||||||
|
|
||||||
if len(aliasParts) > 1 {
|
|
||||||
column = aliasParts[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func initializeValueIfNilPtr(value reflect.Value) {
|
func initializeValueIfNilPtr(value reflect.Value) {
|
||||||
|
|
@ -533,12 +520,14 @@ type scanContext struct {
|
||||||
row []interface{}
|
row []interface{}
|
||||||
uniqueDestObjectsMap map[string]int
|
uniqueDestObjectsMap map[string]int
|
||||||
|
|
||||||
columnNameIndexMap map[string]int
|
aliasIndexMap map[string]int
|
||||||
|
goNameMap map[string]int
|
||||||
|
|
||||||
groupKeyInfoCache map[string]groupKeyInfo
|
groupKeyInfoCache map[string]groupKeyInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func newScanContext(rows *sql.Rows) (*scanContext, error) {
|
func newScanContext(rows *sql.Rows) (*scanContext, error) {
|
||||||
columnNames, err := rows.Columns()
|
aliases, err := rows.Columns()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -550,10 +539,24 @@ func newScanContext(rows *sql.Rows) (*scanContext, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
columnNameIndexMap := map[string]int{}
|
aliasIndexMap := map[string]int{}
|
||||||
|
|
||||||
for i, columnName := range columnNames {
|
for i, columnName := range aliases {
|
||||||
columnNameIndexMap[strings.ToLower(columnName)] = i
|
aliasIndexMap[strings.ToLower(columnName)] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
goNamesMap := map[string]int{}
|
||||||
|
|
||||||
|
for i, alias := range aliases {
|
||||||
|
names := strings.SplitN(alias, ".", 2)
|
||||||
|
|
||||||
|
goName := util.ToGoIdentifier(names[0])
|
||||||
|
|
||||||
|
if len(names) > 1 {
|
||||||
|
goName += "." + util.ToGoIdentifier(names[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
goNamesMap[strings.ToLower(goName)] = i
|
||||||
}
|
}
|
||||||
|
|
||||||
return &scanContext{
|
return &scanContext{
|
||||||
|
|
@ -561,8 +564,8 @@ func newScanContext(rows *sql.Rows) (*scanContext, error) {
|
||||||
uniqueDestObjectsMap: make(map[string]int),
|
uniqueDestObjectsMap: make(map[string]int),
|
||||||
|
|
||||||
groupKeyInfoCache: make(map[string]groupKeyInfo),
|
groupKeyInfoCache: make(map[string]groupKeyInfo),
|
||||||
|
aliasIndexMap: aliasIndexMap,
|
||||||
columnNameIndexMap: columnNameIndexMap,
|
goNameMap: goNamesMap,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -607,12 +610,8 @@ func (s *scanContext) constructGroupKey(groupKeyInfo groupKeyInfo) string {
|
||||||
return "{" + groupKeyInfo.typeName + "(" + strings.Join(groupKeys, ",") + strings.Join(subTypesGroupKeys, ",") + ")}"
|
return "{" + groupKeyInfo.typeName + "(" + strings.Join(groupKeys, ",") + strings.Join(subTypesGroupKeys, ",") + ")}"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanContext) getGroupKeyInfo(structType reflect.Type, structField *reflect.StructField) groupKeyInfo {
|
func (s *scanContext) getGroupKeyInfo(structType reflect.Type, parentField *reflect.StructField) groupKeyInfo {
|
||||||
tableName, _ := getRefAlias(structField)
|
typeName := getTypeName(structType, parentField)
|
||||||
|
|
||||||
if tableName == "" {
|
|
||||||
tableName = structType.Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
ret := groupKeyInfo{typeName: structType.Name()}
|
ret := groupKeyInfo{typeName: structType.Name()}
|
||||||
|
|
||||||
|
|
@ -635,7 +634,7 @@ func (s *scanContext) getGroupKeyInfo(structType reflect.Type, structField *refl
|
||||||
ret.subTypes = append(ret.subTypes, subType)
|
ret.subTypes = append(ret.subTypes, subType)
|
||||||
}
|
}
|
||||||
} else if isPrimaryKey(field) {
|
} else if isPrimaryKey(field) {
|
||||||
index := s.columnIndex(tableName, field.Name)
|
index := s.typeColumnIndex(typeName, field.Name)
|
||||||
|
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
continue
|
continue
|
||||||
|
|
@ -654,47 +653,36 @@ type groupKeyInfo struct {
|
||||||
subTypes []groupKeyInfo
|
subTypes []groupKeyInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanContext) columnIndex(tableName, columnName string) int {
|
func (s *scanContext) aliasColumnIndex(alias string) int {
|
||||||
if tableName == "" {
|
index, ok := s.aliasIndexMap[alias]
|
||||||
name := strings.ToLower(columnName)
|
|
||||||
if i, ok := s.columnNameIndexMap[name]; ok {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
name = strings.ToLower(snaker.CamelToSnake(columnName))
|
|
||||||
if i, ok := s.columnNameIndexMap[name]; ok {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
name := strings.ToLower(tableName + "." + columnName)
|
|
||||||
if i, ok := s.columnNameIndexMap[name]; ok {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
snakedTableName := snaker.CamelToSnake(tableName)
|
|
||||||
snakedColumnName := snaker.CamelToSnake(columnName)
|
|
||||||
|
|
||||||
name = strings.ToLower(snakedTableName + "." + snakedColumnName)
|
|
||||||
if i, ok := s.columnNameIndexMap[name]; ok {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
name = strings.ToLower(tableName + "." + snakedColumnName)
|
|
||||||
if i, ok := s.columnNameIndexMap[name]; ok {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
name = strings.ToLower(snakedTableName + "." + columnName)
|
|
||||||
if i, ok := s.columnNameIndexMap[name]; ok {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if !ok {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanContext) getCellValue(tableName, fieldName string) interface{} {
|
return index
|
||||||
index := s.columnIndex(tableName, fieldName)
|
}
|
||||||
|
|
||||||
|
func (s *scanContext) typeColumnIndex(typeName, fieldName string) int {
|
||||||
|
var key string
|
||||||
|
|
||||||
|
if typeName != "" {
|
||||||
|
key = strings.ToLower(typeName + "." + fieldName)
|
||||||
|
} else {
|
||||||
|
key = strings.ToLower(fieldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
index, ok := s.goNameMap[key]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *scanContext) getCellValue(typeName, fieldName string) interface{} {
|
||||||
|
index := s.typeColumnIndex(typeName, fieldName)
|
||||||
|
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package postgres_metadata
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/serenize/snaker"
|
"github.com/go-jet/jet/internal/util"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ func (c ColumnInfo) SqlBuilderColumnType() string {
|
||||||
func (c ColumnInfo) GoBaseType() string {
|
func (c ColumnInfo) GoBaseType() string {
|
||||||
switch c.DataType {
|
switch c.DataType {
|
||||||
case "USER-DEFINED":
|
case "USER-DEFINED":
|
||||||
return snaker.SnakeToCamel(c.EnumName)
|
return util.ToGoIdentifier(c.EnumName)
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return "bool"
|
return "bool"
|
||||||
case "smallint":
|
case "smallint":
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package postgres_metadata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"github.com/serenize/snaker"
|
"github.com/go-jet/jet/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TableInfo struct {
|
type TableInfo struct {
|
||||||
|
|
@ -58,7 +58,7 @@ func (t TableInfo) GetImports() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t TableInfo) GoStructName() string {
|
func (t TableInfo) GoStructName() string {
|
||||||
return snaker.SnakeToCamel(t.name) + "Table"
|
return util.ToGoIdentifier(t.name) + "Table"
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTableInfo(db *sql.DB, dbName, schemaName, tableName string) (tableInfo TableInfo, err error) {
|
func GetTableInfo(db *sql.DB, dbName, schemaName, tableName string) (tableInfo TableInfo, err error) {
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,10 @@ package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/serenize/snaker"
|
"github.com/go-jet/jet/internal/util"
|
||||||
"go/format"
|
"go/format"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -51,9 +50,7 @@ func EnsureDirPath(dirPath string) error {
|
||||||
func GenerateTemplate(templateText string, templateData interface{}) ([]byte, error) {
|
func GenerateTemplate(templateText string, templateData interface{}) ([]byte, error) {
|
||||||
|
|
||||||
t, err := template.New("sqlBuilderTableTemplate").Funcs(template.FuncMap{
|
t, err := template.New("sqlBuilderTableTemplate").Funcs(template.FuncMap{
|
||||||
"camelize": func(txt string) string {
|
"ToGoIdentifier": util.ToGoIdentifier,
|
||||||
return snaker.SnakeToCamel(strings.Replace(txt, "-", "_", -1))
|
|
||||||
},
|
|
||||||
"now": func() string {
|
"now": func() string {
|
||||||
return time.Now().Format(time.RFC850)
|
return time.Now().Format(time.RFC850)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/go-jet/jet/generator/internal/metadata"
|
"github.com/go-jet/jet/generator/internal/metadata"
|
||||||
"github.com/go-jet/jet/generator/internal/metadata/postgres-metadata"
|
"github.com/go-jet/jet/generator/internal/metadata/postgres-metadata"
|
||||||
"github.com/go-jet/jet/generator/internal/utils"
|
"github.com/go-jet/jet/generator/internal/utils"
|
||||||
|
"github.com/go-jet/jet/internal/util"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -115,7 +116,7 @@ func generate(schemaInfo postgres_metadata.SchemaInfo, dirPath, packageName stri
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = utils.SaveGoFile(modelDirPath, metaData.Name(), append(autoGenWarning, text...))
|
err = utils.SaveGoFile(modelDirPath, util.ToGoFileName(metaData.Name()), append(autoGenWarning, text...))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ package postgresgen
|
||||||
|
|
||||||
var autoGenWarningTemplate = `
|
var autoGenWarningTemplate = `
|
||||||
//
|
//
|
||||||
// Code generated by go-jet DO NOT EDIT.
|
// Code generated by jetgen DO NOT EDIT.
|
||||||
// Generated at {{now}}
|
// Generated at {{now}}
|
||||||
//
|
//
|
||||||
// WARNING: Changes to this file may cause incorrect behavior and will be lost
|
// WARNING: Changes to this file may cause incorrect behavior and will be lost
|
||||||
// if the code is regenerated
|
// if the code is regenerated
|
||||||
//
|
//
|
||||||
// Licence under ...
|
// Licence under github.com/go-jet/jet/LICENSE
|
||||||
//
|
//
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
@ -16,7 +16,7 @@ var autoGenWarningTemplate = `
|
||||||
var sqlBuilderTableTemplate = `
|
var sqlBuilderTableTemplate = `
|
||||||
{{define "column-list" -}}
|
{{define "column-list" -}}
|
||||||
{{- range $i, $c := . }}
|
{{- range $i, $c := . }}
|
||||||
{{- if gt $i 0 }}, {{end}}{{camelize $c.Name}}Column
|
{{- if gt $i 0 }}, {{end}}{{ToGoIdentifier $c.Name}}Column
|
||||||
{{- end}}
|
{{- end}}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
|
|
@ -26,14 +26,14 @@ import (
|
||||||
"github.com/go-jet/jet"
|
"github.com/go-jet/jet"
|
||||||
)
|
)
|
||||||
|
|
||||||
var {{camelize .Name}} = new{{.GoStructName}}()
|
var {{ToGoIdentifier .Name}} = new{{.GoStructName}}()
|
||||||
|
|
||||||
type {{.GoStructName}} struct {
|
type {{.GoStructName}} struct {
|
||||||
jet.Table
|
jet.Table
|
||||||
|
|
||||||
//Columns
|
//Columns
|
||||||
{{- range .Columns}}
|
{{- range .Columns}}
|
||||||
{{camelize .Name}} jet.Column{{.SqlBuilderColumnType}}
|
{{ToGoIdentifier .Name}} jet.Column{{.SqlBuilderColumnType}}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
AllColumns jet.ColumnList
|
AllColumns jet.ColumnList
|
||||||
|
|
@ -52,7 +52,7 @@ func (a *{{.GoStructName}}) AS(alias string) *{{.GoStructName}} {
|
||||||
func new{{.GoStructName}}() *{{.GoStructName}} {
|
func new{{.GoStructName}}() *{{.GoStructName}} {
|
||||||
var (
|
var (
|
||||||
{{- range .Columns}}
|
{{- range .Columns}}
|
||||||
{{camelize .Name}}Column = jet.{{.SqlBuilderColumnType}}Column("{{.Name}}")
|
{{ToGoIdentifier .Name}}Column = jet.{{.SqlBuilderColumnType}}Column("{{.Name}}")
|
||||||
{{- end}}
|
{{- end}}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -61,7 +61,7 @@ func new{{.GoStructName}}() *{{.GoStructName}} {
|
||||||
|
|
||||||
//Columns
|
//Columns
|
||||||
{{- range .Columns}}
|
{{- range .Columns}}
|
||||||
{{camelize .Name}}: {{camelize .Name}}Column,
|
{{ToGoIdentifier .Name}}: {{ToGoIdentifier .Name}}Column,
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
AllColumns: jet.ColumnList{ {{template "column-list" .Columns}} },
|
AllColumns: jet.ColumnList{ {{template "column-list" .Columns}} },
|
||||||
|
|
@ -82,9 +82,9 @@ import (
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|
||||||
type {{camelize .Name}} struct {
|
type {{ToGoIdentifier .Name}} struct {
|
||||||
{{- range .Columns}}
|
{{- range .Columns}}
|
||||||
{{camelize .Name}} {{.GoModelType}} ` + "{{.GoModelTag ($.IsPrimaryKey .Name)}}" + `
|
{{ToGoIdentifier .Name}} {{.GoModelType}} ` + "{{.GoModelTag ($.IsPrimaryKey .Name)}}" + `
|
||||||
{{- end}}
|
{{- end}}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
@ -93,32 +93,32 @@ var enumModelTemplate = `package model
|
||||||
|
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
type {{camelize $.Name}} string
|
type {{ToGoIdentifier $.Name}} string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
{{- range $index, $element := .Values}}
|
{{- range $index, $element := .Values}}
|
||||||
{{camelize $.Name}}_{{camelize $element}} {{camelize $.Name}} = "{{$element}}"
|
{{ToGoIdentifier $.Name}}_{{ToGoIdentifier $element}} {{ToGoIdentifier $.Name}} = "{{$element}}"
|
||||||
{{- end}}
|
{{- end}}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (e *{{camelize $.Name}}) Scan(value interface{}) error {
|
func (e *{{ToGoIdentifier $.Name}}) Scan(value interface{}) error {
|
||||||
if v, ok := value.(string); !ok {
|
if v, ok := value.(string); !ok {
|
||||||
return errors.New("Invalid data for {{camelize $.Name}} enum")
|
return errors.New("Invalid data for {{ToGoIdentifier $.Name}} enum")
|
||||||
} else {
|
} else {
|
||||||
switch string(v) {
|
switch string(v) {
|
||||||
{{- range $index, $element := .Values}}
|
{{- range $index, $element := .Values}}
|
||||||
case "{{$element}}":
|
case "{{$element}}":
|
||||||
*e = {{camelize $.Name}}_{{camelize $element}}
|
*e = {{ToGoIdentifier $.Name}}_{{ToGoIdentifier $element}}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
default:
|
default:
|
||||||
return errors.New("Inavlid data " + string(v) + "for {{camelize $.Name}} enum")
|
return errors.New("Inavlid data " + string(v) + "for {{ToGoIdentifier $.Name}} enum")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e {{camelize $.Name}}) String() string {
|
func (e {{ToGoIdentifier $.Name}}) String() string {
|
||||||
return string(e)
|
return string(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,13 +127,13 @@ var enumTypeTemplate = `package enum
|
||||||
|
|
||||||
import "github.com/go-jet/jet"
|
import "github.com/go-jet/jet"
|
||||||
|
|
||||||
var {{camelize $.Name}} = &struct {
|
var {{ToGoIdentifier $.Name}} = &struct {
|
||||||
{{- range $index, $element := .Values}}
|
{{- range $index, $element := .Values}}
|
||||||
{{camelize $element}} jet.StringExpression
|
{{ToGoIdentifier $element}} jet.StringExpression
|
||||||
{{- end}}
|
{{- end}}
|
||||||
} {
|
} {
|
||||||
{{- range $index, $element := .Values}}
|
{{- range $index, $element := .Values}}
|
||||||
{{camelize $element}}: jet.NewEnumValue("{{$element}}"),
|
{{ToGoIdentifier $element}}: jet.NewEnumValue("{{$element}}"),
|
||||||
{{- end}}
|
{{- end}}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
||||||
192
internal/3rdparty/snaker/snaker.go
vendored
Normal file
192
internal/3rdparty/snaker/snaker.go
vendored
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
package snaker
|
||||||
|
|
||||||
|
// Package snaker provides methods to convert CamelCase names to snake_case and back.
|
||||||
|
// It considers the list of allowed initialsms used by github.com/golang/lint/golint (e.g. ID or HTTP)
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CamelToSnake converts a given string to snake case
|
||||||
|
func CamelToSnake(s string) string {
|
||||||
|
var result string
|
||||||
|
var words []string
|
||||||
|
var lastPos int
|
||||||
|
rs := []rune(s)
|
||||||
|
|
||||||
|
for i := 0; i < len(rs); i++ {
|
||||||
|
if i > 0 && unicode.IsUpper(rs[i]) {
|
||||||
|
if initialism := startsWithInitialism(s[lastPos:]); initialism != "" {
|
||||||
|
words = append(words, initialism)
|
||||||
|
|
||||||
|
i += len(initialism) - 1
|
||||||
|
lastPos = i
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
words = append(words, s[lastPos:i])
|
||||||
|
lastPos = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// append the last word
|
||||||
|
if s[lastPos:] != "" {
|
||||||
|
words = append(words, s[lastPos:])
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, word := range words {
|
||||||
|
if k > 0 {
|
||||||
|
result += "_"
|
||||||
|
}
|
||||||
|
|
||||||
|
result += strings.ToLower(word)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func snakeToCamel(s string, upperCase bool) string {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
var result string
|
||||||
|
|
||||||
|
words := strings.Split(s, "_")
|
||||||
|
|
||||||
|
//// if there is no underscore, first try commons and then just return
|
||||||
|
//if len(words) == 1 {
|
||||||
|
// if exception := snakeToCamelExceptions[words[0]]; len(exception) > 0 {
|
||||||
|
// return exception
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if upperCase {
|
||||||
|
// if upper := strings.ToUpper(words[0]); commonInitialisms[upper] {
|
||||||
|
// return upper
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// w := []rune(s)
|
||||||
|
// if upperCase {
|
||||||
|
// w[0] = unicode.ToUpper(w[0])
|
||||||
|
// } else {
|
||||||
|
// w[0] = unicode.ToLower(w[0])
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return string(w)
|
||||||
|
//}
|
||||||
|
|
||||||
|
for i, word := range words {
|
||||||
|
if exception := snakeToCamelExceptions[word]; len(exception) > 0 {
|
||||||
|
result += exception
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if upperCase || i > 0 {
|
||||||
|
if upper := strings.ToUpper(word); commonInitialisms[upper] {
|
||||||
|
result += upper
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if upperCase || i > 0 {
|
||||||
|
result += camelizeWord(word, len(words) > 1)
|
||||||
|
} else {
|
||||||
|
result += word
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func camelizeWord(word string, force bool) string {
|
||||||
|
runes := []rune(word)
|
||||||
|
|
||||||
|
for i, r := range runes {
|
||||||
|
if i == 0 {
|
||||||
|
runes[i] = unicode.ToUpper(r)
|
||||||
|
} else {
|
||||||
|
if !force && unicode.IsLower(r) { // already camelCase
|
||||||
|
return string(runes)
|
||||||
|
}
|
||||||
|
|
||||||
|
runes[i] = unicode.ToLower(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(runes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SnakeToCamel returns a string converted from snake case to uppercase
|
||||||
|
func SnakeToCamel(s string) string {
|
||||||
|
return snakeToCamel(s, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SnakeToCamelLower returns a string converted from snake case to lowercase
|
||||||
|
func SnakeToCamelLower(s string) string {
|
||||||
|
return snakeToCamel(s, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// startsWithInitialism returns the initialism if the given string begins with it
|
||||||
|
func startsWithInitialism(s string) string {
|
||||||
|
var initialism string
|
||||||
|
// the longest initialism is 5 char, the shortest 2
|
||||||
|
for i := 1; i <= 5; i++ {
|
||||||
|
if len(s) > i-1 && commonInitialisms[s[:i]] {
|
||||||
|
initialism = s[:i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return initialism
|
||||||
|
}
|
||||||
|
|
||||||
|
// commonInitialisms, taken from
|
||||||
|
// https://github.com/golang/lint/blob/206c0f020eba0f7fbcfbc467a5eb808037df2ed6/lint.go#L731
|
||||||
|
var commonInitialisms = map[string]bool{
|
||||||
|
"ACL": true,
|
||||||
|
"API": true,
|
||||||
|
"ASCII": true,
|
||||||
|
"CPU": true,
|
||||||
|
"CSS": true,
|
||||||
|
"DNS": true,
|
||||||
|
"EOF": true,
|
||||||
|
"ETA": true,
|
||||||
|
"GPU": true,
|
||||||
|
"GUID": true,
|
||||||
|
"HTML": true,
|
||||||
|
"HTTP": true,
|
||||||
|
"HTTPS": true,
|
||||||
|
"ID": true,
|
||||||
|
"IP": true,
|
||||||
|
"JSON": true,
|
||||||
|
"LHS": true,
|
||||||
|
"OS": true,
|
||||||
|
"QPS": true,
|
||||||
|
"RAM": true,
|
||||||
|
"RHS": true,
|
||||||
|
"RPC": true,
|
||||||
|
"SLA": true,
|
||||||
|
"SMTP": true,
|
||||||
|
"SQL": true,
|
||||||
|
"SSH": true,
|
||||||
|
"TCP": true,
|
||||||
|
"TLS": true,
|
||||||
|
"TTL": true,
|
||||||
|
"UDP": true,
|
||||||
|
"UI": true,
|
||||||
|
"UID": true,
|
||||||
|
"UUID": true,
|
||||||
|
"URI": true,
|
||||||
|
"URL": true,
|
||||||
|
"UTF8": true,
|
||||||
|
"VM": true,
|
||||||
|
"XML": true,
|
||||||
|
"XMPP": true,
|
||||||
|
"XSRF": true,
|
||||||
|
"XSS": true,
|
||||||
|
"OAuth": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// add exceptions here for things that are not automatically convertable
|
||||||
|
var snakeToCamelExceptions = map[string]string{
|
||||||
|
"oauth": "OAuth",
|
||||||
|
}
|
||||||
13
internal/3rdparty/snaker/snaker_suite_test.go
vendored
Normal file
13
internal/3rdparty/snaker/snaker_suite_test.go
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
package snaker
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDb(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "Snaker Suite")
|
||||||
|
}
|
||||||
121
internal/3rdparty/snaker/snaker_test.go
vendored
Normal file
121
internal/3rdparty/snaker/snaker_test.go
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
package snaker
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Snaker", func() {
|
||||||
|
Describe("CamelToSnake test", func() {
|
||||||
|
It("should return an empty string on an empty input", func() {
|
||||||
|
Expect(CamelToSnake("")).To(Equal(""))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should work with one word", func() {
|
||||||
|
Expect(CamelToSnake("One")).To(Equal("one"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return an uppercase string as seperate words", func() {
|
||||||
|
Expect(CamelToSnake("ONE")).To(Equal("o_n_e"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return ID as lowercase", func() {
|
||||||
|
Expect(CamelToSnake("ID")).To(Equal("id"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should work with a single lowercase character", func() {
|
||||||
|
Expect(CamelToSnake("i")).To(Equal("i"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should work with a single uppcase character", func() {
|
||||||
|
Expect(CamelToSnake("I")).To(Equal("i"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return a long text as expected", func() {
|
||||||
|
Expect(CamelToSnake("ThisHasToBeConvertedCorrectlyID")).To(
|
||||||
|
Equal("this_has_to_be_converted_correctly_id"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return the text as expected if the initialism is in the middle", func() {
|
||||||
|
Expect(CamelToSnake("ThisIDIsFine")).To(Equal("this_id_is_fine"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should work with long initialism", func() {
|
||||||
|
Expect(CamelToSnake("ThisHTTPSConnection")).To(Equal("this_https_connection"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should work with multi initialisms", func() {
|
||||||
|
Expect(CamelToSnake("HelloHTTPSConnectionID")).To(Equal("hello_https_connection_id"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("sould work with concat initialisms", func() {
|
||||||
|
Expect(CamelToSnake("HTTPSID")).To(Equal("https_id"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("sould work with initialism where only certain characters are uppercase", func() {
|
||||||
|
Expect(CamelToSnake("OAuthClient")).To(Equal("oauth_client"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("SnakeToCamel test", func() {
|
||||||
|
It("should return an empty string on an empty input", func() {
|
||||||
|
Expect(SnakeToCamel("")).To(Equal(""))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not blow up on trailing _", func() {
|
||||||
|
Expect(SnakeToCamel("potato_")).To(Equal("Potato"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return a snaked text as camel case", func() {
|
||||||
|
Expect(SnakeToCamel("this_has_to_be_uppercased")).To(
|
||||||
|
Equal("ThisHasToBeUppercased"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return a snaked text as camel case, except the word ID", func() {
|
||||||
|
Expect(SnakeToCamel("this_is_an_id")).To(Equal("ThisIsAnID"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return 'id' not as uppercase", func() {
|
||||||
|
Expect(SnakeToCamel("this_is_an_identifier")).To(Equal("ThisIsAnIdentifier"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should simply work with id", func() {
|
||||||
|
Expect(SnakeToCamel("id")).To(Equal("ID"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("sould work with initialism where only certain characters are uppercase", func() {
|
||||||
|
Expect(SnakeToCamel("oauth_client")).To(Equal("OAuthClient"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("SnakeToCamelLower test", func() {
|
||||||
|
It("should return an empty string on an empty input", func() {
|
||||||
|
Ω(SnakeToCamelLower("")).To(Equal(""))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not blow up on trailing _", func() {
|
||||||
|
Ω(SnakeToCamelLower("potato_")).To(Equal("potato"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return a snaked text as camel case", func() {
|
||||||
|
Ω(SnakeToCamelLower("this_has_to_be_uppercased")).To(
|
||||||
|
Equal("thisHasToBeUppercased"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return a snaked text as camel case, except the word ID", func() {
|
||||||
|
Ω(SnakeToCamelLower("this_is_an_id")).To(Equal("thisIsAnID"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return 'id' not as uppercase", func() {
|
||||||
|
Ω(SnakeToCamelLower("this_is_an_identifier")).To(Equal("thisIsAnIdentifier"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should simply work with id", func() {
|
||||||
|
Ω(SnakeToCamelLower("id")).To(Equal("id"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should simply work with leading id", func() {
|
||||||
|
Ω(SnakeToCamelLower("id_me_please")).To(Equal("idMePlease"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
23
internal/util/utils.go
Normal file
23
internal/util/utils.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-jet/jet/internal/3rdparty/snaker"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ToGoIdentifier(databaseIdentifier string) string {
|
||||||
|
if len(databaseIdentifier) == 0 {
|
||||||
|
return databaseIdentifier
|
||||||
|
}
|
||||||
|
databaseIdentifier = strings.ReplaceAll(databaseIdentifier, " ", "_")
|
||||||
|
databaseIdentifier = strings.ReplaceAll(databaseIdentifier, "-", "_")
|
||||||
|
|
||||||
|
return snaker.SnakeToCamel(databaseIdentifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToGoFileName(databaseIdentifier string) string {
|
||||||
|
databaseIdentifier = strings.ReplaceAll(databaseIdentifier, " ", "_")
|
||||||
|
databaseIdentifier = strings.ReplaceAll(databaseIdentifier, "-", "_")
|
||||||
|
|
||||||
|
return strings.ToLower(databaseIdentifier)
|
||||||
|
}
|
||||||
24
internal/util/utils_test.go
Normal file
24
internal/util/utils_test.go
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestToGoIdentifier(t *testing.T) {
|
||||||
|
assert.Equal(t, ToGoIdentifier("uuid"), "UUID")
|
||||||
|
assert.Equal(t, ToGoIdentifier("col1"), "Col1")
|
||||||
|
assert.Equal(t, ToGoIdentifier("PG-13"), "Pg13")
|
||||||
|
assert.Equal(t, ToGoIdentifier("13_pg"), "13Pg")
|
||||||
|
|
||||||
|
assert.Equal(t, ToGoIdentifier("mytable"), "Mytable")
|
||||||
|
assert.Equal(t, ToGoIdentifier("MYTABLE"), "Mytable")
|
||||||
|
assert.Equal(t, ToGoIdentifier("MyTaBlE"), "MyTaBlE")
|
||||||
|
assert.Equal(t, ToGoIdentifier("myTaBlE"), "MyTaBlE")
|
||||||
|
|
||||||
|
assert.Equal(t, ToGoIdentifier("my_table"), "MyTable")
|
||||||
|
assert.Equal(t, ToGoIdentifier("MY_TABLE"), "MyTable")
|
||||||
|
assert.Equal(t, ToGoIdentifier("My_Table"), "MyTable")
|
||||||
|
assert.Equal(t, ToGoIdentifier("My Table"), "MyTable")
|
||||||
|
assert.Equal(t, ToGoIdentifier("My-Table"), "MyTable")
|
||||||
|
}
|
||||||
6
table.go
6
table.go
|
|
@ -98,12 +98,6 @@ type writableTableInterfaceImpl struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *writableTableInterfaceImpl) INSERT(columns ...column) InsertStatement {
|
func (w *writableTableInterfaceImpl) INSERT(columns ...column) InsertStatement {
|
||||||
//columnList := unwidColumnList(columns)
|
|
||||||
//
|
|
||||||
//if len(columns) == 0 {
|
|
||||||
// columnList = w.parent.columns()
|
|
||||||
//}
|
|
||||||
|
|
||||||
return newInsertStatement(w.parent, unwidColumnList(columns))
|
return newInsertStatement(w.parent, unwidColumnList(columns))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -199,3 +199,33 @@ CREATE TABLE test_sample.person(
|
||||||
DROP TYPE IF EXISTS test_sample.MOOD CASCADE;
|
DROP TYPE IF EXISTS test_sample.MOOD CASCADE;
|
||||||
|
|
||||||
CREATE TYPE test_sample.MOOD AS ENUM ('sad', 'ok', 'happy');
|
CREATE TYPE test_sample.MOOD AS ENUM ('sad', 'ok', 'happy');
|
||||||
|
|
||||||
|
|
||||||
|
-- WEIRD TABLE NAMES --------------
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS test_sample."WEIRD NAMES TABLE";
|
||||||
|
|
||||||
|
CREATE TABLE test_sample."WEIRD NAMES TABLE"(
|
||||||
|
"weird_column_name1" varchar(100) NOT NULL,
|
||||||
|
"Weird_Column_Name2" varchar(100) NOT NULL,
|
||||||
|
"wEiRd_cOluMn_nAmE3" varchar(100) NOT NULL,
|
||||||
|
"WeIrd_CoLuMN_Name4" varchar(100) NOT NULL,
|
||||||
|
"WEIRD_COLUMN_NAME5" varchar(100) NOT NULL,
|
||||||
|
|
||||||
|
"WeirdColumnName6" varchar(100) NOT NULL,
|
||||||
|
"weirdColumnName7" varchar(100) NOT NULL,
|
||||||
|
"weirdcolumnname8" varchar(100),
|
||||||
|
|
||||||
|
"weird col name9" varchar(100) NOT NULL,
|
||||||
|
"wEiRd cOlu nAmE10" varchar(100) NOT NULL,
|
||||||
|
"WEIRD COLU NAME11" varchar(100) NOT NULL,
|
||||||
|
"Weird Colu Name12" varchar(100) NOT NULL,
|
||||||
|
|
||||||
|
"weird-col-name13" varchar(100) NOT NULL,
|
||||||
|
"wEiRd-cOlu-nAmE14" varchar(100) NOT NULL,
|
||||||
|
"WEIRD-COLU-NAME15" varchar(100) NOT NULL,
|
||||||
|
"Weird-Colu-Name16" varchar(100) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO test_sample."WEIRD NAMES TABLE"
|
||||||
|
VALUES ('Doe', 'Doe', 'Doe', 'Doe','Doe', 'Doe', 'Doe', 'Doe','Doe', 'Doe', 'Doe', 'Doe','Doe', 'Doe', 'Doe', 'Doe');
|
||||||
|
|
@ -116,3 +116,35 @@ ORDER BY employee.employee_id;
|
||||||
ManagerID: int32Ptr(3),
|
ManagerID: int32Ptr(3),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWierdNamesTable(t *testing.T) {
|
||||||
|
stmt := WeirdNamesTable.SELECT(WeirdNamesTable.AllColumns)
|
||||||
|
|
||||||
|
fmt.Println(stmt.DebugSql())
|
||||||
|
|
||||||
|
dest := []model.WeirdNamesTable{}
|
||||||
|
|
||||||
|
err := stmt.Query(db, &dest)
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, len(dest), 1)
|
||||||
|
assert.DeepEqual(t, dest[0], model.WeirdNamesTable{
|
||||||
|
WeirdColumnName1: "Doe",
|
||||||
|
WeirdColumnName2: "Doe",
|
||||||
|
WeirdColumnName3: "Doe",
|
||||||
|
WeirdColumnName4: "Doe",
|
||||||
|
WeirdColumnName5: "Doe",
|
||||||
|
WeirdColumnName6: "Doe",
|
||||||
|
WeirdColumnName7: "Doe",
|
||||||
|
Weirdcolumnname8: stringPtr("Doe"),
|
||||||
|
WeirdColName9: "Doe",
|
||||||
|
WeirdColuName10: "Doe",
|
||||||
|
WeirdColuName11: "Doe",
|
||||||
|
WeirdColuName12: "Doe",
|
||||||
|
WeirdColName13: "Doe",
|
||||||
|
WeirdColuName14: "Doe",
|
||||||
|
WeirdColuName15: "Doe",
|
||||||
|
WeirdColuName16: "Doe",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -467,7 +467,7 @@ func TestScanToSlice(t *testing.T) {
|
||||||
t.Run("slice of structs with slice of ints", func(t *testing.T) {
|
t.Run("slice of structs with slice of ints", func(t *testing.T) {
|
||||||
var dest []struct {
|
var dest []struct {
|
||||||
model.Film
|
model.Film
|
||||||
IDs []int32 `alias:"Inventory.inventory_id"`
|
IDs []int32 `alias:"inventory.inventory_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
err := query.Query(db, &dest)
|
err := query.Query(db, &dest)
|
||||||
|
|
@ -483,7 +483,7 @@ func TestScanToSlice(t *testing.T) {
|
||||||
t.Run("slice of structs with slice of pointer to ints", func(t *testing.T) {
|
t.Run("slice of structs with slice of pointer to ints", func(t *testing.T) {
|
||||||
var dest []struct {
|
var dest []struct {
|
||||||
model.Film
|
model.Film
|
||||||
IDs []*int32 `alias:"inventory.InventoryId"`
|
IDs []*int32 `alias:"inventory.inventory_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
err := query.Query(db, &dest)
|
err := query.Query(db, &dest)
|
||||||
|
|
@ -796,7 +796,7 @@ var store1 = model.Store{
|
||||||
LastUpdate: *timestampWithoutTimeZone("2006-02-15 09:57:12", 0),
|
LastUpdate: *timestampWithoutTimeZone("2006-02-15 09:57:12", 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
var pgRating = model.MpaaRating_PG
|
var pgRating = model.MpaaRating_Pg
|
||||||
var gRating = model.MpaaRating_G
|
var gRating = model.MpaaRating_G
|
||||||
|
|
||||||
var language1 = model.Language{
|
var language1 = model.Language{
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,7 @@ LIMIT 15;
|
||||||
query := Film.
|
query := Film.
|
||||||
INNER_JOIN(Language, Film.LanguageID.EQ(Language.LanguageID)).
|
INNER_JOIN(Language, Film.LanguageID.EQ(Language.LanguageID)).
|
||||||
SELECT(Language.AllColumns, Film.AllColumns).
|
SELECT(Language.AllColumns, Film.AllColumns).
|
||||||
WHERE(Film.Rating.EQ(enum.MpaaRating.NC17)).
|
WHERE(Film.Rating.EQ(enum.MpaaRating.Nc17)).
|
||||||
LIMIT(15)
|
LIMIT(15)
|
||||||
|
|
||||||
assertStatementSql(t, query, expectedSql, int64(15))
|
assertStatementSql(t, query, expectedSql, int64(15))
|
||||||
|
|
@ -304,7 +304,7 @@ LIMIT 15;
|
||||||
|
|
||||||
englishFilms := filmsPerLanguage[0]
|
englishFilms := filmsPerLanguage[0]
|
||||||
|
|
||||||
assert.Equal(t, *englishFilms.Film[0].Rating, model.MpaaRating_NC17)
|
assert.Equal(t, *englishFilms.Film[0].Rating, model.MpaaRating_Nc17)
|
||||||
|
|
||||||
filmsPerLanguageWithPtrs := []*FilmsPerLanguage{}
|
filmsPerLanguageWithPtrs := []*FilmsPerLanguage{}
|
||||||
err = query.Query(db, &filmsPerLanguageWithPtrs)
|
err = query.Query(db, &filmsPerLanguageWithPtrs)
|
||||||
|
|
@ -1237,6 +1237,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQuickStartWithSubQueries(t *testing.T) {
|
func TestQuickStartWithSubQueries(t *testing.T) {
|
||||||
|
|
||||||
filmLogerThan180 := Film.
|
filmLogerThan180 := Film.
|
||||||
SELECT(Film.AllColumns).
|
SELECT(Film.AllColumns).
|
||||||
WHERE(Film.Length.GT(Int(180))).
|
WHERE(Film.Length.GT(Int(180))).
|
||||||
|
|
|
||||||
4
utils.go
4
utils.go
|
|
@ -2,7 +2,7 @@ package jet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/serenize/snaker"
|
"github.com/go-jet/jet/internal/util"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
@ -145,7 +145,7 @@ func unwindRowFromModel(columns []column, data interface{}) []clause {
|
||||||
|
|
||||||
for _, column := range columns {
|
for _, column := range columns {
|
||||||
columnName := column.Name()
|
columnName := column.Name()
|
||||||
structFieldName := snaker.SnakeToCamel(columnName)
|
structFieldName := util.ToGoIdentifier(columnName)
|
||||||
|
|
||||||
structField := structValue.FieldByName(structFieldName)
|
structField := structValue.FieldByName(structFieldName)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue