Skip to content

Commit

Permalink
Emulate foreign keys for single links in introspection over SQL adapt…
Browse files Browse the repository at this point in the history
…er (#7946)
  • Loading branch information
aljazerzen authored Nov 13, 2024
1 parent 1c16dbd commit 81a15ef
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 18 deletions.
166 changes: 148 additions & 18 deletions edb/pgsql/metaschema.py
Original file line number Diff line number Diff line change
Expand Up @@ -6362,20 +6362,6 @@ def _generate_sql_information_schema(
)
),
),
# TODO: Should we try to filter here, and fix up some stuff
# elsewhere, instead of overriding pg_get_constraintdef?
trampoline.VersionedView(
name=("edgedbsql", "pg_constraint"),
query="""
SELECT
pc.*,
pc.tableoid, pc.xmin, pc.cmin, pc.xmax, pc.cmax, pc.ctid
FROM pg_constraint pc
JOIN pg_namespace pn ON pc.connamespace = pn.oid
WHERE NOT (pn.nspname = 'edgedbpub' AND pc.conbin IS NOT NULL)
"""
),

# pg_class that contains classes only for tables
# This is needed so we can use it to filter pg_index to indexes only on
# visible tables.
Expand Down Expand Up @@ -6457,10 +6443,16 @@ def _generate_sql_information_schema(
pi.indisclustered,
pi.indisvalid,
pi.indcheckxmin,
pi.indisready,
CASE
WHEN COALESCE(is_id.t, FALSE) THEN TRUE
ELSE FALSE -- override so pg_dump won't try to recreate them
END AS indisready,
pi.indislive,
pi.indisreplident,
pi.indkey,
CASE
WHEN COALESCE(is_id.t, FALSE) THEN ARRAY[1]::int2vector -- id: 1
ELSE pi.indkey
END AS indkey,
pi.indcollation,
pi.indclass,
pi.indoption,
Expand Down Expand Up @@ -6817,6 +6809,88 @@ def _generate_sql_information_schema(
WHERE FALSE
""",
),
trampoline.VersionedView(
name=("edgedbsql", "pg_constraint"),
query=r"""
-- primary keys
SELECT
pc.oid,
vt.table_name || '_pk' AS conname,
pc.connamespace,
'p'::"char" AS contype,
pc.condeferrable,
pc.condeferred,
pc.convalidated,
pc.conrelid,
pc.contypid,
pc.conindid,
pc.conparentid,
pc.confrelid,
pc.confupdtype,
pc.confdeltype,
pc.confmatchtype,
pc.conislocal,
pc.coninhcount,
pc.connoinherit,
pc.conkey,
pc.confkey,
pc.conpfeqop,
pc.conppeqop,
pc.conffeqop,
pc.confdelsetcols,
pc.conexclop,
pc.conbin,
pc.tableoid, pc.xmin, pc.cmin, pc.xmax, pc.cmax, pc.ctid
FROM pg_constraint pc
JOIN edgedbsql_VER.pg_class_tables pct ON pct.oid = pc.conrelid
JOIN edgedbsql_VER.virtual_tables vt ON vt.pg_type_id = pct.reltype
JOIN pg_attribute pa ON (pa.attname = 'id' AND pa.attrelid = pct.oid)
WHERE contype = 'u' -- our ids and all links will have unique constraint
AND attnum = ANY(conkey)
UNION ALL
-- foreign keys
SELECT
edgedbsql_VER.uuid_to_oid(sl.id) as oid,
vt.table_name || '_fk_' || sl.name AS conname,
edgedbsql_VER.uuid_to_oid(vt.module_id) AS connamespace,
'f'::"char" AS contype,
FALSE AS condeferrable,
FALSE AS condeferred,
TRUE AS convalidated,
pc.oid AS conrelid,
0::oid AS contypid,
0::oid AS conindid, -- let's hope this is not needed
0::oid AS conparentid,
pc_target.oid AS confrelid,
'a'::"char" AS confupdtype,
'a'::"char" AS confdeltype,
's'::"char" AS confmatchtype,
TRUE AS conislocal,
0::int2 AS coninhcount,
TRUE AS connoinherit,
ARRAY[pa.attnum]::int2[] AS conkey,
ARRAY[1]::int2[] AS confkey, -- id will always have attnum 1
ARRAY[2972]::oid[] AS conpfeqop, -- 2972 is eq comparison for uuids
ARRAY[2972]::oid[] AS conppeqop, -- 2972 is eq comparison for uuids
ARRAY[2972]::oid[] AS conffeqop, -- 2972 is eq comparison for uuids
NULL::int2[] AS confdelsetcols,
NULL::oid[] AS conexclop,
NULL::pg_node_tree AS conbin,
pa.tableoid, pa.xmin, pa.cmin, pa.xmax, pa.cmax, pa.ctid
FROM edgedbsql_VER.virtual_tables vt
JOIN pg_class pc ON pc.reltype = vt.pg_type_id
JOIN edgedb_VER."_SchemaLink" sl
ON sl.source = vt.id -- AND COALESCE(sl.cardinality = 'One', TRUE)
JOIN edgedbsql_VER.virtual_tables vt_target
ON sl.target = vt_target.id
JOIN pg_class pc_target ON pc_target.reltype = vt_target.pg_type_id
JOIN edgedbsql_VER.pg_attribute pa
ON pa.attrelid = pc.oid
AND pa.attname = sl.name || '_id'
"""
),
trampoline.VersionedView(
name=("edgedbsql", "pg_statistic"),
query="""
Expand Down Expand Up @@ -6993,6 +7067,18 @@ def _generate_sql_information_schema(
WHERE c.relkind = 'v'::"char"
""",
),
# Omit all descriptions (comments), becase all non-system comments
# are our internal implementation details.
trampoline.VersionedView(
name=("edgedbsql", "pg_description"),
query="""
SELECT
*,
tableoid, xmin, cmin, xmax, cmax, ctid
FROM pg_description
WHERE FALSE
""",
),
]

# We expose most of the views as empty tables, just to prevent errors when
Expand Down Expand Up @@ -7041,6 +7127,7 @@ def _generate_sql_information_schema(
'pg_subscription',
'pg_tables',
'pg_views',
'pg_description',
}

PG_TABLES_WITH_SYSTEM_COLS = {
Expand All @@ -7061,7 +7148,6 @@ def _generate_sql_information_schema(
'pg_db_role_setting',
'pg_default_acl',
'pg_depend',
'pg_description',
'pg_enum',
'pg_event_trigger',
'pg_extension',
Expand Down Expand Up @@ -7352,7 +7438,51 @@ def construct_pg_view(
WHERE t.oid = typeoid
''',
)
),
trampoline.VersionedFunction(
name=("edgedbsql", "pg_get_constraintdef"),
args=[
('conid', ('oid',)),
],
returns=('text',),
volatility='stable',
text=r"""
SELECT CASE
WHEN contype = 'p' THEN
'PRIMARY KEY(' || (
SELECT string_agg('"' || attname || '"', ', ')
FROM edgedbsql_VER.pg_attribute
WHERE attrelid = conrelid AND attnum = ANY(conkey)
) || ')'
WHEN contype = 'f' THEN
'FOREIGN KEY ("' || (
SELECT attname
FROM edgedbsql_VER.pg_attribute
WHERE attrelid = conrelid AND attnum = ANY(conkey)
LIMIT 1
) || '")' || ' REFERENCES "'
|| pn.nspname || '"."' || pc.relname || '"(id)'
ELSE ''
END
FROM edgedbsql_VER.pg_constraint con
LEFT JOIN edgedbsql_VER.pg_class_tables pc ON pc.oid = confrelid
LEFT JOIN edgedbsql_VER.pg_namespace pn
ON pc.relnamespace = pn.oid
WHERE con.oid = conid
"""
),
trampoline.VersionedFunction(
name=("edgedbsql", "pg_get_constraintdef"),
args=[
('conid', ('oid',)),
('pretty', ('bool',)),
],
returns=('text',),
volatility='stable',
text=r"""
SELECT pg_get_constraintdef(conid)
"""
),
]

return (
Expand Down
8 changes: 8 additions & 0 deletions edb/pgsql/resolver/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,14 @@ def resolve_SortBy(
common.versioned_schema('edgedbsql'),
'_format_type',
),
('pg_catalog', 'pg_get_constraintdef'): (
common.versioned_schema('edgedbsql'),
'pg_get_constraintdef',
),
('pg_get_constraintdef',): (
common.versioned_schema('edgedbsql'),
'pg_get_constraintdef',
),
}


Expand Down

0 comments on commit 81a15ef

Please sign in to comment.