mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #25476 -- Allowed PostgreSQL introspection to work regardless of table owner.
This commit is contained in:
		
				
					committed by
					
						 Tim Graham
						Tim Graham
					
				
			
			
				
	
			
			
			
						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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user