Skip to content

Commit d37c9d4

Browse files
authored
postgres: Column merging for table inheritence (#2315)
1 parent 0c340f2 commit d37c9d4

File tree

11 files changed

+96
-8
lines changed

11 files changed

+96
-8
lines changed

internal/endtoend/testdata/ddl_create_table_inherits/postgresql/pgx/v4/go/models.go

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/ddl_create_table_inherits/postgresql/pgx/v4/schema.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,8 @@ CREATE TABLE person (
1111
CREATE TABLE organisation (
1212
legal_name text
1313
) INHERITS (party);
14+
15+
CREATE TABLE llc (
16+
incorporation_date timestamp,
17+
legal_name text NOT NULL
18+
) INHERITS (organisation);

internal/endtoend/testdata/ddl_create_table_inherits/postgresql/pgx/v5/go/models.go

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/ddl_create_table_inherits/postgresql/pgx/v5/schema.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,8 @@ CREATE TABLE person (
1111
CREATE TABLE organisation (
1212
legal_name text
1313
) INHERITS (party);
14+
15+
CREATE TABLE llc (
16+
incorporation_date timestamp,
17+
legal_name text NOT NULL
18+
) INHERITS (organisation);

internal/endtoend/testdata/ddl_create_table_inherits/postgresql/stdlib/go/models.go

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/ddl_create_table_inherits/postgresql/stdlib/schema.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,8 @@ CREATE TABLE person (
1111
CREATE TABLE organisation (
1212
legal_name text
1313
) INHERITS (party);
14+
15+
CREATE TABLE llc (
16+
incorporation_date timestamp,
17+
legal_name text NOT NULL
18+
) INHERITS (organisation);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- name: GetAllParties :many
2+
SELECT * FROM party;
3+
4+
-- name: GetAllOrganisations :many
5+
SELECT * FROM organisation;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CREATE TABLE party (
2+
name text NOT NULL
3+
);
4+
5+
CREATE TABLE organisation (
6+
name integer NOT NULL
7+
) INHERITS (party);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": "1",
3+
"packages": [
4+
{
5+
"path": "go",
6+
"engine": "postgresql",
7+
"name": "querytest",
8+
"schema": "schema.sql",
9+
"queries": "query.sql"
10+
}
11+
]
12+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# package querytest
2+
schema.sql:1:1: column "name" has a type conflict

internal/sql/catalog/table.go

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -240,20 +240,28 @@ func (c *Catalog) createTable(stmt *ast.CreateTableStmt) error {
240240
}
241241

242242
tbl := Table{Rel: stmt.Name, Comment: stmt.Comment}
243-
m := make(map[string]struct{}) // used to check for duplicate column names
243+
coltype := make(map[string]ast.TypeName) // used to check for duplicate column names
244+
seen := make(map[string]bool) // used to check for duplicate column names
244245
for _, inheritTable := range stmt.Inherits {
245246
t, _, err := schema.getTable(inheritTable)
246247
if err != nil {
247248
return err
248249
}
249250
// check and ignore duplicate columns
250251
for _, col := range t.Columns {
251-
if _, ok := m[col.Name]; ok {
252+
if notNull, ok := seen[col.Name]; ok {
253+
seen[col.Name] = notNull || col.IsNotNull
254+
if a, ok := coltype[col.Name]; ok {
255+
if !sameType(&a, &col.Type) {
256+
return fmt.Errorf("column \"%s\" has a type conflict", col.Name)
257+
}
258+
}
252259
continue
253-
} else {
254-
m[col.Name] = struct{}{}
255-
tbl.Columns = append(tbl.Columns, col)
256260
}
261+
262+
seen[col.Name] = col.IsNotNull
263+
coltype[col.Name] = col.Type
264+
tbl.Columns = append(tbl.Columns, col)
257265
}
258266
}
259267

@@ -272,6 +280,16 @@ func (c *Catalog) createTable(stmt *ast.CreateTableStmt) error {
272280
}
273281
} else {
274282
for _, col := range stmt.Cols {
283+
if notNull, ok := seen[col.Colname]; ok {
284+
seen[col.Colname] = notNull || col.IsNotNull
285+
if a, ok := coltype[col.Colname]; ok {
286+
if !sameType(&a, col.TypeName) {
287+
return fmt.Errorf("column \"%s\" has a type conflict", col.Colname)
288+
}
289+
}
290+
continue
291+
}
292+
275293
tc := &Column{
276294
Name: col.Colname,
277295
Type: *col.TypeName,
@@ -293,6 +311,14 @@ func (c *Catalog) createTable(stmt *ast.CreateTableStmt) error {
293311
tbl.Columns = append(tbl.Columns, tc)
294312
}
295313
}
314+
315+
// If one of the merged columns was not null, mark the column as not null
316+
for i := range tbl.Columns {
317+
if notNull, ok := seen[tbl.Columns[i].Name]; ok {
318+
tbl.Columns[i].IsNotNull = notNull
319+
}
320+
}
321+
296322
schema.Tables = append(schema.Tables, &tbl)
297323
return nil
298324
}

0 commit comments

Comments
 (0)