self.connection, table.name, schema=effective_schema
)
+ def _can_create_index(self, index):
+ effective_schema = self.connection.schema_for_object(index.table)
+ if effective_schema:
+ self.dialect.validate_identifier(effective_schema)
+ return not self.checkfirst or not self.dialect.has_index(
+ self.connection,
+ index.table.name,
+ index.name,
+ schema=effective_schema,
+ )
+
def _can_create_sequence(self, sequence):
effective_schema = self.connection.schema_for_object(sequence)
if hasattr(table, "indexes"):
for index in table.indexes:
- self.traverse_single(index)
+ self.traverse_single(index, create_ok=True)
if self.dialect.supports_comments and not self.dialect.inline_comments:
if table.comment is not None:
return
self.connection.execute(CreateSequence(sequence))
- def visit_index(self, index):
+ def visit_index(self, index, create_ok=False):
+ if not create_ok and not self._can_create_index(index):
+ return
self.connection.execute(CreateIndex(index))
self.connection, table.name, schema=effective_schema
)
+ def _can_drop_index(self, index):
+ effective_schema = self.connection.schema_for_object(index.table)
+ if effective_schema:
+ self.dialect.validate_identifier(effective_schema)
+ return not self.checkfirst or self.dialect.has_index(
+ self.connection,
+ index.table.name,
+ index.name,
+ schema=effective_schema,
+ )
+
def _can_drop_sequence(self, sequence):
effective_schema = self.connection.schema_for_object(sequence)
return self.dialect.supports_sequences and (
)
)
- def visit_index(self, index):
+ def visit_index(self, index, drop_ok=False):
+ if not drop_ok and not self._can_drop_index(index):
+ return
+
self.connection.execute(DropIndex(index))
def visit_table(self, table, drop_ok=False, _is_metadata_operation=False):
)
+class HasIndexTest(fixtures.TablesTest):
+ __backend__ = True
+
+ @classmethod
+ def define_tables(cls, metadata):
+ tt = Table(
+ "test_table",
+ metadata,
+ Column("id", Integer, primary_key=True),
+ Column("data", String(50)),
+ )
+ Index("my_idx", tt.c.data)
+
+ if testing.requires.schemas.enabled:
+ tt = Table(
+ "test_table",
+ metadata,
+ Column("id", Integer, primary_key=True),
+ Column("data", String(50)),
+ schema=config.test_schema,
+ )
+ Index("my_idx_s", tt.c.data)
+
+ def test_has_index(self):
+ with config.db.begin() as conn:
+ assert config.db.dialect.has_index(conn, "test_table", "my_idx")
+ assert not config.db.dialect.has_index(
+ conn, "test_table", "my_idx_s"
+ )
+ assert not config.db.dialect.has_index(
+ conn, "nonexistent_table", "my_idx"
+ )
+ assert not config.db.dialect.has_index(
+ conn, "test_table", "nonexistent_idx"
+ )
+
+ @testing.requires.schemas
+ def test_has_index_schema(self):
+ with config.db.begin() as conn:
+ assert config.db.dialect.has_index(
+ conn, "test_table", "my_idx_s", schema=config.test_schema
+ )
+ assert not config.db.dialect.has_index(
+ conn, "test_table", "my_idx", schema=config.test_schema
+ )
+ assert not config.db.dialect.has_index(
+ conn,
+ "nonexistent_table",
+ "my_idx_s",
+ schema=config.test_schema,
+ )
+ assert not config.db.dialect.has_index(
+ conn,
+ "test_table",
+ "nonexistent_idx_s",
+ schema=config.test_schema,
+ )
+
+
class ComponentReflectionTest(fixtures.TablesTest):
run_inserts = run_deletes = None
eq_(tablenames[1].upper(), tablenames[1].lower())
-__all__ = ("ComponentReflectionTest", "HasTableTest", "NormalizedNameTest")
+__all__ = (
+ "ComponentReflectionTest",
+ "HasTableTest",
+ "HasIndexTest",
+ "NormalizedNameTest",
+)
from sqlalchemy import Column
from sqlalchemy import ForeignKey
+from sqlalchemy import Index
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import schema
def has_item(connection, name, schema):
return item_exists(name)
+ def has_index(connection, tablename, idxname, schema):
+ return item_exists(idxname)
+
return Mock(
dialect=Mock(
supports_sequences=True,
has_table=Mock(side_effect=has_item),
has_sequence=Mock(side_effect=has_item),
+ has_index=Mock(side_effect=has_index),
supports_comments=True,
inline_comments=False,
)
t2 = Table("t2", m, Column("id", Integer, primary_key=True))
return m, t1, t2
+ def _table_index_fixture(self):
+ m = MetaData()
+ t1 = Table("t1", m, Column("x", Integer), Column("y", Integer))
+ i1 = Index("my_idx", t1.c.x, t1.c.y)
+ return m, t1, i1
+
def _table_seq_fixture(self):
m = MetaData()
self._assert_drop([t1, s1], generator, m)
+ def test_create_table_index_checkfirst(self):
+ """create table that doesn't exist should not require a check
+ on the index"""
+
+ m, t1, i1 = self._table_index_fixture()
+
+ def exists(name):
+ if name == "my_idx":
+ raise NotImplementedError()
+ else:
+ return False
+
+ generator = self._mock_create_fixture(True, [t1], item_exists=exists)
+ self._assert_create([t1, i1], generator, t1)
+
+ def test_create_table_exists_index_checkfirst(self):
+ """for the moment, if the table *does* exist, we are not checking
+ for the index. this can possibly be changed."""
+
+ m, t1, i1 = self._table_index_fixture()
+
+ def exists(name):
+ if name == "my_idx":
+ raise NotImplementedError()
+ else:
+ return True
+
+ generator = self._mock_create_fixture(True, [t1], item_exists=exists)
+ # nothing is created
+ self._assert_create([], generator, t1)
+
+ def test_drop_table_index_checkfirst(self):
+ m, t1, i1 = self._table_index_fixture()
+
+ def exists(name):
+ if name == "my_idx":
+ raise NotImplementedError()
+ else:
+ return True
+
+ generator = self._mock_drop_fixture(True, [t1], item_exists=exists)
+ self._assert_drop_tables([t1], generator, t1)
+
+ def test_create_index_checkfirst_exists(self):
+ m, t1, i1 = self._table_index_fixture()
+ generator = self._mock_create_fixture(
+ True, [i1], item_exists=lambda idx: True
+ )
+ self._assert_create_index([], generator, i1)
+
+ def test_create_index_checkfirst_doesnt_exist(self):
+ m, t1, i1 = self._table_index_fixture()
+ generator = self._mock_create_fixture(
+ True, [i1], item_exists=lambda idx: False
+ )
+ self._assert_create_index([i1], generator, i1)
+
+ def test_create_index_nocheck_exists(self):
+ m, t1, i1 = self._table_index_fixture()
+ generator = self._mock_create_fixture(
+ False, [i1], item_exists=lambda idx: True
+ )
+ self._assert_create_index([i1], generator, i1)
+
+ def test_create_index_nocheck_doesnt_exist(self):
+ m, t1, i1 = self._table_index_fixture()
+ generator = self._mock_create_fixture(
+ False, [i1], item_exists=lambda idx: False
+ )
+ self._assert_create_index([i1], generator, i1)
+
+ def test_drop_index_checkfirst_exists(self):
+ m, t1, i1 = self._table_index_fixture()
+ generator = self._mock_drop_fixture(
+ True, [i1], item_exists=lambda idx: True
+ )
+ self._assert_drop_index([i1], generator, i1)
+
+ def test_drop_index_checkfirst_doesnt_exist(self):
+ m, t1, i1 = self._table_index_fixture()
+ generator = self._mock_drop_fixture(
+ True, [i1], item_exists=lambda idx: False
+ )
+ self._assert_drop_index([], generator, i1)
+
+ def test_drop_index_nocheck_exists(self):
+ m, t1, i1 = self._table_index_fixture()
+ generator = self._mock_drop_fixture(
+ False, [i1], item_exists=lambda idx: True
+ )
+ self._assert_drop_index([i1], generator, i1)
+
+ def test_drop_index_nocheck_doesnt_exist(self):
+ m, t1, i1 = self._table_index_fixture()
+ generator = self._mock_drop_fixture(
+ False, [i1], item_exists=lambda idx: False
+ )
+ self._assert_drop_index([i1], generator, i1)
+
def test_create_collection_checkfirst(self):
m, t1, t2, t3, t4, t5 = self._table_fixture()
generator = self._mock_create_fixture(
def _assert_create(self, elements, generator, argument):
self._assert_ddl(
- (schema.CreateTable, schema.CreateSequence),
+ (schema.CreateTable, schema.CreateSequence, schema.CreateIndex),
elements,
generator,
argument,
argument,
)
+ def _assert_create_index(self, elements, generator, argument):
+ self._assert_ddl((schema.CreateIndex,), elements, generator, argument)
+
+ def _assert_drop_index(self, elements, generator, argument):
+ self._assert_ddl((schema.DropIndex,), elements, generator, argument)
+
def _assert_ddl(self, ddl_cls, elements, generator, argument):
generator.traverse_single(argument)
for call_ in generator.connection.execute.mock_calls: