feat: add uuid support (#1310) · googleapis/python-spanner@3b1792a

This repository was archived by the owner on Mar 31, 2026. It is now read-only.

File tree

5 files changed

lines changed

5 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -21,6 +21,7 @@

2121

import base64

2222

import threading

2323

import logging

24+

import uuid

2425
2526

from google.protobuf.struct_pb2 import ListValue

2627

from google.protobuf.struct_pb2 import Value

@@ -298,6 +299,8 @@ def _make_value_pb(value):

298299

return Value(string_value=base64.b64encode(value))

299300

if isinstance(value, Interval):

300301

return Value(string_value=str(value))

302+

if isinstance(value, uuid.UUID):

303+

return Value(string_value=str(value))

301304
302305

raise ValueError("Unknown type: %s" % (value,))

303306

@@ -399,6 +402,8 @@ def _get_type_decoder(field_type, field_name, column_info=None):

399402

return _parse_numeric

400403

elif type_code == TypeCode.JSON:

401404

return _parse_json

405+

elif type_code == TypeCode.UUID:

406+

return _parse_uuid

402407

elif type_code == TypeCode.PROTO:

403408

return lambda value_pb: _parse_proto(value_pb, column_info, field_name)

404409

elif type_code == TypeCode.ENUM:

@@ -481,6 +486,10 @@ def _parse_json(value_pb):

481486

return JsonObject.from_str(value_pb.string_value)

482487
483488
489+

def _parse_uuid(value_pb):

490+

return uuid.UUID(value_pb.string_value)

491+
492+
484493

def _parse_proto(value_pb, column_info, field_name):

485494

bytes_value = base64.b64decode(value_pb.string_value)

486495

if column_info is not None and column_info.get(field_name) is not None:

Original file line numberDiff line numberDiff line change

@@ -33,6 +33,7 @@

3333

TIMESTAMP = Type(code=TypeCode.TIMESTAMP)

3434

NUMERIC = Type(code=TypeCode.NUMERIC)

3535

JSON = Type(code=TypeCode.JSON)

36+

UUID = Type(code=TypeCode.UUID)

3637

PG_NUMERIC = Type(code=TypeCode.NUMERIC, type_annotation=TypeAnnotationCode.PG_NUMERIC)

3738

PG_JSONB = Type(code=TypeCode.JSON, type_annotation=TypeAnnotationCode.PG_JSONB)

3839

PG_OID = Type(code=TypeCode.INT64, type_annotation=TypeAnnotationCode.PG_OID)

Original file line numberDiff line numberDiff line change

@@ -394,6 +394,7 @@ def _merge_struct(lhs, rhs, type_):

394394

TypeCode.PROTO: _merge_string,

395395

TypeCode.INTERVAL: _merge_string,

396396

TypeCode.ENUM: _merge_string,

397+

TypeCode.UUID: _merge_string,

397398

}

398399
399400
Original file line numberDiff line numberDiff line change

@@ -20,6 +20,7 @@

2020

import struct

2121

import threading

2222

import time

23+

import uuid

2324

import pytest

2425
2526

import grpc

@@ -3056,6 +3057,18 @@ def test_execute_sql_returning_transfinite_floats(sessions_database, not_postgre

30563057

assert math.isnan(float_array[2])

30573058
30583059
3060+

def test_execute_sql_w_uuid_bindings(sessions_database, database_dialect):

3061+

if database_dialect == DatabaseDialect.POSTGRESQL:

3062+

pytest.skip("UUID parameter type is not yet supported in PostgreSQL dialect.")

3063+

_bind_test_helper(

3064+

sessions_database,

3065+

database_dialect,

3066+

spanner_v1.param_types.UUID,

3067+

uuid.uuid4(),

3068+

[uuid.uuid4(), uuid.uuid4()],

3069+

)

3070+
3071+
30593072

def test_partition_query(sessions_database, not_emulator, not_experimental_host):

30603073

row_count = 40

30613074

sql = f"SELECT * FROM {_sample_data.TABLE}"

Original file line numberDiff line numberDiff line change

@@ -14,6 +14,7 @@

1414
1515
1616

import unittest

17+

import uuid

1718

import mock

1819
1920

from opentelemetry.sdk.resources import Resource

@@ -786,6 +787,18 @@ def test_w_proto_enum(self):

786787

self._callFUT(value_pb, field_type, field_name, column_info), VALUE

787788

)

788789
790+

def test_w_uuid(self):

791+

from google.protobuf.struct_pb2 import Value

792+

from google.cloud.spanner_v1 import Type

793+

from google.cloud.spanner_v1 import TypeCode

794+
795+

VALUE = uuid.uuid4()

796+

field_type = Type(code=TypeCode.UUID)

797+

field_name = "uuid_column"

798+

value_pb = Value(string_value=str(VALUE))

799+
800+

self.assertEqual(self._callFUT(value_pb, field_type, field_name), VALUE)

801+
789802
790803

class Test_parse_list_value_pbs(unittest.TestCase):

791804

def _callFUT(self, *args, **kw):