Fixed #25476 -- Allowed PostgreSQL introspection to work regardless of table owner.
This commit is contained in:
parent
8c054ed71d
commit
d6b9aab37c
|
@ -149,65 +149,43 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
|||
Retrieves any constraints or keys (unique, pk, fk, check, index) across one or more columns.
|
||||
"""
|
||||
constraints = {}
|
||||
# Loop over the key table, collecting things as constraints
|
||||
# This will get PKs, FKs, and uniques, but not CHECK
|
||||
# Loop over the key table, collecting things as constraints. The column
|
||||
# array must return column names in the same order in which they were
|
||||
# created.
|
||||
# The subquery containing generate_series can be replaced with
|
||||
# "WITH ORDINALITY" when support for PostgreSQL 9.3 is dropped.
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
kc.constraint_name,
|
||||
kc.column_name,
|
||||
c.constraint_type,
|
||||
array(SELECT table_name::text || '.' || column_name::text
|
||||
FROM information_schema.constraint_column_usage
|
||||
WHERE constraint_name = kc.constraint_name)
|
||||
FROM information_schema.key_column_usage AS kc
|
||||
JOIN information_schema.table_constraints AS c ON
|
||||
kc.table_schema = c.table_schema AND
|
||||
kc.table_name = c.table_name AND
|
||||
kc.constraint_name = c.constraint_name
|
||||
WHERE
|
||||
kc.table_schema = %s AND
|
||||
kc.table_name = %s
|
||||
ORDER BY kc.ordinal_position ASC
|
||||
c.conname,
|
||||
array(
|
||||
SELECT attname
|
||||
FROM (
|
||||
SELECT unnest(c.conkey) AS colid,
|
||||
generate_series(1, array_length(c.conkey, 1)) AS arridx
|
||||
) AS cols
|
||||
JOIN pg_attribute AS ca ON cols.colid = ca.attnum
|
||||
WHERE ca.attrelid = c.conrelid
|
||||
ORDER BY cols.arridx
|
||||
),
|
||||
c.contype,
|
||||
(SELECT fkc.relname || '.' || fka.attname
|
||||
FROM pg_attribute AS fka
|
||||
JOIN pg_class AS fkc ON fka.attrelid = fkc.oid
|
||||
WHERE fka.attrelid = c.confrelid AND fka.attnum = c.confkey[1])
|
||||
FROM pg_constraint AS c
|
||||
JOIN pg_class AS cl ON c.conrelid = cl.oid
|
||||
JOIN pg_namespace AS ns ON cl.relnamespace = ns.oid
|
||||
WHERE ns.nspname = %s AND cl.relname = %s
|
||||
""", ["public", table_name])
|
||||
for constraint, column, kind, used_cols in cursor.fetchall():
|
||||
# If we're the first column, make the record
|
||||
if constraint not in constraints:
|
||||
constraints[constraint] = {
|
||||
"columns": [],
|
||||
"primary_key": kind.lower() == "primary key",
|
||||
"unique": kind.lower() in ["primary key", "unique"],
|
||||
"foreign_key": tuple(used_cols[0].split(".", 1)) if kind.lower() == "foreign key" else None,
|
||||
"check": False,
|
||||
"index": False,
|
||||
}
|
||||
# Record the details
|
||||
constraints[constraint]['columns'].append(column)
|
||||
# Now get CHECK constraint columns
|
||||
cursor.execute("""
|
||||
SELECT kc.constraint_name, kc.column_name
|
||||
FROM information_schema.constraint_column_usage AS kc
|
||||
JOIN information_schema.table_constraints AS c ON
|
||||
kc.table_schema = c.table_schema AND
|
||||
kc.table_name = c.table_name AND
|
||||
kc.constraint_name = c.constraint_name
|
||||
WHERE
|
||||
c.constraint_type = 'CHECK' AND
|
||||
kc.table_schema = %s AND
|
||||
kc.table_name = %s
|
||||
""", ["public", table_name])
|
||||
for constraint, column in cursor.fetchall():
|
||||
# If we're the first column, make the record
|
||||
if constraint not in constraints:
|
||||
constraints[constraint] = {
|
||||
"columns": [],
|
||||
"primary_key": False,
|
||||
"unique": False,
|
||||
"foreign_key": None,
|
||||
"check": True,
|
||||
"index": False,
|
||||
}
|
||||
# Record the details
|
||||
constraints[constraint]['columns'].append(column)
|
||||
for constraint, columns, kind, used_cols in cursor.fetchall():
|
||||
constraints[constraint] = {
|
||||
"columns": columns,
|
||||
"primary_key": kind == "p",
|
||||
"unique": kind in ["p", "u"],
|
||||
"foreign_key": tuple(used_cols.split(".", 1)) if kind == "f" else None,
|
||||
"check": kind == "c",
|
||||
"index": False,
|
||||
}
|
||||
# Now get indexes
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
|
|
Loading…
Reference in New Issue