Skip to content

Commit

Permalink
Fixing comments
Browse files Browse the repository at this point in the history
  • Loading branch information
ankiaga committed Nov 22, 2023
1 parent bedb240 commit 6955a6c
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 25 deletions.
21 changes: 7 additions & 14 deletions google/cloud/spanner_dbapi/client_side_statement_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,11 @@
)


class StatementExecutor(object):
def __init__(self, connection):
self.connection = connection
def execute(connection, parsed_statement: ParsedStatement):
"""Executes the client side statements by calling the relevant method
def execute(self, parsed_statement: ParsedStatement):
"""Executes the client side statements by calling the relevant method
:type parsed_statement: ParsedStatement
:param parsed_statement: parsed_statement based on the sql query
"""
if (
parsed_statement.client_side_statement_type
== ClientSideStatementType.COMMIT
):
self.connection.commit()
:type parsed_statement: ParsedStatement
:param parsed_statement: parsed_statement based on the sql query
"""
if parsed_statement.client_side_statement_type == ClientSideStatementType.COMMIT:
return connection.commit()
19 changes: 10 additions & 9 deletions google/cloud/spanner_dbapi/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,12 @@

from google.cloud import spanner_v1 as spanner
from google.cloud.spanner_dbapi.checksum import ResultsChecksum
from google.cloud.spanner_dbapi.client_side_statement_executor import StatementExecutor
from google.cloud.spanner_dbapi.exceptions import IntegrityError
from google.cloud.spanner_dbapi.exceptions import InterfaceError
from google.cloud.spanner_dbapi.exceptions import OperationalError
from google.cloud.spanner_dbapi.exceptions import ProgrammingError

from google.cloud.spanner_dbapi import _helpers
from google.cloud.spanner_dbapi import _helpers, client_side_statement_executor
from google.cloud.spanner_dbapi._helpers import ColumnInfo
from google.cloud.spanner_dbapi._helpers import CODE_TO_DISPLAY_SIZE

Expand Down Expand Up @@ -87,7 +86,6 @@ def __init__(self, connection):
self._row_count = _UNSET_COUNT
self.lastrowid = None
self.connection = connection
self.client_side_statement_executor = StatementExecutor(connection)
self._is_closed = False
# the currently running SQL statement results checksum
self._checksum = None
Expand Down Expand Up @@ -213,7 +211,7 @@ def _batch_DDLs(self, sql):
for ddl in sqlparse.split(sql):
if ddl:
ddl = ddl.rstrip(";")
if parse_utils.classify_stmt(ddl).statement_type != StatementType.DDL:
if parse_utils._classify_stmt(ddl).statement_type != StatementType.DDL:
raise ValueError("Only DDL statements may be batched.")

statements.append(ddl)
Expand Down Expand Up @@ -242,10 +240,11 @@ def execute(self, sql, args=None):
self._handle_DQL(sql, args or None)
return

parsed_statement = parse_utils.classify_stmt(sql)
parsed_statement = parse_utils._classify_stmt(sql)
if parsed_statement.statement_type == StatementType.CLIENT_SIDE:
self.client_side_statement_executor.execute(parsed_statement)
return
return client_side_statement_executor.execute(
self.connection, parsed_statement
)
if parsed_statement.statement_type == StatementType.DDL:
self._batch_DDLs(sql)
if self.connection.autocommit:
Expand Down Expand Up @@ -315,7 +314,7 @@ def executemany(self, operation, seq_of_params):
self._result_set = None
self._row_count = _UNSET_COUNT

