1
0
Fork 0
arangodb/3rdParty/iresearch/core/iql/query_builder.hpp

184 lines
7.7 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 by EMC Corporation, All Rights Reserved
///
/// 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.
///
/// Copyright holder is EMC Corporation
///
/// @author Andrey Abramov
/// @author Vasiliy Nabatchikov
////////////////////////////////////////////////////////////////////////////////
#ifndef IRESEARCH_IQL_QUERY_BUILDER_H
#define IRESEARCH_IQL_QUERY_BUILDER_H
#include "shared.hpp"
#include "parser_common.hpp"
#include "search/filter.hpp"
namespace iresearch {
namespace iql {
////////////////////////////////////////////////////////////////////////////////
/// @brief class for passing control to the proxied query
////////////////////////////////////////////////////////////////////////////////
template<typename PTR>
class IRESEARCH_API proxy_filter_t: public iresearch::filter {
public:
proxy_filter_t(const type_id& type): iresearch::filter(type) {}
template<typename T, typename... Args>
T& proxy(Args&&... args) {
typedef typename std::enable_if<
std::is_base_of<iresearch::filter, T>::value, T
>::type type;
filter_ = type::make(std::forward<Args>(args)...);
return static_cast<type&>(*filter_);
}
virtual size_t hash() const NOEXCEPT override {
return !filter_ ? 0 : filter_->hash();
}
virtual iresearch::filter::prepared::ptr prepare(
const index_reader& rdr,
const order::prepared& ord,
boost_t boost,
const attribute_view& ctx
) const override {
return filter_->prepare(rdr, ord, boost, ctx);
};
protected:
virtual bool equals(const iresearch::filter& rhs) const NOEXCEPT override {
const auto& typed_rhs =
static_cast<const iresearch::iql::proxy_filter_t<PTR>&>(rhs);
return filter::equals(rhs) && filter_.get() == typed_rhs.filter_.get();
}
protected:
IRESEARCH_API_PRIVATE_VARIABLES_BEGIN
PTR filter_;
IRESEARCH_API_PRIVATE_VARIABLES_END
};
////////////////////////////////////////////////////////////////////////////////
/// @brief proxy_filter specialized for iresearch::filter::ptr
////////////////////////////////////////////////////////////////////////////////
class IRESEARCH_API proxy_filter: public proxy_filter_t<iresearch::filter::ptr> {
public:
DECLARE_FACTORY_DEFAULT();
DECLARE_TYPE_ID(iresearch::type_id);
proxy_filter(): proxy_filter_t(proxy_filter::type()) {}
};
////////////////////////////////////////////////////////////////////////////////
/// @brief result of the build(...) operation
/// filter set to the root of the query
/// limit iff no limit requested in query then nullptr, else limit value
/// error iff no error then nullptr, else the error string
////////////////////////////////////////////////////////////////////////////////
struct query {
iresearch::filter::ptr filter;
iresearch::order* order = nullptr;
size_t* limit = nullptr;
std::string* error = nullptr;
query(): order(nullptr), limit(nullptr), error(nullptr) {}
query(query&& other):
filter(std::move(other.filter)),
order(other.order),
limit(other.limit),
error(other.error) {
}
};
////////////////////////////////////////////////////////////////////////////////
/// @brief helper class for transforming a textual query into an iResearch query
////////////////////////////////////////////////////////////////////////////////
class IRESEARCH_API query_builder {
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief fns to build an iResearch query branch based at 'root' for field/args
/// @param root the root of the future branch
/// @param locale the locale to be used for building the branch (if needed)
/// @param field the field name mentioned in the IQL query
/// @param cookie the user supplied cookie, passed verbatim to callees
/// @param args the function arguments
/// @return the branch was constructed successfully
////////////////////////////////////////////////////////////////////////////////
typedef std::function<bool(
proxy_filter& root,
const std::locale& locale,
const string_ref& field,
void* const& cookie,
const function_arg::fn_args_t& args
)> branch_builder_function_t;
struct IRESEARCH_API branch_builders {
const branch_builder_function_t& range_ee; // range exclude/exclude - (,)
const branch_builder_function_t& range_ei; // range exclude/include - (,]
const branch_builder_function_t& range_ie; // range include/exclude - [,)
const branch_builder_function_t& range_ii; // range include/exclude - [,]
const branch_builder_function_t& similar;
branch_builders(
const branch_builder_function_t* range_ee = nullptr, // nullptr == default
const branch_builder_function_t* range_ei = nullptr, // nullptr == default
const branch_builder_function_t* range_ie = nullptr, // nullptr == default
const branch_builder_function_t* range_ii = nullptr, // nullptr == default
const branch_builder_function_t* similar = nullptr // nullptr == default
);
branch_builders& operator=(branch_builders&) = delete; // because of refs
static const branch_builders& DEFAULT();
};
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor (use defaults for nullptr param values)
/// @brief iql_functions user defined functions callable within the IQL query
/// @brief fv_transform transform of IQL field/value into iResearch field/value
////////////////////////////////////////////////////////////////////////////////
query_builder(
const functions& iql_functions = functions::DEFAULT(),
const branch_builders& branch_builders = branch_builders::DEFAULT()
);
explicit query_builder(const branch_builders& branch_builders):
query_builder(functions::DEFAULT(), branch_builders) {}
query_builder& operator=(query_builder&) = delete; // because of references
////////////////////////////////////////////////////////////////////////////////
/// @brief transform a textual query into an iResearch query
/// @param query the query to parse/build
/// @param locale the locale to use for parsing/building the query
/// @param cookie a user-defined value passed verbatum to function invocations
/// @param root the node to attach the query under (if not null)
/// @return parsed query, iff error <return>.error != nullptr
////////////////////////////////////////////////////////////////////////////////
query build(
const std::string& query,
const std::locale& locale,
void* cookie = nullptr,
proxy_filter* root = nullptr
) const;
private:
const branch_builders& branch_builders_;
const functions& iql_functions_;
};
}
}
#endif