From 2cb4f9b9d1875335fd14dcf2297efe726d4e818a Mon Sep 17 00:00:00 2001 From: Paulo Costa Date: Wed, 30 Aug 2023 14:44:30 -0300 Subject: [PATCH] Ignore Composite Foreign Keys. Boiler doesn't support composite FKs -- And this is OK. However if there is one on the database, it should ignore it and generate valid code. --- drivers/config.go | 14 ++ .../sqlboiler-mssql/driver/mssql.golden.json | 132 ++++++++++++++++++ .../sqlboiler-mssql/driver/testdatabase.sql | 13 ++ .../driver/mysql.golden.enums.json | 132 ++++++++++++++++++ .../sqlboiler-mysql/driver/mysql.golden.json | 132 ++++++++++++++++++ .../sqlboiler-mysql/driver/testdatabase.sql | 22 ++- .../driver/psql.golden.enums.json | 132 ++++++++++++++++++ .../sqlboiler-psql/driver/psql.golden.json | 132 ++++++++++++++++++ .../sqlboiler-psql/driver/testdatabase.sql | 13 ++ .../driver/sqlite3.golden.json | 132 ++++++++++++++++++ .../sqlboiler-sqlite3/driver/testdatabase.sql | 22 ++- 11 files changed, 867 insertions(+), 9 deletions(-) diff --git a/drivers/config.go b/drivers/config.go index 2b4ab8a3c..9731a6ca6 100644 --- a/drivers/config.go +++ b/drivers/config.go @@ -252,12 +252,22 @@ func ColumnsFromList(list []string, tablename string) []string { func CombineConfigAndDBForeignKeys(configForeignKeys []ForeignKey, tableName string, dbForeignKeys []ForeignKey) []ForeignKey { combinedForeignKeys := make([]ForeignKey, 0, len(configForeignKeys)+len(dbForeignKeys)) appearedColumns := make(map[string]bool) + fkNameCount := make(map[string]int) + + // Detect Composite Foreign Keys in the database by counting how many times they appear. + // boiler doesn't support Composite FKs and should ignore those + for _, fk := range dbForeignKeys { + fkNameCount[fk.Name] += 1 + } for _, fk := range configForeignKeys { // need check table name here cause configForeignKeys contains all foreign keys of all tables if fk.Table != tableName { continue } + if appearedColumns[fk.Column] { + continue + } combinedForeignKeys = append(combinedForeignKeys, fk) appearedColumns[fk.Column] = true @@ -268,7 +278,11 @@ func CombineConfigAndDBForeignKeys(configForeignKeys []ForeignKey, tableName str if appearedColumns[fk.Column] { continue } + if fkNameCount[fk.Name] != 1 { + continue + } combinedForeignKeys = append(combinedForeignKeys, fk) + appearedColumns[fk.Column] = true } return combinedForeignKeys diff --git a/drivers/sqlboiler-mssql/driver/mssql.golden.json b/drivers/sqlboiler-mssql/driver/mssql.golden.json index 2a5c018f5..9c65e8e6c 100644 --- a/drivers/sqlboiler-mssql/driver/mssql.golden.json +++ b/drivers/sqlboiler-mssql/driver/mssql.golden.json @@ -1,6 +1,138 @@ { "schema": "dbo", "tables": [ + { + "name": "node", + "schema_name": "", + "columns": [ + { + "name": "id", + "type": "int", + "db_type": "int", + "default": "", + "comment": "", + "nullable": false, + "unique": true, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "int" + }, + { + "name": "parent_id", + "type": "null.Int", + "db_type": "int", + "default": "", + "comment": "", + "nullable": true, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "int" + }, + { + "name": "root_id", + "type": "int", + "db_type": "int", + "default": "", + "comment": "", + "nullable": false, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "int" + } + ], + "p_key": { + "name": "PK__node", + "columns": [ + "id" + ] + }, + "f_keys": [ + { + "table": "node", + "name": "FK_node_parent", + "column": "parent_id", + "nullable": true, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": false, + "foreign_column_unique": true + }, + { + "table": "node", + "name": "FK_node_root", + "column": "root_id", + "nullable": false, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": false, + "foreign_column_unique": true + } + ], + "is_join_table": false, + "to_one_relationships": null, + "to_many_relationships": [ + { + "name": "FK_node_parent", + "table": "node", + "column": "id", + "nullable": false, + "unique": true, + "foreign_table": "node", + "foreign_column": "parent_id", + "foreign_column_nullable": true, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + }, + { + "name": "FK_node_root", + "table": "node", + "column": "id", + "nullable": false, + "unique": true, + "foreign_table": "node", + "foreign_column": "root_id", + "foreign_column_nullable": false, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + } + ], + "is_view": false, + "view_capabilities": { + "can_insert": false, + "can_upsert": false + } + }, { "name": "sponsors", "schema_name": "", diff --git a/drivers/sqlboiler-mssql/driver/testdatabase.sql b/drivers/sqlboiler-mssql/driver/testdatabase.sql index 2db97a5de..bfebebc85 100644 --- a/drivers/sqlboiler-mssql/driver/testdatabase.sql +++ b/drivers/sqlboiler-mssql/driver/testdatabase.sql @@ -1,6 +1,7 @@ SET QUOTED_IDENTIFIER ON; -- Don't forget to maintain order here, foreign keys! +drop table if exists node; drop table if exists video_tags; drop table if exists tags; drop table if exists videos; @@ -158,6 +159,18 @@ create table type_monsters ( generated_virtual AS smallint_nnull * smallint_null ); +create table node ( + id int primary key, + parent_id int, + root_id int not null, + + constraint CK_parent_root check((parent_id is not null and root_id != id) OR (parent_id is null and root_id = id)), + constraint UN_node_parent_root unique(id, root_id), + constraint FK_node_parent foreign key (parent_id) references node(id), + constraint FK_node_root foreign key(root_id) references node(id), + constraint FK_node_parent_root foreign key (parent_id, root_id) references node(id, root_id) +); + GO create view user_videos as diff --git a/drivers/sqlboiler-mysql/driver/mysql.golden.enums.json b/drivers/sqlboiler-mysql/driver/mysql.golden.enums.json index fd0a45fa2..0e43a81be 100644 --- a/drivers/sqlboiler-mysql/driver/mysql.golden.enums.json +++ b/drivers/sqlboiler-mysql/driver/mysql.golden.enums.json @@ -1,6 +1,138 @@ { "schema": "", "tables": [ + { + "name": "node", + "schema_name": "", + "columns": [ + { + "name": "id", + "type": "int", + "db_type": "int", + "default": "", + "comment": "", + "nullable": false, + "unique": true, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "int" + }, + { + "name": "parent_id", + "type": "null.Int", + "db_type": "int", + "default": "", + "comment": "", + "nullable": true, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "int" + }, + { + "name": "root_id", + "type": "int", + "db_type": "int", + "default": "", + "comment": "", + "nullable": false, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "int" + } + ], + "p_key": { + "name": "PRIMARY", + "columns": [ + "id" + ] + }, + "f_keys": [ + { + "table": "node", + "name": "FK_node_parent", + "column": "parent_id", + "nullable": true, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": false, + "foreign_column_unique": true + }, + { + "table": "node", + "name": "FK_node_root", + "column": "root_id", + "nullable": false, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": false, + "foreign_column_unique": true + } + ], + "is_join_table": false, + "to_one_relationships": null, + "to_many_relationships": [ + { + "name": "FK_node_parent", + "table": "node", + "column": "id", + "nullable": false, + "unique": true, + "foreign_table": "node", + "foreign_column": "parent_id", + "foreign_column_nullable": true, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + }, + { + "name": "FK_node_root", + "table": "node", + "column": "id", + "nullable": false, + "unique": true, + "foreign_table": "node", + "foreign_column": "root_id", + "foreign_column_nullable": false, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + } + ], + "is_view": false, + "view_capabilities": { + "can_insert": false, + "can_upsert": false + } + }, { "name": "sponsors", "schema_name": "", diff --git a/drivers/sqlboiler-mysql/driver/mysql.golden.json b/drivers/sqlboiler-mysql/driver/mysql.golden.json index f156fe288..b0fe7e3d7 100644 --- a/drivers/sqlboiler-mysql/driver/mysql.golden.json +++ b/drivers/sqlboiler-mysql/driver/mysql.golden.json @@ -1,6 +1,138 @@ { "schema": "", "tables": [ + { + "name": "node", + "schema_name": "", + "columns": [ + { + "name": "id", + "type": "int", + "db_type": "int", + "default": "", + "comment": "", + "nullable": false, + "unique": true, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "int" + }, + { + "name": "parent_id", + "type": "null.Int", + "db_type": "int", + "default": "", + "comment": "", + "nullable": true, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "int" + }, + { + "name": "root_id", + "type": "int", + "db_type": "int", + "default": "", + "comment": "", + "nullable": false, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "int" + } + ], + "p_key": { + "name": "PRIMARY", + "columns": [ + "id" + ] + }, + "f_keys": [ + { + "table": "node", + "name": "FK_node_parent", + "column": "parent_id", + "nullable": true, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": false, + "foreign_column_unique": true + }, + { + "table": "node", + "name": "FK_node_root", + "column": "root_id", + "nullable": false, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": false, + "foreign_column_unique": true + } + ], + "is_join_table": false, + "to_one_relationships": null, + "to_many_relationships": [ + { + "name": "FK_node_parent", + "table": "node", + "column": "id", + "nullable": false, + "unique": true, + "foreign_table": "node", + "foreign_column": "parent_id", + "foreign_column_nullable": true, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + }, + { + "name": "FK_node_root", + "table": "node", + "column": "id", + "nullable": false, + "unique": true, + "foreign_table": "node", + "foreign_column": "root_id", + "foreign_column_nullable": false, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + } + ], + "is_view": false, + "view_capabilities": { + "can_insert": false, + "can_upsert": false + } + }, { "name": "sponsors", "schema_name": "", diff --git a/drivers/sqlboiler-mysql/driver/testdatabase.sql b/drivers/sqlboiler-mysql/driver/testdatabase.sql index 607e4689b..16f866c8c 100644 --- a/drivers/sqlboiler-mysql/driver/testdatabase.sql +++ b/drivers/sqlboiler-mysql/driver/testdatabase.sql @@ -1,4 +1,5 @@ -- Don't forget to maintain order here, foreign keys! +drop table if exists node; drop table if exists video_tags; drop table if exists tags; drop table if exists videos; @@ -172,13 +173,26 @@ create table type_monsters ( text_nnull text not null, - virtual_nnull text GENERATED ALWAYS AS (UPPER(text_nnull)) VIRTUAL NOT NULL, - virtual_null text GENERATED ALWAYS AS (UPPER(text_null)) VIRTUAL, - generated_nnull text GENERATED ALWAYS AS (UPPER(text_nnull)) STORED NOT NULL, - generated_null text GENERATED ALWAYS AS (UPPER(text_null)) STORED + virtual_nnull text GENERATED ALWAYS AS (UPPER(text_nnull)) VIRTUAL NOT NULL, + virtual_null text GENERATED ALWAYS AS (UPPER(text_null)) VIRTUAL, + generated_nnull text GENERATED ALWAYS AS (UPPER(text_nnull)) STORED NOT NULL, + generated_null text GENERATED ALWAYS AS (UPPER(text_null)) STORED ); create view user_videos as select u.id user_id, v.id video_id, v.sponsor_id sponsor_id from users u inner join videos v on v.user_id = u.id; + +create table node ( + id int primary key, + parent_id int, + root_id int not null, + + constraint CK_parent_root check((parent_id is not null and root_id != id) OR (parent_id is null and root_id = id)), + constraint UN_node_parent_root unique(id, root_id), + constraint FK_node_parent foreign key (parent_id) references node(id), + constraint FK_node_root foreign key(root_id) references node(id), + constraint FK_node_parent_root foreign key (parent_id, root_id) references node(id, root_id) +); + diff --git a/drivers/sqlboiler-psql/driver/psql.golden.enums.json b/drivers/sqlboiler-psql/driver/psql.golden.enums.json index d57fcb580..35db907d0 100644 --- a/drivers/sqlboiler-psql/driver/psql.golden.enums.json +++ b/drivers/sqlboiler-psql/driver/psql.golden.enums.json @@ -1,6 +1,138 @@ { "schema": "public", "tables": [ + { + "name": "node", + "schema_name": "", + "columns": [ + { + "name": "id", + "type": "int", + "db_type": "integer", + "default": "", + "comment": "", + "nullable": false, + "unique": true, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "int4", + "domain_name": null, + "full_db_type": "int4" + }, + { + "name": "parent_id", + "type": "null.Int", + "db_type": "integer", + "default": "NULL", + "comment": "", + "nullable": true, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "int4", + "domain_name": null, + "full_db_type": "int4" + }, + { + "name": "root_id", + "type": "int", + "db_type": "integer", + "default": "", + "comment": "", + "nullable": false, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "int4", + "domain_name": null, + "full_db_type": "int4" + } + ], + "p_key": { + "name": "node_pkey", + "columns": [ + "id" + ] + }, + "f_keys": [ + { + "table": "node", + "name": "fk_node_parent", + "column": "parent_id", + "nullable": true, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": false, + "foreign_column_unique": true + }, + { + "table": "node", + "name": "fk_node_root", + "column": "root_id", + "nullable": false, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": false, + "foreign_column_unique": true + } + ], + "is_join_table": false, + "to_one_relationships": null, + "to_many_relationships": [ + { + "name": "fk_node_parent", + "table": "node", + "column": "id", + "nullable": false, + "unique": true, + "foreign_table": "node", + "foreign_column": "parent_id", + "foreign_column_nullable": true, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + }, + { + "name": "fk_node_root", + "table": "node", + "column": "id", + "nullable": false, + "unique": true, + "foreign_table": "node", + "foreign_column": "root_id", + "foreign_column_nullable": false, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + } + ], + "is_view": false, + "view_capabilities": { + "can_insert": false, + "can_upsert": false + } + }, { "name": "sponsors", "schema_name": "", diff --git a/drivers/sqlboiler-psql/driver/psql.golden.json b/drivers/sqlboiler-psql/driver/psql.golden.json index 2b84157b3..f1e20fb42 100644 --- a/drivers/sqlboiler-psql/driver/psql.golden.json +++ b/drivers/sqlboiler-psql/driver/psql.golden.json @@ -1,6 +1,138 @@ { "schema": "public", "tables": [ + { + "name": "node", + "schema_name": "", + "columns": [ + { + "name": "id", + "type": "int", + "db_type": "integer", + "default": "", + "comment": "", + "nullable": false, + "unique": true, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "int4", + "domain_name": null, + "full_db_type": "int4" + }, + { + "name": "parent_id", + "type": "null.Int", + "db_type": "integer", + "default": "NULL", + "comment": "", + "nullable": true, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "int4", + "domain_name": null, + "full_db_type": "int4" + }, + { + "name": "root_id", + "type": "int", + "db_type": "integer", + "default": "", + "comment": "", + "nullable": false, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "int4", + "domain_name": null, + "full_db_type": "int4" + } + ], + "p_key": { + "name": "node_pkey", + "columns": [ + "id" + ] + }, + "f_keys": [ + { + "table": "node", + "name": "fk_node_parent", + "column": "parent_id", + "nullable": true, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": false, + "foreign_column_unique": true + }, + { + "table": "node", + "name": "fk_node_root", + "column": "root_id", + "nullable": false, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": false, + "foreign_column_unique": true + } + ], + "is_join_table": false, + "to_one_relationships": null, + "to_many_relationships": [ + { + "name": "fk_node_parent", + "table": "node", + "column": "id", + "nullable": false, + "unique": true, + "foreign_table": "node", + "foreign_column": "parent_id", + "foreign_column_nullable": true, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + }, + { + "name": "fk_node_root", + "table": "node", + "column": "id", + "nullable": false, + "unique": true, + "foreign_table": "node", + "foreign_column": "root_id", + "foreign_column_nullable": false, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + } + ], + "is_view": false, + "view_capabilities": { + "can_insert": false, + "can_upsert": false + } + }, { "name": "sponsors", "schema_name": "", diff --git a/drivers/sqlboiler-psql/driver/testdatabase.sql b/drivers/sqlboiler-psql/driver/testdatabase.sql index fa0e29b80..50dd734d3 100644 --- a/drivers/sqlboiler-psql/driver/testdatabase.sql +++ b/drivers/sqlboiler-psql/driver/testdatabase.sql @@ -1,4 +1,5 @@ -- Don't forget to maintain order here, foreign keys! +drop table if exists node; drop table if exists video_tags; drop table if exists tags; drop table if exists videos; @@ -260,3 +261,15 @@ inner join videos v on v.user_id = u.id; create view type_monsters_v as select * from type_monsters; create materialized view type_monsters_mv as select * from type_monsters_v; + +create table node ( + id int primary key, + parent_id int, + root_id int not null, + + constraint CK_parent_root check((parent_id is not null and root_id != id) OR (parent_id is null and root_id = id)), + constraint UN_node_parent_root unique(id, root_id), + constraint FK_node_parent foreign key (parent_id) references node(id), + constraint FK_node_root foreign key(root_id) references node(id), + constraint FK_node_parent_root foreign key (parent_id, root_id) references node(id, root_id) +); diff --git a/drivers/sqlboiler-sqlite3/driver/sqlite3.golden.json b/drivers/sqlboiler-sqlite3/driver/sqlite3.golden.json index b3577c333..fa7b9d959 100644 --- a/drivers/sqlboiler-sqlite3/driver/sqlite3.golden.json +++ b/drivers/sqlboiler-sqlite3/driver/sqlite3.golden.json @@ -236,6 +236,138 @@ "can_upsert": false } }, + { + "name": "node", + "schema_name": "", + "columns": [ + { + "name": "id", + "type": "null.Int64", + "db_type": "INT", + "default": "NULL", + "comment": "", + "nullable": true, + "unique": true, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "INT" + }, + { + "name": "parent_id", + "type": "null.Int64", + "db_type": "INT", + "default": "NULL", + "comment": "", + "nullable": true, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "INT" + }, + { + "name": "root_id", + "type": "int64", + "db_type": "INT", + "default": "", + "comment": "", + "nullable": false, + "unique": false, + "validated": false, + "auto_generated": false, + "arr_type": null, + "udt_name": "", + "domain_name": null, + "full_db_type": "INT" + } + ], + "p_key": { + "name": "", + "columns": [ + "id" + ] + }, + "f_keys": [ + { + "table": "node", + "name": "FK_1", + "column": "root_id", + "nullable": false, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": true, + "foreign_column_unique": true + }, + { + "table": "node", + "name": "FK_2", + "column": "parent_id", + "nullable": true, + "unique": false, + "foreign_table": "node", + "foreign_column": "id", + "foreign_column_nullable": true, + "foreign_column_unique": true + } + ], + "is_join_table": false, + "to_one_relationships": null, + "to_many_relationships": [ + { + "name": "FK_1", + "table": "node", + "column": "id", + "nullable": true, + "unique": true, + "foreign_table": "node", + "foreign_column": "root_id", + "foreign_column_nullable": false, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + }, + { + "name": "FK_2", + "table": "node", + "column": "id", + "nullable": true, + "unique": true, + "foreign_table": "node", + "foreign_column": "parent_id", + "foreign_column_nullable": true, + "foreign_column_unique": false, + "to_join_table": false, + "join_table": "", + "join_local_fkey_name": "", + "join_local_column": "", + "join_local_column_nullable": false, + "join_local_column_unique": false, + "join_foreign_fkey_name": "", + "join_foreign_column": "", + "join_foreign_column_nullable": false, + "join_foreign_column_unique": false + } + ], + "is_view": false, + "view_capabilities": { + "can_insert": false, + "can_upsert": false + } + }, { "name": "sponsors", "schema_name": "", diff --git a/drivers/sqlboiler-sqlite3/driver/testdatabase.sql b/drivers/sqlboiler-sqlite3/driver/testdatabase.sql index d94d1c137..b5dd1c464 100644 --- a/drivers/sqlboiler-sqlite3/driver/testdatabase.sql +++ b/drivers/sqlboiler-sqlite3/driver/testdatabase.sql @@ -186,9 +186,21 @@ from users u inner join videos v on v.user_id = u.id; CREATE TABLE has_generated_columns ( - a INTEGER PRIMARY KEY, - b INT, - c TEXT, - d INT GENERATED ALWAYS AS (a*abs(b)) VIRTUAL, - e TEXT GENERATED ALWAYS AS (substr(c,b,b+1)) STORED + a INTEGER PRIMARY KEY, + b INT, + c TEXT, + d INT GENERATED ALWAYS AS (a*abs(b)) VIRTUAL, + e TEXT GENERATED ALWAYS AS (substr(c,b,b+1)) STORED +); + +CREATE TABLE node ( + id INT PRIMARY KEY, + parent_id INT, + root_id INT NOT NULL, + + constraint CK_parent_root check((parent_id is not null and root_id != id) OR (parent_id is null and root_id = id)), + constraint UN_node_parent_root unique(id, root_id), + constraint FK_node_parent foreign key (parent_id) references node(id), + constraint FK_node_root foreign key(root_id) references node(id), + constraint FK_node_parent_root foreign key (parent_id, root_id) references node(id, root_id) );