parsed_statement = parse_utils.classify_stmt(operation)
parsed_statement = parse_utils._classify_stmt(operation)
if parsed_statement.statement_type == StatementType.DDL:
raise ProgrammingError(
"Executing DDL statements with executemany() method is not allowed."
Expand All @@ -326,7 +325,9 @@ def executemany(self, operation, seq_of_params):
self.connection.run_prior_DDL_statements()
if parsed_statement.statement_type == StatementType.CLIENT_SIDE:
raise ProgrammingError(
"Executing ClientSide statements with executemany() method is not allowed."
"Executing the following operation: "
+ operation
+ ", with executemany() method is not allowed."
)

many_result_set = StreamedManyResultSets()
Expand Down
36 changes: 36 additions & 0 deletions google/cloud/spanner_dbapi/parse_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@
import re

import sqlparse
import warnings
import functools
from google.cloud import spanner_v1 as spanner
from google.cloud.spanner_v1 import JsonObject
from . import client_side_statement_parser
from deprecated import deprecated

from .exceptions import Error
from .parsed_statement import ParsedStatement, StatementType
Expand Down Expand Up @@ -141,6 +144,11 @@
"WITHIN",
}

STMT_DDL = "DDL"
STMT_NON_UPDATING = "NON_UPDATING"
STMT_UPDATING = "UPDATING"
STMT_INSERT = "INSERT"

# Heuristic for identifying statements that don't need to be run as updates.
RE_NON_UPDATE = re.compile(r"^\W*(SELECT)", re.IGNORECASE)

Expand Down Expand Up @@ -171,8 +179,36 @@
RE_PYFORMAT = re.compile(r"(%s|%\([^\(\)]+\)s)+", re.DOTALL)


@deprecated(reason="This method is deprecated. Use _classify_stmt method")
def classify_stmt(query):
"""Determine SQL query type.
:type query: str
:param query: A SQL query.
:rtype: str
:returns: The query type name.
"""
# sqlparse will strip Cloud Spanner comments,
# still, special commenting styles, like
# PostgreSQL dollar quoted comments are not
# supported and will not be stripped.
query = sqlparse.format(query, strip_comments=True).strip()

if RE_DDL.match(query):
return STMT_DDL

if RE_IS_INSERT.match(query):
return STMT_INSERT

if RE_NON_UPDATE.match(query) or RE_WITH.match(query):
# As of 13-March-2020, Cloud Spanner only supports WITH for DQL
# statements and doesn't yet support WITH for DML statements.
return STMT_NON_UPDATING

return STMT_UPDATING


def _classify_stmt(query):
"""Determine SQL query type.
:type query: str
:param query: A SQL query.
Expand Down
14 changes: 14 additions & 0 deletions tests/unit/spanner_dbapi/test_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,20 @@ def test_executemany_DLL(self, mock_client):
with self.assertRaises(ProgrammingError):
cursor.executemany("""DROP DATABASE database_name""", ())

def test_executemany_client_statement(self):
from google.cloud.spanner_dbapi import connect, ProgrammingError

connection = connect("test-instance", "test-database")

cursor = connection.cursor()

with self.assertRaises(ProgrammingError) as error:
cursor.executemany("""COMMIT TRANSACTION""", ())
self.assertEqual(
str(error.exception),
"Executing the following operation: COMMIT TRANSACTION, with executemany() method is not allowed.",
)

@mock.patch("google.cloud.spanner_v1.Client")
def test_executemany(self, mock_client):
from google.cloud.spanner_dbapi import connect
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/spanner_dbapi/test_parse_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class TestParseUtils(unittest.TestCase):
skip_message = "Subtests are not supported in Python 2"

def test_classify_stmt(self):
from google.cloud.spanner_dbapi.parse_utils import classify_stmt
from google.cloud.spanner_dbapi.parse_utils import _classify_stmt

cases = (
("SELECT 1", StatementType.QUERY),
Expand Down Expand Up @@ -65,7 +65,7 @@ def test_classify_stmt(self):
)

for query, want_class in cases:
self.assertEqual(classify_stmt(query).statement_type, want_class)
self.assertEqual(_classify_stmt(query).statement_type, want_class)

@unittest.skipIf(skip_condition, skip_message)
def test_sql_pyformat_args_to_spanner(self):
Expand Down

0 comments on commit 6955a6c

Please sign in to comment.