Files
sqlalchemy/test/dialect/mysql/test_query.py
T
Mike Bayer 7024745a14 - build out a new base type for Array, as well as new any/all operators
- any/all work for Array as well as subqueries, accepted by MySQL
- Postgresql ARRAY now subclasses Array
- fixes #3516
2015-08-25 18:24:46 -04:00

233 lines
7.6 KiB
Python

# coding: utf-8
from sqlalchemy.testing import eq_, is_
from sqlalchemy import *
from sqlalchemy.testing import fixtures, AssertsCompiledSQL
from sqlalchemy import testing
class IdiosyncrasyTest(fixtures.TestBase, AssertsCompiledSQL):
__only_on__ = 'mysql'
__backend__ = True
@testing.emits_warning()
def test_is_boolean_symbols_despite_no_native(self):
is_(
testing.db.scalar(select([cast(true().is_(true()), Boolean)])),
True
)
is_(
testing.db.scalar(select([cast(true().isnot(true()), Boolean)])),
False
)
is_(
testing.db.scalar(select([cast(false().is_(false()), Boolean)])),
True
)
class MatchTest(fixtures.TestBase, AssertsCompiledSQL):
__only_on__ = 'mysql'
__backend__ = True
@classmethod
def setup_class(cls):
global metadata, cattable, matchtable
metadata = MetaData(testing.db)
cattable = Table('cattable', metadata,
Column('id', Integer, primary_key=True),
Column('description', String(50)),
mysql_engine='MyISAM'
)
matchtable = Table('matchtable', metadata,
Column('id', Integer, primary_key=True),
Column('title', String(200)),
Column('category_id', Integer, ForeignKey('cattable.id')),
mysql_engine='MyISAM'
)
metadata.create_all()
cattable.insert().execute([
{'id': 1, 'description': 'Python'},
{'id': 2, 'description': 'Ruby'},
])
matchtable.insert().execute([
{'id': 1,
'title': 'Agile Web Development with Ruby On Rails',
'category_id': 2},
{'id': 2,
'title': 'Dive Into Python',
'category_id': 1},
{'id': 3,
'title': "Programming Matz's Ruby",
'category_id': 2},
{'id': 4,
'title': 'The Definitive Guide to Django',
'category_id': 1},
{'id': 5,
'title': 'Python in a Nutshell',
'category_id': 1}
])
@classmethod
def teardown_class(cls):
metadata.drop_all()
@testing.fails_on('mysql+mysqlconnector', 'uses pyformat')
def test_expression_format(self):
format = testing.db.dialect.paramstyle == 'format' and '%s' or '?'
self.assert_compile(
matchtable.c.title.match('somstr'),
"MATCH (matchtable.title) AGAINST (%s IN BOOLEAN MODE)" % format)
@testing.fails_on('mysql+mysqldb', 'uses format')
@testing.fails_on('mysql+pymysql', 'uses format')
@testing.fails_on('mysql+cymysql', 'uses format')
@testing.fails_on('mysql+oursql', 'uses format')
@testing.fails_on('mysql+pyodbc', 'uses format')
@testing.fails_on('mysql+zxjdbc', 'uses format')
def test_expression_pyformat(self):
format = '%(title_1)s'
self.assert_compile(
matchtable.c.title.match('somstr'),
"MATCH (matchtable.title) AGAINST (%s IN BOOLEAN MODE)" % format)
def test_simple_match(self):
results = (matchtable.select().
where(matchtable.c.title.match('python')).
order_by(matchtable.c.id).
execute().
fetchall())
eq_([2, 5], [r.id for r in results])
def test_not_match(self):
results = (matchtable.select().
where(~matchtable.c.title.match('python')).
order_by(matchtable.c.id).
execute().
fetchall())
eq_([1, 3, 4], [r.id for r in results])
def test_simple_match_with_apostrophe(self):
results = (matchtable.select().
where(matchtable.c.title.match("Matz's")).
execute().
fetchall())
eq_([3], [r.id for r in results])
def test_return_value(self):
# test [ticket:3263]
result = testing.db.execute(
select([
matchtable.c.title.match('Agile Ruby Programming').label('ruby'),
matchtable.c.title.match('Dive Python').label('python'),
matchtable.c.title
]).order_by(matchtable.c.id)
).fetchall()
eq_(
result,
[
(2.0, 0.0, 'Agile Web Development with Ruby On Rails'),
(0.0, 2.0, 'Dive Into Python'),
(2.0, 0.0, "Programming Matz's Ruby"),
(0.0, 0.0, 'The Definitive Guide to Django'),
(0.0, 1.0, 'Python in a Nutshell')
]
)
def test_or_match(self):
results1 = (matchtable.select().
where(or_(matchtable.c.title.match('nutshell'),
matchtable.c.title.match('ruby'))).
order_by(matchtable.c.id).
execute().
fetchall())
eq_([1, 3, 5], [r.id for r in results1])
results2 = (matchtable.select().
where(matchtable.c.title.match('nutshell ruby')).
order_by(matchtable.c.id).
execute().
fetchall())
eq_([1, 3, 5], [r.id for r in results2])
def test_and_match(self):
results1 = (matchtable.select().
where(and_(matchtable.c.title.match('python'),
matchtable.c.title.match('nutshell'))).
execute().
fetchall())
eq_([5], [r.id for r in results1])
results2 = (matchtable.select().
where(matchtable.c.title.match('+python +nutshell')).
execute().
fetchall())
eq_([5], [r.id for r in results2])
def test_match_across_joins(self):
results = (matchtable.select().
where(and_(cattable.c.id==matchtable.c.category_id,
or_(cattable.c.description.match('Ruby'),
matchtable.c.title.match('nutshell')))).
order_by(matchtable.c.id).
execute().
fetchall())
eq_([1, 3, 5], [r.id for r in results])
class AnyAllTest(fixtures.TablesTest, AssertsCompiledSQL):
__only_on__ = 'mysql'
__backend__ = True
@classmethod
def define_tables(cls, metadata):
Table(
'stuff', metadata,
Column('id', Integer, primary_key=True),
Column('value', Integer)
)
@classmethod
def insert_data(cls):
stuff = cls.tables.stuff
testing.db.execute(
stuff.insert(),
[
{'id': 1, 'value': 1},
{'id': 2, 'value': 2},
{'id': 3, 'value': 3},
{'id': 4, 'value': 4},
{'id': 5, 'value': 5},
]
)
def test_any_w_comparator(self):
stuff = self.tables.stuff
stmt = select([stuff.c.id]).where(
stuff.c.value > any_(select([stuff.c.value])))
eq_(
testing.db.execute(stmt).fetchall(),
[(2,), (3,), (4,), (5,)]
)
def test_all_w_comparator(self):
stuff = self.tables.stuff
stmt = select([stuff.c.id]).where(
stuff.c.value >= all_(select([stuff.c.value])))
eq_(
testing.db.execute(stmt).fetchall(),
[(5,)]
)
def test_any_literal(self):
stuff = self.tables.stuff
stmt = select([4 == any_(select([stuff.c.value]))])
is_(
testing.db.execute(stmt).scalar(), True
)