From b9e90faf1f6fa3f0e109cfa2f60608ed5e752b55 Mon Sep 17 00:00:00 2001 From: Richard Phillips Date: Tue, 16 Jan 2018 17:45:55 +0000 Subject: [PATCH 1/2] Added a couple of pgTypes and fall back to using udt to match types for "USER-DEFINED" --- src/sqrible/helpers.go | 44 ++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/sqrible/helpers.go b/src/sqrible/helpers.go index e2a24f6..cfaebb5 100644 --- a/src/sqrible/helpers.go +++ b/src/sqrible/helpers.go @@ -192,21 +192,27 @@ func asGoFieldName(n string) string { func asPgxType(n string, udt string) string { m := map[string]string{ - "bigint": "pgtype.Int8", - "int8": "pgtype.Int8", - "integer": "pgtype.Int4", - "smallint": "pgtype.Int2", - "character varying": "pgtype.Varchar", - "text": "pgtype.Text", - "date": "pgtype.Date", - "inet": "pgtype.Inet", - "cidr": "pgtype.CIDR", - "bytea": "pgtype.Bytea", - "boolean": "pgtype.Bool", - "bool": "pgtype.Bool", - "real": "pgtype.Float4", - "double precision": "pgtype.Float8", - "timestamp with time zone": "pgtype.Timestamptz", + "bigint": "pgtype.Int8", + "int8": "pgtype.Int8", + "integer": "pgtype.Int4", + "smallint": "pgtype.Int2", + "character varying": "pgtype.Varchar", + "text": "pgtype.Text", + "date": "pgtype.Date", + "inet": "pgtype.Inet", + "cidr": "pgtype.CIDR", + "bytea": "pgtype.Bytea", + "boolean": "pgtype.Bool", + "bool": "pgtype.Bool", + "real": "pgtype.Float4", + "double precision": "pgtype.Float8", + "uuid": "pgtype.UUID", + "timestamp without time zone": "pgtype.Timestamp", + "timestamp with time zone": "pgtype.Timestamptz", + "citext": "pgtype.Text", + "jsonb": "pgtype.JSONB", + "geography": "pgtype.Point", + "tsvector": "pgtype.Text", } t, found := m[n] @@ -214,6 +220,14 @@ func asPgxType(n string, udt string) string { return t } + // udt should work for user defined types such as geography and citext + if n == "USER-DEFINED" { + t, found := m[udt] + if found { + return t + } + } + if strings.ToLower(n) == "array" { return asPgxType(strings.ToLower(udt[1:]), "") + "Array" } From ff3f5c9c95d5cf64e8516adb423e48cca5ff5911 Mon Sep 17 00:00:00 2001 From: Richard Phillips Date: Sat, 20 Jan 2018 11:58:31 +0000 Subject: [PATCH 2/2] Added a couple of pgTypes and fall back to using udt to match types for "USER-DEFINED" --- .gitignore | 1 + README.md | 10 +++ src/cmd/sqrible/main.go => main.go | 2 +- src/sqrible/column.go | 2 + src/sqrible/config.go | 3 +- src/sqrible/helpers.go | 127 +++++++++++++++++++++-------- src/sqrible/table.go | 2 + 7 files changed, 109 insertions(+), 38 deletions(-) rename src/cmd/sqrible/main.go => main.go (98%) diff --git a/.gitignore b/.gitignore index 65253aa..902681a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ vendor/pkg sqrible.yml templates/ examples/advanced/generated.go +/go_build_main_go.exe diff --git a/README.md b/README.md index 71cfc79..eef77ec 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ +This is a heavily modified version of sqrible - and a work in progress. +Do not use unless you like the following changes and can customize to your needs. + +* Automatic detection of nullable fields +* Chooses different data types to be used for nullable fields. +* Added "package" variable to the table yaml which I needed in my templates +* Changed transposition of data types away from pgx - this is a work in progress +* Detection of data types handles user defined types - this is a work in progress + + Problematic ----------- diff --git a/src/cmd/sqrible/main.go b/main.go similarity index 98% rename from src/cmd/sqrible/main.go rename to main.go index 60633fc..3ba9f2a 100644 --- a/src/cmd/sqrible/main.go +++ b/main.go @@ -4,7 +4,7 @@ import ( "errors" "flag" "fmt" - "sqrible" + "sqrible/src/sqrible" "github.com/jackc/pgx" ) diff --git a/src/sqrible/column.go b/src/sqrible/column.go index 022c748..6c31a37 100644 --- a/src/sqrible/column.go +++ b/src/sqrible/column.go @@ -5,6 +5,8 @@ type Column struct { PGDataType string PGUDTName string PGOrdinalPosition int32 + PGIsUpdatable string + PGIsNullable string IsPK bool diff --git a/src/sqrible/config.go b/src/sqrible/config.go index ea97081..f946bf3 100644 --- a/src/sqrible/config.go +++ b/src/sqrible/config.go @@ -4,7 +4,7 @@ import ( "io/ioutil" "strings" - yaml "gopkg.in/yaml.v2" + "gopkg.in/yaml.v2" ) func ParseConfig(f string) Config { @@ -27,6 +27,7 @@ type TableConfig struct { Template string `yaml:"template"` ConfigDetails map[string]TableColumnConfigDetails `yaml:"tablecols"` GoStruct string + Package string `yaml:"package"` } type Config struct { diff --git a/src/sqrible/helpers.go b/src/sqrible/helpers.go index cfaebb5..48c2cf7 100644 --- a/src/sqrible/helpers.go +++ b/src/sqrible/helpers.go @@ -86,7 +86,9 @@ func tableColumns(c *pgx.Conn, name string, cfg Config) ([]*Column, error) { `SELECT column_name, data_type, udt_name, - ordinal_position + ordinal_position, + is_nullable, + is_updatable FROM information_schema.columns WHERE table_name=$1 ORDER BY ordinal_position ASC`, @@ -106,6 +108,8 @@ func tableColumns(c *pgx.Conn, name string, cfg Config) ([]*Column, error) { &c.PGDataType, &c.PGUDTName, &c.PGOrdinalPosition, + &c.PGIsNullable, + &c.PGIsUpdatable, ) if err != nil { @@ -113,7 +117,7 @@ func tableColumns(c *pgx.Conn, name string, cfg Config) ([]*Column, error) { } c.GoFieldName = asGoFieldName(c.PGColumnName) - c.PgxType = asPgxType(c.PGDataType, c.PGUDTName) + c.PgxType = asPgxType(c.PGDataType, c.PGUDTName, c.PGIsNullable) c.Config = cfg.columnConfig(name, c.PGColumnName) c.IsPK = colIsPk(c.PGColumnName, pks) @@ -190,46 +194,97 @@ func asGoFieldName(n string) string { return buf.String() } -func asPgxType(n string, udt string) string { - m := map[string]string{ - "bigint": "pgtype.Int8", - "int8": "pgtype.Int8", - "integer": "pgtype.Int4", - "smallint": "pgtype.Int2", - "character varying": "pgtype.Varchar", - "text": "pgtype.Text", - "date": "pgtype.Date", - "inet": "pgtype.Inet", - "cidr": "pgtype.CIDR", - "bytea": "pgtype.Bytea", - "boolean": "pgtype.Bool", - "bool": "pgtype.Bool", - "real": "pgtype.Float4", - "double precision": "pgtype.Float8", - "uuid": "pgtype.UUID", - "timestamp without time zone": "pgtype.Timestamp", - "timestamp with time zone": "pgtype.Timestamptz", - "citext": "pgtype.Text", - "jsonb": "pgtype.JSONB", - "geography": "pgtype.Point", - "tsvector": "pgtype.Text", - } - - t, found := m[n] - if found { - return t - } - - // udt should work for user defined types such as geography and citext - if n == "USER-DEFINED" { - t, found := m[udt] +func asPgxType(n string, udt string, nullable string) string { + // These are the field transpositions IF + // the field is marked nullable + + nulls := map[string]string{ + "int16": "dat.NullInt64", + "int8": "dat.NullInt64", + "bigint": "dat.NullInt64", + "bigserieal": "dat.NullInt64", + "int4": "dat.NullInt64", + "int": "dat.NullInt64", + "serial": "dat.NullInt64", + "int2": "dat.NullInt64", + "smallint": "dat.NullInt64", + "smallserial": "dat.NullInt64", + "double precision": "dat.NullFloat64", + "real": "dat.NullFloat64", + "bool": "bool", + "boolean": "bool", + "text": "dat.NullString", + "varchar": "dat.NullString", + "citext": "dat.NullString", + "character varying": "dat.NullString", + "timestamp": "dat.NullTime", + "inet": "inet", + "uuid": "uuid.UUID", + "bytea": "pgtype.ByteaArray", + "jsonb": "dat.JSON", + "geography": "pgtype.Point", + "tsvector": "dat.NullString", + } + + full := map[string]string{ + + + "int16": "int16", + "int8": "int8", + "bigint": "int8", + "bigserieal": "int8", + "int4": "int", + "int": "int", + "serial": "int", + "int2": "int", + "smallint": "int", + "smallserial": "int", + "double precision": "float64", + "real": "float64", + "bool": "bool", + "boolean": "bool", + "text": "string", + "varchar": "string", + "citext": "string", + "character varying": "string", + "timestamp": "dat.NullTime", + "inet": "inet", + "uuid": "uuid.UUID", + "bytea": "[][]byte", + "jsonb": "dat.JSON", + "geography": "pgtype.Point", + "tsvector": "string", + } + + if nullable == "YES" { + + t, found := nulls[udt] + if found { + return t + } + if !found { + t, found := nulls[n] + if found { + return t + } + } + } else { + + t, found := full[udt] if found { return t } + + if !found { + t, found := full[n] + if found { + return t + } + } } if strings.ToLower(n) == "array" { - return asPgxType(strings.ToLower(udt[1:]), "") + "Array" + return asPgxType(strings.ToLower(udt[1:]), udt, nullable) + "Array" } Quit(fmt.Errorf("Postgres type %s not found in pgx mapping", n)) diff --git a/src/sqrible/table.go b/src/sqrible/table.go index ebb2b14..dc92fbc 100644 --- a/src/sqrible/table.go +++ b/src/sqrible/table.go @@ -5,6 +5,7 @@ type Table struct { Columns Columns GoStructName string Template string + Package string } func NewTable(name string, cols Columns, cfg *TableConfig) *Table { @@ -13,6 +14,7 @@ func NewTable(name string, cols Columns, cfg *TableConfig) *Table { Columns: cols, GoStructName: cfg.GoStruct, Template: cfg.Template, + Package: cfg.Package, } }