/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ /* * Copyright 2015 Cloudius Systems * * Modified by Cloudius Systems */ #pragma once #include "bytes.hh" #include "schema.hh" #include "query-result-reader.hh" #include "cql3/column_specification.hh" #include "exceptions/exceptions.hh" #include "cql3/selection/raw_selector.hh" #include "cql3/selection/selector_factories.hh" #include "unimplemented.hh" namespace cql3 { class result_set; class metadata; namespace selection { class selectors { public: virtual ~selectors() {} virtual bool is_aggregate() = 0; /** * Adds the current row of the specified ResultSetBuilder. * * @param rs the ResultSetBuilder * @throws InvalidRequestException */ virtual void add_input_row(serialization_format sf, result_set_builder& rs) = 0; virtual std::vector get_output_row(serialization_format sf) = 0; virtual void reset() = 0; }; class selection { private: schema_ptr _schema; std::vector _columns; ::shared_ptr _metadata; const bool _collect_timestamps; const bool _collect_TTLs; const bool _contains_static_columns; protected: selection(schema_ptr schema, std::vector columns, std::vector<::shared_ptr> metadata_, bool collect_timestamps, bool collect_TTLs); virtual ~selection() {} public: // Overriden by SimpleSelection when appropriate. virtual bool is_wildcard() const { return false; } /** * Checks if this selection contains static columns. * @return true if this selection contains static columns, false otherwise; */ bool contains_static_columns() const { return _contains_static_columns; } /** * Checks if this selection contains only static columns. * @return true if this selection contains only static columns, false otherwise; */ bool contains_only_static_columns() const { if (!contains_static_columns()) { return false; } if (is_wildcard()) { return false; } for (auto&& def : _columns) { if (!def->is_partition_key() && !def->is_static()) { return false; } } return true; } /** * Checks if this selection contains a collection. * * @return true if this selection contains a collection, false otherwise. */ bool contains_a_collection() const { if (!_schema->has_collections()) { return false; } return std::any_of(_columns.begin(), _columns.end(), [] (auto&& def) { return def->type->is_collection() && def->type->is_multi_cell(); }); } /** * Returns the index of the specified column. * * @param def the column definition * @return the index of the specified column */ int32_t index_of(const column_definition& def) const { auto i = std::find(_columns.begin(), _columns.end(), &def); if (i == _columns.end()) { return -1; } return std::distance(_columns.begin(), i); } bool has_column(const column_definition& def) const { return std::find(_columns.begin(), _columns.end(), &def) != _columns.end(); } ::shared_ptr get_result_metadata() { return _metadata; } static ::shared_ptr wildcard(schema_ptr schema); static ::shared_ptr for_columns(schema_ptr schema, std::vector columns); virtual uint32_t add_column_for_ordering(const column_definition& c); virtual bool uses_function(const sstring &ks_name, const sstring& function_name) const { return false; } query::partition_slice::option_set get_query_options(); private: static bool processes_selection(const std::vector<::shared_ptr>& raw_selectors) { return std::any_of(raw_selectors.begin(), raw_selectors.end(), [] (auto&& s) { return s->processes_selection(); }); } static std::vector<::shared_ptr> collect_metadata(schema_ptr schema, const std::vector<::shared_ptr>& raw_selectors, const selector_factories& factories); public: static ::shared_ptr from_selectors(database& db, schema_ptr schema, const std::vector<::shared_ptr>& raw_selectors); virtual std::unique_ptr new_selectors() = 0; /** * Returns a range of CQL3 columns this selection needs. */ auto const& get_columns() { return _columns; } uint32_t get_column_count() { return _columns.size(); } virtual bool is_aggregate() const = 0; /** * Checks that selectors are either all aggregates or that none of them is. * * @param selectors the selectors to test. * @param messageTemplate the error message template * @param messageArgs the error message arguments * @throws InvalidRequestException if some of the selectors are aggregate but not all of them */ template static void validate_selectors(const std::vector<::shared_ptr>& selectors, const sstring& msg, Args&&... args) { int32_t aggregates = 0; for (auto&& s : selectors) { if (s->is_aggregate()) { ++aggregates; } } if (aggregates != 0 && aggregates != selectors.size()) { throw exceptions::invalid_request_exception(sprint(msg, std::forward(args)...)); } } friend class result_set_builder; }; class result_set_builder { private: std::unique_ptr _result_set; std::unique_ptr _selectors; public: std::experimental::optional> current; private: std::vector _timestamps; std::vector _ttls; const db_clock::time_point _now; serialization_format _serialization_format; public: result_set_builder(selection& s, db_clock::time_point now, serialization_format sf); void add_empty(); void add(bytes_opt value); void add(const column_definition& def, const query::result_atomic_cell_view& c); void add(const column_definition& def, collection_mutation::view c); void new_row(); std::unique_ptr build(); api::timestamp_type timestamp_of(size_t idx); int32_t ttl_of(size_t idx); private: bytes_opt get_value(data_type t, query::result_atomic_cell_view c); }; } }