Skip to content
Closed
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
11222db
feat: release 2.2a0 (#457)
larkee May 26, 2020
5551b58
feat: [WIP] The first stage of `nox` implementation (#468)
mf2199 Aug 25, 2020
bfde221
feat: refactor connect() function, cover it with unit tests (#462)
Aug 27, 2020
e017901
feat: Stage 2 of `nox` implementation - adding `docs` target (#473)
mf2199 Aug 29, 2020
144bdc2
fix: Fix black, isort compatibility (#469)
c24t Aug 31, 2020
7a1f6a6
feat: Stage 3-4 of `nox` implementation - adding auto-format targets …
mf2199 Aug 31, 2020
acd9209
feat: Stage 5 of `nox` implementation - adding coverage targets (#479)
mf2199 Aug 31, 2020
6028f88
feat: cursor must detect if the parent connection is closed (#463)
Sep 1, 2020
94ba284
feat: Stage 6 of `nox` implementation - enabling system tests (#480)
mf2199 Sep 8, 2020
59eb432
chore: Code refactoring to follow common Google API scheme - Stage I …
mf2199 Sep 14, 2020
048566c
chore: release 2.2a1 (#499)
c24t Sep 15, 2020
f5719f8
Merge branch 'master' of https://github.com/googleapis/python-spanner…
Sep 15, 2020
2c0c0a2
fix: Couple of tests are permanently broken while running locally
tina80lvl Sep 21, 2020
05bf7dc
fix: offset for current timezone
tina80lvl Sep 22, 2020
31185df
clean: whitespace
tina80lvl Sep 22, 2020
bd605a5
fix: localtime->gmtime
tina80lvl Sep 25, 2020
23f87ad
fix: gmtime->localtime
tina80lvl Sep 25, 2020
216a92b
refactor
tina80lvl Sep 30, 2020
3b34162
docs: utils.py
tina80lvl Sep 29, 2020
d5ba00c
docs: version.py`
tina80lvl Sep 29, 2020
ccfb6ce
refactor
tina80lvl Sep 30, 2020
9526cc2
Merge pull request #5 from q-logic/fix-472
mf2199 Sep 30, 2020
a921666
Merge remote-tracking branch 'upstream/master'
mf2199 Sep 30, 2020
60fd3fb
docs: parser.py
tina80lvl Oct 1, 2020
d86e8a1
refactor
tina80lvl Oct 1, 2020
325abb9
docs: parse_utils.py
tina80lvl Oct 1, 2020
539b3dd
docs: cursor.py
tina80lvl Oct 1, 2020
5ce0fa9
docs: connection.py
tina80lvl Oct 1, 2020
a9eb4a6
refactor
tina80lvl Oct 1, 2020
bbb3378
conflict
tina80lvl Oct 1, 2020
f364372
corrections
tina80lvl Oct 5, 2020
a703d5c
refactoring
tina80lvl Oct 5, 2020
f94dc9c
fixes
tina80lvl Oct 6, 2020
ec1aeca
conflicts
tina80lvl Oct 6, 2020
29801d9
cc
tina80lvl Oct 6, 2020
28a7faa
imperative
tina80lvl Oct 6, 2020
0d47d9a
merge origin
tina80lvl Oct 8, 2020
717cd4e
fixes
tina80lvl Oct 8, 2020
466e037
conflicts
tina80lvl Oct 8, 2020
8dabb7b
pull
tina80lvl Oct 12, 2020
6437b70
refactor
tina80lvl Oct 12, 2020
8e26153
fixes
tina80lvl Oct 12, 2020
f41acd5
review fixes
tina80lvl Oct 19, 2020
17eaefa
cleanup
tina80lvl Oct 21, 2020
a71ca06
review fix
tina80lvl Oct 21, 2020
a1ecbec
cc
tina80lvl Oct 22, 2020
b701555
draft test
tina80lvl Oct 27, 2020
50570db
resolving conflicts
tina80lvl Oct 29, 2020
a1ad37d
refactor
tina80lvl Oct 29, 2020
3c3572b
revert test
tina80lvl Oct 29, 2020
dc43995
missing parse_values added
tina80lvl Oct 29, 2020
b829809
review fixes
tina80lvl Nov 2, 2020
c6d924b
fixed suggections
tina80lvl Nov 8, 2020
0806ab8
Merge branch 'master' into docstr-1
mf2199 Nov 8, 2020
9e1be73
Merge branch 'master' into docstr-1
c24t Nov 12, 2020
9aa0c63
Rewrap a few docstrings
c24t Nov 12, 2020
467cdaa
merge
tina80lvl Nov 23, 2020
c4857a4
fixed conflicts
tina80lvl Nov 23, 2020
e04627c
merge fetch
tina80lvl Nov 23, 2020
9f286fb
delete google/cloud/spanner_dbapi
tina80lvl Dec 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 75 additions & 5 deletions google/cloud/spanner_dbapi/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ def __init__(self, instance, database):
self._ddl_statements = []

def cursor(self):
"""Factory to create a :class:`Cursor` linked to this Connection.

:rtype: :class:`Cursor`
:returns: A database cursor, which is used to manage the context of a
fetch operation.
"""
self._raise_if_closed()

return Cursor(self)
Expand All @@ -63,28 +69,64 @@ def __handle_update_ddl(self, ddl_statements):
"""
Run the list of Data Definition Language (DDL) statements on the underlying
database. Each DDL statement MUST NOT contain a semicolon.
Args:
ddl_statements: a list of DDL statements, each without a semicolon.
Returns:
google.api_core.operation.Operation.result()

:type ddl_statements: list
:param ddl_statements: A list of DDL statements, each without a
semicolon.
"""
self._raise_if_closed()
# Synchronously wait on the operation's completion.
return self.database.update_ddl(ddl_statements).result()

def read_snapshot(self):
"""Return a Snapshot of the linked Database.

:rtype: :class:`~google.cloud.spanner_v1.snapshot.Snapshot`
:returns: A snapshot of the linked Database.
"""
self._raise_if_closed()
return self.database.snapshot()

def in_transaction(self, fn, *args, **kwargs):
"""Perform a unit of work in a linked Transaction, retrying on abort.

:type fn: callable
:param fn: takes a required positional argument, the transaction,
and additional positional / keyword arguments as supplied
by the caller.

:type *args: tuple
:param *args: additional positional arguments to be passed to ``fn``.

:type **kwargs: dict
:param **kwargs: (Optional) keyword arguments to be passed to ``fn``.
If passed, "timeout_secs" will be removed and used to
override the default retry timeout which defines
maximum timestamp to continue retrying the transaction.

:rtype: Any
:returns: Runs the given function as it would be a transaction.
"""
self._raise_if_closed()
return self.database.run_in_transaction(fn, *args, **kwargs)

def append_ddl_statement(self, ddl_statement):
"""Append DDL statement to the existing list of DDL statements in
linked database.

:type ddl_statements: list
:param ddl_statements: A list of DDL statements, each without a
semicolon.
"""
self._raise_if_closed()
self._ddl_statements.append(ddl_statement)

def run_prior_DDL_statements(self):
"""Run prior Operation.

:rtype: str
:returns: Updated statements.
"""
self._raise_if_closed()

if not self._ddl_statements:
Expand All @@ -96,6 +138,11 @@ def run_prior_DDL_statements(self):
return self.__handle_update_ddl(ddl_statements)

def list_tables(self):
"""List tables contained within the linked Database.

:rtype: list
:returns: Tables with corresponding information.
"""
return self.run_sql_in_snapshot(
"""
SELECT
Expand All @@ -108,6 +155,21 @@ def list_tables(self):
)

def run_sql_in_snapshot(self, sql, params=None, param_types=None):
"""Run an SQL request on the linked Database snapshot.

:type sql: str
:param sql: SQL request.

:type params: list
:param params: (Optional) List of parameters.

:type param_types: dict
:param param_types: (Optional) List of parameters' types.

:rtype: list
:returns: A list of :class:`~google.cloud.spanner_v1.streamed.StreamedResultSet`
results.
"""
# Some SQL e.g. for INFORMATION_SCHEMA cannot be run in read-write transactions
# hence this method exists to circumvent that limit.
self.run_prior_DDL_statements()
Expand All @@ -119,6 +181,14 @@ def run_sql_in_snapshot(self, sql, params=None, param_types=None):
return list(res)

def get_table_column_schema(self, table_name):
"""Get table column schema.

:type table_name: str
:param table_name: Name of the table.

:rtype: dict
:returns: Column description.
"""
rows = self.run_sql_in_snapshot(
"""SELECT
COLUMN_NAME, IS_NULLABLE, SPANNER_TYPE
Expand All @@ -142,7 +212,7 @@ def get_table_column_schema(self, table_name):
def close(self):
"""Close this connection.

The connection will be unusable from this point forward.
.. note:: The connection will be unusable from this point forward.
"""
self.__dbhandle = None
self.is_closed = True
Expand Down
112 changes: 91 additions & 21 deletions google/cloud/spanner_dbapi/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@


class Cursor:
"""
Database cursor to manage the context of a fetch operation.
"""Database cursor to manage the context of a fetch operation.

:type connection: :class:`spanner_dbapi.connection.Connection`
:param connection: Parent connection object for this Cursor.
Expand All @@ -72,14 +71,21 @@ def __init__(self, connection):
self.arraysize = 1

def execute(self, sql, args=None):
"""
Abstracts and implements execute SQL statements on Cloud Spanner.
Args:
sql: A SQL statement
*args: variadic argument list
**kwargs: key worded arguments
Returns:
None
"""Abstracts and implements execute SQL statements on Cloud Spanner.

:type sql: str
:param sql: A SQL statement.

:type *args: list
:param *args: (Optional) variadic argument list.

:type **kwargs: list
:param **kwargs: (Optional) key worded arguments.

:raises: :class:`IntegrityError` if precondition failed or argument
already exists, :class:`ProgrammingError` if there is
invalid argument, :class:`OperationalError` if there is
internal server error.
"""
self._raise_if_closed()

Expand Down Expand Up @@ -212,6 +218,11 @@ def __exit__(self, etype, value, traceback):

@property
def description(self):
"""Give description of the table.

:rtype: tuple
:returns: A tuple of columns' information.
"""
if not (self._res and self._res.metadata):
return None

Expand All @@ -232,13 +243,18 @@ def description(self):

@property
def rowcount(self):
"""Return number of rows in the table.

:rtype: int
:returns: Number of rows that last .execute*() produced.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The number

"""
return self._row_count

@property
def is_closed(self):
"""The cursor close indicator.

:rtype: :class:`bool`
:rtype: bool
:returns: True if this cursor or it's parent connection is closed, False
otherwise.
"""
Expand All @@ -265,14 +281,17 @@ def close(self):

def executemany(self, operation, seq_of_params):
"""
Execute the given SQL with every parameters set
from the given sequence of parameters.
Execute the given SQL with every parameters set from the given sequence
of parameters.

:type operation: :class:`str`
:type operation: str
:param operation: SQL code to execute.

:type seq_of_params: :class:`list`
:type seq_of_params: list
:param seq_of_params: Sequence of params to run the query with.

:raises: :class:`ProgrammingError` if cursor is not connected to
database.
"""
self._raise_if_closed()

Expand All @@ -290,6 +309,10 @@ def __iter__(self):
return self._itr

def fetchone(self):
"""Fetch next resulting row of the last ran query.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fetch the next resulting row


:returns: The next element if it is possible, None otherwise.
"""
self._raise_if_closed()

try:
Expand All @@ -298,6 +321,11 @@ def fetchone(self):
return None

def fetchall(self):
"""Fetch all elements.

:rtype: list
:returns: A list of fetched elements.
"""
self._raise_if_closed()

return list(self.__iter__())
Expand All @@ -307,13 +335,12 @@ def fetchmany(self, size=None):
Fetch the next set of rows of a query result, returning a sequence of sequences.
An empty sequence is returned when no more rows are available.

Args:
size: optional integer to determine the maximum number of results to fetch.
:type size: int
:param size: (Optional) maximum number of results to fetch.


Raises:
Error if the previous call to .execute*() did not produce any result set
or if no call was issued yet.
:raises: An error if the previous call to .execute*() did not produce
any result set or if no call was issued yet.
"""
self._raise_if_closed()

Expand Down Expand Up @@ -343,17 +370,60 @@ def _run_prior_DDL_statements(self):
return self._connection.run_prior_DDL_statements()

def list_tables(self):
"""List tables of linked Database.

:rtype: str
:returns: Tables with theirs' corresponding information.
"""
return self._connection.list_tables()

def run_sql_in_snapshot(self, sql):
"""Run SQL in snapshot.

:type sql: str
:param sql: SQL request.

:rtype: list
:returns: Result of operation.
"""
return self._connection.run_sql_in_snapshot(sql)

def get_table_column_schema(self, table_name):
"""Get table column schema.

:type table_name: str
:param table_name: Name of the table.

:rtype: dict
:returns: A dictionary of table column schema.
"""
return self._connection.get_table_column_schema(table_name)


class ColumnInfo:
"""Row column description object."""
"""Object defines column of the table in linked Database.

:type name: str
:param name: Name of the column.

:type type_code: int
:param type_code: Code of the value type.

:type display_size: int
:param display_size: (Optional) Display size.

:type internal_size: int
:param internal_size: (Optional) Internal size.

:type precision: int
:param precision: (Optional) Number of significant digits.

:type scale: float
:param scale: (Optional) Scale.

:type null_ok: bool
:param null_ok: (Optional) Allows column value to be None. Default is False.
"""

def __init__(
self,
Expand Down
Loading