From b6923604ff5087e18ff4ea18e87f4ef5075d22cd Mon Sep 17 00:00:00 2001 From: IlyaFaer Date: Thu, 17 Jun 2021 11:22:52 +0300 Subject: [PATCH 1/2] fix(db_api): use sqlparse to split DDL statements --- google/cloud/spanner_dbapi/cursor.py | 5 +++-- google/cloud/spanner_dbapi/parse_utils.py | 2 +- tests/unit/spanner_dbapi/test_cursor.py | 20 ++++++++++++++++---- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/google/cloud/spanner_dbapi/cursor.py b/google/cloud/spanner_dbapi/cursor.py index 3569bab605..3e78f27aff 100644 --- a/google/cloud/spanner_dbapi/cursor.py +++ b/google/cloud/spanner_dbapi/cursor.py @@ -14,6 +14,8 @@ """Database cursor for Google Cloud Spanner DB-API.""" +import sqlparse + from google.api_core.exceptions import Aborted from google.api_core.exceptions import AlreadyExists from google.api_core.exceptions import FailedPrecondition @@ -174,8 +176,7 @@ def execute(self, sql, args=None): try: classification = parse_utils.classify_stmt(sql) if classification == parse_utils.STMT_DDL: - for ddl in sql.split(";"): - ddl = ddl.strip() + for ddl in sqlparse.split(sql): if ddl: self.connection._ddl_statements.append(ddl) if self.connection.autocommit: diff --git a/google/cloud/spanner_dbapi/parse_utils.py b/google/cloud/spanner_dbapi/parse_utils.py index aa0e12d75d..d967330cea 100644 --- a/google/cloud/spanner_dbapi/parse_utils.py +++ b/google/cloud/spanner_dbapi/parse_utils.py @@ -199,7 +199,7 @@ def classify_stmt(query): def parse_insert(insert_sql, params): """ - Parse an INSERT statement an generate a list of tuples of the form: + Parse an INSERT statement and generate a list of tuples of the form: [ (SQL, params_per_row1), (SQL, params_per_row2), diff --git a/tests/unit/spanner_dbapi/test_cursor.py b/tests/unit/spanner_dbapi/test_cursor.py index 57a3375e49..4bb5033069 100644 --- a/tests/unit/spanner_dbapi/test_cursor.py +++ b/tests/unit/spanner_dbapi/test_cursor.py @@ -939,9 +939,16 @@ def test_ddls_with_semicolon(self): from google.cloud.spanner_dbapi.connection import connect EXP_DDLS = [ - "CREATE TABLE table_name (row_id INT64) PRIMARY KEY ()", - "DROP INDEX index_name", - "DROP TABLE table_name", + "CREATE TABLE table_name (row_id INT64) PRIMARY KEY ();", + "DROP INDEX index_name;", + ( + "CREATE TABLE papers (" + "\n id INT64," + "\n authors ARRAY," + '\n author_list STRING(MAX) AS (ARRAY_TO_STRING(authors, ";")) stored' + ") PRIMARY KEY (id);" + ), + "DROP TABLE table_name;", ] with mock.patch( @@ -956,7 +963,12 @@ def test_ddls_with_semicolon(self): cursor.execute( "CREATE TABLE table_name (row_id INT64) PRIMARY KEY ();" "DROP INDEX index_name;\n" - "DROP TABLE table_name;" + "CREATE TABLE papers (" + "\n id INT64," + "\n authors ARRAY," + '\n author_list STRING(MAX) AS (ARRAY_TO_STRING(authors, ";")) stored' + ") PRIMARY KEY (id);" + "DROP TABLE table_name;", ) self.assertEqual(connection._ddl_statements, EXP_DDLS) From 338441df98d63a17dc340df846bb7d8bfea94651 Mon Sep 17 00:00:00 2001 From: IlyaFaer Date: Fri, 18 Jun 2021 11:35:32 +0300 Subject: [PATCH 2/2] erase semicolons --- google/cloud/spanner_dbapi/cursor.py | 2 ++ tests/unit/spanner_dbapi/test_cursor.py | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/google/cloud/spanner_dbapi/cursor.py b/google/cloud/spanner_dbapi/cursor.py index 3e78f27aff..689ba8cf66 100644 --- a/google/cloud/spanner_dbapi/cursor.py +++ b/google/cloud/spanner_dbapi/cursor.py @@ -178,6 +178,8 @@ def execute(self, sql, args=None): if classification == parse_utils.STMT_DDL: for ddl in sqlparse.split(sql): if ddl: + if ddl[-1] == ";": + ddl = ddl[:-1] self.connection._ddl_statements.append(ddl) if self.connection.autocommit: self.connection.run_prior_DDL_statements() diff --git a/tests/unit/spanner_dbapi/test_cursor.py b/tests/unit/spanner_dbapi/test_cursor.py index 4bb5033069..789ca06695 100644 --- a/tests/unit/spanner_dbapi/test_cursor.py +++ b/tests/unit/spanner_dbapi/test_cursor.py @@ -939,16 +939,16 @@ def test_ddls_with_semicolon(self): from google.cloud.spanner_dbapi.connection import connect EXP_DDLS = [ - "CREATE TABLE table_name (row_id INT64) PRIMARY KEY ();", - "DROP INDEX index_name;", + "CREATE TABLE table_name (row_id INT64) PRIMARY KEY ()", + "DROP INDEX index_name", ( "CREATE TABLE papers (" "\n id INT64," "\n authors ARRAY," '\n author_list STRING(MAX) AS (ARRAY_TO_STRING(authors, ";")) stored' - ") PRIMARY KEY (id);" + ") PRIMARY KEY (id)" ), - "DROP TABLE table_name;", + "DROP TABLE table_name", ] with mock.patch(