def test_w_array_empty(self): from google.protobuf.struct_pb2 import Value from google.cloud.proto.spanner.v1.type_pb2 import Type, ARRAY, INT64 field_type = Type(code=ARRAY, array_element_type=Type(code=INT64)) value_pb = Value() self.assertEqual(self._callFUT(value_pb, field_type), [])
def test__merge_chunk_array_of_array_of_int(self): from google.cloud.proto.spanner.v1.type_pb2 import StructType from google.cloud.proto.spanner.v1.type_pb2 import Type subarray_type = Type( code='ARRAY', array_element_type=Type(code='INT64')) array_type = Type(code='ARRAY', array_element_type=subarray_type) iterator = _MockCancellableIterator() streamed = self._make_one(iterator) FIELDS = [ StructType.Field(name='loloi', type=array_type) ] streamed._metadata = self._make_result_set_metadata(FIELDS) streamed._pending_chunk = self._make_list_value(value_pbs=[ self._make_list_value([0, 1]), self._make_list_value([2]), ]) chunk = self._make_list_value(value_pbs=[ self._make_list_value([3]), self._make_list_value([4, 5]), ]) merged = streamed._merge_chunk(chunk) expected = self._make_list_value(value_pbs=[ self._make_list_value([0, 1]), self._make_list_value([23]), self._make_list_value([4, 5]), ]) self.assertEqual(merged, expected) self.assertIsNone(streamed._pending_chunk)
def _makeArrayField(name, element_type_code=None, element_type=None): from google.cloud.proto.spanner.v1.type_pb2 import StructType from google.cloud.proto.spanner.v1.type_pb2 import Type if element_type is None: element_type = Type(code=element_type_code) array_type = Type(code='ARRAY', array_element_type=element_type) return StructType.Field(name=name, type=array_type)
def test__merge_chunk_array_of_array_of_string(self): from google.cloud.proto.spanner.v1.type_pb2 import StructType from google.cloud.proto.spanner.v1.type_pb2 import Type subarray_type = Type(code='ARRAY', array_element_type=Type(code='STRING')) array_type = Type(code='ARRAY', array_element_type=subarray_type) iterator = _MockCancellableIterator() streamed = self._make_one(iterator) FIELDS = [StructType.Field(name='lolos', type=array_type)] streamed._metadata = _ResultSetMetadataPB(FIELDS) streamed._pending_chunk = self._makeListValue(value_pbs=[ self._makeListValue([u'A', u'B']), self._makeListValue([u'C']), ]) chunk = self._makeListValue(value_pbs=[ self._makeListValue([u'D']), self._makeListValue([u'E', u'F']), ]) merged = streamed._merge_chunk(chunk) expected = self._makeListValue(value_pbs=[ self._makeListValue([u'A', u'B']), self._makeListValue([u'CD']), self._makeListValue([u'E', u'F']), ]) self.assertEqual(merged, expected) self.assertIsNone(streamed._pending_chunk)
def _makeStructType(struct_type_fields): from google.cloud.proto.spanner.v1.type_pb2 import StructType from google.cloud.proto.spanner.v1.type_pb2 import Type fields = [ StructType.Field(name=key, type=Type(code=value)) for key, value in struct_type_fields ] struct_type = StructType(fields=fields) return Type(code='STRUCT', struct_type=struct_type)
def test_empty(self): from google.cloud.proto.spanner.v1.type_pb2 import Type, StructType from google.cloud.proto.spanner.v1.type_pb2 import STRING, INT64 struct_type_pb = StructType(fields=[ StructType.Field(name='name', type=Type(code=STRING)), StructType.Field(name='age', type=Type(code=INT64)), ]) self.assertEqual(self._callFUT(rows=[], row_type=struct_type_pb), [])
def test_w_array_non_empty(self): from google.protobuf.struct_pb2 import Value, ListValue from google.cloud.proto.spanner.v1.type_pb2 import Type, ARRAY, INT64 field_type = Type(code=ARRAY, array_element_type=Type(code=INT64)) VALUES = [32, 19, 5] values_pb = ListValue( values=[Value(string_value=str(value)) for value in VALUES]) value_pb = Value(list_value=values_pb) self.assertEqual(self._callFUT(value_pb, field_type), VALUES)
def test_w_struct(self): from google.protobuf.struct_pb2 import Value from google.cloud.proto.spanner.v1.type_pb2 import Type, StructType from google.cloud.proto.spanner.v1.type_pb2 import (STRUCT, STRING, INT64) from google.cloud.spanner._helpers import _make_list_value_pb VALUES = [u'phred', 32] struct_type_pb = StructType(fields=[ StructType.Field(name='name', type=Type(code=STRING)), StructType.Field(name='age', type=Type(code=INT64)), ]) field_type = Type(code=STRUCT, struct_type=struct_type_pb) value_pb = Value(list_value=_make_list_value_pb(VALUES)) self.assertEqual(self._callFUT(value_pb, field_type), VALUES)
def test_w_null(self): from google.protobuf.struct_pb2 import Value, NULL_VALUE from google.cloud.proto.spanner.v1.type_pb2 import Type, STRING field_type = Type(code=STRING) value_pb = Value(null_value=NULL_VALUE) self.assertEqual(self._callFUT(value_pb, field_type), None)
def test_non_empty(self): from google.cloud.proto.spanner.v1.type_pb2 import Type, StructType from google.cloud.proto.spanner.v1.type_pb2 import STRING, INT64 from google.cloud.spanner._helpers import _make_list_value_pbs VALUES = [ [u'phred', 32], [u'bharney', 31], ] struct_type_pb = StructType(fields=[ StructType.Field(name='name', type=Type(code=STRING)), StructType.Field(name='age', type=Type(code=INT64)), ]) values_pbs = _make_list_value_pbs(VALUES) self.assertEqual( self._callFUT(rows=values_pbs, row_type=struct_type_pb), VALUES)
def test_w_bool(self): from google.protobuf.struct_pb2 import Value from google.cloud.proto.spanner.v1.type_pb2 import Type, BOOL VALUE = True field_type = Type(code=BOOL) value_pb = Value(bool_value=VALUE) self.assertEqual(self._callFUT(value_pb, field_type), VALUE)
def test_w_int(self): from google.protobuf.struct_pb2 import Value from google.cloud.proto.spanner.v1.type_pb2 import Type, INT64 VALUE = 12345 field_type = Type(code=INT64) value_pb = Value(string_value=str(VALUE)) self.assertEqual(self._callFUT(value_pb, field_type), VALUE)
def test_w_float(self): from google.protobuf.struct_pb2 import Value from google.cloud.proto.spanner.v1.type_pb2 import Type, FLOAT64 VALUE = 3.14159 field_type = Type(code=FLOAT64) value_pb = Value(number_value=VALUE) self.assertEqual(self._callFUT(value_pb, field_type), VALUE)
def test_w_bytes(self): from google.protobuf.struct_pb2 import Value from google.cloud.proto.spanner.v1.type_pb2 import Type, BYTES VALUE = b'Value' field_type = Type(code=BYTES) value_pb = Value(string_value=VALUE) self.assertEqual(self._callFUT(value_pb, field_type), VALUE)
def test_w_date(self): import datetime from google.protobuf.struct_pb2 import Value from google.cloud.proto.spanner.v1.type_pb2 import Type, DATE VALUE = datetime.date.today() field_type = Type(code=DATE) value_pb = Value(string_value=VALUE.isoformat()) self.assertEqual(self._callFUT(value_pb, field_type), VALUE)
def test_w_unknown_type(self): from google.protobuf.struct_pb2 import Value from google.cloud.proto.spanner.v1.type_pb2 import Type from google.cloud.proto.spanner.v1.type_pb2 import ( TYPE_CODE_UNSPECIFIED) field_type = Type(code=TYPE_CODE_UNSPECIFIED) value_pb = Value(string_value='Borked') with self.assertRaises(ValueError): self._callFUT(value_pb, field_type)
def _query_w_concurrent_update(self, transaction, pkey): SQL = 'SELECT * FROM counters WHERE name = @name' rows = list(transaction.execute_sql( SQL, params={'name': pkey}, param_types={'name': Type(code=STRING)}, )) self.assertEqual(len(rows), 1) pkey, value = rows[0] transaction.update( COUNTERS_TABLE, COUNTERS_COLUMNS, [[pkey, value + 1]])
def test_execute_sql_w_query_param(self): SQL = 'SELECT * FROM contacts WHERE first_name = @first_name' ROW_COUNT = 10 session, _, committed = self._set_up_table(ROW_COUNT) snapshot = session.snapshot(read_timestamp=committed) rows = list(snapshot.execute_sql( SQL, params={'first_name': 'First%09d' % (0,)}, param_types={'first_name': Type(code=STRING)}, )) self.assertEqual(len(rows), 1)
def test_w_timestamp_w_nanos(self): from google.protobuf.struct_pb2 import Value from google.cloud.proto.spanner.v1.type_pb2 import Type, TIMESTAMP from google.cloud._helpers import UTC, _datetime_to_rfc3339 from google.cloud.spanner._helpers import TimestampWithNanoseconds VALUE = TimestampWithNanoseconds(2016, 12, 20, 21, 13, 47, nanosecond=123456789, tzinfo=UTC) field_type = Type(code=TIMESTAMP) value_pb = Value(string_value=_datetime_to_rfc3339(VALUE)) parsed = self._callFUT(value_pb, field_type) self.assertIsInstance(parsed, TimestampWithNanoseconds) self.assertEqual(parsed, VALUE)
def test_execute_sql_w_query_param(self): session = self._db.session() session.create() self.to_delete.append(session) with session.batch() as batch: batch.delete(self.ALL_TYPES_TABLE, self.ALL) batch.insert(self.ALL_TYPES_TABLE, self.ALL_TYPES_COLUMNS, self.ALL_TYPES_ROWDATA) snapshot = session.snapshot(read_timestamp=batch.committed) # Cannot equality-test array values. See below for a test w/ # array of IDs. self._check_sql_results( snapshot, sql='SELECT eye_d FROM all_types WHERE are_you_sure = @sure', params={'sure': True}, param_types={'sure': Type(code=BOOL)}, expected=[(19, ), (99, )], ) self._check_sql_results( snapshot, sql='SELECT eye_d FROM all_types WHERE raw_data = @bytes_1', params={'bytes_1': self.BYTES_1}, param_types={'bytes_1': Type(code=BYTES)}, expected=[(19, ), (99, )], ) self._check_sql_results( snapshot, sql='SELECT eye_d FROM all_types WHERE hwhen = @hwhen', params={'hwhen': self.SOME_DATE}, param_types={'hwhen': Type(code=DATE)}, expected=[(19, )], ) self._check_sql_results( snapshot, sql=('SELECT eye_d FROM all_types WHERE approx_value >= @lower' ' AND approx_value < @upper '), params={ 'lower': 0.0, 'upper': 1.0 }, param_types={ 'lower': Type(code=FLOAT64), 'upper': Type(code=FLOAT64) }, expected=[(19, )], ) # Find -inf self._check_sql_results( snapshot, sql='SELECT eye_d FROM all_types WHERE approx_value = @pos_inf', params={'pos_inf': float('+inf')}, param_types={'pos_inf': Type(code=FLOAT64)}, expected=[(107, )], ) # Find +inf self._check_sql_results( snapshot, sql='SELECT eye_d FROM all_types WHERE approx_value = @neg_inf', params={'neg_inf': float('-inf')}, param_types={'neg_inf': Type(code=FLOAT64)}, expected=[(207, )], ) self._check_sql_results( snapshot, sql='SELECT description FROM all_types WHERE eye_d = @my_id', params={'my_id': 19}, param_types={'my_id': Type(code=INT64)}, expected=[(u'dog', )], ) self._check_sql_results( snapshot, sql='SELECT eye_d FROM all_types WHERE description = @description', params={'description': u'dog'}, param_types={'description': Type(code=STRING)}, expected=[(19, )], ) # NaNs cannot be searched for by equality. self._check_sql_results( snapshot, sql='SELECT eye_d FROM all_types WHERE exactly_hwhen = @hwhen', params={'hwhen': self.SOME_TIME}, param_types={'hwhen': Type(code=TIMESTAMP)}, expected=[(19, )], ) array_type = Type(code=ARRAY, array_element_type=Type(code=INT64)) self._check_sql_results( snapshot, sql=('SELECT description FROM all_types ' 'WHERE eye_d in UNNEST(@my_list)'), params={'my_list': [19, 99]}, param_types={'my_list': array_type}, expected=[(u'dog', ), (u'cat', )], )
def _execute_sql_helper(self, multi_use, first=True, count=0): from google.protobuf.struct_pb2 import Struct from google.cloud.proto.spanner.v1.result_set_pb2 import ( PartialResultSet, ResultSetMetadata, ResultSetStats) from google.cloud.proto.spanner.v1.transaction_pb2 import ( TransactionSelector) from google.cloud.proto.spanner.v1.type_pb2 import Type, StructType from google.cloud.proto.spanner.v1.type_pb2 import STRING, INT64 from google.cloud.spanner._helpers import _make_value_pb TXN_ID = b'DEADBEEF' VALUES = [ [u'bharney', u'rhubbyl', 31], [u'phred', u'phlyntstone', 32], ] VALUE_PBS = [[_make_value_pb(item) for item in row] for row in VALUES] MODE = 2 # PROFILE TOKEN = b'DEADBEEF' struct_type_pb = StructType(fields=[ StructType.Field(name='first_name', type=Type(code=STRING)), StructType.Field(name='last_name', type=Type(code=STRING)), StructType.Field(name='age', type=Type(code=INT64)), ]) metadata_pb = ResultSetMetadata(row_type=struct_type_pb) stats_pb = ResultSetStats(query_stats=Struct( fields={ 'rows_returned': _make_value_pb(2), })) result_sets = [ PartialResultSet(values=VALUE_PBS[0], metadata=metadata_pb), PartialResultSet(values=VALUE_PBS[1], stats=stats_pb), ] iterator = _MockIterator(*result_sets) database = _Database() api = database.spanner_api = _FauxSpannerAPI( _execute_streaming_sql_response=iterator) session = _Session(database) derived = self._makeDerived(session) derived._multi_use = multi_use derived._read_request_count = count if not first: derived._transaction_id = TXN_ID result_set = derived.execute_sql(SQL_QUERY_WITH_PARAM, PARAMS, PARAM_TYPES, query_mode=MODE) self.assertEqual(derived._read_request_count, count + 1) if multi_use: self.assertIs(result_set._source, derived) else: self.assertIsNone(result_set._source) result_set.consume_all() self.assertEqual(list(result_set.rows), VALUES) self.assertEqual(result_set.metadata, metadata_pb) self.assertEqual(result_set.stats, stats_pb) (r_session, sql, transaction, params, param_types, resume_token, query_mode, options) = api._executed_streaming_sql_with self.assertEqual(r_session, self.SESSION_NAME) self.assertEqual(sql, SQL_QUERY_WITH_PARAM) self.assertIsInstance(transaction, TransactionSelector) if multi_use: if first: self.assertTrue(transaction.begin.read_only.strong) else: self.assertEqual(transaction.id, TXN_ID) else: self.assertTrue(transaction.single_use.read_only.strong) expected_params = Struct(fields={ key: _make_value_pb(value) for (key, value) in PARAMS.items() }) self.assertEqual(params, expected_params) self.assertEqual(param_types, PARAM_TYPES) self.assertEqual(query_mode, MODE) self.assertEqual(resume_token, b'') self.assertEqual(options.kwargs['metadata'], [('google-cloud-resource-prefix', database.name)])
def _read_helper(self, multi_use, first=True, count=0): from google.protobuf.struct_pb2 import Struct from google.cloud.proto.spanner.v1.result_set_pb2 import ( PartialResultSet, ResultSetMetadata, ResultSetStats) from google.cloud.proto.spanner.v1.transaction_pb2 import ( TransactionSelector) from google.cloud.proto.spanner.v1.type_pb2 import Type, StructType from google.cloud.proto.spanner.v1.type_pb2 import STRING, INT64 from google.cloud.spanner.keyset import KeySet from google.cloud.spanner._helpers import _make_value_pb TXN_ID = b'DEADBEEF' VALUES = [ [u'bharney', 31], [u'phred', 32], ] VALUE_PBS = [[_make_value_pb(item) for item in row] for row in VALUES] struct_type_pb = StructType(fields=[ StructType.Field(name='name', type=Type(code=STRING)), StructType.Field(name='age', type=Type(code=INT64)), ]) metadata_pb = ResultSetMetadata(row_type=struct_type_pb) stats_pb = ResultSetStats(query_stats=Struct( fields={ 'rows_returned': _make_value_pb(2), })) result_sets = [ PartialResultSet(values=VALUE_PBS[0], metadata=metadata_pb), PartialResultSet(values=VALUE_PBS[1], stats=stats_pb), ] KEYS = ['*****@*****.**', '*****@*****.**'] KEYSET = KeySet(keys=KEYS) INDEX = 'email-address-index' LIMIT = 20 TOKEN = b'DEADBEEF' database = _Database() api = database.spanner_api = _FauxSpannerAPI( _streaming_read_response=_MockIterator(*result_sets)) session = _Session(database) derived = self._makeDerived(session) derived._multi_use = multi_use derived._read_request_count = count if not first: derived._transaction_id = TXN_ID result_set = derived.read(TABLE_NAME, COLUMNS, KEYSET, index=INDEX, limit=LIMIT) self.assertEqual(derived._read_request_count, count + 1) if multi_use: self.assertIs(result_set._source, derived) else: self.assertIsNone(result_set._source) result_set.consume_all() self.assertEqual(list(result_set.rows), VALUES) self.assertEqual(result_set.metadata, metadata_pb) self.assertEqual(result_set.stats, stats_pb) (r_session, table, columns, key_set, transaction, index, limit, resume_token, options) = api._streaming_read_with self.assertEqual(r_session, self.SESSION_NAME) self.assertEqual(table, TABLE_NAME) self.assertEqual(columns, COLUMNS) self.assertEqual(key_set, KEYSET.to_pb()) self.assertIsInstance(transaction, TransactionSelector) if multi_use: if first: self.assertTrue(transaction.begin.read_only.strong) else: self.assertEqual(transaction.id, TXN_ID) else: self.assertTrue(transaction.single_use.read_only.strong) self.assertEqual(index, INDEX) self.assertEqual(limit, LIMIT) self.assertEqual(resume_token, b'') self.assertEqual(options.kwargs['metadata'], [('google-cloud-resource-prefix', database.name)])
def _makeScalarField(name, type_): from google.cloud.proto.spanner.v1.type_pb2 import StructType from google.cloud.proto.spanner.v1.type_pb2 import Type return StructType.Field(name=name, type=Type(code=type_))