diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-10-20 16:59:56 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-10-20 16:59:56 -0400 |
| commit | 4663ec98b226a7d495846f0d89c646110705bb30 (patch) | |
| tree | f9eaab0e77a2aced7fce73014661cb8f757060e7 /lib/sqlalchemy/testing/suite | |
| parent | 0b0764b62ba87bdec41d0fc86618f3779cb4e3f0 (diff) | |
| download | sqlalchemy-4663ec98b226a7d495846f0d89c646110705bb30.tar.gz | |
- The typing system now handles the task of rendering "literal bind" values,
e.g. values that are normally bound parameters but due to context must
be rendered as strings, typically within DDL constructs such as
CHECK constraints and indexes (note that "literal bind" values
become used by DDL as of :ticket:`2742`). A new method
:meth:`.TypeEngine.literal_processor` serves as the base, and
:meth:`.TypeDecorator.process_literal_param` is added to allow wrapping
of a native literal rendering method. [ticket:2838]
- enhance _get_colparams so that we can send flags like literal_binds into
INSERT statements
- add support in PG for inspecting standard_conforming_strings
- add a new series of roundtrip tests based on INSERT of literal plus SELECT
for basic literal rendering in dialect suite
Diffstat (limited to 'lib/sqlalchemy/testing/suite')
| -rw-r--r-- | lib/sqlalchemy/testing/suite/test_types.py | 101 |
1 files changed, 94 insertions, 7 deletions
diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py index 0de462eb7..5523523aa 100644 --- a/lib/sqlalchemy/testing/suite/test_types.py +++ b/lib/sqlalchemy/testing/suite/test_types.py @@ -5,7 +5,7 @@ from ..assertions import eq_ from ..config import requirements from sqlalchemy import Integer, Unicode, UnicodeText, select from sqlalchemy import Date, DateTime, Time, MetaData, String, \ - Text, Numeric, Float + Text, Numeric, Float, literal from ..schema import Table, Column from ... import testing import decimal @@ -13,7 +13,31 @@ import datetime from ...util import u from ... import util -class _UnicodeFixture(object): + +class _LiteralRoundTripFixture(object): + @testing.provide_metadata + def _literal_round_trip(self, type_, input_, output): + """test literal rendering """ + + # for literal, we test the literal render in an INSERT + # into a typed column. we can then SELECT it back as it's + # official type; ideally we'd be able to use CAST here + # but MySQL in particular can't CAST fully + t = Table('t', self.metadata, Column('x', type_)) + t.create() + + for value in input_: + ins = t.insert().values(x=literal(value)).compile( + dialect=testing.db.dialect, + compile_kwargs=dict(literal_binds=True) + ) + testing.db.execute(ins) + + for row in t.select().execute(): + assert row[0] in output + + +class _UnicodeFixture(_LiteralRoundTripFixture): __requires__ = 'unicode_data', data = u("Alors vous imaginez ma surprise, au lever du jour, "\ @@ -87,6 +111,9 @@ class _UnicodeFixture(object): ).first() eq_(row, (u(''),)) + def test_literal(self): + self._literal_round_trip(self.datatype, [self.data], [self.data]) + class UnicodeVarcharTest(_UnicodeFixture, fixtures.TablesTest): __requires__ = 'unicode_data', @@ -107,7 +134,7 @@ class UnicodeTextTest(_UnicodeFixture, fixtures.TablesTest): def test_empty_strings_text(self): self._test_empty_strings() -class TextTest(fixtures.TablesTest): +class TextTest(_LiteralRoundTripFixture, fixtures.TablesTest): @classmethod def define_tables(cls, metadata): Table('text_table', metadata, @@ -140,8 +167,18 @@ class TextTest(fixtures.TablesTest): ).first() eq_(row, ('',)) + def test_literal(self): + self._literal_round_trip(Text, ["some text"], ["some text"]) + + def test_literal_quoting(self): + data = '''some 'text' hey "hi there" that's text''' + self._literal_round_trip(Text, [data], [data]) + + def test_literal_backslashes(self): + data = r'backslash one \ backslash two \\ end' + self._literal_round_trip(Text, [data], [data]) -class StringTest(fixtures.TestBase): +class StringTest(_LiteralRoundTripFixture, fixtures.TestBase): @requirements.unbounded_varchar def test_nolength_string(self): metadata = MetaData() @@ -152,8 +189,19 @@ class StringTest(fixtures.TestBase): foo.create(config.db) foo.drop(config.db) + def test_literal(self): + self._literal_round_trip(String(40), ["some text"], ["some text"]) -class _DateFixture(object): + def test_literal_quoting(self): + data = '''some 'text' hey "hi there" that's text''' + self._literal_round_trip(String(40), [data], [data]) + + def test_literal_backslashes(self): + data = r'backslash one \ backslash two \\ end' + self._literal_round_trip(Text, [data], [data]) + + +class _DateFixture(_LiteralRoundTripFixture): compare = None @classmethod @@ -198,6 +246,12 @@ class _DateFixture(object): ).first() eq_(row, (None,)) + @testing.requires.datetime_literals + def test_literal(self): + compare = self.compare or self.data + self._literal_round_trip(self.datatype, [self.data], [compare]) + + class DateTimeTest(_DateFixture, fixtures.TablesTest): __requires__ = 'datetime', @@ -247,7 +301,12 @@ class DateHistoricTest(_DateFixture, fixtures.TablesTest): datatype = Date data = datetime.date(1727, 4, 1) -class NumericTest(fixtures.TestBase): + +class IntegerTest(_LiteralRoundTripFixture, fixtures.TestBase): + def test_literal(self): + self._literal_round_trip(Integer, [5], [5]) + +class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase): @testing.emits_warning(r".*does \*not\* support Decimal objects natively") @testing.provide_metadata @@ -269,6 +328,30 @@ class NumericTest(fixtures.TestBase): [str(x) for x in output], ) + + @testing.emits_warning(r".*does \*not\* support Decimal objects natively") + def test_render_literal_numeric(self): + self._literal_round_trip( + Numeric(precision=8, scale=4), + [15.7563, decimal.Decimal("15.7563")], + [decimal.Decimal("15.7563")], + ) + + @testing.emits_warning(r".*does \*not\* support Decimal objects natively") + def test_render_literal_numeric_asfloat(self): + self._literal_round_trip( + Numeric(precision=8, scale=4, asdecimal=False), + [15.7563, decimal.Decimal("15.7563")], + [15.7563], + ) + + def test_render_literal_float(self): + self._literal_round_trip( + Float(4), + [15.7563, decimal.Decimal("15.7563")], + [15.7563], + ) + def test_numeric_as_decimal(self): self._do_test( Numeric(precision=8, scale=4), @@ -291,6 +374,7 @@ class NumericTest(fixtures.TestBase): [decimal.Decimal("15.7563"), None], ) + def test_float_as_float(self): self._do_test( Float(precision=8), @@ -299,6 +383,7 @@ class NumericTest(fixtures.TestBase): filter_=lambda n: n is not None and round(n, 5) or None ) + @testing.requires.precision_numerics_general def test_precision_decimal(self): numbers = set([ @@ -313,6 +398,7 @@ class NumericTest(fixtures.TestBase): numbers, ) + @testing.requires.precision_numerics_enotation_large def test_enotation_decimal(self): """test exceedingly small decimals. @@ -342,6 +428,7 @@ class NumericTest(fixtures.TestBase): numbers ) + @testing.requires.precision_numerics_enotation_large def test_enotation_decimal_large(self): """test exceedingly large decimals. @@ -389,7 +476,7 @@ class NumericTest(fixtures.TestBase): __all__ = ('UnicodeVarcharTest', 'UnicodeTextTest', 'DateTest', 'DateTimeTest', 'TextTest', - 'NumericTest', + 'NumericTest', 'IntegerTest', 'DateTimeHistoricTest', 'DateTimeCoercedToDateTimeTest', 'TimeMicrosecondsTest', 'TimeTest', 'DateTimeMicrosecondsTest', 'DateHistoricTest', 'StringTest') |
