diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-10-02 11:20:58 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-10-02 14:54:12 -0400 |
| commit | 70c9bc03395fc372e1451bd1bc47c737bd0a44d4 (patch) | |
| tree | 9f39fb8caeb79f77fef875167b9b28f515ebb468 /lib/sqlalchemy/engine | |
| parent | 60e64a2c35e7e5a0125c5fefbf0caf531eeb2eda (diff) | |
| download | sqlalchemy-70c9bc03395fc372e1451bd1bc47c737bd0a44d4.tar.gz | |
Add max_identifier_length parameter; warn for Oracle
Added new :func:`.create_engine` parameter
:paramref:`.create_engine.max_identifier_length`. This overrides the
dialect-coded "max identifier length" in order to accommodate for databases
that have recently changed this length and the SQLAlchemy dialect has
not yet been adjusted to detect for that version. This parameter interacts
with the existing :paramref:`.create_engine.label_length` parameter in that
it establishes the maximum (and default) value for anonymously generated
labels.
The Oracle dialect now emits a warning if Oracle version 12.2 or greater is
used, and the :paramref:`.create_engine.max_identifier_length` parameter is
not set. The version in this specific case defaults to that of the
"compatibility" version set in the Oracle server configuration, not the
actual server version. In version 1.4, the default max_identifier_length
for 12.2 or greater will move to 128 characters. In order to maintain
forwards compatibility, applications should set
:paramref:`.create_engine.max_identifier_length` to 30 in order to maintain
the same length behavior, or to 128 in order to test the upcoming behavior.
This length determines among other things how generated constraint names
are truncated for statements like ``CREATE CONSTRAINT`` and ``DROP
CONSTRAINT``, which means a the new length may produce a name-mismatch
against a name that was generated with the old length, impacting database
migrations.
Fixes: #4857
Change-Id: Ib62efb00c6180c375869029b57353d90385d7950
Diffstat (limited to 'lib/sqlalchemy/engine')
| -rw-r--r-- | lib/sqlalchemy/engine/create.py | 25 | ||||
| -rw-r--r-- | lib/sqlalchemy/engine/default.py | 38 |
2 files changed, 57 insertions, 6 deletions
diff --git a/lib/sqlalchemy/engine/create.py b/lib/sqlalchemy/engine/create.py index 43378f24e..ed3d452e0 100644 --- a/lib/sqlalchemy/engine/create.py +++ b/lib/sqlalchemy/engine/create.py @@ -260,7 +260,15 @@ def create_engine(url, **kwargs): the size of dynamically generated column labels to that many characters. If less than 6, labels are generated as "_(counter)". If ``None``, the value of - ``dialect.max_identifier_length`` is used instead. + ``dialect.max_identifier_length``, which may be affected via the + :paramref:`.create_engine.max_identifier_length` parameter, + is used instead. The value of :paramref:`.create_engine.label_length` + may not be larger than that of + :paramref:`.create_engine.max_identfier_length`. + + .. seealso:: + + :paramref:`.create_engine.max_identifier_length` :param listeners: A list of one or more :class:`~sqlalchemy.interfaces.PoolListener` objects which will @@ -271,6 +279,21 @@ def create_engine(url, **kwargs): "sqlalchemy.engine" logger. Defaults to a hexstring of the object's id. + :param max_identifier_length: integer; override the max_identifier_length + determined by the dialect. if ``None`` or zero, has no effect. This + is the database's configured maximum number of characters that may be + used in a SQL identifier such as a table name, column name, or label + name. All dialects determine this value automatically, however in the + case of a new database version for which this value has changed but + SQLAlchemy's dialect has not been adjusted, the value may be passed + here. + + .. versionadded:: 1.3.9 + + .. seealso:: + + :paramref:`.create_engine.label_length` + :param max_overflow=10: the number of connections to allow in connection pool "overflow", that is connections that can be opened above and beyond the pool_size setting, which defaults diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index eac593125..8d9962c59 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -109,6 +109,7 @@ class DefaultDialect(interfaces.Dialect): # length at which to truncate # any identifier. max_identifier_length = 9999 + _user_defined_max_identifier_length = None # length at which to truncate # the name of an index. @@ -204,6 +205,7 @@ class DefaultDialect(interfaces.Dialect): case_sensitive=True, supports_native_boolean=None, empty_in_strategy="static", + max_identifier_length=None, label_length=None, **kwargs ): @@ -248,11 +250,10 @@ class DefaultDialect(interfaces.Dialect): "'dynamic', or 'dynamic_warn'" ) - if label_length and label_length > self.max_identifier_length: - raise exc.ArgumentError( - "Label length of %d is greater than this dialect's" - " maximum identifier length of %d" - % (label_length, self.max_identifier_length) + self._user_defined_max_identifier_length = max_identifier_length + if self._user_defined_max_identifier_length: + self.max_identifier_length = ( + self._user_defined_max_identifier_length ) self.label_length = label_length @@ -312,6 +313,21 @@ class DefaultDialect(interfaces.Dialect): ): self._description_decoder = self.description_encoding = None + if not self._user_defined_max_identifier_length: + max_ident_length = self._check_max_identifier_length(connection) + if max_ident_length: + self.max_identifier_length = max_ident_length + + if ( + self.label_length + and self.label_length > self.max_identifier_length + ): + raise exc.ArgumentError( + "Label length of %d is greater than this dialect's" + " maximum identifier length of %d" + % (self.label_length, self.max_identifier_length) + ) + def on_connect(self): """return a callable which sets up a newly created DBAPI connection. @@ -326,6 +342,18 @@ class DefaultDialect(interfaces.Dialect): """ return None + def _check_max_identifier_length(self, connection): + """Perform a connection / server version specific check to determine + the max_identifier_length. + + If the dialect's class level max_identifier_length should be used, + can return None. + + .. versionadded:: 1.3.9 + + """ + return None + def _check_unicode_returns(self, connection, additional_tests=None): if util.py2k and not self.supports_unicode_statements: cast_to = util.binary_type |
