From 70c9bc03395fc372e1451bd1bc47c737bd0a44d4 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 2 Oct 2019 11:20:58 -0400 Subject: 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 --- lib/sqlalchemy/engine/default.py | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'lib/sqlalchemy/engine/default.py') 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 -- cgit v1.2.1