diff --git a/generator/metadata/column_meta_data.go b/generator/metadata/column_meta_data.go index 5c888a3..1502719 100644 --- a/generator/metadata/column_meta_data.go +++ b/generator/metadata/column_meta_data.go @@ -10,6 +10,7 @@ type Column struct { IsPrimaryKey bool IsNullable bool IsGenerated bool + HasDefault bool DataType DataType Comment string } diff --git a/generator/mysql/query_set.go b/generator/mysql/query_set.go index bd4d593..6dc2714 100644 --- a/generator/mysql/query_set.go +++ b/generator/mysql/query_set.go @@ -18,6 +18,7 @@ func (m mySqlQuerySet) GetTablesMetaData(db *sql.DB, schemaName string, tableTyp SELECT t.table_name as "table.name", col.COLUMN_NAME AS "column.Name", + col.COLUMN_DEFAULT IS NOT NULL as "column.HasDefault", col.IS_NULLABLE = "YES" AS "column.IsNullable", col.COLUMN_COMMENT AS "column.Comment", COALESCE(pk.IsPrimaryKey, 0) AS "column.IsPrimaryKey", diff --git a/generator/postgres/query_set.go b/generator/postgres/query_set.go index 2d8835b..d61bd34 100644 --- a/generator/postgres/query_set.go +++ b/generator/postgres/query_set.go @@ -64,6 +64,7 @@ select ) as "column.IsPrimaryKey", not attr.attnotnull as "column.isNullable", attr.attgenerated = 's' as "column.isGenerated", + attr.atthasdef as "column.hasDefault", (case tp.typtype when 'b' then 'base' when 'd' then 'base' diff --git a/generator/sqlite/query_set.go b/generator/sqlite/query_set.go index 745aae4..dbf9d15 100644 --- a/generator/sqlite/query_set.go +++ b/generator/sqlite/query_set.go @@ -4,10 +4,11 @@ import ( "context" "database/sql" "fmt" + "strings" + "github.com/go-jet/jet/v2/generator/metadata" "github.com/go-jet/jet/v2/internal/utils/semantic" "github.com/go-jet/jet/v2/qrm" - "strings" ) // sqliteQuerySet is dialect query set for SQLite @@ -74,11 +75,12 @@ func (p sqliteQuerySet) GetTableColumnsMetaData(db *sql.DB, schemaName string, t } var columnInfos []struct { - Name string - Type string - NotNull int32 - Pk int32 - Hidden int32 + Name string + Type string + NotNull int32 + DfltValue string + Pk int32 + Hidden int32 } _, err = qrm.Query(context.Background(), db, tableInfoQuery, []interface{}{tableName}, &columnInfos) @@ -91,12 +93,14 @@ func (p sqliteQuerySet) GetTableColumnsMetaData(db *sql.DB, schemaName string, t for _, columnInfo := range columnInfos { columnType := strings.TrimSuffix(getColumnType(columnInfo.Type), " GENERATED ALWAYS") isGenerated := columnInfo.Hidden == 2 || columnInfo.Hidden == 3 // stored or virtual column + hasDefault := columnInfo.DfltValue != "" columns = append(columns, metadata.Column{ Name: columnInfo.Name, IsPrimaryKey: columnInfo.Pk != 0, IsNullable: columnInfo.NotNull != 1, IsGenerated: isGenerated, + HasDefault: hasDefault, DataType: metadata.DataType{ Name: columnType, Kind: metadata.BaseType, diff --git a/tests/mysql/generator_test.go b/tests/mysql/generator_test.go index a7b5554..2a915a5 100644 --- a/tests/mysql/generator_test.go +++ b/tests/mysql/generator_test.go @@ -8,8 +8,11 @@ import ( "github.com/stretchr/testify/require" + "github.com/go-jet/jet/v2/generator/metadata" "github.com/go-jet/jet/v2/generator/mysql" + "github.com/go-jet/jet/v2/generator/template" "github.com/go-jet/jet/v2/internal/testutils" + mysql2 "github.com/go-jet/jet/v2/mysql" "github.com/go-jet/jet/v2/tests/dbconfig" ) @@ -39,6 +42,39 @@ func TestGenerator(t *testing.T) { require.NoError(t, err) } +func TestGenerator_TableMetadata(t *testing.T) { + var schema metadata.Schema + err := mysql.Generate(genTestDir3, dbConnection("dvds"), + template.Default(mysql2.Dialect).UseSchema(func(m metadata.Schema) template.Schema { + schema = m + return template.DefaultSchema(m) + })) + require.NoError(t, err) + + // Spot check the actor table and assert that the emitted + // properties are as expected. + var got metadata.Table + for _, table := range schema.TablesMetaData { + if table.Name == "actor" { + got = table + } + } + + want := metadata.Table{ + Name: "actor", + Columns: []metadata.Column{ + {Name: "actor_id", IsPrimaryKey: true, IsNullable: false, IsGenerated: false, HasDefault: false, DataType: metadata.DataType{Name: "smallint", Kind: "base", IsUnsigned: true}, Comment: ""}, + {Name: "first_name", IsPrimaryKey: false, IsNullable: false, IsGenerated: false, HasDefault: false, DataType: metadata.DataType{Name: "varchar", Kind: "base", IsUnsigned: false}, Comment: ""}, + {Name: "last_name", IsPrimaryKey: false, IsNullable: false, IsGenerated: false, HasDefault: false, DataType: metadata.DataType{Name: "varchar", Kind: "base", IsUnsigned: false}, Comment: ""}, + {Name: "last_update", IsPrimaryKey: false, IsNullable: false, IsGenerated: false, HasDefault: true, DataType: metadata.DataType{Name: "timestamp", Kind: "base", IsUnsigned: false}, Comment: ""}, + }, + } + require.Equal(t, want, got) + + err = os.RemoveAll(genTestDirRoot) + require.NoError(t, err) +} + func TestCmdGenerator(t *testing.T) { err := os.RemoveAll(genTestDir3) require.NoError(t, err) diff --git a/tests/postgres/generator_template_test.go b/tests/postgres/generator_template_test.go index 2bc2d32..4d87295 100644 --- a/tests/postgres/generator_template_test.go +++ b/tests/postgres/generator_template_test.go @@ -3,6 +3,9 @@ package postgres import ( "database/sql" "fmt" + "path" + "testing" + "github.com/go-jet/jet/v2/generator/metadata" "github.com/go-jet/jet/v2/generator/postgres" "github.com/go-jet/jet/v2/generator/template" @@ -13,8 +16,6 @@ import ( "github.com/go-jet/jet/v2/tests/dbconfig" file2 "github.com/go-jet/jet/v2/tests/internal/utils/file" "github.com/stretchr/testify/require" - "path" - "testing" ) const tempTestDir = "./.tempTestDir" diff --git a/tests/postgres/generator_test.go b/tests/postgres/generator_test.go index 479d82f..a1ea307 100644 --- a/tests/postgres/generator_test.go +++ b/tests/postgres/generator_test.go @@ -2,7 +2,6 @@ package postgres import ( "fmt" - "github.com/go-jet/jet/v2/tests/internal/utils/file" "os" "os/exec" "path/filepath" @@ -12,11 +11,14 @@ import ( "github.com/stretchr/testify/require" + "github.com/go-jet/jet/v2/generator/metadata" "github.com/go-jet/jet/v2/generator/postgres" + "github.com/go-jet/jet/v2/generator/template" "github.com/go-jet/jet/v2/internal/testutils" - "github.com/go-jet/jet/v2/tests/dbconfig" - + postgres2 "github.com/go-jet/jet/v2/postgres" "github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/dvds/model" + "github.com/go-jet/jet/v2/tests/dbconfig" + "github.com/go-jet/jet/v2/tests/internal/utils/file" ) func dsn(host string, port int, dbName, user, password string) string { @@ -208,6 +210,36 @@ func TestGenerator(t *testing.T) { require.NoError(t, err) } +func TestGenerator_TableMetadata(t *testing.T) { + var schema metadata.Schema + err := postgres.GenerateDSN(defaultDSN(), "dvds", genTestDir2, + template.Default(postgres2.Dialect).UseSchema(func(m metadata.Schema) template.Schema { + schema = m + return template.DefaultSchema(m) + })) + require.NoError(t, err) + + // Spot check the actor table and assert that the emitted + // properties are as expected. + var got metadata.Table + for _, table := range schema.TablesMetaData { + if table.Name == "actor" { + got = table + } + } + + want := metadata.Table{ + Name: "actor", + Columns: []metadata.Column{ + {Name: "actor_id", IsPrimaryKey: true, IsNullable: false, IsGenerated: false, HasDefault: true, DataType: metadata.DataType{Name: "int4", Kind: "base", IsUnsigned: false}, Comment: ""}, + {Name: "first_name", IsPrimaryKey: false, IsNullable: false, IsGenerated: false, HasDefault: false, DataType: metadata.DataType{Name: "varchar", Kind: "base", IsUnsigned: false}, Comment: ""}, + {Name: "last_name", IsPrimaryKey: false, IsNullable: false, IsGenerated: false, HasDefault: false, DataType: metadata.DataType{Name: "varchar", Kind: "base", IsUnsigned: false}, Comment: ""}, + {Name: "last_update", IsPrimaryKey: false, IsNullable: false, IsGenerated: false, HasDefault: false, DataType: metadata.DataType{Name: "timestamp", Kind: "base", IsUnsigned: false}, Comment: ""}, + }, + } + require.Equal(t, want, got) +} + func TestGeneratorSpecialCharacters(t *testing.T) { t.SkipNow() err := postgres.Generate(genTestDir2, postgres.DBConnection{ diff --git a/tests/sqlite/generator_test.go b/tests/sqlite/generator_test.go index b232aba..8a15568 100644 --- a/tests/sqlite/generator_test.go +++ b/tests/sqlite/generator_test.go @@ -8,8 +8,11 @@ import ( "github.com/stretchr/testify/require" + "github.com/go-jet/jet/v2/generator/metadata" "github.com/go-jet/jet/v2/generator/sqlite" + "github.com/go-jet/jet/v2/generator/template" "github.com/go-jet/jet/v2/internal/testutils" + sqlite2 "github.com/go-jet/jet/v2/sqlite" "github.com/go-jet/jet/v2/tests/.gentestdata/sqlite/sakila/model" "github.com/go-jet/jet/v2/tests/internal/utils/repo" ) @@ -58,6 +61,36 @@ func TestGenerator(t *testing.T) { require.NoError(t, err) } +func TestGenerator_TableMetadata(t *testing.T) { + var schema metadata.Schema + err := sqlite.GenerateDSN(testDatabaseFilePath, genDestDir, + template.Default(sqlite2.Dialect).UseSchema(func(m metadata.Schema) template.Schema { + schema = m + return template.DefaultSchema(m) + })) + require.NoError(t, err) + + // Spot check the actor table and assert that the emitted + // properties are as expected. + var got metadata.Table + for _, table := range schema.TablesMetaData { + if table.Name == "actor" { + got = table + } + } + + want := metadata.Table{ + Name: "actor", + Columns: []metadata.Column{ + {Name: "actor_id", IsPrimaryKey: true, IsNullable: false, IsGenerated: false, HasDefault: false, DataType: metadata.DataType{Name: "INTEGER", Kind: "base", IsUnsigned: false}, Comment: ""}, + {Name: "first_name", IsPrimaryKey: false, IsNullable: false, IsGenerated: false, HasDefault: false, DataType: metadata.DataType{Name: "VARCHAR", Kind: "base", IsUnsigned: false}, Comment: ""}, + {Name: "last_name", IsPrimaryKey: false, IsNullable: false, IsGenerated: false, HasDefault: false, DataType: metadata.DataType{Name: "VARCHAR", Kind: "base", IsUnsigned: false}, Comment: ""}, + {Name: "last_update", IsPrimaryKey: false, IsNullable: false, IsGenerated: false, HasDefault: true, DataType: metadata.DataType{Name: "TIMESTAMP", Kind: "base", IsUnsigned: false}, Comment: ""}, + }, + } + require.Equal(t, want, got) +} + func TestCmdGenerator(t *testing.T) { cmd := exec.Command("jet", "-source=SQLite", "-dsn=file://"+testDatabaseFilePath, "-path="+genDestDir)