frontend/converters/keys.cc (102 lines of code) (raw):

// // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "frontend/converters/keys.h" #include "zetasql/public/value.h" #include "absl/status/statusor.h" #include "backend/schema/catalog/column.h" #include "backend/schema/catalog/index.h" #include "backend/schema/catalog/table.h" #include "common/errors.h" #include "frontend/converters/values.h" namespace google { namespace spanner { namespace emulator { namespace frontend { namespace { namespace spanner_api = ::google::spanner::v1; absl::StatusOr<backend::Key> KeyFromProtoInternal( const google::protobuf::ListValue& list_pb, const backend::Table& table, bool allow_prefix_key) { // Check that the user did not specify more than the required number of key // parts. For normal tables, this is the size of the primary key. For index // data tables, this is the number of index columns specified in the index // definition. size_t required_key_parts = (table.owner_index() ? table.owner_index()->key_columns().size() : table.primary_key().size()); if (list_pb.values_size() > required_key_parts) { return error::WrongNumberOfKeyParts( (table.owner_index() ? table.owner_index()->Name() : table.Name()), required_key_parts, list_pb.values_size(), list_pb.ShortDebugString()); } // Prefix keys are allowed only when part of key ranges. When prefix keys are // not allowed in other cases, check that the required number of key parts are // present. if (!allow_prefix_key && list_pb.values_size() < required_key_parts) { return error::WrongNumberOfKeyParts( (table.owner_index() ? table.owner_index()->Name() : table.Name()), required_key_parts, list_pb.values_size(), list_pb.ShortDebugString()); } backend::Key key; for (int i = 0; i < list_pb.values_size(); ++i) { ZETASQL_ASSIGN_OR_RETURN( zetasql::Value value, ValueFromProto(list_pb.values(i), table.primary_key()[i]->column()->GetType())); key.AddColumn(value, table.primary_key()[i]->is_descending()); } return key; } } // namespace absl::StatusOr<backend::Key> KeyFromProto( const google::protobuf::ListValue& list_pb, const backend::Table& table) { // Prefix key parts are only allowed in key ranges. return KeyFromProtoInternal(list_pb, table, /*allow_prefix_key=*/false); } absl::StatusOr<backend::KeyRange> KeyRangeFromProto( const spanner_api::KeyRange& range_pb, const backend::Table& table) { // Parse the start endpoint. backend::EndpointType start_type; backend::Key start_key; if (range_pb.has_start_open()) { start_type = backend::EndpointType::kOpen; ZETASQL_ASSIGN_OR_RETURN(start_key, KeyFromProtoInternal(range_pb.start_open(), table, /*allow_prefix_key=*/true)); } else if (range_pb.has_start_closed()) { start_type = backend::EndpointType::kClosed; ZETASQL_ASSIGN_OR_RETURN(start_key, KeyFromProtoInternal(range_pb.start_closed(), table, /*allow_prefix_key=*/true)); } else { return error::KeyRangeMissingStart(); } // Parse the limit endpoint. backend::EndpointType limit_type; backend::Key limit_key; if (range_pb.has_end_open()) { limit_type = backend::EndpointType::kOpen; ZETASQL_ASSIGN_OR_RETURN(limit_key, KeyFromProtoInternal(range_pb.end_open(), table, /*allow_prefix_key=*/true)); } else if (range_pb.has_end_closed()) { limit_type = backend::EndpointType::kClosed; ZETASQL_ASSIGN_OR_RETURN(limit_key, KeyFromProtoInternal(range_pb.end_closed(), table, /*allow_prefix_key=*/true)); } else { return error::KeyRangeMissingEnd(); } return backend::KeyRange(start_type, start_key, limit_type, limit_key); } absl::StatusOr<backend::KeySet> KeySetFromProto( const spanner_api::KeySet& key_set_pb, const backend::Table& table) { backend::KeySet key_set; // Parse individual keys. for (const auto& key_pb : key_set_pb.keys()) { ZETASQL_ASSIGN_OR_RETURN( backend::Key key, KeyFromProtoInternal(key_pb, table, /*allow_prefix_key=*/false)); key_set.AddKey(key); } // Parse key ranges. for (const auto& range_pb : key_set_pb.ranges()) { ZETASQL_ASSIGN_OR_RETURN(backend::KeyRange range, KeyRangeFromProto(range_pb, table)); key_set.AddRange(range); } // Handle the special "all" key set. if (key_set_pb.all()) { key_set.AddRange(backend::KeyRange::All()); } return key_set; } } // namespace frontend } // namespace emulator } // namespace spanner } // namespace google