From a64cd8f22fbd8386adf0c295fd3582259acaa1ee Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 11 Mar 2015 13:19:30 +0200 Subject: [PATCH] cql3: convert maps::literal to C++ --- cql3/maps.hh | 77 ++++++++++++++++++++++++++++------------------------ cql3/term.hh | 2 +- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/cql3/maps.hh b/cql3/maps.hh index b96d8f0565..e6b79c086d 100644 --- a/cql3/maps.hh +++ b/cql3/maps.hh @@ -29,6 +29,8 @@ #include "cql3/term.hh" #include "operation.hh" #include "update_parameters.hh" +#include "exceptions/exceptions.hh" +#include "cql3/cql3_type.hh" namespace cql3 { @@ -86,49 +88,52 @@ public: { } virtual ::shared_ptr prepare(const sstring& keyspace, ::shared_ptr receiver) override { - throw std::runtime_error("not implemented"); -#if 0 - validateAssignableTo(keyspace, receiver); + validate_assignable_to(keyspace, *receiver); - ColumnSpecification keySpec = Maps.keySpecOf(receiver); - ColumnSpecification valueSpec = Maps.valueSpecOf(receiver); - Map values = new HashMap(entries.size()); - boolean allTerminal = true; - for (Pair entry : entries) - { - Term k = entry.left.prepare(keyspace, keySpec); - Term v = entry.right.prepare(keyspace, valueSpec); + auto key_spec = maps::key_spec_of(*receiver); + auto value_spec = maps::value_spec_of(*receiver); + std::unordered_map, shared_ptr> values; + values.reserve(entries.size()); + bool all_terminal = true; + for (auto&& entry : entries) { + auto k = entry.first->prepare(keyspace, key_spec); + auto v = entry.second->prepare(keyspace, value_spec); - if (k.containsBindMarker() || v.containsBindMarker()) - throw new InvalidRequestException(String.format("Invalid map literal for %s: bind variables are not supported inside collection literals", receiver.name)); + if (k->contains_bind_marker() || v->contains_bind_marker()) { + throw exceptions::invalid_request_exception(sprint("Invalid map literal for %s: bind variables are not supported inside collection literals", *receiver->name)); + } - if (k instanceof Term.NonTerminal || v instanceof Term.NonTerminal) - allTerminal = false; + if (dynamic_pointer_cast(k) || dynamic_pointer_cast(v)) { + all_terminal = false; + } - values.put(k, v); + values.emplace(k, v); } - DelayedValue value = new DelayedValue(((MapType)receiver.type).getKeysType(), values); - return allTerminal ? value.bind(QueryOptions.DEFAULT) : value; -#endif - } - -#if 0 - private void validateAssignableTo(String keyspace, ColumnSpecification receiver) throws InvalidRequestException - { - if (!(receiver.type instanceof MapType)) - throw new InvalidRequestException(String.format("Invalid map literal for %s of type %s", receiver.name, receiver.type.asCQL3Type())); - - ColumnSpecification keySpec = Maps.keySpecOf(receiver); - ColumnSpecification valueSpec = Maps.valueSpecOf(receiver); - for (Pair entry : entries) - { - if (!entry.left.testAssignment(keyspace, keySpec).isAssignable()) - throw new InvalidRequestException(String.format("Invalid map literal for %s: key %s is not of type %s", receiver.name, entry.left, keySpec.type.asCQL3Type())); - if (!entry.right.testAssignment(keyspace, valueSpec).isAssignable()) - throw new InvalidRequestException(String.format("Invalid map literal for %s: value %s is not of type %s", receiver.name, entry.right, valueSpec.type.asCQL3Type())); + delayed_value value(static_pointer_cast(receiver->type)->get_keys_type()->as_less_comparator(), values); + if (all_terminal) { + return value.bind(query_options::DEFAULT); + } else { + return make_shared(std::move(value)); } } -#endif + + private: + void validate_assignable_to(const sstring& keyspace, column_specification& receiver) { + if (!dynamic_pointer_cast(receiver.type)) { + throw exceptions::invalid_request_exception(sprint("Invalid map literal for %s of type %s", *receiver.name, *receiver.type->as_cql3_type())); + } + auto&& key_spec = maps::key_spec_of(receiver); + auto&& value_spec = maps::value_spec_of(receiver); + for (auto&& entry : entries) { + if (!is_assignable(entry.first->test_assignment(keyspace, key_spec))) { + throw exceptions::invalid_request_exception(sprint("Invalid map literal for %s: key %s is not of type %s", *receiver.name, *entry.first, *key_spec->type->as_cql3_type())); + } + if (!is_assignable(entry.second->test_assignment(keyspace, value_spec))) { + throw exceptions::invalid_request_exception(sprint("Invalid map literal for %s: value %s is not of type %s", *receiver.name, *entry.second, *value_spec->type->as_cql3_type())); + } + } + } + public: virtual assignment_testable::test_result test_assignment(const sstring& keyspace, ::shared_ptr receiver) override { throw std::runtime_error("not implemented"); diff --git a/cql3/term.hh b/cql3/term.hh index 7431a7fde6..bd378b4f30 100644 --- a/cql3/term.hh +++ b/cql3/term.hh @@ -122,7 +122,6 @@ public: virtual ::shared_ptr prepare(const sstring& keyspace, const std::vector& receiver) = 0; }; }; - /** * A terminal term, one that can be reduced to a byte buffer directly. * @@ -204,6 +203,7 @@ public: return {}; }; }; + } #endif