diff --git a/cql3/cql3_type.cc b/cql3/cql3_type.cc index 77516e971d..2eb7e6e28a 100644 --- a/cql3/cql3_type.cc +++ b/cql3/cql3_type.cc @@ -24,6 +24,15 @@ namespace cql3 { +shared_ptr cql3_type::raw::prepare(database& db, const sstring& keyspace) { + try { + auto&& ks = db.find_keyspace(keyspace); + return prepare_internal(keyspace, ks.metadata()->user_types()); + } catch (no_such_keyspace& nsk) { + throw exceptions::invalid_request_exception("Unknown keyspace " + keyspace); + } +} + class cql3_type::raw_type : public raw { private: shared_ptr _type; @@ -35,6 +44,9 @@ public: virtual shared_ptr prepare(database& db, const sstring& keyspace) { return _type; } + shared_ptr prepare_internal(const sstring&, lw_shared_ptr) override { + return _type; + } virtual bool supports_freezing() const { return false; @@ -76,7 +88,7 @@ public: return true; } - virtual shared_ptr prepare(database& db, const sstring& keyspace) override { + virtual shared_ptr prepare_internal(const sstring& keyspace, lw_shared_ptr user_types) override { assert(_values); // "Got null values type for a collection"; if (!_frozen && _values->supports_freezing() && !_values->_frozen) { @@ -93,12 +105,12 @@ public: } if (_kind == &collection_type_impl::kind::list) { - return make_shared(cql3_type(to_string(), list_type_impl::get_instance(_values->prepare(db, keyspace)->get_type(), !_frozen), false)); + return make_shared(cql3_type(to_string(), list_type_impl::get_instance(_values->prepare_internal(keyspace, user_types)->get_type(), !_frozen), false)); } else if (_kind == &collection_type_impl::kind::set) { - return make_shared(cql3_type(to_string(), set_type_impl::get_instance(_values->prepare(db, keyspace)->get_type(), !_frozen), false)); + return make_shared(cql3_type(to_string(), set_type_impl::get_instance(_values->prepare_internal(keyspace, user_types)->get_type(), !_frozen), false)); } else if (_kind == &collection_type_impl::kind::map) { assert(_keys); // "Got null keys type for a collection"; - return make_shared(cql3_type(to_string(), map_type_impl::get_instance(_keys->prepare(db, keyspace)->get_type(), _values->prepare(db, keyspace)->get_type(), !_frozen), false)); + return make_shared(cql3_type(to_string(), map_type_impl::get_instance(_keys->prepare_internal(keyspace, user_types)->get_type(), _values->prepare_internal(keyspace, user_types)->get_type(), !_frozen), false)); } abort(); } @@ -132,7 +144,7 @@ public: _frozen = true; } - virtual shared_ptr prepare(database& db, const sstring& keyspace) override { + virtual shared_ptr prepare_internal(const sstring& keyspace, lw_shared_ptr user_types) override { if (_name.has_keyspace()) { // The provided keyspace is the one of the current statement this is part of. If it's different from the keyspace of // the UTName, we reject since we want to limit user types to their own keyspace (see #6643) @@ -146,18 +158,13 @@ public: } try { - auto&& ks = db.find_keyspace(_name.get_keyspace()); - try { - auto&& type = ks.metadata()->user_types()->get_type(_name.get_user_type_name()); - if (!_frozen) { - throw exceptions::invalid_request_exception("Non-frozen User-Defined types are not supported, please use frozen<>"); - } - return make_shared(_name.to_string(), std::move(type)); - } catch (std::out_of_range& e) { - throw exceptions::invalid_request_exception(sprint("Unknown type %s", _name)); + auto&& type = user_types->get_type(_name.get_user_type_name()); + if (!_frozen) { + throw exceptions::invalid_request_exception("Non-frozen User-Defined types are not supported, please use frozen<>"); } - } catch (no_such_keyspace& nsk) { - throw exceptions::invalid_request_exception("Unknown keyspace " + _name.get_keyspace()); + return make_shared(_name.to_string(), std::move(type)); + } catch (std::out_of_range& e) { + throw exceptions::invalid_request_exception(sprint("Unknown type %s", _name)); } } @@ -191,7 +198,7 @@ public: } _frozen = true; } - virtual shared_ptr prepare(database& db, const sstring& keyspace) override { + virtual shared_ptr prepare_internal(const sstring& keyspace, lw_shared_ptr user_types) override { if (!_frozen) { freeze(); } @@ -200,7 +207,7 @@ public: if (t->is_counter()) { throw exceptions::invalid_request_exception("Counters are not allowed inside tuples"); } - ts.push_back(t->prepare(db, keyspace)->get_type()); + ts.push_back(t->prepare_internal(keyspace, user_types)->get_type()); } return make_cql3_tuple_type(tuple_type_impl::get_instance(std::move(ts))); } diff --git a/cql3/cql3_type.hh b/cql3/cql3_type.hh index 8fed1d8e90..fb6cfc8625 100644 --- a/cql3/cql3_type.hh +++ b/cql3/cql3_type.hh @@ -47,6 +47,7 @@ #include "enum_set.hh" class database; +class user_types_metadata; namespace cql3 { @@ -76,7 +77,8 @@ public: virtual bool is_counter() const; virtual std::experimental::optional keyspace() const; virtual void freeze(); - virtual shared_ptr prepare(database& db, const sstring& keyspace) = 0; + virtual shared_ptr prepare_internal(const sstring& keyspace, lw_shared_ptr) = 0; + virtual shared_ptr prepare(database& db, const sstring& keyspace); static shared_ptr from(shared_ptr type); static shared_ptr user_type(ut_name name); static shared_ptr map(shared_ptr t1, shared_ptr t2);