From b5e4562702cb9a218092ae4f56b573049edd21fd Mon Sep 17 00:00:00 2001 From: HemangChothani Date: Mon, 8 Mar 2021 16:59:33 +0530 Subject: [PATCH 1/5] fix: integer complaince tests --- test/test_suite.py | 72 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/test/test_suite.py b/test/test_suite.py index 490d2d36..89e93d90 100644 --- a/test/test_suite.py +++ b/test/test_suite.py @@ -14,14 +14,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -from sqlalchemy.testing import config +from sqlalchemy.testing import config, db from sqlalchemy.testing import eq_ from sqlalchemy.testing import provide_metadata from sqlalchemy.testing.schema import Column from sqlalchemy.testing.schema import Table from sqlalchemy import literal_column -from sqlalchemy import select +from sqlalchemy import literal, select, util from sqlalchemy import String +from sqlalchemy.types import Integer from sqlalchemy.testing.suite.test_update_delete import * # noqa: F401, F403 from sqlalchemy.testing.suite.test_dialect import * # noqa: F401, F403 @@ -30,6 +31,8 @@ EscapingTest as _EscapingTest, ) +from sqlalchemy.testing.suite.test_types import IntegerTest as _IntegerTest + class EscapingTest(_EscapingTest): @provide_metadata @@ -68,3 +71,68 @@ def test_percent_sign_round_trip(self): ), "some %% other value", ) + + +class IntegerTest(_IntegerTest): + @provide_metadata + def _round_trip(self, datatype, data): + metadata = self.metadata + int_table = Table( + "integer_table", + metadata, + Column("id", Integer, primary_key=True, test_needs_autoincrement=True), + Column("integer_data", Integer), + ) + + metadata.create_all(config.db) + + config.db.execute(int_table.insert(), {"id": 1, "integer_data": data}) + + row = config.db.execute(select([int_table.c.integer_data])).first() + + eq_(row, (data,)) + + if util.py3k: + assert isinstance(row[0], int) + else: + assert isinstance(row[0], (long, int)) # noqa + + config.db.execute(int_table.delete()) + + @provide_metadata + def _literal_round_trip(self, type_, input_, output, filter_=None): + """test literal rendering """ + + # for literal, we test the literal render in an INSERT + # into a typed column. we can then SELECT it back as its + # official type; ideally we'd be able to use CAST here + # but MySQL in particular can't CAST fully + t = Table("int_t", self.metadata, Column("x", type_)) + t.drop(checkfirst=True) + t.create() + + with db.connect() as conn: + for value in input_: + ins = ( + t.insert() + .values(x=literal(value)) + .compile( + dialect=db.dialect, compile_kwargs=dict(literal_binds=True), + ) + ) + conn.execute(ins) + + if self.supports_whereclause: + stmt = t.select().where(t.c.x == literal(value)) + else: + stmt = t.select() + + stmt = stmt.compile( + dialect=db.dialect, compile_kwargs=dict(literal_binds=True), + ) + for row in conn.execute(stmt): + value = row[0] + if filter_ is not None: + value = filter_(value) + assert value in output + conn.execute(t.delete()) From 04da5fd3b3c490b89226c3bbe8f61d3f8f215ba5 Mon Sep 17 00:00:00 2001 From: HemangChothani Date: Wed, 10 Mar 2021 20:18:39 +0530 Subject: [PATCH 2/5] fix: add docstring for tests --- test/test_suite.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/test/test_suite.py b/test/test_suite.py index 89e93d90..c299035c 100644 --- a/test/test_suite.py +++ b/test/test_suite.py @@ -76,6 +76,17 @@ def test_percent_sign_round_trip(self): class IntegerTest(_IntegerTest): @provide_metadata def _round_trip(self, datatype, data): + """This is the helper method for integer class tests which creates table and + perform insert operation. + Cloud Spanner supports tables with empty primary key, but + only single one row can be inserted into such a table - + following insertions will fail with `400 id must not be NULL in table date_table`. + Overriding the tests and add a manual primary key value to avoid the same failures + and delete the from the table at the end. + + Cloud Spanner doesn't support BIGINT data type, so column data type converted + in to the Integer. + """ metadata = self.metadata int_table = Table( "integer_table", @@ -101,7 +112,13 @@ def _round_trip(self, datatype, data): @provide_metadata def _literal_round_trip(self, type_, input_, output, filter_=None): - """test literal rendering """ + """Sql alchemy is not able cleanup data and drop the table correctly, + table was already exists after related tests finished, so it doesn't + create a new table and when started tests for other data type following + insertions will fail with `400 Duplicate name in schema: t. + Overriding the tests to create a new table for test and drop table manually + before it creates a new table to avoid the same failures. + """ # for literal, we test the literal render in an INSERT # into a typed column. we can then SELECT it back as its @@ -135,4 +152,3 @@ def _literal_round_trip(self, type_, input_, output, filter_=None): if filter_ is not None: value = filter_(value) assert value in output - conn.execute(t.delete()) From 79241a4bd5cf3fa3d365cc0f34951de8e66ff7cb Mon Sep 17 00:00:00 2001 From: HemangChothani Date: Thu, 11 Mar 2021 18:56:47 +0530 Subject: [PATCH 3/5] fix: change docstring to be consistent --- test/test_suite.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/test_suite.py b/test/test_suite.py index e82d4ff8..2676690f 100644 --- a/test/test_suite.py +++ b/test/test_suite.py @@ -199,7 +199,10 @@ def test_select_exists_false(self, connection): class IntegerTest(_IntegerTest): @provide_metadata def _round_trip(self, datatype, data): - """This is the helper method for integer class tests which creates table and + """ + SPANNER OVERRIDE: + + This is the helper method for integer class tests which creates table and perform insert operation. Cloud Spanner supports tables with empty primary key, but only single one row can be inserted into such a table - @@ -235,7 +238,10 @@ def _round_trip(self, datatype, data): @provide_metadata def _literal_round_trip(self, type_, input_, output, filter_=None): - """Sql alchemy is not able cleanup data and drop the table correctly, + """ + SPANNER OVERRIDE: + + Sql alchemy is not able cleanup data and drop the table correctly, table was already exists after related tests finished, so it doesn't create a new table and when started tests for other data type following insertions will fail with `400 Duplicate name in schema: t. From eec115024b56ea66421e39c018eccd25d8d59141 Mon Sep 17 00:00:00 2001 From: HemangChothani Date: Wed, 17 Mar 2021 19:04:42 +0530 Subject: [PATCH 4/5] test: add todo note to remove override method --- test/test_suite.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/test_suite.py b/test/test_suite.py index 5c46f700..3e7866f8 100644 --- a/test/test_suite.py +++ b/test/test_suite.py @@ -432,13 +432,13 @@ def _round_trip(self, datatype, data): """ SPANNER OVERRIDE: - This is the helper method for integer class tests which creates table and - perform insert operation. - Cloud Spanner supports tables with empty primary key, but only single one + This is the helper method for integer class tests which creates a table and + performs an insert operation. + Cloud Spanner supports tables with an empty primary key, but only one row can be inserted into such a table - following insertions will fail with `400 id must not be NULL in table date_table`. - Overriding the tests and add a manual primary key value to avoid the same - failures and delete the from the table at the end. + Overriding the tests and adding a manual primary key value to avoid the same + failures and deleting the table at the end. """ metadata = self.metadata int_table = Table( @@ -466,6 +466,8 @@ def _round_trip(self, datatype, data): @provide_metadata def _literal_round_trip(self, type_, input_, output, filter_=None): """ + TODO: Remove this override method once DDL issue resolved in spanner_dbapi + SPANNER OVERRIDE: Spanner is not able cleanup data and drop the table correctly, From 26cb225c8c84bb374cc24371302597e8d381fdc3 Mon Sep 17 00:00:00 2001 From: HemangChothani Date: Thu, 18 Mar 2021 19:29:38 +0530 Subject: [PATCH 5/5] test: nit --- test/test_suite.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/test/test_suite.py b/test/test_suite.py index cfc845e2..bebfd01b 100644 --- a/test/test_suite.py +++ b/test/test_suite.py @@ -48,9 +48,6 @@ from sqlalchemy.testing.suite.test_types import BooleanTest as _BooleanTest from sqlalchemy.testing.suite.test_types import IntegerTest as _IntegerTest -config.test_schema = "" - - from sqlalchemy.testing.suite.test_types import ( # noqa: F401, F403 DateTest as _DateTest, DateTimeHistoricTest, @@ -62,6 +59,8 @@ TimestampMicrosecondsTest, ) +config.test_schema = "" + class EscapingTest(_EscapingTest): @provide_metadata @@ -467,16 +466,15 @@ def _round_trip(self, datatype, data): @provide_metadata def _literal_round_trip(self, type_, input_, output, filter_=None): """ - TODO: Remove this override method once DDL issue resolved in spanner_dbapi - SPANNER OVERRIDE: - Spanner is not able cleanup data and drop the table correctly, - table was already exists after related tests finished, so it doesn't - create a new table and when started tests for other data type following - insertions will fail with `400 Duplicate name in schema: t. - Overriding the tests to create a new table for test and drop table manually - before it creates a new table to avoid the same failures. + Spanner DBAPI does not execute DDL statements unless followed by a + non DDL statement, which is preventing correct table clean up. + The table already exists after related tests finish, so it doesn't + create a new table and when running tests for other data types + insertions will fail with `400 Duplicate name in schema: t`. + Overriding the tests to create and drop a new table to prevent + database existence errors. """ # for literal, we test the literal render in an INSERT @@ -484,7 +482,6 @@ def _literal_round_trip(self, type_, input_, output, filter_=None): # official type; ideally we'd be able to use CAST here # but MySQL in particular can't CAST fully t = Table("int_t", self.metadata, Column("x", type_)) - t.drop(checkfirst=True) t.create() with db.connect() as conn: @@ -497,6 +494,7 @@ def _literal_round_trip(self, type_, input_, output, filter_=None): ) ) conn.execute(ins) + conn.execute("SELECT 1") if self.supports_whereclause: stmt = t.select().where(t.c.x == literal(value))