Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add support for json data type #593

Merged
merged 9 commits into from Oct 4, 2021
1 change: 1 addition & 0 deletions google/cloud/spanner_dbapi/parse_utils.py
Expand Up @@ -38,6 +38,7 @@
DateStr: spanner.param_types.DATE,
TimestampStr: spanner.param_types.TIMESTAMP,
decimal.Decimal: spanner.param_types.NUMERIC,
dict: spanner.param_types.JSON,
}

SPANNER_RESERVED_KEYWORDS = {
Expand Down
5 changes: 5 additions & 0 deletions google/cloud/spanner_v1/_helpers.py
Expand Up @@ -17,6 +17,7 @@
import datetime
import decimal
import math
import json

import six

Expand Down Expand Up @@ -166,6 +167,10 @@ def _make_value_pb(value):
if isinstance(value, decimal.Decimal):
_assert_numeric_precision_and_scale(value)
return Value(string_value=str(value))
if isinstance(value, dict):
return Value(
string_value=json.dumps(value, sort_keys=True, separators=(",", ":"),)
)
raise ValueError("Unknown type: %s" % (value,))


Expand Down
3 changes: 1 addition & 2 deletions google/cloud/spanner_v1/batch.py
Expand Up @@ -118,8 +118,7 @@ def delete(self, table, keyset):


class Batch(_BatchBase):
"""Accumulate mutations for transmission during :meth:`commit`.
"""
"""Accumulate mutations for transmission during :meth:`commit`."""

committed = None
commit_stats = None
Expand Down
47 changes: 47 additions & 0 deletions tests/system/test_dbapi.py
Expand Up @@ -328,6 +328,53 @@ def test_DDL_autocommit(shared_instance, dbapi_database):
conn.commit()


@pytest.mark.skipif(_helpers.USE_EMULATOR, reason="Emulator does not support json.")
def test_autocommit_with_json_data(shared_instance, dbapi_database):
"""Check that DDLs in autocommit mode are immediately executed for
json fields."""
# Create table
conn = Connection(shared_instance, dbapi_database)
conn.autocommit = True

cur = conn.cursor()
cur.execute(
"""
CREATE TABLE JsonDetails (
DataId INT64 NOT NULL,
Details JSON,
) PRIMARY KEY (DataId)
"""
)
conn.close()
vi3k6i5 marked this conversation as resolved.
Show resolved Hide resolved

# Insert data to table
conn = Connection(shared_instance, dbapi_database)
conn.autocommit = True
cur = conn.cursor()
cur.execute(
sql="INSERT INTO JsonDetails (DataId, Details) VALUES (%s, %s)",
args=(123, {"name": "Jakob", "age": "26"}),
)

# Read back the data.
conn = Connection(shared_instance, dbapi_database)
cur = conn.cursor()
cur.execute("""select * from JsonDetails;""")
got_rows = cur.fetchall()
conn.close()

# Assert the response
assert len(got_rows) == 1
assert got_rows[0][0] == 123
assert got_rows[0][1] == '{"age":"26","name":"Jakob"}'

# Drop the table
conn = Connection(shared_instance, dbapi_database)
cur = conn.cursor()
cur.execute("DROP TABLE JsonDetails")
conn.commit()


def test_DDL_commit(shared_instance, dbapi_database):
"""Check that DDLs in commit mode are executed on calling `commit()`."""
conn = Connection(shared_instance, dbapi_database)
Expand Down