update sqlalchemy

This commit is contained in:
j 2016-02-22 16:43:36 +05:30
commit 3b436646a2
362 changed files with 37720 additions and 11021 deletions

View file

@ -1,4 +1,5 @@
from sqlalchemy.testing.suite.test_dialect import *
from sqlalchemy.testing.suite.test_ddl import *
from sqlalchemy.testing.suite.test_insert import *
from sqlalchemy.testing.suite.test_sequence import *

View file

@ -0,0 +1,41 @@
from .. import fixtures, config
from ..config import requirements
from sqlalchemy import exc
from sqlalchemy import Integer, String
from .. import assert_raises
from ..schema import Table, Column
class ExceptionTest(fixtures.TablesTest):
"""Test basic exception wrapping.
DBAPIs vary a lot in exception behavior so to actually anticipate
specific exceptions from real round trips, we need to be conservative.
"""
run_deletes = 'each'
__backend__ = True
@classmethod
def define_tables(cls, metadata):
Table('manual_pk', metadata,
Column('id', Integer, primary_key=True, autoincrement=False),
Column('data', String(50))
)
@requirements.duplicate_key_raises_integrity_error
def test_integrity_error(self):
with config.db.begin() as conn:
conn.execute(
self.tables.manual_pk.insert(),
{'id': 1, 'data': 'd1'}
)
assert_raises(
exc.IntegrityError,
conn.execute,
self.tables.manual_pk.insert(),
{'id': 1, 'data': 'd1'}
)

View file

@ -4,7 +4,7 @@ from .. import exclusions
from ..assertions import eq_
from .. import engines
from sqlalchemy import Integer, String, select, util
from sqlalchemy import Integer, String, select, literal_column, literal
from ..schema import Table, Column
@ -90,6 +90,13 @@ class InsertBehaviorTest(fixtures.TablesTest):
Column('id', Integer, primary_key=True, autoincrement=False),
Column('data', String(50))
)
Table('includes_defaults', metadata,
Column('id', Integer, primary_key=True,
test_needs_autoincrement=True),
Column('data', String(50)),
Column('x', Integer, default=5),
Column('y', Integer,
default=literal_column("2", type_=Integer) + literal(2)))
def test_autoclose_on_insert(self):
if requirements.returning.enabled:
@ -102,7 +109,8 @@ class InsertBehaviorTest(fixtures.TablesTest):
self.tables.autoinc_pk.insert(),
data="some data"
)
assert r.closed
assert r._soft_closed
assert not r.closed
assert r.is_insert
assert not r.returns_rows
@ -112,7 +120,8 @@ class InsertBehaviorTest(fixtures.TablesTest):
self.tables.autoinc_pk.insert(),
data="some data"
)
assert r.closed
assert r._soft_closed
assert not r.closed
assert r.is_insert
assert not r.returns_rows
@ -121,7 +130,8 @@ class InsertBehaviorTest(fixtures.TablesTest):
r = config.db.execute(
self.tables.autoinc_pk.insert(),
)
assert r.closed
assert r._soft_closed
assert not r.closed
r = config.db.execute(
self.tables.autoinc_pk.select().
@ -158,6 +168,34 @@ class InsertBehaviorTest(fixtures.TablesTest):
("data3", ), ("data3", )]
)
@requirements.insert_from_select
def test_insert_from_select_with_defaults(self):
table = self.tables.includes_defaults
config.db.execute(
table.insert(),
[
dict(id=1, data="data1"),
dict(id=2, data="data2"),
dict(id=3, data="data3"),
]
)
config.db.execute(
table.insert(inline=True).
from_select(("id", "data",),
select([table.c.id + 5, table.c.data]).
where(table.c.data.in_(["data2", "data3"]))
),
)
eq_(
config.db.execute(
select([table]).order_by(table.c.data, table.c.id)
).fetchall(),
[(1, 'data1', 5, 4), (2, 'data2', 5, 4),
(7, 'data2', 5, 4), (3, 'data3', 5, 4), (8, 'data3', 5, 4)]
)
class ReturningTest(fixtures.TablesTest):
run_create_tables = 'each'

