From: Mike Bayer Date: Tue, 15 Jul 2014 01:11:16 +0000 (-0400) Subject: - allow the compilation rule that gets the formatted name X-Git-Tag: rel_1_0_0b1~315 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dbc8bbfba3591d2ea704673d90e95014765d0f10;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - allow the compilation rule that gets the formatted name to again have the chance to veto rendering, as the naming convention can make the decision that the name is "none" or not now. --- diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 99b74b3c84..da810e9feb 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -2537,8 +2537,9 @@ class DDLCompiler(Compiled): def visit_check_constraint(self, constraint): text = "" if constraint.name is not None: - text += "CONSTRAINT %s " % \ - self.preparer.format_constraint(constraint) + formatted_name = self.preparer.format_constraint(constraint) + if formatted_name is not None: + text += "CONSTRAINT %s " % formatted_name text += "CHECK (%s)" % self.sql_compiler.process(constraint.sqltext, include_table=False, literal_binds=True) @@ -2548,8 +2549,9 @@ class DDLCompiler(Compiled): def visit_column_check_constraint(self, constraint): text = "" if constraint.name is not None: - text += "CONSTRAINT %s " % \ - self.preparer.format_constraint(constraint) + formatted_name = self.preparer.format_constraint(constraint) + if formatted_name is not None: + text += "CONSTRAINT %s " % formatted_name text += "CHECK (%s)" % constraint.sqltext text += self.define_constraint_deferrability(constraint) return text @@ -2559,8 +2561,9 @@ class DDLCompiler(Compiled): return '' text = "" if constraint.name is not None: - text += "CONSTRAINT %s " % \ - self.preparer.format_constraint(constraint) + formatted_name = self.preparer.format_constraint(constraint) + if formatted_name is not None: + text += "CONSTRAINT %s " % formatted_name text += "PRIMARY KEY " text += "(%s)" % ', '.join(self.preparer.quote(c.name) for c in constraint) @@ -2571,14 +2574,15 @@ class DDLCompiler(Compiled): preparer = self.dialect.identifier_preparer text = "" if constraint.name is not None: - text += "CONSTRAINT %s " % \ - preparer.format_constraint(constraint) + formatted_name = self.preparer.format_constraint(constraint) + if formatted_name is not None: + text += "CONSTRAINT %s " % formatted_name remote_table = list(constraint._elements.values())[0].column.table text += "FOREIGN KEY(%s) REFERENCES %s (%s)" % ( ', '.join(preparer.quote(f.parent.name) for f in constraint._elements.values()), self.define_constraint_remote_table( - constraint, remote_table, preparer), + constraint, remote_table, preparer), ', '.join(preparer.quote(f.column.name) for f in constraint._elements.values()) ) @@ -2597,11 +2601,11 @@ class DDLCompiler(Compiled): return '' text = "" if constraint.name is not None: - text += "CONSTRAINT %s " % \ - self.preparer.format_constraint(constraint) + formatted_name = self.preparer.format_constraint(constraint) + text += "CONSTRAINT %s " % formatted_name text += "UNIQUE (%s)" % ( - ', '.join(self.preparer.quote(c.name) - for c in constraint)) + ', '.join(self.preparer.quote(c.name) + for c in constraint)) text += self.define_constraint_deferrability(constraint) return text @@ -2909,6 +2913,8 @@ class IdentifierPreparer(object): constraint, constraint.table) if name: return self.quote(name) + elif isinstance(constraint.name, elements._defer_none_name): + return None return self.quote(constraint.name) def format_table(self, table, use_schema=True, name=None): diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index d273d98816..1447787cef 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -3209,7 +3209,7 @@ class _defer_name(_truncated_label): """ def __new__(cls, value): if value is None: - return _defer_none_name('_unnamed_') + return _NONE_NAME else: return super(_defer_name, cls).__new__(cls, value) @@ -3217,6 +3217,8 @@ class _defer_name(_truncated_label): class _defer_none_name(_defer_name): """indicate a 'deferred' name that was ultimately the value None.""" +_NONE_NAME = _defer_none_name("_unnamed_") + # for backwards compatibility in case # someone is re-implementing the # _truncated_identifier() sequence in a custom diff --git a/lib/sqlalchemy/sql/naming.py b/lib/sqlalchemy/sql/naming.py index bb838c5423..eb017eb259 100644 --- a/lib/sqlalchemy/sql/naming.py +++ b/lib/sqlalchemy/sql/naming.py @@ -155,6 +155,8 @@ def _constraint_name_for_table(const, table): convention % ConventionDict(const, table, metadata.naming_convention) ) + elif isinstance(convention, _defer_none_name): + return None @event.listens_for(Constraint, "after_parent_attach") @event.listens_for(Index, "after_parent_attach") diff --git a/test/sql/test_metadata.py b/test/sql/test_metadata.py index 7aa2059dcf..ee7d372d79 100644 --- a/test/sql/test_metadata.py +++ b/test/sql/test_metadata.py @@ -3013,6 +3013,25 @@ class NamingConventionTest(fixtures.TestBase, AssertsCompiledSQL): schema.CreateTable(u1).compile ) + def test_schematype_no_ck_name_boolean_no_name(self): + m1 = MetaData() # no naming convention + + u1 = Table( + 'user', m1, + Column('x', Boolean()) + ) + # constraint gets special _defer_none_name + eq_( + [c for c in u1.constraints + if isinstance(c, CheckConstraint)][0].name, "_unnamed_" + ) + + self.assert_compile( + schema.CreateTable(u1), + "CREATE TABLE user (x BOOLEAN, CHECK (x IN (0, 1)))" + ) + + def test_ck_constraint_redundant_event(self): u1 = self._fixture(naming_convention={ "ck": "ck_%(table_name)s_%(constraint_name)s"})