Repository navigation
Fix changing the inherited tables of an existing table. #10657 #10661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| {### Inheritable CHECK constraints of the given parents that the table does not have yet ###} | ||
| SELECT name, definition FROM ( | ||
| SELECT DISTINCT ON (c.conname) c.conname AS name, | ||
| pg_catalog.pg_get_constraintdef(c.oid, true) AS definition, p.ord | ||
| FROM | ||
| pg_catalog.unnest(ARRAY[{% for val in parents %}{{val|qtLiteral(conn)}}::regclass::oid{% if not loop.last %}, {% endif %}{% endfor %}]) | ||
| WITH ORDINALITY AS p(oid, ord) | ||
| JOIN | ||
| pg_catalog.pg_constraint c ON c.conrelid = p.oid | ||
| WHERE c.contype = 'c' AND NOT c.connoinherit | ||
| AND NOT EXISTS ( | ||
| SELECT 1 FROM pg_catalog.pg_constraint cc | ||
| WHERE cc.conrelid = {{tid}}::oid AND cc.contype = 'c' | ||
| AND cc.conname = c.conname) | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| ORDER BY c.conname, p.ord | ||
| ) checks | ||
| ORDER BY ord, name | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| {### Columns of the given parents that the table must have before it can inherit from them: ###} | ||
| {### the ones it does not have yet, and the ones it has without the NOT NULL a parent requires ###} | ||
| SELECT name, displaytypname, collspcname, attnotnull, genexpr, is_missing FROM ( | ||
| SELECT DISTINCT ON (a.attname) a.attname AS name, | ||
| pg_catalog.format_type(a.atttypid, a.atttypmod) AS displaytypname, | ||
| CASE WHEN a.attcollation <> ty.typcollation THEN | ||
| pg_catalog.quote_ident(cn.nspname)||'.'||pg_catalog.quote_ident(co.collname) | ||
| END AS collspcname, | ||
| pg_catalog.bool_or(a.attnotnull) OVER (PARTITION BY a.attname) AS attnotnull, | ||
| CASE WHEN a.attgenerated = 's' THEN | ||
| pg_catalog.pg_get_expr(def.adbin, def.adrelid) | ||
| END AS genexpr, | ||
| ca.attname IS NULL AS is_missing, ca.attnotnull AS child_attnotnull, | ||
| p.ord, a.attnum | ||
| FROM | ||
| pg_catalog.unnest(ARRAY[{% for val in parents %}{{val|qtLiteral(conn)}}::regclass::oid{% if not loop.last %}, {% endif %}{% endfor %}]) | ||
| WITH ORDINALITY AS p(oid, ord) | ||
| JOIN | ||
| pg_catalog.pg_attribute a ON a.attrelid = p.oid AND a.attnum > 0 AND NOT a.attisdropped | ||
| JOIN | ||
| pg_catalog.pg_type ty ON ty.oid = a.atttypid | ||
| LEFT OUTER JOIN | ||
| pg_catalog.pg_collation co ON co.oid = a.attcollation | ||
| LEFT OUTER JOIN | ||
| pg_catalog.pg_namespace cn ON cn.oid = co.collnamespace | ||
| LEFT OUTER JOIN | ||
| pg_catalog.pg_attrdef def ON def.adrelid = a.attrelid AND def.adnum = a.attnum | ||
| LEFT OUTER JOIN | ||
| pg_catalog.pg_attribute ca ON ca.attrelid = {{tid}}::oid AND ca.attname = a.attname | ||
| AND ca.attnum > 0 AND NOT ca.attisdropped | ||
| ORDER BY a.attname, p.ord, a.attnum | ||
| ) cols | ||
| WHERE is_missing OR (attnotnull AND NOT child_attnotnull) | ||
| {### Generated columns go last, as their expressions use the other columns ###} | ||
| ORDER BY genexpr IS NOT NULL, ord, attnum |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| {### CHECK constraints the table inherits from the given removed parents and from none of the remaining ones, ###} | ||
| {### which NO INHERIT would leave on the table as local constraints ###} | ||
| {% macro PARENT_CHECK(tables) %} | ||
| SELECT 1 FROM pg_catalog.pg_constraint pc | ||
| WHERE pc.conrelid = ANY(ARRAY[{% for val in tables %}{{val|qtLiteral(conn)}}::regclass::oid{% if not loop.last %}, {% endif %}{% endfor %}]::pg_catalog.oid[]) | ||
| AND pc.contype = 'c' AND NOT pc.connoinherit AND pc.conname = c.conname | ||
| {%- endmacro %} | ||
| SELECT c.conname AS name | ||
| FROM pg_catalog.pg_constraint c | ||
| WHERE c.conrelid = {{tid}}::oid AND c.contype = 'c' AND c.coninhcount > 0 | ||
| AND EXISTS ({{ PARENT_CHECK(removed) }}) | ||
| AND NOT EXISTS ({{ PARENT_CHECK(remaining) }}) | ||
| ORDER BY c.conname |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,22 @@ ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} | |
| {## Update Inherits table definition ##} | ||
| {#####################################################} | ||
| {% if data.coll_inherits_added|length > 0 %} | ||
| {### A table must have the parent's columns and CHECK constraints before it can inherit from it ###} | ||
| {% for col in inherit_columns %} | ||
| {% if col.is_missing %} | ||
| ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} | ||
| ADD COLUMN {{conn|qtIdent(col.name)}} {{col.displaytypname}}{% if col.collspcname %} COLLATE {{col.collspcname}}{% endif %}{% if col.attnotnull %} NOT NULL{% endif %}{% if col.genexpr %} GENERATED ALWAYS AS ({{col.genexpr}}) STORED{% endif %}; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift Handle existing rows before adding a required column. If the child has rows and a new parent supplies a missing 🤖 Prompt for AI Agents |
||
| {% else %} | ||
| ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} | ||
| ALTER COLUMN {{conn|qtIdent(col.name)}} SET NOT NULL; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift 🔎 Supported by static analysis🏁 Script executed: sed -n '1285,1312p' web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py
sed -n '1341,1368p' web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py
sed -n '1,40p' web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/get_inherit_prerequisite_columns.sqlRepository: pgadmin-org/pgadmin4 Length of output: 4513 🏁 Script executed: set -o pipefail
printf '%s\n' '--- table.ui.js removal logic ---'
nl -ba web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.ui.js | sed -n '650,725p'
printf '%s\n' '--- column properties metadata ---'
nl -ba web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/properties.sql | sed -n '1,35p'
printf '%s\n' '--- inheritance change and delete caller ---'
nl -ba web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py | sed -n '1685,1735p'
printf '%s\n' '--- default update template ---'
nl -ba web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/update.sql | sed -n '1,85p'
printf '%s\n' '--- 15_plus update template ---'
nl -ba web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/15_plus/update.sql | sed -n '1,95p'Repository: pgadmin-org/pgadmin4 Length of output: 17262 Drop the explicit When parent A requires When A is removed, the dialog removes the column row associated with A. Track columns changed from nullable to 🤖 Prompt for AI Agents |
||
| {% endif %} | ||
|
|
||
| {% endfor %} | ||
| {% for chk in inherit_checks %} | ||
| ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} | ||
| ADD CONSTRAINT {{conn|qtIdent(chk.name)}} {{chk.definition}}; | ||
|
|
||
| {% endfor %} | ||
| {% for val in data.coll_inherits_added %} | ||
| ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} | ||
| INHERIT {{val}}; | ||
|
|
@@ -40,6 +56,12 @@ ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} | |
| ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} | ||
| NO INHERIT {{val}}; | ||
|
|
||
| {% endfor %} | ||
| {### NO INHERIT keeps the removed parents' CHECK constraints on the table ###} | ||
| {% for chk in uninherit_checks %} | ||
| ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} | ||
| DROP CONSTRAINT IF EXISTS {{conn|qtIdent(chk.name)}}; | ||
|
|
||
| {% endfor %} | ||
| {% endif %} | ||
| {#####################################################} | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.