View file

@ -39,11 +39,20 @@ class ComponentReflectionTest(fixtures.TablesTest):
__backend__ = True
@classmethod
def setup_bind(cls):
if config.requirements.independent_connections.enabled:
from sqlalchemy import pool
return engines.testing_engine(
options=dict(poolclass=pool.StaticPool))
else:
return config.db
@classmethod
def define_tables(cls, metadata):
cls.define_reflected_tables(metadata, None)
if testing.requires.schemas.enabled:
cls.define_reflected_tables(metadata, "test_schema")
cls.define_reflected_tables(metadata, testing.config.test_schema)
@classmethod
def define_reflected_tables(cls, metadata, schema):
@ -95,6 +104,43 @@ class ComponentReflectionTest(fixtures.TablesTest):
cls.define_index(metadata, users)
if testing.requires.view_column_reflection.enabled:
cls.define_views(metadata, schema)
if not schema and testing.requires.temp_table_reflection.enabled:
cls.define_temp_tables(metadata)
@classmethod
def define_temp_tables(cls, metadata):
# cheat a bit, we should fix this with some dialect-level
# temp table fixture
if testing.against("oracle"):
kw = {
'prefixes': ["GLOBAL TEMPORARY"],
'oracle_on_commit': 'PRESERVE ROWS'
}
else:
kw = {
'prefixes': ["TEMPORARY"],
}
user_tmp = Table(
"user_tmp", metadata,
Column("id", sa.INT, primary_key=True),
Column('name', sa.VARCHAR(50)),
Column('foo', sa.INT),
sa.UniqueConstraint('name', name='user_tmp_uq'),
sa.Index("user_tmp_ix", "foo"),
**kw
)
if testing.requires.view_reflection.enabled and \
testing.requires.temporary_views.enabled:
event.listen(
user_tmp, "after_create",
DDL("create temporary view user_tmp_v as "
"select * from user_tmp")
)
event.listen(
user_tmp, "before_drop",
DDL("drop view user_tmp_v")
)
@classmethod
def define_index(cls, metadata, users):
@ -126,7 +172,7 @@ class ComponentReflectionTest(fixtures.TablesTest):
def test_get_schema_names(self):
insp = inspect(testing.db)
self.assert_('test_schema' in insp.get_schema_names())
self.assert_(testing.config.test_schema in insp.get_schema_names())
@testing.requires.schema_reflection
def test_dialect_initialize(self):
@ -147,6 +193,7 @@ class ComponentReflectionTest(fixtures.TablesTest):
users, addresses, dingalings = self.tables.users, \
self.tables.email_addresses, self.tables.dingalings
insp = inspect(meta.bind)
if table_type == 'view':
table_names = insp.get_view_names(schema)
table_names.sort()
@ -162,6 +209,20 @@ class ComponentReflectionTest(fixtures.TablesTest):
answer = ['dingalings', 'email_addresses', 'users']
eq_(sorted(table_names), answer)
@testing.requires.temp_table_names
def test_get_temp_table_names(self):
insp = inspect(self.bind)
temp_table_names = insp.get_temp_table_names()
eq_(sorted(temp_table_names), ['user_tmp'])
@testing.requires.view_reflection
@testing.requires.temp_table_names
@testing.requires.temporary_views
def test_get_temp_view_names(self):
insp = inspect(self.bind)
temp_table_names = insp.get_temp_view_names()
eq_(sorted(temp_table_names), ['user_tmp_v'])
@testing.requires.table_reflection
def test_get_table_names(self):
self._test_get_table_names()
@ -174,7 +235,7 @@ class ComponentReflectionTest(fixtures.TablesTest):
@testing.requires.table_reflection
@testing.requires.schemas
def test_get_table_names_with_schema(self):
self._test_get_table_names('test_schema')
self._test_get_table_names(testing.config.test_schema)
@testing.requires.view_column_reflection
def test_get_view_names(self):
@ -183,7 +244,8 @@ class ComponentReflectionTest(fixtures.TablesTest):
@testing.requires.view_column_reflection
@testing.requires.schemas
def test_get_view_names_with_schema(self):
self._test_get_table_names('test_schema', table_type='view')
self._test_get_table_names(
testing.config.test_schema, table_type='view')
@testing.requires.table_reflection
@testing.requires.view_column_reflection
@ -291,7 +353,29 @@ class ComponentReflectionTest(fixtures.TablesTest):
@testing.requires.table_reflection
@testing.requires.schemas
def test_get_columns_with_schema(self):
self._test_get_columns(schema='test_schema')
self._test_get_columns(schema=testing.config.test_schema)
@testing.requires.temp_table_reflection
def test_get_temp_table_columns(self):
meta = MetaData(self.bind)
user_tmp = self.tables.user_tmp
insp = inspect(meta.bind)
cols = insp.get_columns('user_tmp')
self.assert_(len(cols) > 0, len(cols))
for i, col in enumerate(user_tmp.columns):
eq_(col.name, cols[i]['name'])
@testing.requires.temp_table_reflection
@testing.requires.view_column_reflection
@testing.requires.temporary_views
def test_get_temp_view_columns(self):
insp = inspect(self.bind)
cols = insp.get_columns('user_tmp_v')
eq_(
[col['name'] for col in cols],
['id', 'name', 'foo']
)
@testing.requires.view_column_reflection
def test_get_view_columns(self):
@ -300,7 +384,8 @@ class ComponentReflectionTest(fixtures.TablesTest):
@testing.requires.view_column_reflection
@testing.requires.schemas
def test_get_view_columns_with_schema(self):
self._test_get_columns(schema='test_schema', table_type='view')
self._test_get_columns(
schema=testing.config.test_schema, table_type='view')
@testing.provide_metadata
def _test_get_pk_constraint(self, schema=None):
@ -327,7 +412,7 @@ class ComponentReflectionTest(fixtures.TablesTest):
@testing.requires.primary_key_constraint_reflection
@testing.requires.schemas
def test_get_pk_constraint_with_schema(self):
self._test_get_pk_constraint(schema='test_schema')
self._test_get_pk_constraint(schema=testing.config.test_schema)
@testing.requires.table_reflection
@testing.provide_metadata
@ -385,7 +470,7 @@ class ComponentReflectionTest(fixtures.TablesTest):
@testing.requires.foreign_key_constraint_reflection
@testing.requires.schemas
def test_get_foreign_keys_with_schema(self):
self._test_get_foreign_keys(schema='test_schema')
self._test_get_foreign_keys(schema=testing.config.test_schema)
@testing.provide_metadata
def _test_get_indexes(self, schema=None):
@ -418,25 +503,57 @@ class ComponentReflectionTest(fixtures.TablesTest):
@testing.requires.index_reflection
@testing.requires.schemas
def test_get_indexes_with_schema(self):
self._test_get_indexes(schema='test_schema')
self._test_get_indexes(schema=testing.config.test_schema)
@testing.requires.unique_constraint_reflection
def test_get_unique_constraints(self):
self._test_get_unique_constraints()
@testing.requires.temp_table_reflection
@testing.requires.unique_constraint_reflection
def test_get_temp_table_unique_constraints(self):
insp = inspect(self.bind)
reflected = insp.get_unique_constraints('user_tmp')
for refl in reflected:
# Different dialects handle duplicate index and constraints
# differently, so ignore this flag
refl.pop('duplicates_index', None)
eq_(reflected, [{'column_names': ['name'], 'name': 'user_tmp_uq'}])
@testing.requires.temp_table_reflection
def test_get_temp_table_indexes(self):
insp = inspect(self.bind)
indexes = insp.get_indexes('user_tmp')
for ind in indexes:
ind.pop('dialect_options', None)
eq_(
# TODO: we need to add better filtering for indexes/uq constraints
# that are doubled up
[idx for idx in indexes if idx['name'] == 'user_tmp_ix'],
[{'unique': False, 'column_names': ['foo'], 'name': 'user_tmp_ix'}]
)
@testing.requires.unique_constraint_reflection
@testing.requires.schemas
def test_get_unique_constraints_with_schema(self):
self._test_get_unique_constraints(schema='test_schema')
self._test_get_unique_constraints(schema=testing.config.test_schema)
@testing.provide_metadata
def _test_get_unique_constraints(self, schema=None):
# SQLite dialect needs to parse the names of the constraints
# separately from what it gets from PRAGMA index_list(), and
# then matches them up. so same set of column_names in two
# constraints will confuse it. Perhaps we should no longer
# bother with index_list() here since we have the whole
# CREATE TABLE?
uniques = sorted(
[
{'name': 'unique_a', 'column_names': ['a']},
{'name': 'unique_a_b_c', 'column_names': ['a', 'b', 'c']},
{'name': 'unique_c_a_b', 'column_names': ['c', 'a', 'b']},
{'name': 'unique_asc_key', 'column_names': ['asc', 'key']},
{'name': 'i.have.dots', 'column_names': ['b']},
{'name': 'i have spaces', 'column_names': ['c']},
],
key=operator.itemgetter('name')
)
@ -464,6 +581,9 @@ class ComponentReflectionTest(fixtures.TablesTest):
)
for orig, refl in zip(uniques, reflected):
# Different dialects handle duplicate index and constraints
# differently, so ignore this flag
refl.pop('duplicates_index', None)
eq_(orig, refl)
@testing.provide_metadata
@ -486,7 +606,7 @@ class ComponentReflectionTest(fixtures.TablesTest):
@testing.requires.view_reflection
@testing.requires.schemas
def test_get_view_definition_with_schema(self):
self._test_get_view_definition(schema='test_schema')
self._test_get_view_definition(schema=testing.config.test_schema)
@testing.only_on("postgresql", "PG specific feature")
@testing.provide_metadata
@ -503,7 +623,7 @@ class ComponentReflectionTest(fixtures.TablesTest):
@testing.requires.schemas
def test_get_table_oid_with_schema(self):
self._test_get_table_oid('users', schema='test_schema')
self._test_get_table_oid('users', schema=testing.config.test_schema)
@testing.requires.table_reflection
@testing.provide_metadata

