From 0ef85e2be6ad2eb9ccb65c6888e54b1ae3063eef Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 26 Apr 2015 18:35:05 +0300 Subject: [PATCH] cql3: implement cql3_type support for user types --- cql3/cql3_type.cc | 60 +++++++++++++++++++++++++++++++++++++++ cql3/cql3_type.hh | 71 +++-------------------------------------------- 2 files changed, 64 insertions(+), 67 deletions(-) diff --git a/cql3/cql3_type.cc b/cql3/cql3_type.cc index a7beb8b388..64bcd8a55a 100644 --- a/cql3/cql3_type.cc +++ b/cql3/cql3_type.cc @@ -3,6 +3,7 @@ */ #include "cql3_type.hh" +#include "ut_name.hh" namespace cql3 { @@ -102,6 +103,60 @@ public: } }; +class cql3_type::raw_ut : public raw { + ut_name _name; +public: + raw_ut(ut_name name) + : _name(std::move(name)) { + } + + virtual std::experimental::optional keyspace() const override { + return _name.get_keyspace(); + } + + virtual void freeze() override { + _frozen = true; + } + + virtual shared_ptr prepare(database& db, const sstring& keyspace) 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) + if (!keyspace.empty() && keyspace != _name.get_keyspace()) { + throw exceptions::invalid_request_exception(sprint("Statement on keyspace %s cannot refer to a user type in keyspace %s; " + "user types can only be used in the keyspace they are defined in", + keyspace, _name.get_keyspace())); + } + } else { + _name.set_keyspace(keyspace); + } + + try { + auto&& ks = db.find_keyspace(_name.get_keyspace()); + try { + auto&& type = ks._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)); + } + } catch (no_such_keyspace& nsk) { + throw exceptions::invalid_request_exception("Unknown keyspace " + _name.get_keyspace()); + } + } + + virtual bool supports_freezing() const override { + return true; + } + + virtual sstring to_string() const override { + return _name.to_string(); + } +}; + + class cql3_type::raw_tuple : public raw { std::vector> _types; public: @@ -166,6 +221,11 @@ cql3_type::raw::from(shared_ptr type) { return ::make_shared(type); } +shared_ptr +cql3_type::raw::user_type(ut_name name) { + return ::make_shared(name); +} + shared_ptr cql3_type::raw::map(shared_ptr t1, shared_ptr t2) { return make_shared(raw_collection(&collection_type_impl::kind::map, std::move(t1), std::move(t2))); diff --git a/cql3/cql3_type.hh b/cql3/cql3_type.hh index 14db8eba75..76b6481d8f 100644 --- a/cql3/cql3_type.hh +++ b/cql3/cql3_type.hh @@ -33,6 +33,8 @@ class database; namespace cql3 { +class ut_name; + class cql3_type final { sstring _name; data_type _type; @@ -57,12 +59,7 @@ public: virtual void freeze(); virtual shared_ptr prepare(database& db, const sstring& keyspace) = 0; static shared_ptr from(shared_ptr type); -#if 0 - public static Raw userType(UTName name) - { - return new RawUT(name); - } -#endif + static shared_ptr user_type(ut_name name); static shared_ptr map(shared_ptr t1, shared_ptr t2); static shared_ptr list(shared_ptr t); static shared_ptr set(shared_ptr t); @@ -81,67 +78,7 @@ public: private: class raw_type; class raw_collection; -#if 0 - private static class RawUT extends Raw - { - private final UTName name; - - private RawUT(UTName name) - { - this.name = name; - } - - public String keyspace() - { - return name.getKeyspace(); - } - - public void freeze() - { - frozen = true; - } - - public CQL3Type prepare(String keyspace) throws InvalidRequestException - { - if (name.hasKeyspace()) - { - // 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) - if (keyspace != null && !keyspace.equals(name.getKeyspace())) - throw new InvalidRequestException(String.format("Statement on keyspace %s cannot refer to a user type in keyspace %s; " - + "user types can only be used in the keyspace they are defined in", - keyspace, name.getKeyspace())); - } - else - { - name.setKeyspace(keyspace); - } - - KSMetaData ksm = Schema.instance.getKSMetaData(name.getKeyspace()); - if (ksm == null) - throw new InvalidRequestException("Unknown keyspace " + name.getKeyspace()); - UserType type = ksm.userTypes.getType(name.getUserTypeName()); - if (type == null) - throw new InvalidRequestException("Unknown type " + name); - - if (!frozen) - throw new InvalidRequestException("Non-frozen User-Defined types are not supported, please use frozen<>"); - - return new UserDefined(name.toString(), type); - } - - protected boolean supportsFreezing() - { - return true; - } - - @Override - public String toString() - { - return name.toString(); - } - } -#endif + class raw_ut; class raw_tuple; friend std::ostream& operator<<(std::ostream& os, const cql3_type& t) { return os << t.to_string();