Replies: 2 comments 7 replies
-
I understand this use case, but if the tables are already prefixed in the database why not just generate them into Go structs as usual? Or do the tables exist in the database, but are not prefixed? |
Beta Was this translation helpful? Give feedback.
-
Ohh I just had an idea, you can basically copy the implementation of sq.New (it doesn't access any private fields) and modify it to take in an additional table prefix. Here's a runnable example: https://go.dev/play/p/So4M2iGy6hk type USERS struct {
sq.TableStruct
USER_ID sq.NumberField
NAME sq.StringField
EMAIL sq.StringField
CREATED_AT sq.TimeField
}
prefixes := []string{"", "t001_", "lorem_ipsum_"}
for _, prefix := range prefixes {
u := New[USERS]("u", prefix)
q := sq.Select(u.NAME, u.EMAIL).From(u)
query, _, err := sq.ToSQL("", q, nil)
if err != nil {
log.Fatal(err)
}
log.Println(query)
}
// 2009/11/10 23:00:00 SELECT u.name, u.email FROM users AS u
// 2009/11/10 23:00:00 SELECT u.name, u.email FROM t001_users AS u
// 2009/11/10 23:00:00 SELECT u.name, u.email FROM lorem_ipsum_users AS u
// New is copied from https://pkg.go.dev/github.com/bokwoon95/sq#New, but takes
// an additional table prefix.
func New[T sq.Table](alias string, prefix string) T {
var tbl T
ptrvalue := reflect.ValueOf(&tbl)
value := reflect.Indirect(ptrvalue)
typ := value.Type()
if typ.Kind() != reflect.Struct {
return tbl
}
if value.NumField() == 0 {
return tbl
}
firstfield := value.Field(0)
firstfieldType := typ.Field(0)
if !firstfield.CanInterface() {
return tbl
}
_, ok := firstfield.Interface().(sq.TableStruct)
if !ok {
return tbl
}
if !firstfield.CanSet() {
return tbl
}
var tableSchema, tableName string
tag := firstfieldType.Tag.Get("sq")
if i := strings.IndexByte(tag, '.'); i >= 0 {
tableSchema = tag[:i]
tableName = tag[i+1:]
} else {
tableName = tag
}
if tableName == "" {
tableName = strings.ToLower(typ.Name())
}
tableStruct := sq.NewTableStruct(tableSchema, prefix+tableName, alias)
firstfield.Set(reflect.ValueOf(tableStruct))
for i := 1; i < value.NumField(); i++ {
v := value.Field(i)
if !v.CanInterface() {
continue
}
if !v.CanSet() {
continue
}
fieldType := typ.Field(i)
name := fieldType.Tag.Get("sq")
if name == "" {
name = strings.ToLower(fieldType.Name)
}
switch v.Interface().(type) {
case sq.AnyField:
v.Set(reflect.ValueOf(sq.NewAnyField(name, tableStruct)))
case sq.ArrayField:
v.Set(reflect.ValueOf(sq.NewArrayField(name, tableStruct)))
case sq.BinaryField:
v.Set(reflect.ValueOf(sq.NewBinaryField(name, tableStruct)))
case sq.BooleanField:
v.Set(reflect.ValueOf(sq.NewBooleanField(name, tableStruct)))
case sq.EnumField:
v.Set(reflect.ValueOf(sq.NewEnumField(name, tableStruct)))
case sq.JSONField:
v.Set(reflect.ValueOf(sq.NewJSONField(name, tableStruct)))
case sq.NumberField:
v.Set(reflect.ValueOf(sq.NewNumberField(name, tableStruct)))
case sq.StringField:
v.Set(reflect.ValueOf(sq.NewStringField(name, tableStruct)))
case sq.TimeField:
v.Set(reflect.ValueOf(sq.NewTimeField(name, tableStruct)))
case sq.UUIDField:
v.Set(reflect.ValueOf(sq.NewUUIDField(name, tableStruct)))
}
}
return tbl
} Let me know if this is what you need. |
Beta Was this translation helpful? Give feedback.
-
Could be possible to add option to provide table prefix while generating go structs? What I mean: sometime people use cheap database hosting with one database only and to distinct tables that belong to different application the tables are prefixed. This will not be case if you have dedicated database this such prefixing is not needed but to make generated structs to cover both cases will be nice to have to provide the prefix string via some kind of configuration from the application.
Beta Was this translation helpful? Give feedback.
All reactions