From: Mike Bayer Date: Sun, 22 Jun 2008 17:44:35 +0000 (+0000) Subject: - The index name generated when you say "index=True" X-Git-Tag: rel_0_4_7~14 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bd708ad176f936a94551280795c735d59ad32bf4;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - The index name generated when you say "index=True" on a Column is truncated to the length appropriate for the dialect. Additionally, an Index with a too- long name cannot be explicitly dropped with Index.drop(), similar to [ticket:571]. [ticket:820] --- diff --git a/CHANGES b/CHANGES index 37741670c8..f5e50fbc0e 100644 --- a/CHANGES +++ b/CHANGES @@ -38,6 +38,13 @@ CHANGES looking for the name within the DB's catalog tables. [ticket:571] + - The index name generated when you say "index=True" + on a Column is truncated to the length appropriate + for the dialect. Additionally, an Index with a too- + long name cannot be explicitly dropped with + Index.drop(), similar to [ticket:571]. + [ticket:820] + - postgres - Repaired server_side_cursors to properly detect text() clauses. diff --git a/lib/sqlalchemy/databases/access.py b/lib/sqlalchemy/databases/access.py index 38dba17a5a..be6e58b2d7 100644 --- a/lib/sqlalchemy/databases/access.py +++ b/lib/sqlalchemy/databases/access.py @@ -408,7 +408,8 @@ class AccessSchemaGenerator(compiler.SchemaGenerator): class AccessSchemaDropper(compiler.SchemaDropper): def visit_index(self, index): - self.append("\nDROP INDEX [%s].[%s]" % (index.table.name, index.name)) + + self.append("\nDROP INDEX [%s].[%s]" % (index.table.name, self._validate_identifier(index.name, False))) self.execute() class AccessDefaultRunner(base.DefaultRunner): diff --git a/lib/sqlalchemy/databases/mssql.py b/lib/sqlalchemy/databases/mssql.py index ab5a968716..8b370650f6 100644 --- a/lib/sqlalchemy/databases/mssql.py +++ b/lib/sqlalchemy/databases/mssql.py @@ -1030,7 +1030,7 @@ class MSSQLSchemaDropper(compiler.SchemaDropper): def visit_index(self, index): self.append("\nDROP INDEX %s.%s" % ( self.preparer.quote_identifier(index.table.name), - self.preparer.quote_identifier(index.name) + self.preparer.quote(index, self._validate_identifier(index.name, False)) )) self.execute() diff --git a/lib/sqlalchemy/databases/mysql.py b/lib/sqlalchemy/databases/mysql.py index d91d9f08f8..3e718655ad 100644 --- a/lib/sqlalchemy/databases/mysql.py +++ b/lib/sqlalchemy/databases/mysql.py @@ -2064,7 +2064,7 @@ class MySQLSchemaGenerator(compiler.SchemaGenerator): class MySQLSchemaDropper(compiler.SchemaDropper): def visit_index(self, index): self.append("\nDROP INDEX %s ON %s" % - (self.preparer.format_index(index), + (self.preparer.quote(index, self._validate_identifier(index.name, False)), self.preparer.format_table(index.table))) self.execute() diff --git a/lib/sqlalchemy/databases/postgres.py b/lib/sqlalchemy/databases/postgres.py index 212daa06da..0ab6dd8b4d 100644 --- a/lib/sqlalchemy/databases/postgres.py +++ b/lib/sqlalchemy/databases/postgres.py @@ -747,7 +747,7 @@ class PGSchemaGenerator(compiler.SchemaGenerator): if index.unique: self.append("UNIQUE ") self.append("INDEX %s ON %s (%s)" \ - % (preparer.format_index(index), + % (preparer.quote(index, self._validate_identifier(index.name, True)), preparer.format_table(index.table), string.join([preparer.format_column(c) for c in index.columns], ', '))) whereclause = index.kwargs.get('postgres_where', None) diff --git a/lib/sqlalchemy/databases/sybase.py b/lib/sqlalchemy/databases/sybase.py index 2551e90c53..912cb47626 100644 --- a/lib/sqlalchemy/databases/sybase.py +++ b/lib/sqlalchemy/databases/sybase.py @@ -844,7 +844,7 @@ class SybaseSQLSchemaDropper(compiler.SchemaDropper): def visit_index(self, index): self.append("\nDROP INDEX %s.%s" % ( self.preparer.quote_identifier(index.table.name), - self.preparer.quote_identifier(index.name) + self.preparer.quote(index, self._validate_identifier(index.name, False)) )) self.execute() diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 439710cee5..408d24c278 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -741,6 +741,19 @@ class DDLBase(engine.SchemaIterator): findalterables.traverse(c) return alterables + def _validate_identifier(self, ident, truncate): + if truncate: + if len(ident) > self.dialect.max_identifier_length: + counter = getattr(self, 'counter', 0) + self.counter = counter + 1 + return ident[0:self.dialect.max_identifier_length - 6] + "_" + hex(self.counter)[2:] + else: + return ident + else: + self.dialect.validate_identifier(ident) + return ident + + class SchemaGenerator(DDLBase): def __init__(self, dialect, connection, checkfirst=False, tables=None, **kwargs): super(SchemaGenerator, self).__init__(connection, **kwargs) @@ -900,7 +913,7 @@ class SchemaGenerator(DDLBase): if index.unique: self.append("UNIQUE ") self.append("INDEX %s ON %s (%s)" \ - % (preparer.format_index(index), + % (preparer.quote(index, self._validate_identifier(index.name, True)), preparer.format_table(index.table), string.join([preparer.quote(c, c.name) for c in index.columns], ', '))) self.execute() @@ -929,7 +942,7 @@ class SchemaDropper(DDLBase): return not self.checkfirst or self.dialect.has_table(self.connection, table.name, schema=table.schema) def visit_index(self, index): - self.append("\nDROP INDEX " + self.preparer.format_index(index)) + self.append("\nDROP INDEX " + self.preparer.quote(index, self._validate_identifier(index.name, False))) self.execute() def drop_foreignkey(self, constraint): @@ -1050,9 +1063,6 @@ class IdentifierPreparer(object): def format_constraint(self, constraint): return self.quote(constraint, constraint.name) - def format_index(self, index): - return self.quote(index, index.name) - def format_table(self, table, use_schema=True, name=None): """Prepare a quoted table and schema name.""" diff --git a/test/sql/constraints.py b/test/sql/constraints.py index 2908e07da9..a40c5644df 100644 --- a/test/sql/constraints.py +++ b/test/sql/constraints.py @@ -201,7 +201,25 @@ class ConstraintTest(TestBase, AssertsExecutionResults): winner='sweden') ss = events.select().execute().fetchall() + def test_too_long_idx_name(self): + dialect = testing.db.dialect.__class__() + dialect.max_identifier_length = 20 + schemagen = dialect.schemagenerator(dialect, None) + schemagen.execute = lambda : None + + t1 = Table("sometable", MetaData(), Column("foo", Integer)) + schemagen.visit_index(Index("this_name_is_too_long_for_what_were_doing", t1.c.foo)) + self.assertEquals(schemagen.buffer.getvalue(), "CREATE INDEX this_name_is_t_1 ON sometable (foo)") + schemagen.buffer.truncate(0) + schemagen.visit_index(Index("this_other_name_is_too_long_for_what_were_doing", t1.c.foo)) + self.assertEquals(schemagen.buffer.getvalue(), "CREATE INDEX this_other_nam_2 ON sometable (foo)") + + schemadrop = dialect.schemadropper(dialect, None) + schemadrop.execute = lambda: None + self.assertRaises(exceptions.IdentifierError, schemadrop.visit_index, Index("this_name_is_too_long_for_what_were_doing", t1.c.foo)) + + class ConstraintCompilationTest(TestBase, AssertsExecutionResults): class accum(object): def __init__(self):