View file

@ -2,13 +2,13 @@ from .. import fixtures, config
from ..assertions import eq_
from sqlalchemy import util
from sqlalchemy import Integer, String, select, func
from sqlalchemy import Integer, String, select, func, bindparam
from sqlalchemy import testing
from ..schema import Table, Column
class OrderByLabelTest(fixtures.TablesTest):
"""Test the dialect sends appropriate ORDER BY expressions when
labels are used.
@ -85,3 +85,108 @@ class OrderByLabelTest(fixtures.TablesTest):
select([lx]).order_by(lx.desc()),
[(7, ), (5, ), (3, )]
)
def test_group_by_composed(self):
table = self.tables.some_table
expr = (table.c.x + table.c.y).label('lx')
stmt = select([func.count(table.c.id), expr]).group_by(expr).order_by(expr)
self._assert_result(
stmt,
[(1, 3), (1, 5), (1, 7)]
)
class LimitOffsetTest(fixtures.TablesTest):
__backend__ = True
@classmethod
def define_tables(cls, metadata):
Table("some_table", metadata,
Column('id', Integer, primary_key=True),
Column('x', Integer),
Column('y', Integer))
@classmethod
def insert_data(cls):
config.db.execute(
cls.tables.some_table.insert(),
[
{"id": 1, "x": 1, "y": 2},
{"id": 2, "x": 2, "y": 3},
{"id": 3, "x": 3, "y": 4},
{"id": 4, "x": 4, "y": 5},
]
)
def _assert_result(self, select, result, params=()):
eq_(
config.db.execute(select, params).fetchall(),
result
)
def test_simple_limit(self):
table = self.tables.some_table
self._assert_result(
select([table]).order_by(table.c.id).limit(2),
[(1, 1, 2), (2, 2, 3)]
)
@testing.requires.offset
def test_simple_offset(self):
table = self.tables.some_table
self._assert_result(
select([table]).order_by(table.c.id).offset(2),
[(3, 3, 4), (4, 4, 5)]
)
@testing.requires.offset
def test_simple_limit_offset(self):
table = self.tables.some_table
self._assert_result(
select([table]).order_by(table.c.id).limit(2).offset(1),
[(2, 2, 3), (3, 3, 4)]
)
@testing.requires.offset
def test_limit_offset_nobinds(self):
"""test that 'literal binds' mode works - no bound params."""
table = self.tables.some_table
stmt = select([table]).order_by(table.c.id).limit(2).offset(1)
sql = stmt.compile(
dialect=config.db.dialect,
compile_kwargs={"literal_binds": True})
sql = str(sql)
self._assert_result(
sql,
[(2, 2, 3), (3, 3, 4)]
)
@testing.requires.bound_limit_offset
def test_bound_limit(self):
table = self.tables.some_table
self._assert_result(
select([table]).order_by(table.c.id).limit(bindparam('l')),
[(1, 1, 2), (2, 2, 3)],
params={"l": 2}
)
@testing.requires.bound_limit_offset
def test_bound_offset(self):
table = self.tables.some_table
self._assert_result(
select([table]).order_by(table.c.id).offset(bindparam('o')),
[(3, 3, 4), (4, 4, 5)],
params={"o": 2}
)
@testing.requires.bound_limit_offset
def test_bound_limit_offset(self):
table = self.tables.some_table
self._assert_result(
select([table]).order_by(table.c.id).
limit(bindparam("l")).offset(bindparam("o")),
[(2, 2, 3), (3, 3, 4)],
params={"l": 2, "o": 1}
)

View file

@ -86,11 +86,11 @@ class HasSequenceTest(fixtures.TestBase):
@testing.requires.schemas
def test_has_sequence_schema(self):
s1 = Sequence('user_id_seq', schema="test_schema")
s1 = Sequence('user_id_seq', schema=config.test_schema)
testing.db.execute(schema.CreateSequence(s1))
try:
eq_(testing.db.dialect.has_sequence(
testing.db, 'user_id_seq', schema="test_schema"), True)
testing.db, 'user_id_seq', schema=config.test_schema), True)
finally:
testing.db.execute(schema.DropSequence(s1))
@ -101,7 +101,7 @@ class HasSequenceTest(fixtures.TestBase):
@testing.requires.schemas
def test_has_sequence_schemas_neg(self):
eq_(testing.db.dialect.has_sequence(testing.db, 'user_id_seq',
schema="test_schema"),
schema=config.test_schema),
False)
@testing.requires.schemas
@ -110,14 +110,14 @@ class HasSequenceTest(fixtures.TestBase):
testing.db.execute(schema.CreateSequence(s1))
try:
eq_(testing.db.dialect.has_sequence(testing.db, 'user_id_seq',
schema="test_schema"),
schema=config.test_schema),
False)
finally:
testing.db.execute(schema.DropSequence(s1))
@testing.requires.schemas
def test_has_sequence_remote_not_in_default(self):
s1 = Sequence('user_id_seq', schema="test_schema")
s1 = Sequence('user_id_seq', schema=config.test_schema)
testing.db.execute(schema.CreateSequence(s1))
try:
eq_(testing.db.dialect.has_sequence(testing.db, 'user_id_seq'),