Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions internal/diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -1064,9 +1064,6 @@ func (d *ddlDiff) generateCreateSQL(targetSchema string, collector *diffCollecto
// Create tables WITHOUT function dependencies first (functions may reference these)
deferredPolicies1, deferredConstraints1 := generateCreateTablesSQL(tablesWithoutFunctionDeps, targetSchema, collector, existingTables, shouldDeferPolicy)

// Add deferred foreign key constraints from first batch
generateDeferredConstraintsSQL(deferredConstraints1, targetSchema, collector)

// Create functions (functions may depend on tables created above)
generateCreateFunctionsSQL(d.addedFunctions, targetSchema, collector)

Expand All @@ -1076,8 +1073,10 @@ func (d *ddlDiff) generateCreateSQL(targetSchema string, collector *diffCollecto
// Create tables WITH function dependencies (now that functions exist)
deferredPolicies2, deferredConstraints2 := generateCreateTablesSQL(tablesWithFunctionDeps, targetSchema, collector, existingTables, shouldDeferPolicy)

// Add deferred foreign key constraints from second batch
generateDeferredConstraintsSQL(deferredConstraints2, targetSchema, collector)
// Add deferred foreign key constraints from BOTH batches AFTER all tables are created
// This ensures FK references to tables in the second batch (function-dependent tables) work correctly
allDeferredConstraints := append(deferredConstraints1, deferredConstraints2...)
generateDeferredConstraintsSQL(allDeferredConstraints, targetSchema, collector)

// Merge deferred policies from both batches
allDeferredPolicies := append(deferredPolicies1, deferredPolicies2...)
Expand Down
23 changes: 23 additions & 0 deletions testdata/diff/dependency/table_fk_to_generated_column/diff.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
CREATE TABLE IF NOT EXISTS articlesource (
id integer,
article_id integer NOT NULL,
source_url text,
CONSTRAINT articlesource_pkey PRIMARY KEY (id)
);

CREATE OR REPLACE FUNCTION calc_priority()
RETURNS integer
LANGUAGE sql
IMMUTABLE
AS $$SELECT 1
$$;

CREATE TABLE IF NOT EXISTS article (
id integer,
title text NOT NULL,
priority integer GENERATED ALWAYS AS (public.calc_priority()) STORED,
CONSTRAINT article_pkey PRIMARY KEY (id)
);

ALTER TABLE articlesource
ADD CONSTRAINT articlesource_article_id_fkey FOREIGN KEY (article_id) REFERENCES article (id);
20 changes: 20 additions & 0 deletions testdata/diff/dependency/table_fk_to_generated_column/new.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- Function used in generated column
CREATE FUNCTION public.calc_priority() RETURNS integer
LANGUAGE sql
IMMUTABLE
AS $$SELECT 1$$;

-- Table with generated column using the function
CREATE TABLE public.article (
id integer PRIMARY KEY,
title text NOT NULL,
priority integer GENERATED ALWAYS AS (calc_priority()) STORED
);

-- Table with FK referencing article
CREATE TABLE public.articlesource (
id integer PRIMARY KEY,
article_id integer NOT NULL,
source_url text,
CONSTRAINT articlesource_article_id_fkey FOREIGN KEY (article_id) REFERENCES public.article(id)
);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-- Empty schema (no objects)
38 changes: 38 additions & 0 deletions testdata/diff/dependency/table_fk_to_generated_column/plan.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"version": "1.0.0",
"pgschema_version": "1.5.1",
"created_at": "1970-01-01T00:00:00Z",
"source_fingerprint": {
"hash": "965b1131737c955e24c7f827c55bd78e4cb49a75adfd04229e0ba297376f5085"
},
"groups": [
{
"steps": [
{
"sql": "CREATE TABLE IF NOT EXISTS articlesource (\n id integer,\n article_id integer NOT NULL,\n source_url text,\n CONSTRAINT articlesource_pkey PRIMARY KEY (id)\n);",
"type": "table",
"operation": "create",
"path": "public.articlesource"
},
{
"sql": "CREATE OR REPLACE FUNCTION calc_priority()\nRETURNS integer\nLANGUAGE sql\nIMMUTABLE\nAS $$SELECT 1\n$$;",
"type": "function",
"operation": "create",
"path": "public.calc_priority"
},
{
"sql": "CREATE TABLE IF NOT EXISTS article (\n id integer,\n title text NOT NULL,\n priority integer GENERATED ALWAYS AS (public.calc_priority()) STORED,\n CONSTRAINT article_pkey PRIMARY KEY (id)\n);",
"type": "table",
"operation": "create",
"path": "public.article"
},
{
"sql": "ALTER TABLE articlesource\nADD CONSTRAINT articlesource_article_id_fkey FOREIGN KEY (article_id) REFERENCES article (id);",
"type": "table.constraint",
"operation": "create",
"path": "public.articlesource.articlesource_article_id_fkey"
}
]
}
]
}
23 changes: 23 additions & 0 deletions testdata/diff/dependency/table_fk_to_generated_column/plan.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
CREATE TABLE IF NOT EXISTS articlesource (
id integer,
article_id integer NOT NULL,
source_url text,
CONSTRAINT articlesource_pkey PRIMARY KEY (id)
);

CREATE OR REPLACE FUNCTION calc_priority()
RETURNS integer
LANGUAGE sql
IMMUTABLE
AS $$SELECT 1
$$;

CREATE TABLE IF NOT EXISTS article (
id integer,
title text NOT NULL,
priority integer GENERATED ALWAYS AS (public.calc_priority()) STORED,
CONSTRAINT article_pkey PRIMARY KEY (id)
);

ALTER TABLE articlesource
ADD CONSTRAINT articlesource_article_id_fkey FOREIGN KEY (article_id) REFERENCES article (id);
40 changes: 40 additions & 0 deletions testdata/diff/dependency/table_fk_to_generated_column/plan.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Plan: 3 to add.

Summary by type:
functions: 1 to add
tables: 2 to add

Functions:
+ calc_priority

Tables:
+ article
+ articlesource
+ articlesource_article_id_fkey (constraint)

DDL to be executed:
--------------------------------------------------

CREATE TABLE IF NOT EXISTS articlesource (
id integer,
article_id integer NOT NULL,
source_url text,
CONSTRAINT articlesource_pkey PRIMARY KEY (id)
);

CREATE OR REPLACE FUNCTION calc_priority()
RETURNS integer
LANGUAGE sql
IMMUTABLE
AS $$SELECT 1
$$;

CREATE TABLE IF NOT EXISTS article (
id integer,
title text NOT NULL,
priority integer GENERATED ALWAYS AS (public.calc_priority()) STORED,
CONSTRAINT article_pkey PRIMARY KEY (id)
);

ALTER TABLE articlesource
ADD CONSTRAINT articlesource_article_id_fkey FOREIGN KEY (article_id) REFERENCES article (id);
14 changes: 7 additions & 7 deletions testdata/dump/tenant/pgschema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,6 @@ CREATE TABLE IF NOT EXISTS posts (
CONSTRAINT posts_pkey PRIMARY KEY (id)
);

--
-- Name: posts_author_id_fkey; Type: CONSTRAINT; Schema: -; Owner: -
--

ALTER TABLE posts
ADD CONSTRAINT posts_author_id_fkey FOREIGN KEY (author_id) REFERENCES users (id);

--
-- Name: auth_uid(); Type: FUNCTION; Schema: -; Owner: -
--
Expand Down Expand Up @@ -198,6 +191,13 @@ CREATE INDEX IF NOT EXISTS idx_users_email ON users (email);

ALTER TABLE users ENABLE ROW LEVEL SECURITY;

--
-- Name: posts_author_id_fkey; Type: CONSTRAINT; Schema: -; Owner: -
--

ALTER TABLE posts
ADD CONSTRAINT posts_author_id_fkey FOREIGN KEY (author_id) REFERENCES users (id);

--
-- Name: users_isolation; Type: POLICY; Schema: -; Owner: -
--
Expand Down