Add support for additional array types.
This commit is contained in:
parent
45d4ced9b0
commit
4ee047a675
47 changed files with 1994 additions and 4277 deletions
|
|
@ -19,7 +19,6 @@ const (
|
|||
BaseType DataTypeKind = "base"
|
||||
EnumType DataTypeKind = "enum"
|
||||
UserDefinedType DataTypeKind = "user-defined"
|
||||
ArrayType DataTypeKind = "array"
|
||||
RangeType DataTypeKind = "range"
|
||||
)
|
||||
|
||||
|
|
@ -30,3 +29,7 @@ type DataType struct {
|
|||
IsUnsigned bool
|
||||
Dimensions int // The number of array dimensions
|
||||
}
|
||||
|
||||
func (d DataType) IsArray() bool {
|
||||
return d.Dimensions > 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,23 +66,25 @@ select
|
|||
not attr.attnotnull as "column.isNullable",
|
||||
attr.attgenerated = 's' as "column.isGenerated",
|
||||
attr.atthasdef as "column.hasDefault",
|
||||
attr.attndims as "dataType.dimensions",
|
||||
(case
|
||||
when tp.typtype = 'b' AND tp.typcategory <> 'A' then 'base'
|
||||
when tp.typtype = 'b' AND tp.typcategory = 'A' then 'array'
|
||||
when tp.typtype = 'd' then 'base'
|
||||
when tp.typtype = 'e' then 'enum'
|
||||
when tp.typtype = 'r' then 'range'
|
||||
end) as "dataType.Kind",
|
||||
(case when tp.typcategory = 'A' then greatest(1, attr.attndims) --cockroach num dims fix
|
||||
else 0
|
||||
end) as "dataType.dimensions",
|
||||
(case coalesce(elem.typtype, tp.typtype)
|
||||
when 'b' then 'base'
|
||||
when 'd' then 'base'
|
||||
when 'e' then 'enum'
|
||||
when 'r' then 'range'
|
||||
end) as "dataType.Kind",
|
||||
(case when tp.typtype = 'd' then (select pg_type.typname from pg_catalog.pg_type where pg_type.oid = tp.typbasetype)
|
||||
when tp.typcategory = 'A' then pg_catalog.format_type(attr.atttypid, attr.atttypmod)
|
||||
when tp.typcategory = 'A' then elem.typname
|
||||
else tp.typname
|
||||
end) as "dataType.Name",
|
||||
end) as "dataType.Name",
|
||||
false as "dataType.isUnsigned"
|
||||
from pg_catalog.pg_attribute as attr
|
||||
join pg_catalog.pg_class as cls on cls.oid = attr.attrelid
|
||||
join pg_catalog.pg_namespace as ns on ns.oid = cls.relnamespace
|
||||
join pg_catalog.pg_type as tp on tp.oid = attr.atttypid
|
||||
left join pg_catalog.pg_type elem ON tp.typelem = elem.oid -- only for arrays
|
||||
where
|
||||
ns.nspname = $1 and
|
||||
cls.relname = $2 and
|
||||
|
|
|
|||
|
|
@ -2,15 +2,17 @@ package template
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-jet/jet/v2/generator/metadata"
|
||||
"github.com/go-jet/jet/v2/internal/utils/dbidentifier"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgtype"
|
||||
"github.com/lib/pq"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgtype"
|
||||
|
||||
"github.com/go-jet/jet/v2/generator/metadata"
|
||||
"github.com/go-jet/jet/v2/internal/utils/dbidentifier"
|
||||
)
|
||||
|
||||
// Model is template for model files generation
|
||||
|
|
@ -246,10 +248,21 @@ func getType(columnMetadata metadata.Column) Type {
|
|||
userDefinedType := getUserDefinedType(columnMetadata)
|
||||
|
||||
if userDefinedType != "" {
|
||||
if columnMetadata.IsNullable {
|
||||
return Type{Name: "*" + userDefinedType}
|
||||
var importPath string
|
||||
|
||||
if columnMetadata.DataType.IsArray() {
|
||||
userDefinedType = "pq.StringArray"
|
||||
importPath = "github.com/lib/pq"
|
||||
}
|
||||
|
||||
if columnMetadata.IsNullable {
|
||||
userDefinedType = "*" + userDefinedType
|
||||
}
|
||||
|
||||
return Type{
|
||||
Name: userDefinedType,
|
||||
ImportPath: importPath,
|
||||
}
|
||||
return Type{Name: userDefinedType}
|
||||
}
|
||||
|
||||
return NewType(getGoType(columnMetadata))
|
||||
|
|
@ -267,21 +280,44 @@ func getUserDefinedType(column metadata.Column) string {
|
|||
}
|
||||
|
||||
func getGoType(column metadata.Column) interface{} {
|
||||
defaultGoType := toGoType(column)
|
||||
goType := toGoType(column)
|
||||
|
||||
if column.IsNullable {
|
||||
return reflect.New(reflect.TypeOf(defaultGoType)).Interface()
|
||||
if column.DataType.IsArray() {
|
||||
goType = toGoArrayType(goType, column)
|
||||
}
|
||||
|
||||
return defaultGoType
|
||||
if column.IsNullable {
|
||||
return reflect.New(reflect.TypeOf(goType)).Interface()
|
||||
}
|
||||
|
||||
return goType
|
||||
}
|
||||
|
||||
func toGoArrayType(elemType any, column metadata.Column) any {
|
||||
if column.DataType.Dimensions > 1 {
|
||||
return "" // unsupported multidimensional arrays
|
||||
}
|
||||
|
||||
switch elemType.(type) {
|
||||
case bool:
|
||||
return pq.BoolArray{}
|
||||
case int32:
|
||||
return pq.Int32Array{}
|
||||
case int64:
|
||||
return pq.Int64Array{}
|
||||
case float32:
|
||||
return pq.Float32Array{}
|
||||
case float64:
|
||||
return pq.Float64Array{}
|
||||
case []byte:
|
||||
return pq.ByteaArray{}
|
||||
default:
|
||||
return pq.StringArray{}
|
||||
}
|
||||
}
|
||||
|
||||
// toGoType returns model type for column info.
|
||||
func toGoType(column metadata.Column) interface{} {
|
||||
// We don't support multi-dimensional arrays
|
||||
if column.DataType.Dimensions > 1 {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch strings.ToLower(column.DataType.Name) {
|
||||
case "user-defined", "enum":
|
||||
|
|
@ -348,14 +384,6 @@ func toGoType(column metadata.Column) interface{} {
|
|||
return pgtype.Int8range{}
|
||||
case "numrange":
|
||||
return pgtype.Numrange{}
|
||||
case "bool[]":
|
||||
return pq.BoolArray{}
|
||||
case "integer[]", "int4[]":
|
||||
return pq.Int32Array{}
|
||||
case "bigint[]":
|
||||
return pq.Int64Array{}
|
||||
case "text[]", "jsonb[]", "json[]":
|
||||
return pq.StringArray{}
|
||||
default:
|
||||
fmt.Println("- [Model ] Unsupported sql column '" + column.Name + " " + column.DataType.Name + "', using string instead.")
|
||||
return ""
|
||||
|
|
|
|||
|
|
@ -162,43 +162,33 @@ func DefaultTableSQLBuilderColumn(columnMetaData metadata.Column) TableSQLBuilde
|
|||
|
||||
// getSqlBuilderColumnType returns type of jet sql builder column
|
||||
func getSqlBuilderColumnType(columnMetaData metadata.Column) string {
|
||||
if columnMetaData.DataType.Kind != metadata.BaseType &&
|
||||
columnMetaData.DataType.Kind != metadata.RangeType &&
|
||||
columnMetaData.DataType.Kind != metadata.ArrayType {
|
||||
switch columnMetaData.DataType.Kind {
|
||||
case metadata.EnumType, metadata.UserDefinedType:
|
||||
if columnMetaData.DataType.IsArray() {
|
||||
return "StringArray"
|
||||
}
|
||||
return "String"
|
||||
}
|
||||
|
||||
typeName := columnMetaData.DataType.Name
|
||||
columnName := columnMetaData.Name
|
||||
columnType := sqlToColumnType(columnMetaData)
|
||||
|
||||
if columnMetaData.DataType.Kind == metadata.ArrayType {
|
||||
if columnMetaData.DataType.IsArray() {
|
||||
if columnMetaData.DataType.Dimensions > 1 {
|
||||
fmt.Println("- [SQL Builder] Unsupported sql array with multiple dimensions column '" + columnName + " " + typeName + "', using StringColumn instead.")
|
||||
fmt.Println("- [SQL Builder] Unsupported sql array with multiple dimensions column '" +
|
||||
columnMetaData.Name + " " + columnMetaData.DataType.Name + "', using StringColumn instead.")
|
||||
return "String"
|
||||
}
|
||||
|
||||
c := sqlToColumnType(strings.TrimSuffix(typeName, "[]"))
|
||||
|
||||
// These are the supported array types
|
||||
if slices.Index([]string{"Bool", "String", "Integer"}, c) == -1 {
|
||||
fmt.Println("- [SQL Builder] Unsupported sql array column '" + columnName + " " + typeName + "', using StringColumn instead.")
|
||||
return "String"
|
||||
}
|
||||
|
||||
return c + "Array"
|
||||
}
|
||||
|
||||
columnType := sqlToColumnType(typeName)
|
||||
if columnType == "" {
|
||||
fmt.Println("- [SQL Builder] Unsupported sql column '" + columnName + " " + typeName + "', using StringColumn instead.")
|
||||
return "String"
|
||||
columnType = columnType + "Array"
|
||||
}
|
||||
|
||||
return columnType
|
||||
}
|
||||
|
||||
func sqlToColumnType(typeName string) string {
|
||||
switch strings.ToLower(typeName) {
|
||||
// sqlToColumnType maps the type of a SQL column type to a go jet sql builder column. The second return value returns
|
||||
// whether the given type is supported.
|
||||
func sqlToColumnType(columnMetaData metadata.Column) string {
|
||||
switch strings.ToLower(columnMetaData.DataType.Name) {
|
||||
case "boolean", "bool":
|
||||
return "Bool"
|
||||
case "smallint", "integer", "bigint", "int2", "int4", "int8",
|
||||
|
|
@ -243,7 +233,8 @@ func sqlToColumnType(typeName string) string {
|
|||
case "numrange":
|
||||
return "NumericRange"
|
||||
default:
|
||||
return ""
|
||||
fmt.Println("- [SQL Builder] Unsupported sql column '" + columnMetaData.Name + " " + columnMetaData.DataType.Name + "', using StringColumn instead.")
|
||||
return "String"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue