From ad4d34095f66d39360864f357233257430e80f29 Mon Sep 17 00:00:00 2001 From: ankiaga Date: Wed, 8 Nov 2023 14:35:34 +0530 Subject: [PATCH 1/5] Executing existing DDL statements on executemany statement execution --- google/cloud/spanner_dbapi/cursor.py | 4 +++ tests/system/test_dbapi.py | 37 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/google/cloud/spanner_dbapi/cursor.py b/google/cloud/spanner_dbapi/cursor.py index 91bccedd4c..f6043bcf3b 100644 --- a/google/cloud/spanner_dbapi/cursor.py +++ b/google/cloud/spanner_dbapi/cursor.py @@ -317,6 +317,10 @@ def executemany(self, operation, seq_of_params): many_result_set = StreamedManyResultSets() + # For every operation, we've got to ensure that any prior DDL + # statements were run. + self.connection.run_prior_DDL_statements() + if class_ in (parse_utils.STMT_INSERT, parse_utils.STMT_UPDATING): statements = [] diff --git a/tests/system/test_dbapi.py b/tests/system/test_dbapi.py index 29617ad614..3720a055e8 100644 --- a/tests/system/test_dbapi.py +++ b/tests/system/test_dbapi.py @@ -344,6 +344,43 @@ def test_DDL_autocommit(shared_instance, dbapi_database): op.result() +def test_ddl_executemany(shared_instance, dbapi_database): + """Check that DDLs in autocommit mode are immediately executed.""" + + conn = Connection(shared_instance, dbapi_database) + want_row = ( + 1, + "first-name", + ) + cur = conn.cursor() + cur.execute( + """ + CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + Name STRING(1024), + ) PRIMARY KEY (SingerId) + """ + ) + cur.executemany( + """ +INSERT INTO Singers (SingerId, Name) +VALUES (%s, %s) +""", + [want_row], + ) + conn.commit() + + # read the resulting data from the database + cur.execute("SELECT * FROM Singers") + got_rows = cur.fetchall() + conn.commit() + + assert got_rows == [want_row] + + cur.close() + conn.close() + + @pytest.mark.skipif(_helpers.USE_EMULATOR, reason="Emulator does not support json.") def test_autocommit_with_json_data(shared_instance, dbapi_database): """ From d71b53a9eda1ee06ba0a9aec5403174740c84508 Mon Sep 17 00:00:00 2001 From: ankiaga Date: Wed, 8 Nov 2023 15:00:09 +0530 Subject: [PATCH 2/5] Fixing test --- tests/system/test_dbapi.py | 63 +++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/tests/system/test_dbapi.py b/tests/system/test_dbapi.py index 3720a055e8..a909ae8ee6 100644 --- a/tests/system/test_dbapi.py +++ b/tests/system/test_dbapi.py @@ -347,38 +347,45 @@ def test_DDL_autocommit(shared_instance, dbapi_database): def test_ddl_executemany(shared_instance, dbapi_database): """Check that DDLs in autocommit mode are immediately executed.""" - conn = Connection(shared_instance, dbapi_database) - want_row = ( - 1, - "first-name", - ) - cur = conn.cursor() - cur.execute( - """ - CREATE TABLE Singers ( - SingerId INT64 NOT NULL, - Name STRING(1024), - ) PRIMARY KEY (SingerId) - """ - ) - cur.executemany( + try: + conn = Connection(shared_instance, dbapi_database) + want_row = ( + 1, + "first-name", + ) + cur = conn.cursor() + cur.execute( + """ + CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + Name STRING(1024), + ) PRIMARY KEY (SingerId) """ -INSERT INTO Singers (SingerId, Name) -VALUES (%s, %s) -""", - [want_row], - ) - conn.commit() + ) + cur.executemany( + """ + INSERT INTO Singers (SingerId, Name) + VALUES (%s, %s) + """, + [want_row], + ) + conn.commit() - # read the resulting data from the database - cur.execute("SELECT * FROM Singers") - got_rows = cur.fetchall() - conn.commit() + # read the resulting data from the database + cur.execute("SELECT * FROM Singers") + got_rows = cur.fetchall() - assert got_rows == [want_row] + assert got_rows == [want_row] - cur.close() - conn.close() + cur.close() + conn.close() + + finally: + # Delete table + table = dbapi_database.table("Singers") + if table.exists(): + op = dbapi_database.update_ddl(["DROP TABLE Singers"]) + op.result() @pytest.mark.skipif(_helpers.USE_EMULATOR, reason="Emulator does not support json.") From 2f4889e91835b051745dc09520d8fdc84b3e6ebb Mon Sep 17 00:00:00 2001 From: ankiaga Date: Thu, 9 Nov 2023 12:37:14 +0530 Subject: [PATCH 3/5] Added more tests and resolved comments --- google/cloud/spanner_dbapi/cursor.py | 4 +- tests/system/test_dbapi.py | 145 +++++++++++++++++++++------ 2 files changed, 115 insertions(+), 34 deletions(-) diff --git a/google/cloud/spanner_dbapi/cursor.py b/google/cloud/spanner_dbapi/cursor.py index f6043bcf3b..330aeb2c72 100644 --- a/google/cloud/spanner_dbapi/cursor.py +++ b/google/cloud/spanner_dbapi/cursor.py @@ -315,12 +315,12 @@ def executemany(self, operation, seq_of_params): "Executing DDL statements with executemany() method is not allowed." ) - many_result_set = StreamedManyResultSets() - # For every operation, we've got to ensure that any prior DDL # statements were run. self.connection.run_prior_DDL_statements() + many_result_set = StreamedManyResultSets() + if class_ in (parse_utils.STMT_INSERT, parse_utils.STMT_UPDATING): statements = [] diff --git a/tests/system/test_dbapi.py b/tests/system/test_dbapi.py index a909ae8ee6..0ba3b5659c 100644 --- a/tests/system/test_dbapi.py +++ b/tests/system/test_dbapi.py @@ -27,7 +27,6 @@ from google.cloud.spanner_v1 import gapic_version as package_version from . import _helpers - DATABASE_NAME = "dbapi-txn" DDL_STATEMENTS = ( @@ -344,48 +343,130 @@ def test_DDL_autocommit(shared_instance, dbapi_database): op.result() -def test_ddl_executemany(shared_instance, dbapi_database): - """Check that DDLs in autocommit mode are immediately executed.""" +def test_ddl_execute_autocommit_true(shared_instance, dbapi_database): + """Check that DDL statement in autocommit mode results in successful + DDL statement execution for execute method.""" - try: - conn = Connection(shared_instance, dbapi_database) - want_row = ( - 1, - "first-name", - ) - cur = conn.cursor() - cur.execute( + conn = Connection(shared_instance, dbapi_database) + conn.autocommit = True + cur = conn.cursor() + cur.execute( + """ + CREATE TABLE DdlExecuteAutocommit ( + SingerId INT64 NOT NULL, + Name STRING(1024), + ) PRIMARY KEY (SingerId) + """ + ) + table = dbapi_database.table("DdlExecuteAutocommit") + assert table.exists() is True + + cur.close() + conn.close() + + +def test_ddl_executemany_autocommit_true(shared_instance, dbapi_database): + """Check that DDL statement in autocommit mode results in exception for + executemany method .""" + + conn = Connection(shared_instance, dbapi_database) + conn.autocommit = True + cur = conn.cursor() + with pytest.raises(ProgrammingError): + cur.executemany( """ - CREATE TABLE Singers ( + CREATE TABLE DdlExecuteManyAutocommit ( SingerId INT64 NOT NULL, Name STRING(1024), ) PRIMARY KEY (SingerId) """ ) - cur.executemany( - """ - INSERT INTO Singers (SingerId, Name) - VALUES (%s, %s) - """, - [want_row], - ) - conn.commit() + table = dbapi_database.table("DdlExecuteManyAutocommit") + assert table.exists() is True - # read the resulting data from the database - cur.execute("SELECT * FROM Singers") - got_rows = cur.fetchall() + cur.close() + conn.close() - assert got_rows == [want_row] - cur.close() - conn.close() +def test_ddl_execute(shared_instance, dbapi_database): + """Check that DDL statement followed by non-DDL execute statement in + non autocommit mode results in successful DDL statement execution.""" - finally: - # Delete table - table = dbapi_database.table("Singers") - if table.exists(): - op = dbapi_database.update_ddl(["DROP TABLE Singers"]) - op.result() + conn = Connection(shared_instance, dbapi_database) + want_row = ( + 1, + "first-name", + ) + cur = conn.cursor() + cur.execute( + """ + CREATE TABLE DdlExecute ( + SingerId INT64 NOT NULL, + Name STRING(1024), + ) PRIMARY KEY (SingerId) + """ + ) + table = dbapi_database.table("DdlExecute") + assert table.exists() is False + + cur.execute( + """ +INSERT INTO DdlExecute (SingerId, Name) +VALUES (1, "first-name") +""" + ) + assert table.exists() is True + conn.commit() + + # read the resulting data from the database + cur.execute("SELECT * FROM DdlExecute") + got_rows = cur.fetchall() + + assert got_rows == [want_row] + + cur.close() + conn.close() + + +def test_ddl_executemany(shared_instance, dbapi_database): + """Check that DDL statement followed by non-DDL executemany statement in + non autocommit mode results in successful DDL statement execution.""" + + conn = Connection(shared_instance, dbapi_database) + want_row = ( + 1, + "first-name", + ) + cur = conn.cursor() + cur.execute( + """ + CREATE TABLE DdlExecuteMany ( + SingerId INT64 NOT NULL, + Name STRING(1024), + ) PRIMARY KEY (SingerId) + """ + ) + table = dbapi_database.table("DdlExecuteMany") + assert table.exists() is False + + cur.executemany( + """ +INSERT INTO DdlExecuteMany (SingerId, Name) +VALUES (%s, %s) +""", + [want_row], + ) + assert table.exists() is True + conn.commit() + + # read the resulting data from the database + cur.execute("SELECT * FROM DdlExecuteMany") + got_rows = cur.fetchall() + + assert got_rows == [want_row] + + cur.close() + conn.close() @pytest.mark.skipif(_helpers.USE_EMULATOR, reason="Emulator does not support json.") From b81649ad2bb2aa5acc862519541f409a6171b581 Mon Sep 17 00:00:00 2001 From: ankiaga Date: Thu, 9 Nov 2023 12:46:43 +0530 Subject: [PATCH 4/5] Fixing test --- tests/system/test_dbapi.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/system/test_dbapi.py b/tests/system/test_dbapi.py index 0ba3b5659c..c9aa6d53d6 100644 --- a/tests/system/test_dbapi.py +++ b/tests/system/test_dbapi.py @@ -379,10 +379,11 @@ def test_ddl_executemany_autocommit_true(shared_instance, dbapi_database): SingerId INT64 NOT NULL, Name STRING(1024), ) PRIMARY KEY (SingerId) - """ + """, + [], ) table = dbapi_database.table("DdlExecuteManyAutocommit") - assert table.exists() is True + assert table.exists() is False cur.close() conn.close() From 8e53910daf780e24bd6db2f06dc5320e6343ddb3 Mon Sep 17 00:00:00 2001 From: ankiaga Date: Wed, 15 Nov 2023 10:15:25 +0000 Subject: [PATCH 5/5] Resolved comments --- tests/system/test_dbapi.py | 43 +++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/tests/system/test_dbapi.py b/tests/system/test_dbapi.py index c9aa6d53d6..f3c5da1f46 100644 --- a/tests/system/test_dbapi.py +++ b/tests/system/test_dbapi.py @@ -356,7 +356,7 @@ def test_ddl_execute_autocommit_true(shared_instance, dbapi_database): SingerId INT64 NOT NULL, Name STRING(1024), ) PRIMARY KEY (SingerId) - """ + """ ) table = dbapi_database.table("DdlExecuteAutocommit") assert table.exists() is True @@ -379,7 +379,30 @@ def test_ddl_executemany_autocommit_true(shared_instance, dbapi_database): SingerId INT64 NOT NULL, Name STRING(1024), ) PRIMARY KEY (SingerId) - """, + """, + [], + ) + table = dbapi_database.table("DdlExecuteManyAutocommit") + assert table.exists() is False + + cur.close() + conn.close() + + +def test_ddl_executemany_autocommit_false(shared_instance, dbapi_database): + """Check that DDL statement in non-autocommit mode results in exception for + executemany method .""" + + conn = Connection(shared_instance, dbapi_database) + cur = conn.cursor() + with pytest.raises(ProgrammingError): + cur.executemany( + """ + CREATE TABLE DdlExecuteManyAutocommit ( + SingerId INT64 NOT NULL, + Name STRING(1024), + ) PRIMARY KEY (SingerId) + """, [], ) table = dbapi_database.table("DdlExecuteManyAutocommit") @@ -405,16 +428,16 @@ def test_ddl_execute(shared_instance, dbapi_database): SingerId INT64 NOT NULL, Name STRING(1024), ) PRIMARY KEY (SingerId) - """ + """ ) table = dbapi_database.table("DdlExecute") assert table.exists() is False cur.execute( """ -INSERT INTO DdlExecute (SingerId, Name) -VALUES (1, "first-name") -""" + INSERT INTO DdlExecute (SingerId, Name) + VALUES (1, "first-name") + """ ) assert table.exists() is True conn.commit() @@ -445,16 +468,16 @@ def test_ddl_executemany(shared_instance, dbapi_database): SingerId INT64 NOT NULL, Name STRING(1024), ) PRIMARY KEY (SingerId) - """ + """ ) table = dbapi_database.table("DdlExecuteMany") assert table.exists() is False cur.executemany( """ -INSERT INTO DdlExecuteMany (SingerId, Name) -VALUES (%s, %s) -""", + INSERT INTO DdlExecuteMany (SingerId, Name) + VALUES (%s, %s) + """, [want_row], ) assert table.exists() is True