Fixed #28258 -- Optimized Oracle introspection by using LISTAGG.
Thanks Tim Graham and Jani Tiainen for reviews.
This commit is contained in:
parent
45585d3cbb
commit
8149bd00d8
|
@ -180,29 +180,19 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
user_constraints.constraint_name,
|
user_constraints.constraint_name,
|
||||||
LOWER(cols.column_name) AS column_name,
|
LISTAGG(LOWER(cols.column_name), ',') WITHIN GROUP (ORDER BY cols.position),
|
||||||
CASE user_constraints.constraint_type
|
CASE user_constraints.constraint_type
|
||||||
WHEN 'P' THEN 1
|
WHEN 'P' THEN 1
|
||||||
ELSE 0
|
ELSE 0
|
||||||
END AS is_primary_key,
|
END AS is_primary_key,
|
||||||
CASE
|
CASE
|
||||||
WHEN EXISTS (
|
WHEN user_constraints.constraint_type IN ('P', 'U') THEN 1
|
||||||
SELECT 1
|
|
||||||
FROM user_indexes
|
|
||||||
WHERE user_indexes.index_name = user_constraints.index_name
|
|
||||||
AND user_indexes.uniqueness = 'UNIQUE'
|
|
||||||
)
|
|
||||||
THEN 1
|
|
||||||
ELSE 0
|
ELSE 0
|
||||||
END AS is_unique,
|
END AS is_unique,
|
||||||
CASE user_constraints.constraint_type
|
CASE user_constraints.constraint_type
|
||||||
WHEN 'C' THEN 1
|
WHEN 'C' THEN 1
|
||||||
ELSE 0
|
ELSE 0
|
||||||
END AS is_check_constraint,
|
END AS is_check_constraint
|
||||||
CASE
|
|
||||||
WHEN user_constraints.constraint_type IN ('P', 'U') THEN 1
|
|
||||||
ELSE 0
|
|
||||||
END AS has_index
|
|
||||||
FROM
|
FROM
|
||||||
user_constraints
|
user_constraints
|
||||||
LEFT OUTER JOIN
|
LEFT OUTER JOIN
|
||||||
|
@ -210,57 +200,51 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
WHERE
|
WHERE
|
||||||
user_constraints.constraint_type = ANY('P', 'U', 'C')
|
user_constraints.constraint_type = ANY('P', 'U', 'C')
|
||||||
AND user_constraints.table_name = UPPER(%s)
|
AND user_constraints.table_name = UPPER(%s)
|
||||||
ORDER BY cols.position
|
GROUP BY user_constraints.constraint_name, user_constraints.constraint_type
|
||||||
""", [table_name])
|
""", [table_name])
|
||||||
for constraint, column, pk, unique, check, index in cursor.fetchall():
|
for constraint, columns, pk, unique, check in cursor.fetchall():
|
||||||
# If we're the first column, make the record
|
constraints[constraint] = {
|
||||||
if constraint not in constraints:
|
'columns': columns.split(','),
|
||||||
constraints[constraint] = {
|
'primary_key': pk,
|
||||||
"columns": [],
|
'unique': unique,
|
||||||
"primary_key": pk,
|
'foreign_key': None,
|
||||||
"unique": unique,
|
'check': check,
|
||||||
"foreign_key": None,
|
'index': unique, # All uniques come with an index
|
||||||
"check": check,
|
}
|
||||||
"index": index, # All P and U come with index
|
|
||||||
}
|
|
||||||
# Record the details
|
|
||||||
constraints[constraint]['columns'].append(column)
|
|
||||||
# Foreign key constraints
|
# Foreign key constraints
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
cons.constraint_name,
|
cons.constraint_name,
|
||||||
LOWER(cols.column_name) AS column_name,
|
LISTAGG(LOWER(cols.column_name), ',') WITHIN GROUP (ORDER BY cols.position),
|
||||||
LOWER(rcols.table_name),
|
LOWER(rcols.table_name),
|
||||||
LOWER(rcols.column_name)
|
LOWER(rcols.column_name)
|
||||||
FROM
|
FROM
|
||||||
user_constraints cons
|
user_constraints cons
|
||||||
INNER JOIN
|
INNER JOIN
|
||||||
user_cons_columns rcols ON rcols.constraint_name = cons.r_constraint_name
|
user_cons_columns rcols ON rcols.constraint_name = cons.r_constraint_name AND rcols.position = 1
|
||||||
LEFT OUTER JOIN
|
LEFT OUTER JOIN
|
||||||
user_cons_columns cols ON cons.constraint_name = cols.constraint_name
|
user_cons_columns cols ON cons.constraint_name = cols.constraint_name
|
||||||
WHERE
|
WHERE
|
||||||
cons.constraint_type = 'R' AND
|
cons.constraint_type = 'R' AND
|
||||||
cons.table_name = UPPER(%s)
|
cons.table_name = UPPER(%s)
|
||||||
ORDER BY cols.position
|
GROUP BY cons.constraint_name, rcols.table_name, rcols.column_name
|
||||||
""", [table_name])
|
""", [table_name])
|
||||||
for constraint, column, other_table, other_column in cursor.fetchall():
|
for constraint, columns, other_table, other_column in cursor.fetchall():
|
||||||
# If we're the first column, make the record
|
constraints[constraint] = {
|
||||||
if constraint not in constraints:
|
'primary_key': False,
|
||||||
constraints[constraint] = {
|
'unique': False,
|
||||||
"columns": [],
|
'foreign_key': (other_table, other_column),
|
||||||
"primary_key": False,
|
'check': False,
|
||||||
"unique": False,
|
'index': False,
|
||||||
"foreign_key": (other_table, other_column),
|
'columns': columns.split(','),
|
||||||
"check": False,
|
}
|
||||||
"index": False,
|
|
||||||
}
|
|
||||||
# Record the details
|
|
||||||
constraints[constraint]['columns'].append(column)
|
|
||||||
# Now get indexes
|
# Now get indexes
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
cols.index_name, LOWER(cols.column_name), cols.descend,
|
ind.index_name,
|
||||||
LOWER(ind.index_type)
|
LOWER(ind.index_type),
|
||||||
|
LISTAGG(LOWER(cols.column_name), ',') WITHIN GROUP (ORDER BY cols.column_position),
|
||||||
|
LISTAGG(cols.descend, ',') WITHIN GROUP (ORDER BY cols.column_position)
|
||||||
FROM
|
FROM
|
||||||
user_ind_columns cols, user_indexes ind
|
user_ind_columns cols, user_indexes ind
|
||||||
WHERE
|
WHERE
|
||||||
|
@ -268,24 +252,19 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
NOT EXISTS (
|
NOT EXISTS (
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM user_constraints cons
|
FROM user_constraints cons
|
||||||
WHERE cols.index_name = cons.index_name
|
WHERE ind.index_name = cons.index_name
|
||||||
) AND cols.index_name = ind.index_name
|
) AND cols.index_name = ind.index_name
|
||||||
ORDER BY cols.column_position
|
GROUP BY ind.index_name, ind.index_type
|
||||||
""", [table_name])
|
""", [table_name])
|
||||||
for constraint, column, order, type_ in cursor.fetchall():
|
for constraint, type_, columns, orders in cursor.fetchall():
|
||||||
# If we're the first column, make the record
|
constraints[constraint] = {
|
||||||
if constraint not in constraints:
|
'primary_key': False,
|
||||||
constraints[constraint] = {
|
'unique': False,
|
||||||
"columns": [],
|
'foreign_key': None,
|
||||||
"orders": [],
|
'check': False,
|
||||||
"primary_key": False,
|
'index': True,
|
||||||
"unique": False,
|
'type': 'idx' if type_ == 'normal' else type_,
|
||||||
"foreign_key": None,
|
'columns': columns.split(','),
|
||||||
"check": False,
|
'orders': orders.split(','),
|
||||||
"index": True,
|
}
|
||||||
"type": 'idx' if type_ == 'normal' else type_,
|
|
||||||
}
|
|
||||||
# Record the details
|
|
||||||
constraints[constraint]['columns'].append(column)
|
|
||||||
constraints[constraint]['orders'].append(order)
|
|
||||||
return constraints
|
return constraints
|
||||||
|
|
Loading…
Reference in New Issue