@@ -365,150 +365,6 @@ def get_multi_indexes(
365365 result .pop (k , None )
366366 return result
367367
368- def get_foreign_keys_v1 (self , conn , table_name , schema = None , ** kw ):
369- fkeys = []
370- FK_REGEX = re .compile (r"(?P<referred_table>.+)?\.\[(?P<referred_columns>.+)?]" )
371-
372- for row in conn .execute (
373- text (f'SHOW CONSTRAINTS FROM "{ schema or self .default_schema_name } "."{ table_name } "' )
374- ):
375- if row .Type .startswith ("FOREIGN KEY" ):
376- m = re .search (FK_REGEX , row .Details )
377-
378- name = row .Name
379- constrained_columns = row ["Column(s)" ].split (", " )
380- referred_table = m .group ("referred_table" )
381- referred_columns = m .group ("referred_columns" ).split ()
382- referred_schema = schema
383- fkey_d = {
384- "name" : name ,
385- "constrained_columns" : constrained_columns ,
386- "referred_table" : referred_table ,
387- "referred_columns" : referred_columns ,
388- "referred_schema" : referred_schema ,
389- }
390- fkeys .append (fkey_d )
391- return fkeys
392-
393- @util .memoized_property
394- def _fk_regex_pattern (self ):
395- # optionally quoted token
396- qtoken = r'(?:"[^"]+"|[\w]+?)'
397-
398- # https://www.postgresql.org/docs/current/static/sql-createtable.html
399- return re .compile (
400- r"FOREIGN KEY \((.*?)\) "
401- rf"REFERENCES (?:({ qtoken } )\.)?({ qtoken } )\(((?:{ qtoken } (?: *, *)?)+)\)" # noqa: E501
402- r"[\s]?(MATCH (FULL|PARTIAL|SIMPLE)+)?"
403- r"[\s]?(ON DELETE "
404- r"(CASCADE|RESTRICT|NO ACTION|SET NULL|SET DEFAULT)+)?"
405- r"[\s]?(ON UPDATE "
406- r"(CASCADE|RESTRICT|NO ACTION|SET NULL|SET DEFAULT)+)?"
407- r"[\s]?(DEFERRABLE|NOT DEFERRABLE)?"
408- r"[\s]?(INITIALLY (DEFERRED|IMMEDIATE)+)?"
409- )
410-
411- def get_foreign_keys (
412- self , connection , table_name , schema = None , postgresql_ignore_search_path = False , ** kw
413- ):
414- if not self ._is_v2plus :
415- # v1.1 or earlier.
416- return self .get_foreign_keys_v1 (connection , table_name , schema , ** kw )
417-
418- # v2.0 or later.
419- # This method is the same as the one in SQLAlchemy's pg dialect, with
420- # a tweak to the FK regular expressions to tolerate whitespace between
421- # the table name and the column list.
422- # See also: https://github.com/cockroachdb/cockroach/issues/27123
423-
424- preparer = self .identifier_preparer
425- table_oid = self .get_table_oid (
426- connection , table_name , schema , info_cache = kw .get ("info_cache" )
427- )
428-
429- FK_SQL = """
430- SELECT r.conname,
431- pg_catalog.pg_get_constraintdef(r.oid, true) as condef,
432- n.nspname as conschema
433- FROM pg_catalog.pg_constraint r,
434- pg_namespace n,
435- pg_class c
436-
437- WHERE r.conrelid = :table AND
438- r.contype = 'f' AND
439- c.oid = confrelid AND
440- n.oid = c.relnamespace
441- ORDER BY 1
442- """
443- # http://www.postgresql.org/docs/9.0/static/sql-createtable.html
444- FK_REGEX = self ._fk_regex_pattern
445-
446- t = sql .text (FK_SQL ).columns (conname = sqltypes .Unicode , condef = sqltypes .Unicode )
447- c = connection .execute (t , {"table" : table_oid })
448- fkeys = []
449- for conname , condef , conschema in c .fetchall ():
450- m = re .search (FK_REGEX , condef ).groups ()
451-
452- (
453- constrained_columns ,
454- referred_schema ,
455- referred_table ,
456- referred_columns ,
457- _ ,
458- match ,
459- _ ,
460- ondelete ,
461- _ ,
462- onupdate ,
463- deferrable ,
464- _ ,
465- initially ,
466- ) = m
467-
468- if deferrable is not None :
469- deferrable = True if deferrable == "DEFERRABLE" else False
470- constrained_columns = [
471- preparer ._unquote_identifier (x ) for x in re .split (r"\s*,\s*" , constrained_columns )
472- ]
473-
474- if postgresql_ignore_search_path :
475- # when ignoring search path, we use the actual schema
476- # provided it isn't the "default" schema
477- if conschema != self .default_schema_name :
478- referred_schema = conschema
479- else :
480- referred_schema = schema
481- elif referred_schema :
482- # referred_schema is the schema that we regexp'ed from
483- # pg_get_constraintdef(). If the schema is in the search
484- # path, pg_get_constraintdef() will give us None.
485- referred_schema = preparer ._unquote_identifier (referred_schema )
486- elif schema is not None and schema == conschema :
487- # If the actual schema matches the schema of the table
488- # we're reflecting, then we will use that.
489- referred_schema = schema
490-
491- referred_table = preparer ._unquote_identifier (referred_table )
492- referred_columns = [
493- preparer ._unquote_identifier (x ) for x in re .split (r"\s*,\s" , referred_columns )
494- ]
495- fkey_d = {
496- "name" : conname ,
497- "constrained_columns" : constrained_columns ,
498- "referred_schema" : referred_schema ,
499- "referred_table" : referred_table ,
500- "referred_columns" : referred_columns ,
501- "options" : {
502- "onupdate" : onupdate ,
503- "ondelete" : ondelete ,
504- "deferrable" : deferrable ,
505- "initially" : initially ,
506- "match" : match ,
507- },
508- }
509- fkeys .append (fkey_d )
510- return fkeys
511-
512368 def get_pk_constraint (self , conn , table_name , schema = None , ** kw ):
513369 if self ._is_v21plus :
514370 return super ().get_pk_constraint (conn , table_name , schema , ** kw )
0 commit comments