From f6198d9abf453182f4b111e0579a7a4ef1614e79 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 12 Aug 2013 17:50:37 -0400 Subject: - A large refactoring of the ``sqlalchemy.sql`` package has reorganized the import structure of many core modules. ``sqlalchemy.schema`` and ``sqlalchemy.types`` remain in the top-level package, but are now just lists of names that pull from within ``sqlalchemy.sql``. Their implementations are now broken out among ``sqlalchemy.sql.type_api``, ``sqlalchemy.sql.sqltypes``, ``sqlalchemy.sql.schema`` and ``sqlalchemy.sql.ddl``, the last of which was moved from ``sqlalchemy.engine``. ``sqlalchemy.sql.expression`` is also a namespace now which pulls implementations mostly from ``sqlalchemy.sql.elements``, ``sqlalchemy.sql.selectable``, and ``sqlalchemy.sql.dml``. Most of the "factory" functions used to create SQL expression objects have been moved to classmethods or constructors, which are exposed in ``sqlalchemy.sql.expression`` using a programmatic system. Care has been taken such that all the original import namespaces remain intact and there should be no impact on any existing applications. The rationale here was to break out these very large modules into smaller ones, provide more manageable lists of function names, to greatly reduce "import cycles" and clarify the up-front importing of names, and to remove the need for redundant functions and documentation throughout the expression package. --- lib/sqlalchemy/engine/reflection.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 50b3f774c..29ede9579 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -25,9 +25,9 @@ methods such as get_table_names, get_columns, etc. """ from .. import exc, sql -from .. import schema as sa_schema +from ..sql import schema as sa_schema from .. import util -from ..types import TypeEngine +from ..sql.type_api import TypeEngine from ..util import deprecated from ..util import topological from .. import inspection -- cgit v1.2.1 From 031ef0807838842a827135dbace760da7aec215e Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 27 Aug 2013 20:43:22 -0400 Subject: - A rework to the way that "quoted" identifiers are handled, in that instead of relying upon various ``quote=True`` flags being passed around, these flags are converted into rich string objects with quoting information included at the point at which they are passed to common schema constructs like :class:`.Table`, :class:`.Column`, etc. This solves the issue of various methods that don't correctly honor the "quote" flag such as :meth:`.Engine.has_table` and related methods. The :class:`.quoted_name` object is a string subclass that can also be used explicitly if needed; the object will hold onto the quoting preferences passed and will also bypass the "name normalization" performed by dialects that standardize on uppercase symbols, such as Oracle, Firebird and DB2. The upshot is that the "uppercase" backends can now work with force-quoted names, such as lowercase-quoted names and new reserved words. [ticket:2812] --- lib/sqlalchemy/engine/reflection.py | 49 ++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 29ede9579..340af1abb 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -169,7 +169,7 @@ class Inspector(object): database's default schema is used, else the named schema is searched. If the database does not support named schemas, behavior is undefined if ``schema`` is not - passed as ``None``. + passed as ``None``. For special quoting, use :class:`.quoted_name`. :param order_by: Optional, may be the string "foreign_key" to sort the result on foreign key dependencies. @@ -206,6 +206,13 @@ class Inspector(object): This currently includes some options that apply to MySQL tables. + :param table_name: string name of the table. For special quoting, + use :class:`.quoted_name`. + + :param schema: string schema name; if omitted, uses the default schema + of the database connection. For special quoting, + use :class:`.quoted_name`. + """ if hasattr(self.dialect, 'get_table_options'): return self.dialect.get_table_options( @@ -217,6 +224,8 @@ class Inspector(object): """Return all view names in `schema`. :param schema: Optional, retrieve names from a non-default schema. + For special quoting, use :class:`.quoted_name`. + """ return self.dialect.get_view_names(self.bind, schema, @@ -226,6 +235,8 @@ class Inspector(object): """Return definition for `view_name`. :param schema: Optional, retrieve names from a non-default schema. + For special quoting, use :class:`.quoted_name`. + """ return self.dialect.get_view_definition( @@ -251,6 +262,14 @@ class Inspector(object): attrs dict containing optional column attributes + + :param table_name: string name of the table. For special quoting, + use :class:`.quoted_name`. + + :param schema: string schema name; if omitted, uses the default schema + of the database connection. For special quoting, + use :class:`.quoted_name`. + """ col_defs = self.dialect.get_columns(self.bind, table_name, schema, @@ -288,6 +307,13 @@ class Inspector(object): name optional name of the primary key constraint. + :param table_name: string name of the table. For special quoting, + use :class:`.quoted_name`. + + :param schema: string schema name; if omitted, uses the default schema + of the database connection. For special quoting, + use :class:`.quoted_name`. + """ return self.dialect.get_pk_constraint(self.bind, table_name, schema, info_cache=self.info_cache, @@ -315,6 +341,13 @@ class Inspector(object): name optional name of the foreign key constraint. + :param table_name: string name of the table. For special quoting, + use :class:`.quoted_name`. + + :param schema: string schema name; if omitted, uses the default schema + of the database connection. For special quoting, + use :class:`.quoted_name`. + """ return self.dialect.get_foreign_keys(self.bind, table_name, schema, @@ -336,6 +369,13 @@ class Inspector(object): unique boolean + :param table_name: string name of the table. For special quoting, + use :class:`.quoted_name`. + + :param schema: string schema name; if omitted, uses the default schema + of the database connection. For special quoting, + use :class:`.quoted_name`. + """ return self.dialect.get_indexes(self.bind, table_name, @@ -354,6 +394,13 @@ class Inspector(object): column_names list of column names in order + :param table_name: string name of the table. For special quoting, + use :class:`.quoted_name`. + + :param schema: string schema name; if omitted, uses the default schema + of the database connection. For special quoting, + use :class:`.quoted_name`. + .. versionadded:: 0.9.0 """ -- cgit v1.2.1 From fe66951f5de6a2b201dc3ecc2261f4f8b8888e9f Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 28 Aug 2013 17:25:44 -0400 Subject: Fixed bug where using the ``column_reflect`` event to change the ``.key`` of the incoming :class:`.Column` would prevent primary key constraints, indexes, and foreign key constraints from being correctly reflected. Also in 0.8.3. [ticket:2811] --- lib/sqlalchemy/engine/reflection.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 340af1abb..28494dc7d 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -433,7 +433,8 @@ class Inspector(object): # table attributes we might need. reflection_options = dict( - (k, table.kwargs.get(k)) for k in dialect.reflection_options if k in table.kwargs) + (k, table.kwargs.get(k)) + for k in dialect.reflection_options if k in table.kwargs) schema = table.schema table_name = table.name @@ -458,8 +459,12 @@ class Inspector(object): # columns found_table = False + cols_by_orig_name = {} + for col_d in self.get_columns(table_name, schema, **tblkw): found_table = True + orig_name = col_d['name'] + table.dispatch.column_reflect(self, table, col_d) name = col_d['name'] @@ -497,7 +502,9 @@ class Inspector(object): sequence.increment = seq['increment'] colargs.append(sequence) - col = sa_schema.Column(name, coltype, *colargs, **col_kw) + cols_by_orig_name[orig_name] = col = \ + sa_schema.Column(name, coltype, *colargs, **col_kw) + table.append_column(col) if not found_table: @@ -507,9 +514,9 @@ class Inspector(object): pk_cons = self.get_pk_constraint(table_name, schema, **tblkw) if pk_cons: pk_cols = [ - table.c[pk] + cols_by_orig_name[pk] for pk in pk_cons['constrained_columns'] - if pk in table.c and pk not in exclude_columns + if pk in cols_by_orig_name and pk not in exclude_columns ] pk_cols += [ pk @@ -527,7 +534,11 @@ class Inspector(object): fkeys = self.get_foreign_keys(table_name, schema, **tblkw) for fkey_d in fkeys: conname = fkey_d['name'] - constrained_columns = fkey_d['constrained_columns'] + constrained_columns = [ + cols_by_orig_name[c].key + if c in cols_by_orig_name else c + for c in fkey_d['constrained_columns'] + ] if exclude_columns and set(constrained_columns).intersection( exclude_columns): continue @@ -567,5 +578,5 @@ class Inspector(object): "Omitting %s KEY for (%s), key covers omitted columns." % (flavor, ', '.join(columns))) continue - sa_schema.Index(name, *[table.columns[c] for c in columns], + sa_schema.Index(name, *[cols_by_orig_name[c] for c in columns], **dict(unique=unique)) -- cgit v1.2.1 From 97168dbf69f8aa21de2e764a4a4993215cb9b726 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 28 Aug 2013 17:31:40 -0400 Subject: plus some more adjustments for mysql, or in general if an Index refers to in-python only cols --- lib/sqlalchemy/engine/reflection.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 28494dc7d..a9ccf5539 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -534,6 +534,8 @@ class Inspector(object): fkeys = self.get_foreign_keys(table_name, schema, **tblkw) for fkey_d in fkeys: conname = fkey_d['name'] + # look for columns by orig name in cols_by_orig_name, + # but support columns that are in-Python only as fallback constrained_columns = [ cols_by_orig_name[c].key if c in cols_by_orig_name else c @@ -578,5 +580,11 @@ class Inspector(object): "Omitting %s KEY for (%s), key covers omitted columns." % (flavor, ', '.join(columns))) continue - sa_schema.Index(name, *[cols_by_orig_name[c] for c in columns], + # look for columns by orig name in cols_by_orig_name, + # but support columns that are in-Python only as fallback + sa_schema.Index(name, *[ + cols_by_orig_name[c] if c in cols_by_orig_name + else table.c[c] + for c in columns + ], **dict(unique=unique)) -- cgit v1.2.1 From 52cfa74e094c32910fa1076375f1ae0c9795d45d Mon Sep 17 00:00:00 2001 From: ijl Date: Sun, 13 Oct 2013 17:13:28 -0400 Subject: #2183: Metadata.reflect() foreign keys include options when the dialect exposes it --- lib/sqlalchemy/engine/reflection.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index a9ccf5539..461f5eb23 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -564,9 +564,14 @@ class Inspector(object): ) for column in referred_columns: refspec.append(".".join([referred_table, column])) + if 'options' in fkey_d: + options = fkey_d['options'] + else: + options = {} table.append_constraint( sa_schema.ForeignKeyConstraint(constrained_columns, refspec, - conname, link_to_name=True)) + conname, link_to_name=True, + **options)) # Indexes indexes = self.get_indexes(table_name, schema) for index_d in indexes: -- cgit v1.2.1 From 1a6dd8b393991cb0cdba044d1c560c08ca426f89 Mon Sep 17 00:00:00 2001 From: Vraj Mohan Date: Thu, 14 Nov 2013 15:59:06 -0500 Subject: Fix cross references --- lib/sqlalchemy/engine/reflection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 461f5eb23..1f219e30c 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -161,7 +161,7 @@ class Inspector(object): """Return all table names in referred to within a particular schema. The names are expected to be real tables only, not views. - Views are instead returned using the :meth:`.get_view_names` + Views are instead returned using the :meth:`.Inspector.get_view_names` method. -- cgit v1.2.1 From 59ca4633acd42d90dc01aef9a40373ee98080481 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 17 Nov 2013 13:45:23 -0500 Subject: - remove informix dialect, moved out to https://bitbucket.org/zzzeek/sqlalchemy_informixdb - remove informix, maxdb, access symbols from tests etc. --- lib/sqlalchemy/engine/reflection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 1f219e30c..4a884453b 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -493,7 +493,7 @@ class Inspector(object): ) if 'sequence' in col_d: - # TODO: mssql, maxdb and sybase are using this. + # TODO: mssql and sybase are using this. seq = col_d['sequence'] sequence = sa_schema.Sequence(seq['name'], 1, 1) if 'start' in seq: -- cgit v1.2.1 From bddf55fef6d62b180042f367eb0ad73166d5bf00 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 3 Dec 2013 15:01:34 -0500 Subject: - reflection of unique constraints backported to 0.8.4 [ticket:1443] --- lib/sqlalchemy/engine/reflection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 4a884453b..4380ee32e 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -401,7 +401,7 @@ class Inspector(object): of the database connection. For special quoting, use :class:`.quoted_name`. - .. versionadded:: 0.9.0 + .. versionadded:: 0.8.4 """ -- cgit v1.2.1 From f89d4d216bd7605c920b7b8a10ecde6bfea2238c Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 5 Jan 2014 16:57:05 -0500 Subject: - happy new year --- lib/sqlalchemy/engine/reflection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 4380ee32e..badec84ea 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -1,5 +1,5 @@ # engine/reflection.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php -- cgit v1.2.1 From 1af8e2491dcbed723d2cdafd44fd37f1a6908e91 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 18 Jan 2014 19:26:56 -0500 Subject: - implement kwarg validation and type system for dialect-specific arguments; [ticket:2866] - add dialect specific kwarg functionality to ForeignKeyConstraint, ForeignKey --- lib/sqlalchemy/engine/reflection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index badec84ea..93b66bf0c 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -442,7 +442,7 @@ class Inspector(object): # apply table options tbl_opts = self.get_table_options(table_name, schema, **table.kwargs) if tbl_opts: - table.kwargs.update(tbl_opts) + table._validate_dialect_kwargs(tbl_opts) # table.kwargs will need to be passed to each reflection method. Make # sure keywords are strings. -- cgit v1.2.1 From 8e1a4fdced253a58af309c93c24a8a492b646bb7 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 19 Jan 2014 00:34:37 -0500 Subject: - some test fixes - clean up some shenanigans in reflection --- lib/sqlalchemy/engine/reflection.py | 49 +++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 26 deletions(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 93b66bf0c..d82aac7fd 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -431,37 +431,36 @@ class Inspector(object): """ dialect = self.bind.dialect - # table attributes we might need. - reflection_options = dict( - (k, table.kwargs.get(k)) - for k in dialect.reflection_options if k in table.kwargs) - schema = table.schema table_name = table.name - # apply table options - tbl_opts = self.get_table_options(table_name, schema, **table.kwargs) + # get table-level arguments that are specifically + # intended for reflection, e.g. oracle_resolve_synonyms. + # these are unconditionally passed to related Table + # objects + reflection_options = dict( + (k, table.dialect_kwargs.get(k)) + for k in dialect.reflection_options + if k in table.dialect_kwargs + ) + + # reflect table options, like mysql_engine + tbl_opts = self.get_table_options(table_name, schema, **table.dialect_kwargs) if tbl_opts: + # add additional kwargs to the Table if the dialect + # returned them table._validate_dialect_kwargs(tbl_opts) - # table.kwargs will need to be passed to each reflection method. Make - # sure keywords are strings. - tblkw = table.kwargs.copy() - for (k, v) in list(tblkw.items()): - del tblkw[k] - tblkw[str(k)] = v - if util.py2k: if isinstance(schema, str): schema = schema.decode(dialect.encoding) if isinstance(table_name, str): table_name = table_name.decode(dialect.encoding) - # columns found_table = False cols_by_orig_name = {} - for col_d in self.get_columns(table_name, schema, **tblkw): + for col_d in self.get_columns(table_name, schema, **table.dialect_kwargs): found_table = True orig_name = col_d['name'] @@ -474,12 +473,12 @@ class Inspector(object): continue coltype = col_d['type'] - col_kw = { - 'nullable': col_d['nullable'], - } - for k in ('autoincrement', 'quote', 'info', 'key'): - if k in col_d: - col_kw[k] = col_d[k] + + col_kw = dict( + (k, col_d[k]) + for k in ['nullable', 'autoincrement', 'quote', 'info', 'key'] + if k in col_d + ) colargs = [] if col_d.get('default') is not None: @@ -510,8 +509,7 @@ class Inspector(object): if not found_table: raise exc.NoSuchTableError(table.name) - # Primary keys - pk_cons = self.get_pk_constraint(table_name, schema, **tblkw) + pk_cons = self.get_pk_constraint(table_name, schema, **table.dialect_kwargs) if pk_cons: pk_cols = [ cols_by_orig_name[pk] @@ -530,8 +528,7 @@ class Inspector(object): table.append_constraint(primary_key_constraint) - # Foreign keys - fkeys = self.get_foreign_keys(table_name, schema, **tblkw) + fkeys = self.get_foreign_keys(table_name, schema, **table.dialect_kwargs) for fkey_d in fkeys: conname = fkey_d['name'] # look for columns by orig name in cols_by_orig_name, -- cgit v1.2.1 From 49f1807f8f2acea5494fa77d217dce813a933147 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 20 Jan 2014 17:55:01 -0500 Subject: - simplify the mechanics of PrimaryKeyConstraint with regards to reflection; reflection now updates the PKC in place. - support the use case of the empty PrimaryKeyConstraint in order to specify constraint options; the columns marked as primary_key=True will now be gathered into the columns collection, rather than being ignored. [ticket:2910] - add validation such that column specification should only take place in the PrimaryKeyConstraint directly, or by using primary_key=True flags; if both are present, they have to match exactly, otherwise the condition is assumed to be ambiguous, and a warning is emitted; the old behavior of using the PKC columns only is maintained. --- lib/sqlalchemy/engine/reflection.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index d82aac7fd..9e6cf61dc 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -504,6 +504,8 @@ class Inspector(object): cols_by_orig_name[orig_name] = col = \ sa_schema.Column(name, coltype, *colargs, **col_kw) + if col.key in table.primary_key: + col.primary_key = True table.append_column(col) if not found_table: @@ -516,17 +518,20 @@ class Inspector(object): for pk in pk_cons['constrained_columns'] if pk in cols_by_orig_name and pk not in exclude_columns ] - pk_cols += [ - pk - for pk in table.primary_key - if pk.key in exclude_columns - ] - primary_key_constraint = sa_schema.PrimaryKeyConstraint( - name=pk_cons.get('name'), - *pk_cols - ) - table.append_constraint(primary_key_constraint) + # update pk constraint name + table.primary_key.name = pk_cons.get('name') + + # set the primary key flag on new columns. + # note any existing PK cols on the table also have their + # flag still set. + for col in pk_cols: + col.primary_key = True + + # tell the PKConstraint to re-initialize + # it's column collection + table.primary_key._reload() + fkeys = self.get_foreign_keys(table_name, schema, **table.dialect_kwargs) for fkey_d in fkeys: -- cgit v1.2.1 From 417aeaf1453c67130fb8f1a2bb21c38e6795ce25 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 20 Jan 2014 18:14:02 -0500 Subject: - further refine this so that the ordering of columns is maintained as sent to the primary key constraint; existing tests in the PG dialect confirm this. --- lib/sqlalchemy/engine/reflection.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'lib/sqlalchemy/engine/reflection.py') diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 9e6cf61dc..45f100518 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -522,16 +522,9 @@ class Inspector(object): # update pk constraint name table.primary_key.name = pk_cons.get('name') - # set the primary key flag on new columns. - # note any existing PK cols on the table also have their - # flag still set. - for col in pk_cols: - col.primary_key = True - # tell the PKConstraint to re-initialize # it's column collection - table.primary_key._reload() - + table.primary_key._reload(pk_cols) fkeys = self.get_foreign_keys(table_name, schema, **table.dialect_kwargs) for fkey_d in fkeys: -- cgit v1.2.1