//////////////////////////////////////////////////////////////////////////////// /// @brief fundamental types for the optimisation and execution of AQL /// /// @file arangod/Aql/AqlValue.h /// /// DISCLAIMER /// /// Copyright 2010-2014 triagens GmbH, Cologne, Germany /// /// 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 triAGENS GmbH, Cologne, Germany /// /// @author Max Neunhoeffer /// @author Copyright 2014, triagens GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// #ifndef ARANGODB_AQL_AQL_VALUE_H #define ARANGODB_AQL_AQL_VALUE_H 1 #include "Basics/Common.h" #include "Aql/Range.h" #include "Aql/types.h" #include "Basics/JsonHelper.h" #include "Basics/StringBuffer.h" #include "Utils/V8TransactionContext.h" #include "Utils/AqlTransaction.h" #include "VocBase/document-collection.h" namespace triagens { namespace aql { class AqlItemBlock; // ----------------------------------------------------------------------------- // --SECTION-- struct AqlValue // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief a struct to hold a value, registers hole AqlValue* during the /// execution //////////////////////////////////////////////////////////////////////////////// struct AqlValue { // ----------------------------------------------------------------------------- // --SECTION-- typedefs // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief AqlValueType, indicates what sort of value we have //////////////////////////////////////////////////////////////////////////////// enum AqlValueType { EMPTY, // contains no data JSON, // Json* SHAPED, // TRI_df_marker_t* DOCVEC, // a vector of blocks of results coming from a subquery RANGE // a pointer to a range remembering lower and upper bound }; // ----------------------------------------------------------------------------- // --SECTION-- constructors / destructors // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief constructors for the various value types, note that they all take /// ownership of the corresponding pointers //////////////////////////////////////////////////////////////////////////////// AqlValue () : _json(nullptr), _type(EMPTY) { } explicit AqlValue (triagens::basics::Json* json) : _json(json), _type(JSON) { } explicit AqlValue (TRI_df_marker_t const* marker) : _marker(marker), _type(SHAPED) { } explicit AqlValue (std::vector* vector) : _vector(vector), _type(DOCVEC) { } AqlValue (int64_t low, int64_t high) : _range(nullptr), _type(RANGE) { _range = new Range(low, high); } //////////////////////////////////////////////////////////////////////////////// /// @brief destructor, doing nothing automatically! //////////////////////////////////////////////////////////////////////////////// ~AqlValue () { } // ----------------------------------------------------------------------------- // --SECTION-- public methods // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief return the value type //////////////////////////////////////////////////////////////////////////////// inline AqlValueType type () const noexcept { return _type; } //////////////////////////////////////////////////////////////////////////////// /// @brief a quick method to decide whether the destroy value needs to be /// called for a value //////////////////////////////////////////////////////////////////////////////// inline bool requiresDestruction () const noexcept { return (_type != EMPTY && _type != SHAPED); } //////////////////////////////////////////////////////////////////////////////// /// @brief a quick method to decide whether a value is empty //////////////////////////////////////////////////////////////////////////////// inline bool isEmpty () const noexcept { return _type == EMPTY; } //////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the AqlValue is a shape //////////////////////////////////////////////////////////////////////////////// inline bool isShaped () const noexcept { return _type == SHAPED; } //////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the AqlValue is a JSON //////////////////////////////////////////////////////////////////////////////// inline bool isJson () const noexcept { return _type == JSON; } //////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the AqlValue is a RANGE //////////////////////////////////////////////////////////////////////////////// inline bool isRange () const noexcept { return _type == RANGE; } //////////////////////////////////////////////////////////////////////////////// /// @brief return the shape marker //////////////////////////////////////////////////////////////////////////////// TRI_df_marker_t const* getMarker () const { TRI_ASSERT_EXPENSIVE(isShaped()); return _marker; } //////////////////////////////////////////////////////////////////////////////// /// @brief return the range //////////////////////////////////////////////////////////////////////////////// inline Range const* getRange () const { TRI_ASSERT(isRange()); return _range; } //////////////////////////////////////////////////////////////////////////////// /// @brief a quick method to decide whether a value is true //////////////////////////////////////////////////////////////////////////////// bool isTrue () const; //////////////////////////////////////////////////////////////////////////////// /// @brief erase, this does not free the stuff in the AqlValue, it only /// erases the pointers and makes the AqlValue structure EMPTY, this /// is used when the AqlValue is stolen and stored in another object //////////////////////////////////////////////////////////////////////////////// inline void erase () noexcept { _type = EMPTY; _json = nullptr; } //////////////////////////////////////////////////////////////////////////////// /// @brief destroy, explicit destruction, only when needed //////////////////////////////////////////////////////////////////////////////// void destroy (); //////////////////////////////////////////////////////////////////////////////// /// @brief get the name of an AqlValue type //////////////////////////////////////////////////////////////////////////////// std::string getTypeString () const; //////////////////////////////////////////////////////////////////////////////// /// @brief clone for recursive copying //////////////////////////////////////////////////////////////////////////////// AqlValue clone () const; //////////////////////////////////////////////////////////////////////////////// /// @brief shallow clone //////////////////////////////////////////////////////////////////////////////// AqlValue shallowClone () const; //////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the AqlValue contains a string value //////////////////////////////////////////////////////////////////////////////// bool isString () const; //////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the AqlValue contains a numeric value //////////////////////////////////////////////////////////////////////////////// bool isNumber () const; //////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the AqlValue contains a boolean value //////////////////////////////////////////////////////////////////////////////// bool isBoolean () const; //////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the AqlValue contains an array value //////////////////////////////////////////////////////////////////////////////// bool isArray () const; //////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the AqlValue contains an object value //////////////////////////////////////////////////////////////////////////////// bool isObject () const; //////////////////////////////////////////////////////////////////////////////// /// @brief whether or not the AqlValue contains a null value //////////////////////////////////////////////////////////////////////////////// bool isNull (bool emptyIsNull) const; //////////////////////////////////////////////////////////////////////////////// /// @brief returns the array member at position i //////////////////////////////////////////////////////////////////////////////// triagens::basics::Json at (triagens::arango::AqlTransaction*, size_t i) const; //////////////////////////////////////////////////////////////////////////////// /// @brief returns the length of an AqlValue containing an array //////////////////////////////////////////////////////////////////////////////// size_t arraySize () const; //////////////////////////////////////////////////////////////////////////////// /// @brief get the numeric value of an AqlValue //////////////////////////////////////////////////////////////////////////////// int64_t toInt64 () const; //////////////////////////////////////////////////////////////////////////////// /// @brief get the numeric value of an AqlValue //////////////////////////////////////////////////////////////////////////////// double toNumber (bool&) const; //////////////////////////////////////////////////////////////////////////////// /// @brief get a string representation of the AqlValue /// this will fail if the value is not a string //////////////////////////////////////////////////////////////////////////////// std::string toString () const; //////////////////////////////////////////////////////////////////////////////// /// @brief construct a V8 value as input for the expression execution in V8 //////////////////////////////////////////////////////////////////////////////// v8::Handle toV8 (v8::Isolate* isolate, triagens::arango::AqlTransaction*, TRI_document_collection_t const*) const; //////////////////////////////////////////////////////////////////////////////// /// @brief construct a V8 value as input for the expression execution in V8 /// only construct those attributes that are needed in the expression //////////////////////////////////////////////////////////////////////////////// v8::Handle toV8Partial (v8::Isolate* isolate, triagens::arango::AqlTransaction*, std::unordered_set const&, TRI_document_collection_t const*) const; //////////////////////////////////////////////////////////////////////////////// /// @brief toJson method //////////////////////////////////////////////////////////////////////////////// triagens::basics::Json toJson (triagens::arango::AqlTransaction*, TRI_document_collection_t const*, bool) const; //////////////////////////////////////////////////////////////////////////////// /// @brief creates a hash value for the AqlValue //////////////////////////////////////////////////////////////////////////////// uint64_t hash (triagens::arango::AqlTransaction*, TRI_document_collection_t const*) const; //////////////////////////////////////////////////////////////////////////////// /// @brief extract an attribute value from the AqlValue /// this will return null if the value is not an object //////////////////////////////////////////////////////////////////////////////// triagens::basics::Json extractObjectMember (triagens::arango::AqlTransaction*, TRI_document_collection_t const*, char const*, bool, triagens::basics::StringBuffer&) const; //////////////////////////////////////////////////////////////////////////////// /// @brief extract a value from an array AqlValue /// this will return null if the value is not an array /// depending on the last parameter, the return value will either contain a /// copy of the original value in the array or a reference to it (which must /// not be freed) //////////////////////////////////////////////////////////////////////////////// triagens::basics::Json extractArrayMember (triagens::arango::AqlTransaction*, TRI_document_collection_t const*, int64_t, bool) const; //////////////////////////////////////////////////////////////////////////////// /// @brief create an AqlValue from a vector of AqlItemBlock*s //////////////////////////////////////////////////////////////////////////////// static AqlValue CreateFromBlocks (triagens::arango::AqlTransaction*, std::vector const&, std::vector const&); //////////////////////////////////////////////////////////////////////////////// /// @brief create an AqlValue from a vector of AqlItemBlock*s //////////////////////////////////////////////////////////////////////////////// static AqlValue CreateFromBlocks (triagens::arango::AqlTransaction*, std::vector const&, triagens::aql::RegisterId); //////////////////////////////////////////////////////////////////////////////// /// @brief 3-way comparison for AqlValue objects //////////////////////////////////////////////////////////////////////////////// static int Compare (triagens::arango::AqlTransaction*, AqlValue const&, TRI_document_collection_t const*, AqlValue const&, TRI_document_collection_t const*, bool compareUtf8); // ----------------------------------------------------------------------------- // --SECTION-- public variables // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief the actual data //////////////////////////////////////////////////////////////////////////////// union { triagens::basics::Json* _json; TRI_df_marker_t const* _marker; std::vector* _vector; Range const* _range; }; //////////////////////////////////////////////////////////////////////////////// /// @brief _type, the type of value //////////////////////////////////////////////////////////////////////////////// AqlValueType _type; }; } //closes namespace triagens::aql } //closes namespace triagens // ----------------------------------------------------------------------------- // --SECTION-- hash function helpers for AqlValue // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief hash function for AqlValue objects //////////////////////////////////////////////////////////////////////////////// namespace std { template<> struct hash { size_t operator () (triagens::aql::AqlValue const& x) const { std::hash intHash; std::hash ptrHash; size_t res = intHash(static_cast(x._type)); switch (x._type) { case triagens::aql::AqlValue::JSON: { return res ^ ptrHash(x._json); } case triagens::aql::AqlValue::SHAPED: { return res ^ ptrHash(x._marker); } case triagens::aql::AqlValue::DOCVEC: { return res ^ ptrHash(x._vector); } case triagens::aql::AqlValue::RANGE: { return res ^ ptrHash(x._range); } case triagens::aql::AqlValue::EMPTY: { return res; } } TRI_ASSERT(false); return 0; } }; template<> struct equal_to { bool operator () (triagens::aql::AqlValue const& a, triagens::aql::AqlValue const& b) const { if (a._type != b._type) { return false; } switch (a._type) { case triagens::aql::AqlValue::JSON: { return a._json == b._json; } case triagens::aql::AqlValue::SHAPED: { return a._marker == b._marker; } case triagens::aql::AqlValue::DOCVEC: { return a._vector == b._vector; } case triagens::aql::AqlValue::RANGE: { return a._range == b._range; } // case triagens::aql::AqlValue::EMPTY intentionally not handled here! // (should fall through and fail!) default: { TRI_ASSERT(false); return true; } } } }; } //closes namespace std #endif // Local Variables: // mode: outline-minor // outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" // End: