diff --git a/BasicsC/json.c b/BasicsC/json.c index 3063ef6e0e..96596cbd1d 100644 --- a/BasicsC/json.c +++ b/BasicsC/json.c @@ -151,9 +151,11 @@ TRI_json_t* TRI_CreateNullJson () { TRI_json_t* result; result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t)); - if (!result) { + + if (result == NULL) { return NULL; } + result->_type = TRI_JSON_NULL; return result; @@ -167,9 +169,11 @@ TRI_json_t* TRI_CreateBooleanJson (bool value) { TRI_json_t* result; result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t)); - if (!result) { + + if (result == NULL) { return NULL; } + result->_type = TRI_JSON_BOOLEAN; result->_value._boolean = value; @@ -184,9 +188,11 @@ TRI_json_t* TRI_CreateNumberJson (double value) { TRI_json_t* result; result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t)); - if (!result) { + + if (result == NULL) { return NULL; } + result->_type = TRI_JSON_NUMBER; result->_value._number = value; @@ -213,9 +219,11 @@ TRI_json_t* TRI_CreateStringJson (char* value) { length = strlen(value); result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t)); - if (!result) { + + if (result == NULL) { return NULL; } + result->_type = TRI_JSON_STRING; result->_value._string.length = length + 1; result->_value._string.data = value; @@ -234,13 +242,16 @@ TRI_json_t* TRI_CreateStringCopyJson (char const* value) { length = strlen(value); result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t)); - if (!result) { + + if (result == NULL) { return NULL; } + result->_type = TRI_JSON_STRING; result->_value._string.length = length + 1; result->_value._string.data = TRI_DuplicateString2(value, length); - if (!result->_value._string.data) { + + if (result->_value._string.data == NULL) { TRI_Free(result); return NULL; } @@ -256,9 +267,11 @@ TRI_json_t* TRI_CreateString2Json (char* value, size_t length) { TRI_json_t* result; result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t)); - if (!result) { + + if (result == NULL) { return NULL; } + result->_type = TRI_JSON_STRING; result->_value._string.length = length + 1; result->_value._string.data = value; @@ -274,13 +287,16 @@ TRI_json_t* TRI_CreateString2CopyJson (char const* value, size_t length) { TRI_json_t* result; result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t)); - if (!result) { + + if (result == NULL) { return NULL; } + result->_type = TRI_JSON_STRING; result->_value._string.length = length + 1; result->_value._string.data = TRI_DuplicateString2(value, length); - if (!result->_value._string.data) { + + if (result->_value._string.data == NULL) { TRI_Free(result); return NULL; } @@ -296,9 +312,11 @@ TRI_json_t* TRI_CreateListJson () { TRI_json_t* result; result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t)); - if (!result) { + + if (result == NULL) { return NULL; } + result->_type = TRI_JSON_LIST; TRI_InitVector(&result->_value._objects, sizeof(TRI_json_t)); @@ -313,9 +331,11 @@ TRI_json_t* TRI_CreateArrayJson () { TRI_json_t* result; result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t)); - if (!result) { + + if (result == NULL) { return NULL; } + result->_type = TRI_JSON_ARRAY; TRI_InitVector(&result->_value._objects, sizeof(TRI_json_t)); @@ -356,12 +376,10 @@ void TRI_DestroyJson (TRI_json_t* object) { for (i = 0; i < n; ++i) { TRI_json_t* v = TRI_AtVector(&object->_value._objects, i); - TRI_DestroyJson(v); } TRI_DestroyVector(&object->_value._objects); - break; } } @@ -410,6 +428,8 @@ void TRI_PushBack2ListJson (TRI_json_t* list, TRI_json_t* object) { assert(list->_type == TRI_JSON_LIST); TRI_PushBackVector(&list->_value._objects, object); + + TRI_Free(object); } //////////////////////////////////////////////////////////////////////////////// @@ -427,7 +447,8 @@ void TRI_InsertArrayJson (TRI_json_t* object, char const* name, TRI_json_t* subo copy._type = TRI_JSON_STRING; copy._value._string.length = length + 1; copy._value._string.data = TRI_DuplicateString2(name, length); // including '\0' - if (!copy._value._string.data) { + + if (copy._value._string.data == NULL) { // OOM return; } @@ -454,13 +475,15 @@ void TRI_Insert2ArrayJson (TRI_json_t* object, char const* name, TRI_json_t* sub copy._value._string.length = length + 1; copy._value._string.data = TRI_DuplicateString2(name, length); // including '\0' - if (!copy._value._string.data) { + if (copy._value._string.data == NULL) { // OOM return; } TRI_PushBackVector(&object->_value._objects, ©); TRI_PushBackVector(&object->_value._objects, subobject); + + TRI_Free(subobject); } //////////////////////////////////////////////////////////////////////////////// @@ -551,7 +574,8 @@ bool TRI_SaveJson (char const* filename, TRI_json_t const* object) { ssize_t m; tmp = TRI_Concatenate2String(filename, ".tmp"); - if (!tmp) { + + if (tmp == NULL) { return false; } @@ -671,9 +695,11 @@ TRI_json_t* TRI_CopyJson (TRI_json_t* src) { TRI_json_t* dst; dst = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t)); - if (!dst) { + + if (dst == NULL) { return NULL; } + TRI_CopyToJson(dst, src); return dst; diff --git a/HashIndex/hashindex.c b/HashIndex/hashindex.c index 028daae7fb..e5205f59b7 100755 --- a/HashIndex/hashindex.c +++ b/HashIndex/hashindex.c @@ -331,7 +331,7 @@ static uint64_t hashKey (struct TRI_associative_array_s* associativeArray, void* HashIndex* HashIndex_new() { HashIndex* hashIndex; - hashIndex = malloc(sizeof(HashIndex)); + hashIndex = TRI_Allocate(sizeof(HashIndex)); if (hashIndex == NULL) { return NULL; } diff --git a/Makefile.doxygen b/Makefile.doxygen index 5f8b8553b4..91bd0ade0f 100644 --- a/Makefile.doxygen +++ b/Makefile.doxygen @@ -38,7 +38,7 @@ Doxygen/xml/%.md: Doxygen/xml/%.xml .PHONY: doxygen doxygen: Doxygen/avocado.doxy $(DOXYGEN) - doxygen Doxygen/avocado.doxy + doxygen Doxygen/avocado.doxy > /dev/null ################################################################################ ## wiki diff --git a/Makefile.files b/Makefile.files index 3aa19b9d9f..9ad87165c1 100644 --- a/Makefile.files +++ b/Makefile.files @@ -107,7 +107,7 @@ avocado_SOURCES = \ Rest/SslInterface.cpp \ Rest/Url.cpp \ RestHandler/RestActionHandler.cpp \ - RestHandler/RestDocumentHandler.cpp \ + RestHandler/RestCollectionHandler.cpp \ RestHandler/RestSystemActionHandler.cpp \ RestHandler/RestVocbaseBaseHandler.cpp \ RestServer/ActionDispatcherThread.cpp \ @@ -166,6 +166,7 @@ avocado_SOURCES = \ Variant/VariantUInt64.cpp \ Variant/VariantUInt8.cpp \ Variant/VariantVector.cpp \ + VocBase/barrier.c \ VocBase/blob-collection.c \ VocBase/collection.c \ VocBase/compactor.c \ diff --git a/Makefile.in b/Makefile.in index 344960e420..5a4d18eecc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -192,7 +192,7 @@ am_avocado_OBJECTS = Admin/ApplicationAdminServer.$(OBJEXT) \ Rest/HttpRequest.$(OBJEXT) Rest/HttpResponse.$(OBJEXT) \ Rest/Initialise.$(OBJEXT) Rest/SslInterface.$(OBJEXT) \ Rest/Url.$(OBJEXT) RestHandler/RestActionHandler.$(OBJEXT) \ - RestHandler/RestDocumentHandler.$(OBJEXT) \ + RestHandler/RestCollectionHandler.$(OBJEXT) \ RestHandler/RestSystemActionHandler.$(OBJEXT) \ RestHandler/RestVocbaseBaseHandler.$(OBJEXT) \ RestServer/ActionDispatcherThread.$(OBJEXT) \ @@ -236,7 +236,7 @@ am_avocado_OBJECTS = Admin/ApplicationAdminServer.$(OBJEXT) \ Variant/VariantUInt16.$(OBJEXT) \ Variant/VariantUInt32.$(OBJEXT) \ Variant/VariantUInt64.$(OBJEXT) Variant/VariantUInt8.$(OBJEXT) \ - Variant/VariantVector.$(OBJEXT) \ + Variant/VariantVector.$(OBJEXT) VocBase/barrier.$(OBJEXT) \ VocBase/blob-collection.$(OBJEXT) VocBase/collection.$(OBJEXT) \ VocBase/compactor.$(OBJEXT) VocBase/data-feeder.$(OBJEXT) \ VocBase/datafile.$(OBJEXT) \ @@ -612,7 +612,7 @@ avocado_SOURCES = \ Rest/SslInterface.cpp \ Rest/Url.cpp \ RestHandler/RestActionHandler.cpp \ - RestHandler/RestDocumentHandler.cpp \ + RestHandler/RestCollectionHandler.cpp \ RestHandler/RestSystemActionHandler.cpp \ RestHandler/RestVocbaseBaseHandler.cpp \ RestServer/ActionDispatcherThread.cpp \ @@ -671,6 +671,7 @@ avocado_SOURCES = \ Variant/VariantUInt64.cpp \ Variant/VariantUInt8.cpp \ Variant/VariantVector.cpp \ + VocBase/barrier.c \ VocBase/blob-collection.c \ VocBase/collection.c \ VocBase/compactor.c \ @@ -1206,7 +1207,7 @@ RestHandler/$(DEPDIR)/$(am__dirstamp): @: > RestHandler/$(DEPDIR)/$(am__dirstamp) RestHandler/RestActionHandler.$(OBJEXT): RestHandler/$(am__dirstamp) \ RestHandler/$(DEPDIR)/$(am__dirstamp) -RestHandler/RestDocumentHandler.$(OBJEXT): \ +RestHandler/RestCollectionHandler.$(OBJEXT): \ RestHandler/$(am__dirstamp) \ RestHandler/$(DEPDIR)/$(am__dirstamp) RestHandler/RestSystemActionHandler.$(OBJEXT): \ @@ -1374,6 +1375,8 @@ VocBase/$(am__dirstamp): VocBase/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) VocBase/$(DEPDIR) @: > VocBase/$(DEPDIR)/$(am__dirstamp) +VocBase/barrier.$(OBJEXT): VocBase/$(am__dirstamp) \ + VocBase/$(DEPDIR)/$(am__dirstamp) VocBase/blob-collection.$(OBJEXT): VocBase/$(am__dirstamp) \ VocBase/$(DEPDIR)/$(am__dirstamp) VocBase/collection.$(OBJEXT): VocBase/$(am__dirstamp) \ @@ -1520,7 +1523,7 @@ mostlyclean-compile: -rm -f Rest/SslInterface.$(OBJEXT) -rm -f Rest/Url.$(OBJEXT) -rm -f RestHandler/RestActionHandler.$(OBJEXT) - -rm -f RestHandler/RestDocumentHandler.$(OBJEXT) + -rm -f RestHandler/RestCollectionHandler.$(OBJEXT) -rm -f RestHandler/RestSystemActionHandler.$(OBJEXT) -rm -f RestHandler/RestVocbaseBaseHandler.$(OBJEXT) -rm -f RestServer/ActionDispatcherThread.$(OBJEXT) @@ -1579,6 +1582,7 @@ mostlyclean-compile: -rm -f Variant/VariantUInt64.$(OBJEXT) -rm -f Variant/VariantUInt8.$(OBJEXT) -rm -f Variant/VariantVector.$(OBJEXT) + -rm -f VocBase/barrier.$(OBJEXT) -rm -f VocBase/blob-collection.$(OBJEXT) -rm -f VocBase/collection.$(OBJEXT) -rm -f VocBase/compactor.$(OBJEXT) @@ -1704,7 +1708,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@Rest/$(DEPDIR)/SslInterface.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@Rest/$(DEPDIR)/Url.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@RestHandler/$(DEPDIR)/RestActionHandler.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@RestHandler/$(DEPDIR)/RestDocumentHandler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@RestHandler/$(DEPDIR)/RestCollectionHandler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@RestHandler/$(DEPDIR)/RestSystemActionHandler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@RestHandler/$(DEPDIR)/RestVocbaseBaseHandler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@RestServer/$(DEPDIR)/ActionDispatcherThread.Po@am__quote@ @@ -1763,6 +1767,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@Variant/$(DEPDIR)/VariantUInt64.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@Variant/$(DEPDIR)/VariantUInt8.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@Variant/$(DEPDIR)/VariantVector.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@VocBase/$(DEPDIR)/barrier.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@VocBase/$(DEPDIR)/blob-collection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@VocBase/$(DEPDIR)/collection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@VocBase/$(DEPDIR)/compactor.Po@am__quote@ @@ -2252,7 +2257,7 @@ Doxygen/xml/%.md: Doxygen/xml/%.xml .PHONY: doxygen doxygen: Doxygen/avocado.doxy $(DOXYGEN) - doxygen Doxygen/avocado.doxy + doxygen Doxygen/avocado.doxy > /dev/null ################################################################################ ################################################################################ diff --git a/QL/ParserWrapper.cpp b/QL/ParserWrapper.cpp index 3506a848fd..0ce1fb3957 100644 --- a/QL/ParserWrapper.cpp +++ b/QL/ParserWrapper.cpp @@ -113,7 +113,7 @@ bool ParserWrapper::parse () { _isParsed = true; - if (!QLParseInit(_vocbase,_context, _query)) { + if (!QLParseInit(_vocbase, _context, _query)) { return false; } @@ -123,16 +123,44 @@ bool ParserWrapper::parse () { return false; } - if (!QLParseValidate(_context, _context->_query->_select._base)) { + size_t order; + if (!QLParseValidateCollections(_context, + _context->_query->_select._base, + &QLAstQueryIsValidAlias, + &order)) { + // select expression invalid setParseError(); return false; } - if (!QLParseValidate(_context, _context->_query->_where._base)) { + if (!QLParseValidateCollections(_context, + _context->_query->_where._base, + &QLAstQueryIsValidAlias, + &order)) { + // where expression invalid setParseError(); return false; } - + + if (!QLParseValidateCollections(_context, + _context->_query->_order._base, + &QLAstQueryIsValidAlias, + &order)) { + // where expression invalid + setParseError(); + return false; + } + + order = 0; + if (!QLParseValidateCollections(_context, + _context->_query->_from._base, + &QLAstQueryIsValidAliasOrdered, + &order)) { + // from expression(s) invalid + setParseError(); + return false; + } + return true; } diff --git a/QL/ast-query.c b/QL/ast-query.c index 5eb79bdb2d..69512ea443 100644 --- a/QL/ast-query.c +++ b/QL/ast-query.c @@ -61,7 +61,9 @@ static uint64_t HashElement (TRI_associative_pointer_t* array, void const* eleme /// @brief Comparison function used to determine hash key equality //////////////////////////////////////////////////////////////////////////////// -static bool EqualKeyElement (TRI_associative_pointer_t* array, void const* key, void const* element) { +static bool EqualKeyElement (TRI_associative_pointer_t* array, + void const* key, + void const* element) { char const* k = (char const*) key; QL_ast_query_collection_t *collection = (QL_ast_query_collection_t*) element; @@ -154,10 +156,32 @@ void QLAstQueryAddRefCount (QL_ast_query_t* query, const char* alias) { /// @brief Check if a collection was defined in a query //////////////////////////////////////////////////////////////////////////////// -bool QLAstQueryIsValidAlias (QL_ast_query_t* query, const char* alias) { +bool QLAstQueryIsValidAlias (QL_ast_query_t* query, + const char* alias, + const size_t order) { return (0 != TRI_LookupByKeyAssociativePointer(&query->_from._collections, alias)); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief Check if a collection was defined in a query, taking order of +/// declaration into account +//////////////////////////////////////////////////////////////////////////////// + +bool QLAstQueryIsValidAliasOrdered (QL_ast_query_t* query, + const char* alias, + const size_t order) { + QL_ast_query_collection_t* collection; + + collection = (QL_ast_query_collection_t*) + TRI_LookupByKeyAssociativePointer(&query->_from._collections, alias); + + if (!collection) { + return false; + } + + return (collection->_declarationOrder <= order); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief Return the collection name for its alias //////////////////////////////////////////////////////////////////////////////// @@ -183,6 +207,7 @@ bool QLAstQueryAddCollection (QL_ast_query_t* query, const char* alias) { QL_ast_query_collection_t* collection; QL_ast_query_collection_t* previous; + size_t num; previous = (QL_ast_query_collection_t*) TRI_LookupByKeyAssociativePointer (&query->_from._collections, alias); @@ -192,17 +217,20 @@ bool QLAstQueryAddCollection (QL_ast_query_t* query, return false; } - collection = (QL_ast_query_collection_t *) TRI_Allocate(sizeof(QL_ast_query_collection_t)); + collection = + (QL_ast_query_collection_t *) TRI_Allocate(sizeof(QL_ast_query_collection_t)); if (collection == 0) { return false; } - collection->_name = (char*) name; - collection->_alias = (char*) alias; - // first collection added is always the primary collection - collection->_isPrimary = (&query->_from._collections._nrUsed == 0); - collection->_refCount = 0; // will be used later when optimizing joins + num = query->_from._collections._nrUsed; + collection->_name = (char*) name; + collection->_alias = (char*) alias; + // first collection added is always the primary collection + collection->_isPrimary = (num == 0); + collection->_refCount = 0; // will be used later when optimizing joins + collection->_declarationOrder = num + 1; TRI_InsertKeyAssociativePointer(&query->_from._collections, collection->_alias, collection, diff --git a/QL/ast-query.h b/QL/ast-query.h index 96edcc6e40..5331201dcd 100644 --- a/QL/ast-query.h +++ b/QL/ast-query.h @@ -177,10 +177,11 @@ QL_ast_query_t; //////////////////////////////////////////////////////////////////////////////// typedef struct QL_ast_query_collection_s { - char* _name; - char* _alias; - bool _isPrimary; + char* _name; + char* _alias; + bool _isPrimary; size_t _refCount; + size_t _declarationOrder; } QL_ast_query_collection_t; @@ -212,7 +213,14 @@ void QLAstQueryAddRefCount (QL_ast_query_t*, const char*); /// @brief Check if a collection was defined in a query //////////////////////////////////////////////////////////////////////////////// -bool QLAstQueryIsValidAlias (QL_ast_query_t*, const char*); +bool QLAstQueryIsValidAlias (QL_ast_query_t*, const char*, const size_t); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief Check if a collection was defined in a query, taking order of +/// declaration into account +//////////////////////////////////////////////////////////////////////////////// + +bool QLAstQueryIsValidAliasOrdered (QL_ast_query_t*, const char*, const size_t); //////////////////////////////////////////////////////////////////////////////// /// @brief Return the collection name for its alias diff --git a/QL/javascripter.c b/QL/javascripter.c index 57e63a48fe..b4d02d21b6 100644 --- a/QL/javascripter.c +++ b/QL/javascripter.c @@ -129,10 +129,10 @@ void QLJavascripterConvert (QL_javascript_conversion_t* converter, TRI_AppendStringStringBuffer(converter->_buffer, node->_value._boolValue ? "true" : "false"); return; case QLNodeValueString: - TRI_AppendCharStringBuffer(converter->_buffer, '\''); + TRI_AppendCharStringBuffer(converter->_buffer, '"'); TRI_AppendStringStringBuffer(converter->_buffer, TRI_EscapeUtf8String(node->_value._stringValue, strlen(node->_value._stringValue), false, &outLength)); - TRI_AppendCharStringBuffer(converter->_buffer, '\''); + TRI_AppendCharStringBuffer(converter->_buffer, '"'); return; case QLNodeValueNumberInt: TRI_AppendInt64StringBuffer(converter->_buffer, node->_value._intValue); diff --git a/QL/optimize.c b/QL/optimize.c index 1f79e2b535..7fe1f1d9d6 100644 --- a/QL/optimize.c +++ b/QL/optimize.c @@ -820,6 +820,7 @@ void QLOptimizeFrom (const QL_parser_context_t* context) { QL_ast_node_t* next = 0; QL_ast_node_t* node = (QL_ast_node_t*) context->_query->_from._base; + // count usages of collections in select, where and order clause QLOptimizeCountRefs(context); responsibleNode = node; @@ -848,6 +849,7 @@ void QLOptimizeFrom (const QL_parser_context_t* context) { (next->_type == QLNodeJoinLeft || next->_type == QLNodeJoinRight || next->_type == QLNodeJoinList)) { + // collection is joined but unused in select, where, order clause // remove unused list or outer joined collections // move joined collection one up node->_next = next->_next; @@ -928,13 +930,18 @@ void QLOptimizeFreeRangeVector (TRI_vector_pointer_t* vector) { TRI_FreeString(range->_refValue._field); } - if ((range->_valueType == RANGE_TYPE_STRING || range->_valueType == RANGE_TYPE_JSON) - && range->_minValue._stringValue) { + if (range->_valueType == RANGE_TYPE_JSON) { + // minValue and maxValue point to the same string, just free it once! TRI_FreeString(range->_minValue._stringValue); } - if ((range->_valueType == RANGE_TYPE_STRING || range->_valueType == RANGE_TYPE_JSON) - && range->_maxValue._stringValue) { - TRI_FreeString(range->_maxValue._stringValue); + + if (range->_valueType == RANGE_TYPE_STRING) { + if (range->_minValue._stringValue) { + TRI_FreeString(range->_minValue._stringValue); + } + if (range->_maxValue._stringValue) { + TRI_FreeString(range->_maxValue._stringValue); + } } TRI_Free(range); @@ -1407,7 +1414,8 @@ static QL_optimize_range_t* QLOptimizeCreateRange (QL_ast_node_t* memberNode, // range is of type string range->_valueType = RANGE_TYPE_STRING; } - else if (valueNode->_type == QLNodeValueDocument) { + else if (valueNode->_type == QLNodeValueDocument || + valueNode->_type == QLNodeValueArray) { range->_valueType = RANGE_TYPE_JSON; } else if (valueNode->_type == QLNodeContainerMemberAccess) { @@ -1457,9 +1465,15 @@ static QL_optimize_range_t* QLOptimizeCreateRange (QL_ast_node_t* memberNode, return NULL; } QLJavascripterConvert(documentJs, valueNode); - range->_minValue._stringValue = documentJs->_buffer->_buffer; + range->_minValue._stringValue = TRI_DuplicateString(documentJs->_buffer->_buffer); range->_maxValue._stringValue = range->_minValue._stringValue; QLJavascripterFree(documentJs); + if (!range->_minValue._stringValue) { + TRI_FreeStringBuffer(name); + TRI_Free(name); + TRI_Free(range); + return NULL; + } } range->_minStatus = RANGE_VALUE_INCLUDED; range->_maxStatus = RANGE_VALUE_INCLUDED; @@ -1563,7 +1577,9 @@ TRI_vector_pointer_t* QLOptimizeCondition (QL_ast_node_t* node) { type == QLNodeBinaryOperatorGreaterEqual) { // comparison operator if (lhs->_type == QLNodeContainerMemberAccess && - rhs->_type == QLNodeContainerMemberAccess) { + rhs->_type == QLNodeContainerMemberAccess && + (type == QLNodeBinaryOperatorIdentical || + type == QLNodeBinaryOperatorEqual)) { // collection.attribute relop collection.attribute return QLOptimizeMergeRangeVectors( QLOptimizeCreateRangeVector(QLOptimizeCreateRange(lhs, rhs, type)), @@ -1573,7 +1589,7 @@ TRI_vector_pointer_t* QLOptimizeCondition (QL_ast_node_t* node) { else if (lhs->_type == QLNodeContainerMemberAccess && (type == QLNodeBinaryOperatorIdentical || type == QLNodeBinaryOperatorEqual) && - rhs->_type == QLNodeValueDocument && + (rhs->_type == QLNodeValueDocument || rhs->_type == QLNodeValueArray) && QLOptimizeIsStaticDocument(rhs)) { // collection.attribute == document return QLOptimizeCreateRangeVector(QLOptimizeCreateRange(lhs, rhs, type)); diff --git a/QL/optimize.h b/QL/optimize.h index 21ffea6e0c..bcf1c57406 100644 --- a/QL/optimize.h +++ b/QL/optimize.h @@ -46,11 +46,13 @@ extern "C" { #endif //////////////////////////////////////////////////////////////////////////////// -/// @page optimizer Query optimizer +/// @page Optimizer Query optimizer /// /// The AQL query optimizer inspects incoming select queries and applies simple /// transformations to optimize them. The goal of all optimization is to do /// less work when executing the query and produce the results faster. +/// +/// @section Optimizer transformations /// /// Currently, the AQL query optimizer applies the following transformations: /// - constant folding: numeric literals, boolean values and null are folded @@ -77,6 +79,15 @@ extern "C" { /// are combined with logical ands. For example, the following range condition /// will be detected as being impossible and removed: /// @LIT{users.id > 3 && users.id < 3} +/// +/// @section Optimizer issues +/// +/// The optimizer currently cannot optimize subconditions combined with a +/// logical @LIT{||}. Furthermore, it will not optimize negated conditions or +/// subconditions. It can only combine multiple subconditions on the same +/// attribute if the compare values have the same type (numeric or string). +/// The optimizer will not merge conditions from the where clause and any of the +/// on clauses although this might be theoretically possible in some cases. //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// diff --git a/QL/parser-context.c b/QL/parser-context.c index d48e5cb81c..305e1b605c 100644 --- a/QL/parser-context.c +++ b/QL/parser-context.c @@ -301,7 +301,8 @@ void QLParseRegisterParseError (QL_parser_context_t* context, context->_lexState._errorState._column = QLget_column(context->_scanner); context->_lexState._errorState._code = errorCode; va_start(args, errorCode); - context->_lexState._errorState._message = QLParseAllocString(context, QLErrorFormat(errorCode, args)); + context->_lexState._errorState._message = QLParseAllocString(context, + QLErrorFormat(errorCode, args)); va_end(args); } @@ -319,7 +320,8 @@ void QLParseRegisterPostParseError (QL_parser_context_t* context, context->_lexState._errorState._column = column; context->_lexState._errorState._code = errorCode; va_start(args, errorCode); - context->_lexState._errorState._message = QLParseAllocString(context, QLErrorFormat(errorCode, args)); + context->_lexState._errorState._message = QLParseAllocString(context, + QLErrorFormat(errorCode, args)); va_end(args); } @@ -334,11 +336,14 @@ bool QLParseValidateCollectionName (const char* name) { while ('\0' != (c = *p++)) { if (length == 0) { - if (!(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z')) { + if (!(c >= 'A' && c <= 'Z') && + !(c >= 'a' && c <= 'z')) { return false; } } - if (!(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') && !(c >= '0' && c <= '9')) { + if (!(c >= 'A' && c <= 'Z') && + !(c >= 'a' && c <= 'z') && + !(c >= '0' && c <= '9')) { return false; } length++; @@ -359,15 +364,21 @@ bool QLParseValidateCollectionAlias (const char* name) { c = *p; // must start with one these chars - if (!(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') && !(c == '_')) { + if (!(c >= 'A' && c <= 'Z') && + !(c >= 'a' && c <= 'z') && + !(c == '_')) { return false; } while ('\0' != (c = *p++)) { - if (!(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') && !(c >= '0' && c <='9') && !(c == '_')) { + if (!(c >= 'A' && c <= 'Z') && + !(c >= 'a' && c <= 'z') && + !(c >= '0' && c <='9') && + !(c == '_')) { return false; } - if (!(c >= '0' && c <='9') && !(c == '_')) { + if (!(c >= '0' && c <='9') && + !(c == '_')) { // must include at least one letter charLength++; } @@ -383,10 +394,13 @@ bool QLParseValidateCollectionAlias (const char* name) { } //////////////////////////////////////////////////////////////////////////////// -/// @brief Validate the query +/// @brief Validate the collections used in a query part //////////////////////////////////////////////////////////////////////////////// -bool QLParseValidate (QL_parser_context_t* context, QL_ast_node_t* node) { +bool QLParseValidateCollections (QL_parser_context_t* context, + QL_ast_node_t* node, + QL_parser_validate_func validateFunc, + size_t* order) { QL_ast_node_t *lhs, *rhs, *next; if (node == 0) { @@ -396,15 +410,19 @@ bool QLParseValidate (QL_parser_context_t* context, QL_ast_node_t* node) { if (node->_type == QLNodeContainerList) { next = node->_next; while (next) { - if (!QLParseValidate(context, next)) { + if (!QLParseValidateCollections(context, next, validateFunc, order)) { return false; } next = next->_next; } } + if (node->_type == QLNodeReferenceCollection) { + ++(*order); + } + if (node->_type == QLNodeReferenceCollectionAlias) { - if (!QLAstQueryIsValidAlias(context->_query, node->_value._stringValue)) { + if (!validateFunc(context->_query, node->_value._stringValue, *order)) { QLParseRegisterPostParseError(context, node->_line, node->_column, @@ -416,14 +434,14 @@ bool QLParseValidate (QL_parser_context_t* context, QL_ast_node_t* node) { lhs = node->_lhs; if (lhs != 0) { - if (!QLParseValidate(context, lhs)) { + if (!QLParseValidateCollections(context, lhs, validateFunc, order)) { return false; } } rhs = node->_rhs; if (rhs != 0) { - if (!QLParseValidate(context, rhs)) { + if (!QLParseValidateCollections(context, rhs, validateFunc, order)) { return false; } } diff --git a/QL/parser-context.h b/QL/parser-context.h index 3c809ed71e..a5438e21d5 100644 --- a/QL/parser-context.h +++ b/QL/parser-context.h @@ -122,6 +122,12 @@ typedef struct QL_parser_context_s { } QL_parser_context_t; +//////////////////////////////////////////////////////////////////////////////// +/// @brief Validation function for collection names +//////////////////////////////////////////////////////////////////////////////// + +typedef bool(*QL_parser_validate_func) (QL_ast_query_t*, const char*, const size_t); + //////////////////////////////////////////////////////////////////////////////// /// @brief Forward declaration for parse function as generated by flex/bison //////////////////////////////////////////////////////////////////////////////// @@ -271,14 +277,16 @@ bool QLParseValidateCollectionName (const char*); bool QLParseValidateCollectionAlias (const char*); //////////////////////////////////////////////////////////////////////////////// -/// @brief Validate the query +/// @brief Validate the collections used in a query part /// -/// Currently validates if all used collection names are actually declared in -/// the query's from clause. -/// Furthermore validates collection names for syntactic correctness. +/// Currently validates if all used collection names in the query part are +/// actually declared in the query's from clause. //////////////////////////////////////////////////////////////////////////////// -bool QLParseValidate (QL_parser_context_t*, QL_ast_node_t*); +bool QLParseValidateCollections (QL_parser_context_t*, + QL_ast_node_t*, + QL_parser_validate_func, + size_t*); //////////////////////////////////////////////////////////////////////////////// /// @} diff --git a/QL/parser.c b/QL/parser.c index 6cfbd4f3c7..4ef7a4ae45 100644 --- a/QL/parser.c +++ b/QL/parser.c @@ -142,36 +142,38 @@ BY = 269, ASC = 270, DESC = 271, - LIMIT = 272, - AND = 273, - OR = 274, - NOT = 275, - IN = 276, - ASSIGNMENT = 277, - GREATER = 278, - LESS = 279, - GREATER_EQUAL = 280, - LESS_EQUAL = 281, - EQUAL = 282, - UNEQUAL = 283, - IDENTICAL = 284, - UNIDENTICAL = 285, - NULLX = 286, - TRUE = 287, - FALSE = 288, - UNDEFINED = 289, - IDENTIFIER = 290, - QUOTED_IDENTIFIER = 291, - PARAMETER = 292, - PARAMETER_NAMED = 293, - STRING = 294, - REAL = 295, - COLON = 296, - TERNARY = 297, - FCALL = 298, - UPLUS = 299, - UMINUS = 300, - MEMBER = 301 + WITHIN = 272, + NEAR = 273, + LIMIT = 274, + AND = 275, + OR = 276, + NOT = 277, + IN = 278, + ASSIGNMENT = 279, + GREATER = 280, + LESS = 281, + GREATER_EQUAL = 282, + LESS_EQUAL = 283, + EQUAL = 284, + UNEQUAL = 285, + IDENTICAL = 286, + UNIDENTICAL = 287, + NULLX = 288, + TRUE = 289, + FALSE = 290, + UNDEFINED = 291, + IDENTIFIER = 292, + QUOTED_IDENTIFIER = 293, + PARAMETER = 294, + PARAMETER_NAMED = 295, + STRING = 296, + REAL = 297, + COLON = 298, + TERNARY = 299, + FCALL = 300, + UPLUS = 301, + UMINUS = 302, + MEMBER = 303 }; #endif @@ -192,7 +194,7 @@ typedef union YYSTYPE /* Line 214 of yacc.c */ -#line 196 "QL/parser.c" +#line 198 "QL/parser.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -231,7 +233,7 @@ void QLerror (YYLTYPE *locp,QL_parser_context_t *context, const char *err) { /* Line 264 of yacc.c */ -#line 235 "QL/parser.c" +#line 237 "QL/parser.c" #ifdef short # undef short @@ -448,20 +450,20 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 11 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 259 +#define YYLAST 295 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 61 +#define YYNTOKENS 63 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 43 +#define YYNNTS 44 /* YYNRULES -- Number of rules. */ -#define YYNRULES 109 +#define YYNRULES 112 /* YYNRULES -- Number of states. */ -#define YYNSTATES 171 +#define YYNSTATES 201 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 301 +#define YYMAXUTOK 303 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -472,16 +474,16 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 47, 2, 2, - 56, 57, 45, 43, 53, 44, 58, 46, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 52, + 2, 2, 2, 2, 2, 2, 2, 49, 2, 2, + 55, 57, 47, 45, 56, 46, 60, 48, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 54, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 59, 2, 60, 2, 2, 2, 2, 2, 2, + 2, 61, 2, 62, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 54, 2, 55, 2, 2, 2, 2, + 2, 2, 2, 58, 2, 59, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -498,8 +500,8 @@ static const yytype_uint8 yytranslate[] = 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 48, 49, - 50, 51 + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 50, 51, 52, 53 }; #if YYDEBUG @@ -508,70 +510,75 @@ static const yytype_uint8 yytranslate[] = static const yytype_uint16 yyprhs[] = { 0, 0, 3, 5, 8, 10, 13, 14, 21, 23, - 24, 28, 30, 36, 37, 40, 41, 42, 47, 49, - 53, 56, 57, 59, 61, 62, 65, 69, 74, 80, - 82, 85, 86, 91, 93, 97, 99, 103, 107, 110, - 112, 114, 116, 118, 120, 122, 124, 127, 129, 132, - 136, 139, 143, 146, 150, 152, 154, 156, 158, 159, - 163, 165, 166, 170, 172, 173, 177, 179, 182, 185, - 189, 193, 196, 199, 202, 206, 210, 214, 218, 222, - 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, - 266, 272, 274, 278, 279, 285, 287, 291, 294, 295, - 300, 302, 306, 308, 310, 312, 314, 316, 318, 320 + 24, 28, 31, 38, 39, 54, 69, 70, 73, 74, + 75, 80, 82, 86, 89, 90, 92, 94, 95, 98, + 102, 107, 113, 115, 118, 119, 124, 126, 130, 132, + 136, 140, 143, 145, 147, 149, 151, 153, 155, 157, + 160, 162, 165, 169, 172, 176, 179, 183, 185, 187, + 189, 191, 192, 196, 198, 199, 203, 205, 206, 210, + 212, 215, 218, 222, 226, 229, 232, 235, 239, 243, + 247, 251, 255, 259, 263, 267, 271, 275, 279, 283, + 287, 291, 295, 299, 305, 307, 311, 312, 318, 320, + 324, 327, 328, 333, 335, 339, 341, 343, 345, 347, + 349, 351, 353 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 62, 0, -1, 64, -1, 64, 52, -1, 63, -1, - 63, 52, -1, -1, 3, 65, 66, 69, 70, 75, - -1, 76, -1, -1, 4, 67, 68, -1, 81, -1, - 68, 84, 81, 12, 88, -1, -1, 5, 88, -1, - -1, -1, 13, 14, 71, 72, -1, 73, -1, 72, - 53, 73, -1, 88, 74, -1, -1, 15, -1, 16, - -1, -1, 17, 40, -1, 17, 44, 40, -1, 17, - 40, 53, 40, -1, 17, 40, 53, 44, 40, -1, - 83, -1, 54, 55, -1, -1, 54, 77, 78, 55, - -1, 79, -1, 78, 53, 79, -1, 80, -1, 35, - 41, 88, -1, 39, 41, 88, -1, 82, 83, -1, - 35, -1, 36, -1, 35, -1, 36, -1, 85, -1, - 86, -1, 87, -1, 7, 6, -1, 6, -1, 8, - 6, -1, 10, 9, 6, -1, 10, 6, -1, 11, - 9, 6, -1, 11, 6, -1, 56, 88, 57, -1, - 93, -1, 94, -1, 95, -1, 96, -1, -1, 76, - 89, 92, -1, 76, -1, -1, 100, 90, 92, -1, - 100, -1, -1, 103, 91, 92, -1, 103, -1, 58, - 35, -1, 58, 96, -1, 92, 58, 35, -1, 92, - 58, 96, -1, 43, 88, -1, 44, 88, -1, 20, - 88, -1, 88, 19, 88, -1, 88, 18, 88, -1, - 88, 43, 88, -1, 88, 44, 88, -1, 88, 45, - 88, -1, 88, 46, 88, -1, 88, 47, 88, -1, - 88, 29, 88, -1, 88, 30, 88, -1, 88, 27, - 88, -1, 88, 28, 88, -1, 88, 24, 88, -1, - 88, 23, 88, -1, 88, 26, 88, -1, 88, 25, - 88, -1, 88, 21, 88, -1, 88, 42, 88, 41, - 88, -1, 97, -1, 35, 56, 57, -1, -1, 35, - 56, 98, 99, 57, -1, 88, -1, 99, 53, 88, - -1, 59, 60, -1, -1, 59, 101, 102, 60, -1, - 88, -1, 102, 53, 88, -1, 39, -1, 40, -1, - 31, -1, 34, -1, 32, -1, 33, -1, 37, -1, - 38, -1 + 64, 0, -1, 66, -1, 66, 54, -1, 65, -1, + 65, 54, -1, -1, 3, 67, 68, 72, 73, 78, + -1, 79, -1, -1, 4, 69, 70, -1, 84, 71, + -1, 70, 87, 84, 71, 12, 91, -1, -1, 17, + 86, 24, 55, 95, 56, 95, 56, 42, 56, 42, + 56, 42, 57, -1, 18, 86, 24, 55, 95, 56, + 95, 56, 42, 56, 42, 56, 42, 57, -1, -1, + 5, 91, -1, -1, -1, 13, 14, 74, 75, -1, + 76, -1, 75, 56, 76, -1, 91, 77, -1, -1, + 15, -1, 16, -1, -1, 19, 42, -1, 19, 46, + 42, -1, 19, 42, 56, 42, -1, 19, 42, 56, + 46, 42, -1, 86, -1, 58, 59, -1, -1, 58, + 80, 81, 59, -1, 82, -1, 81, 56, 82, -1, + 83, -1, 37, 43, 91, -1, 41, 43, 91, -1, + 85, 86, -1, 37, -1, 38, -1, 37, -1, 38, + -1, 88, -1, 89, -1, 90, -1, 7, 6, -1, + 6, -1, 8, 6, -1, 10, 9, 6, -1, 10, + 6, -1, 11, 9, 6, -1, 11, 6, -1, 55, + 91, 57, -1, 96, -1, 97, -1, 98, -1, 99, + -1, -1, 79, 92, 95, -1, 79, -1, -1, 103, + 93, 95, -1, 103, -1, -1, 106, 94, 95, -1, + 106, -1, 60, 37, -1, 60, 99, -1, 95, 60, + 37, -1, 95, 60, 99, -1, 45, 91, -1, 46, + 91, -1, 22, 91, -1, 91, 21, 91, -1, 91, + 20, 91, -1, 91, 45, 91, -1, 91, 46, 91, + -1, 91, 47, 91, -1, 91, 48, 91, -1, 91, + 49, 91, -1, 91, 31, 91, -1, 91, 32, 91, + -1, 91, 29, 91, -1, 91, 30, 91, -1, 91, + 26, 91, -1, 91, 25, 91, -1, 91, 28, 91, + -1, 91, 27, 91, -1, 91, 23, 91, -1, 91, + 44, 91, 43, 91, -1, 100, -1, 37, 55, 57, + -1, -1, 37, 55, 101, 102, 57, -1, 91, -1, + 102, 56, 91, -1, 61, 62, -1, -1, 61, 104, + 105, 62, -1, 91, -1, 105, 56, 91, -1, 41, + -1, 42, -1, 33, -1, 36, -1, 34, -1, 35, + -1, 39, -1, 40, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 125, 125, 127, 129, 131, 136, 142, 155, 163, - 163, 175, 180, 194, 197, 205, 208, 208, 220, 224, - 231, 242, 247, 252, 260, 262, 275, 288, 308, 331, - 336, 341, 341, 354, 358, 365, 372, 384, 400, 432, - 438, 448, 454, 464, 468, 472, 479, 486, 490, 497, - 501, 505, 509, 516, 520, 524, 528, 532, 536, 536, - 547, 551, 551, 562, 566, 566, 577, 585, 592, 596, - 603, 611, 617, 623, 632, 640, 648, 656, 664, 672, - 680, 688, 696, 704, 712, 720, 728, 736, 744, 752, - 763, 780, 787, 799, 799, 817, 820, 827, 831, 831, - 843, 846, 853, 860, 871, 875, 879, 884, 889, 902 + 0, 127, 127, 129, 131, 133, 138, 144, 157, 165, + 165, 177, 182, 196, 199, 201, 207, 210, 218, 221, + 221, 233, 237, 244, 255, 260, 265, 273, 275, 288, + 301, 321, 344, 349, 354, 354, 367, 371, 378, 385, + 398, 414, 446, 452, 462, 468, 478, 482, 486, 493, + 500, 504, 511, 515, 519, 523, 530, 534, 538, 542, + 546, 550, 550, 561, 565, 565, 576, 580, 580, 591, + 599, 606, 610, 617, 625, 631, 637, 646, 654, 662, + 670, 678, 686, 694, 702, 710, 718, 726, 734, 742, + 750, 758, 766, 777, 794, 801, 813, 813, 831, 834, + 841, 845, 845, 857, 860, 867, 874, 885, 889, 893, + 898, 903, 916 }; #endif @@ -582,19 +589,20 @@ static const char *const yytname[] = { "$end", "error", "$undefined", "SELECT", "FROM", "WHERE", "JOIN", "LIST", "INNER", "OUTER", "LEFT", "RIGHT", "ON", "ORDER", "BY", "ASC", - "DESC", "LIMIT", "AND", "OR", "NOT", "IN", "ASSIGNMENT", "GREATER", - "LESS", "GREATER_EQUAL", "LESS_EQUAL", "EQUAL", "UNEQUAL", "IDENTICAL", - "UNIDENTICAL", "NULLX", "TRUE", "FALSE", "UNDEFINED", "IDENTIFIER", - "QUOTED_IDENTIFIER", "PARAMETER", "PARAMETER_NAMED", "STRING", "REAL", - "COLON", "TERNARY", "'+'", "'-'", "'*'", "'/'", "'%'", "FCALL", "UPLUS", - "UMINUS", "MEMBER", "';'", "','", "'{'", "'}'", "'('", "')'", "'.'", - "'['", "']'", "$accept", "query", "empty_query", "select_query", - "select_clause", "from_clause", "$@1", "from_list", "where_clause", - "order_clause", "$@2", "order_list", "order_element", "order_direction", - "limit_clause", "document", "$@3", "attribute_list", "attribute", - "named_attribute", "collection_reference", "collection_name", - "collection_alias", "join_type", "list_join", "inner_join", "outer_join", - "expression", "$@4", "$@5", "$@6", "object_access", "unary_operator", + "DESC", "WITHIN", "NEAR", "LIMIT", "AND", "OR", "NOT", "IN", + "ASSIGNMENT", "GREATER", "LESS", "GREATER_EQUAL", "LESS_EQUAL", "EQUAL", + "UNEQUAL", "IDENTICAL", "UNIDENTICAL", "NULLX", "TRUE", "FALSE", + "UNDEFINED", "IDENTIFIER", "QUOTED_IDENTIFIER", "PARAMETER", + "PARAMETER_NAMED", "STRING", "REAL", "COLON", "TERNARY", "'+'", "'-'", + "'*'", "'/'", "'%'", "FCALL", "UPLUS", "UMINUS", "MEMBER", "';'", "'('", + "','", "')'", "'{'", "'}'", "'.'", "'['", "']'", "$accept", "query", + "empty_query", "select_query", "select_clause", "from_clause", "$@1", + "from_list", "geo_expression", "where_clause", "order_clause", "$@2", + "order_list", "order_element", "order_direction", "limit_clause", + "document", "$@3", "attribute_list", "attribute", "named_attribute", + "collection_reference", "collection_name", "collection_alias", + "join_type", "list_join", "inner_join", "outer_join", "expression", + "$@4", "$@5", "$@6", "object_access", "unary_operator", "binary_operator", "conditional_operator", "function_call", "function_invocation", "$@7", "function_args_list", "array_declaration", "$@8", "array_list", "atom", 0 @@ -610,42 +618,44 @@ static const yytype_uint16 yytoknum[] = 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 43, 45, 42, 47, 37, 298, 299, - 300, 301, 59, 44, 123, 125, 40, 41, 46, 91, - 93 + 295, 296, 297, 298, 299, 43, 45, 42, 47, 37, + 300, 301, 302, 303, 59, 40, 44, 41, 123, 125, + 46, 91, 93 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 61, 62, 62, 62, 62, 63, 64, 65, 67, - 66, 68, 68, 69, 69, 70, 71, 70, 72, 72, - 73, 74, 74, 74, 75, 75, 75, 75, 75, 76, - 76, 77, 76, 78, 78, 79, 80, 80, 81, 82, - 82, 83, 83, 84, 84, 84, 85, 86, 86, 87, - 87, 87, 87, 88, 88, 88, 88, 88, 89, 88, - 88, 90, 88, 88, 91, 88, 88, 92, 92, 92, - 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, - 95, 96, 97, 98, 97, 99, 99, 100, 101, 100, - 102, 102, 103, 103, 103, 103, 103, 103, 103, 103 + 0, 63, 64, 64, 64, 64, 65, 66, 67, 69, + 68, 70, 70, 71, 71, 71, 72, 72, 73, 74, + 73, 75, 75, 76, 77, 77, 77, 78, 78, 78, + 78, 78, 79, 79, 80, 79, 81, 81, 82, 83, + 83, 84, 85, 85, 86, 86, 87, 87, 87, 88, + 89, 89, 90, 90, 90, 90, 91, 91, 91, 91, + 91, 92, 91, 91, 93, 91, 91, 94, 91, 91, + 95, 95, 95, 95, 96, 96, 96, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 98, 99, 100, 101, 100, 102, 102, + 103, 104, 103, 105, 105, 106, 106, 106, 106, 106, + 106, 106, 106 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 1, 2, 1, 2, 0, 6, 1, 0, - 3, 1, 5, 0, 2, 0, 0, 4, 1, 3, - 2, 0, 1, 1, 0, 2, 3, 4, 5, 1, - 2, 0, 4, 1, 3, 1, 3, 3, 2, 1, - 1, 1, 1, 1, 1, 1, 2, 1, 2, 3, - 2, 3, 2, 3, 1, 1, 1, 1, 0, 3, - 1, 0, 3, 1, 0, 3, 1, 2, 2, 3, - 3, 2, 2, 2, 3, 3, 3, 3, 3, 3, + 3, 2, 6, 0, 14, 14, 0, 2, 0, 0, + 4, 1, 3, 2, 0, 1, 1, 0, 2, 3, + 4, 5, 1, 2, 0, 4, 1, 3, 1, 3, + 3, 2, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 2, 3, 2, 3, 2, 3, 1, 1, 1, + 1, 0, 3, 1, 0, 3, 1, 0, 3, 1, + 2, 2, 3, 3, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 5, 1, 3, 0, 5, 1, 3, 2, 0, 4, - 1, 3, 1, 1, 1, 1, 1, 1, 1, 1 + 3, 3, 3, 5, 1, 3, 0, 5, 1, 3, + 2, 0, 4, 1, 3, 1, 1, 1, 1, 1, + 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -653,158 +663,175 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 6, 0, 0, 4, 2, 41, 42, 31, 0, 8, - 29, 1, 5, 3, 30, 0, 9, 13, 0, 0, - 0, 33, 35, 0, 0, 15, 0, 0, 0, 32, - 39, 40, 10, 11, 0, 0, 104, 106, 107, 105, - 41, 108, 109, 102, 103, 0, 0, 0, 98, 60, - 14, 54, 55, 56, 57, 91, 63, 66, 0, 24, - 36, 37, 34, 47, 0, 0, 0, 0, 0, 43, - 44, 45, 38, 73, 93, 71, 72, 0, 97, 0, + 6, 0, 0, 4, 2, 44, 45, 34, 0, 8, + 32, 1, 5, 3, 33, 0, 9, 16, 0, 0, + 0, 36, 38, 0, 0, 18, 0, 0, 0, 35, + 42, 43, 10, 13, 0, 0, 107, 109, 110, 108, + 44, 111, 112, 105, 106, 0, 0, 0, 101, 63, + 17, 57, 58, 59, 60, 94, 66, 69, 0, 27, + 39, 40, 37, 50, 0, 0, 0, 0, 0, 46, + 47, 48, 0, 0, 11, 41, 76, 96, 74, 75, + 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16, 0, 7, 46, 48, 50, 0, 52, 0, 0, - 92, 0, 53, 100, 0, 0, 59, 75, 74, 89, - 86, 85, 88, 87, 83, 84, 81, 82, 0, 76, - 77, 78, 79, 80, 62, 65, 0, 25, 0, 49, - 51, 0, 95, 0, 0, 99, 67, 68, 0, 0, - 17, 18, 21, 0, 26, 12, 0, 94, 101, 69, - 70, 90, 0, 22, 23, 20, 27, 0, 96, 19, - 28 + 0, 0, 0, 19, 0, 7, 49, 51, 53, 0, + 55, 0, 13, 0, 0, 95, 0, 56, 103, 0, + 0, 62, 78, 77, 92, 89, 88, 91, 90, 86, + 87, 84, 85, 0, 79, 80, 81, 82, 83, 65, + 68, 0, 28, 0, 52, 54, 0, 0, 0, 98, + 0, 0, 102, 70, 71, 0, 0, 20, 21, 24, + 0, 29, 0, 0, 0, 0, 97, 104, 72, 73, + 93, 0, 25, 26, 23, 30, 0, 12, 0, 0, + 99, 22, 31, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 15 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 2, 3, 4, 8, 17, 23, 32, 25, 59, - 136, 150, 151, 165, 102, 49, 15, 20, 21, 22, - 33, 34, 10, 68, 69, 70, 71, 152, 80, 98, - 99, 116, 51, 52, 53, 54, 55, 111, 143, 56, - 79, 114, 57 + -1, 2, 3, 4, 8, 17, 23, 32, 74, 25, + 59, 141, 157, 158, 174, 105, 49, 15, 20, 21, + 22, 33, 34, 10, 68, 69, 70, 71, 159, 83, + 101, 102, 121, 51, 52, 53, 54, 55, 116, 150, + 56, 82, 119, 57 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -112 +#define YYPACT_NINF -115 static const yytype_int16 yypact[] = { - -2, -30, 9, -32, -26, -112, -112, -13, 77, -112, - -112, -112, -112, -112, -112, 17, -112, 81, 67, 78, - 71, -112, -112, 18, 57, 105, 57, 57, 17, -112, - -112, -112, 33, -112, 63, 57, -112, -112, -112, -112, - 73, -112, -112, -112, -112, 57, 57, 57, 74, 90, - 172, -112, -112, -112, -112, -112, 91, 92, 137, 135, - 172, 172, -112, -112, 147, 156, 101, 103, 18, -112, - -112, -112, -112, -112, 107, -112, -112, -11, -112, 57, - 115, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 57, 57, 57, 57, 57, 57, 57, 57, 115, 115, - -112, 34, -112, -112, -112, -112, 168, -112, 169, 164, - -112, 57, -112, 172, -15, 143, 119, 212, 202, 59, - 100, 100, 100, 100, 4, 4, 4, 4, 142, 76, - 76, -112, -112, -112, 119, 119, 57, 126, 140, -112, - -112, 57, 172, 22, 57, -112, 73, -112, 146, 57, - 129, -112, 112, 36, -112, 172, 57, -112, 172, 73, - -112, 172, 57, -112, -112, -112, -112, 152, 172, -112, - -112 + 4, -20, 14, -12, 5, -115, -115, 22, 79, -115, + -115, -115, -115, -115, -115, -32, -115, 107, 75, 83, + 77, -115, -115, -18, -9, 104, -9, -9, -32, -115, + -115, -115, 37, 17, 13, -9, -115, -115, -115, -115, + 76, -115, -115, -115, -115, -9, -9, -9, 81, 70, + 179, -115, -115, -115, -115, -115, 93, 94, 123, 140, + 179, 179, -115, -115, 154, 155, 87, 146, -18, -115, + -115, -115, 13, 13, -115, -115, -115, 105, -115, -115, + 59, -115, -9, 111, -9, -9, -9, -9, -9, -9, + -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, + -9, 111, 111, -115, -34, -115, -115, -115, -115, 167, + -115, 176, 17, 159, 160, -115, -9, -115, 179, -52, + 148, 126, 219, 209, 74, 8, 8, 8, 8, 246, + 246, 246, 246, 149, 109, 109, -115, -115, -115, 126, + 126, -9, 131, 147, -115, -115, 178, 133, 136, 179, + 38, -9, -115, 76, -115, 164, -9, 156, -115, 119, + 67, -115, -9, 111, 111, -9, -115, 179, 76, -115, + 179, -9, -115, -115, -115, -115, 161, 179, 54, 55, + 179, -115, -115, 111, 111, 68, 69, 171, 172, 162, + 163, 173, 174, 165, 166, 175, 188, 186, 195, -115, + -115 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -112, -112, -112, -112, -112, -112, -112, -112, -112, -112, - -112, -112, 32, -112, -112, 203, -112, -112, 175, -112, - 138, -112, 171, -112, -112, -112, -112, -24, -112, -112, - -112, 16, -112, -112, -112, -111, -112, -112, -112, -112, - -112, -112, -112 + -115, -115, -115, -115, -115, -115, -115, -115, 108, -115, + -115, -115, -115, 60, -115, -115, 232, -115, -115, 225, + -115, 191, -115, -33, -115, -115, -115, -115, -24, -115, + -115, -115, -86, -115, -115, -115, -114, -115, -115, -115, + -115, -115, -115, -115 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -65 +#define YYTABLE_NINF -68 static const yytype_int16 yytable[] = { - 50, 1, 60, 61, 147, 5, 6, 81, 82, 11, - 83, 73, 84, 85, 86, 87, 88, 89, 90, 91, - 12, 75, 76, 77, 7, 83, 13, 84, 85, 86, - 87, 92, 93, 94, 95, 96, 97, 160, 144, 63, - 64, 65, 14, 66, 67, 145, 112, 93, 94, 95, - 96, 97, 18, 30, 31, 113, 19, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 137, 156, 166, 35, 138, 157, - 167, 16, 84, 85, 86, 87, 24, 142, 36, 37, - 38, 39, 40, 6, 41, 42, 43, 44, 5, 6, - 45, 46, 93, 94, 95, 96, 97, 105, 26, 107, - 106, 7, 108, 47, 134, 135, 48, 155, 58, 27, - 158, 95, 96, 97, 28, 161, 29, 163, 164, 74, - 81, 82, 168, 83, 78, 84, 85, 86, 87, 88, - 89, 90, 91, 93, 94, 95, 96, 97, -58, -61, - -64, 100, 101, 103, 92, 93, 94, 95, 96, 97, - 81, 82, 104, 83, 110, 84, 85, 86, 87, 88, - 89, 90, 91, 115, 139, 140, 141, 148, 146, 153, - 154, 159, 162, 149, 92, 93, 94, 95, 96, 97, - 81, 82, 170, 83, 169, 84, 85, 86, 87, 88, - 89, 90, 91, 62, 9, 72, 109, 0, 0, 0, - 0, 0, 0, 0, 92, 93, 94, 95, 96, 97, - 81, 0, 0, 83, 0, 84, 85, 86, 87, 88, - 89, 90, 91, 83, 0, 84, 85, 86, 87, 88, - 89, 90, 91, 0, 0, 93, 94, 95, 96, 97, - 0, 0, 0, 0, 0, 93, 94, 95, 96, 97 + 50, 75, 60, 61, 151, 18, 154, 1, 142, 19, + 152, 76, 143, 35, 11, 139, 140, 5, 6, 30, + 31, 78, 79, 80, 36, 37, 38, 39, 40, 6, + 41, 42, 43, 44, 72, 73, 45, 46, 7, 113, + 114, 169, 12, 63, 64, 65, 47, 66, 67, 7, + 5, 6, 48, 96, 97, 98, 99, 100, 118, 13, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 178, 179, 84, + 85, 14, 86, 16, 87, 88, 89, 90, 91, 92, + 93, 94, 149, 108, 165, 166, 109, 185, 186, 87, + 88, 89, 90, 95, 96, 97, 98, 99, 100, 175, + 183, 184, 24, 176, 155, 155, 117, 58, 26, 96, + 97, 98, 99, 100, 187, 188, 27, 167, 155, 155, + -61, 77, 170, 28, 172, 173, 29, 103, 177, 84, + 85, 180, 86, 81, 87, 88, 89, 90, 91, 92, + 93, 94, 110, -64, -67, 111, 98, 99, 100, 104, + 106, 107, 115, 95, 96, 97, 98, 99, 100, 84, + 85, 120, 86, 144, 87, 88, 89, 90, 91, 92, + 93, 94, 145, 147, 148, 153, 155, 160, 163, 161, + 162, 164, 156, 95, 96, 97, 98, 99, 100, 84, + 85, 168, 86, 182, 87, 88, 89, 90, 91, 92, + 93, 94, 171, 189, 190, 193, 194, 197, 191, 192, + 146, 195, 196, 95, 96, 97, 98, 99, 100, 84, + 198, 181, 86, 9, 87, 88, 89, 90, 91, 92, + 93, 94, 86, 199, 87, 88, 89, 90, 91, 92, + 93, 94, 200, 62, 96, 97, 98, 99, 100, 112, + 0, 0, 0, 0, 96, 97, 98, 99, 100, 86, + 0, 87, 88, 89, 90, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 96, 97, 98, 99, 100 }; static const yytype_int16 yycheck[] = { - 24, 3, 26, 27, 115, 35, 36, 18, 19, 0, - 21, 35, 23, 24, 25, 26, 27, 28, 29, 30, - 52, 45, 46, 47, 54, 21, 52, 23, 24, 25, - 26, 42, 43, 44, 45, 46, 47, 148, 53, 6, - 7, 8, 55, 10, 11, 60, 57, 43, 44, 45, - 46, 47, 35, 35, 36, 79, 39, 81, 82, 83, + 24, 34, 26, 27, 56, 37, 120, 3, 42, 41, + 62, 35, 46, 22, 0, 101, 102, 37, 38, 37, + 38, 45, 46, 47, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 17, 18, 45, 46, 58, 72, + 73, 155, 54, 6, 7, 8, 55, 10, 11, 58, + 37, 38, 61, 45, 46, 47, 48, 49, 82, 54, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 40, 53, 40, 20, 44, 57, - 44, 4, 23, 24, 25, 26, 5, 111, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 35, 36, - 43, 44, 43, 44, 45, 46, 47, 6, 41, 6, - 9, 54, 9, 56, 98, 99, 59, 141, 13, 41, - 144, 45, 46, 47, 53, 149, 55, 15, 16, 56, - 18, 19, 156, 21, 60, 23, 24, 25, 26, 27, - 28, 29, 30, 43, 44, 45, 46, 47, 58, 58, - 58, 14, 17, 6, 42, 43, 44, 45, 46, 47, - 18, 19, 6, 21, 57, 23, 24, 25, 26, 27, - 28, 29, 30, 58, 6, 6, 12, 58, 35, 53, - 40, 35, 53, 41, 42, 43, 44, 45, 46, 47, - 18, 19, 40, 21, 162, 23, 24, 25, 26, 27, - 28, 29, 30, 28, 1, 34, 68, -1, -1, -1, - -1, -1, -1, -1, 42, 43, 44, 45, 46, 47, - 18, -1, -1, 21, -1, 23, 24, 25, 26, 27, - 28, 29, 30, 21, -1, 23, 24, 25, 26, 27, - 28, 29, 30, -1, -1, 43, 44, 45, 46, 47, - -1, -1, -1, -1, -1, 43, 44, 45, 46, 47 + 94, 95, 96, 97, 98, 99, 100, 163, 164, 20, + 21, 59, 23, 4, 25, 26, 27, 28, 29, 30, + 31, 32, 116, 6, 56, 57, 9, 183, 184, 25, + 26, 27, 28, 44, 45, 46, 47, 48, 49, 42, + 56, 56, 5, 46, 60, 60, 57, 13, 43, 45, + 46, 47, 48, 49, 56, 56, 43, 151, 60, 60, + 60, 55, 156, 56, 15, 16, 59, 14, 162, 20, + 21, 165, 23, 62, 25, 26, 27, 28, 29, 30, + 31, 32, 6, 60, 60, 9, 47, 48, 49, 19, + 6, 6, 57, 44, 45, 46, 47, 48, 49, 20, + 21, 60, 23, 6, 25, 26, 27, 28, 29, 30, + 31, 32, 6, 24, 24, 37, 60, 56, 55, 42, + 12, 55, 43, 44, 45, 46, 47, 48, 49, 20, + 21, 37, 23, 42, 25, 26, 27, 28, 29, 30, + 31, 32, 56, 42, 42, 42, 42, 42, 56, 56, + 112, 56, 56, 44, 45, 46, 47, 48, 49, 20, + 42, 171, 23, 1, 25, 26, 27, 28, 29, 30, + 31, 32, 23, 57, 25, 26, 27, 28, 29, 30, + 31, 32, 57, 28, 45, 46, 47, 48, 49, 68, + -1, -1, -1, -1, 45, 46, 47, 48, 49, 23, + -1, 25, 26, 27, 28, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 45, 46, 47, 48, 49 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 3, 62, 63, 64, 35, 36, 54, 65, 76, - 83, 0, 52, 52, 55, 77, 4, 66, 35, 39, - 78, 79, 80, 67, 5, 69, 41, 41, 53, 55, - 35, 36, 68, 81, 82, 20, 31, 32, 33, 34, - 35, 37, 38, 39, 40, 43, 44, 56, 59, 76, - 88, 93, 94, 95, 96, 97, 100, 103, 13, 70, - 88, 88, 79, 6, 7, 8, 10, 11, 84, 85, - 86, 87, 83, 88, 56, 88, 88, 88, 60, 101, - 89, 18, 19, 21, 23, 24, 25, 26, 27, 28, - 29, 30, 42, 43, 44, 45, 46, 47, 90, 91, - 14, 17, 75, 6, 6, 6, 9, 6, 9, 81, - 57, 98, 57, 88, 102, 58, 92, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 92, 92, 71, 40, 44, 6, - 6, 12, 88, 99, 53, 60, 35, 96, 58, 41, - 72, 73, 88, 53, 40, 88, 53, 57, 88, 35, - 96, 88, 53, 15, 16, 74, 40, 44, 88, 73, - 40 + 0, 3, 64, 65, 66, 37, 38, 58, 67, 79, + 86, 0, 54, 54, 59, 80, 4, 68, 37, 41, + 81, 82, 83, 69, 5, 72, 43, 43, 56, 59, + 37, 38, 70, 84, 85, 22, 33, 34, 35, 36, + 37, 39, 40, 41, 42, 45, 46, 55, 61, 79, + 91, 96, 97, 98, 99, 100, 103, 106, 13, 73, + 91, 91, 82, 6, 7, 8, 10, 11, 87, 88, + 89, 90, 17, 18, 71, 86, 91, 55, 91, 91, + 91, 62, 104, 92, 20, 21, 23, 25, 26, 27, + 28, 29, 30, 31, 32, 44, 45, 46, 47, 48, + 49, 93, 94, 14, 19, 78, 6, 6, 6, 9, + 6, 9, 84, 86, 86, 57, 101, 57, 91, 105, + 60, 95, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 95, + 95, 74, 42, 46, 6, 6, 71, 24, 24, 91, + 102, 56, 62, 37, 99, 60, 43, 75, 76, 91, + 56, 42, 12, 55, 55, 56, 57, 91, 37, 99, + 91, 56, 15, 16, 77, 42, 46, 91, 95, 95, + 91, 76, 42, 56, 56, 95, 95, 56, 56, 42, + 42, 56, 56, 42, 42, 56, 56, 42, 42, 57, + 57 }; #define yyerrok (yyerrstatus = 0) @@ -1658,7 +1685,7 @@ yyreduce: case 2: /* Line 1455 of yacc.c */ -#line 125 "QL/parser.y" +#line 127 "QL/parser.y" { ;} break; @@ -1666,7 +1693,7 @@ yyreduce: case 3: /* Line 1455 of yacc.c */ -#line 127 "QL/parser.y" +#line 129 "QL/parser.y" { ;} break; @@ -1674,7 +1701,7 @@ yyreduce: case 4: /* Line 1455 of yacc.c */ -#line 129 "QL/parser.y" +#line 131 "QL/parser.y" { ;} break; @@ -1682,7 +1709,7 @@ yyreduce: case 5: /* Line 1455 of yacc.c */ -#line 131 "QL/parser.y" +#line 133 "QL/parser.y" { ;} break; @@ -1690,7 +1717,7 @@ yyreduce: case 6: /* Line 1455 of yacc.c */ -#line 136 "QL/parser.y" +#line 138 "QL/parser.y" { context->_query->_type = QLQueryTypeEmpty; ;} @@ -1699,7 +1726,7 @@ yyreduce: case 7: /* Line 1455 of yacc.c */ -#line 142 "QL/parser.y" +#line 144 "QL/parser.y" { // full blown SELECT query context->_query->_type = QLQueryTypeSelect; @@ -1713,7 +1740,7 @@ yyreduce: case 8: /* Line 1455 of yacc.c */ -#line 155 "QL/parser.y" +#line 157 "QL/parser.y" { // select part of a SELECT (yyval.node) = (yyvsp[(1) - (1)].node); @@ -1724,7 +1751,7 @@ yyreduce: case 9: /* Line 1455 of yacc.c */ -#line 163 "QL/parser.y" +#line 165 "QL/parser.y" { // from part of a SELECT QL_ast_node_t* list = QLAstNodeCreate(context, QLNodeContainerList); @@ -1736,7 +1763,7 @@ yyreduce: case 10: /* Line 1455 of yacc.c */ -#line 168 "QL/parser.y" +#line 170 "QL/parser.y" { (yyval.node) = QLParseContextPop(context); ABORT_IF_OOM((yyval.node)); @@ -1746,35 +1773,35 @@ yyreduce: case 11: /* Line 1455 of yacc.c */ -#line 175 "QL/parser.y" +#line 177 "QL/parser.y" { // single table query - ABORT_IF_OOM((yyvsp[(1) - (1)].node)); - QLParseContextAddElement(context, (yyvsp[(1) - (1)].node)); + ABORT_IF_OOM((yyvsp[(1) - (2)].node)); + QLParseContextAddElement(context, (yyvsp[(1) - (2)].node)); ;} break; case 12: /* Line 1455 of yacc.c */ -#line 180 "QL/parser.y" +#line 182 "QL/parser.y" { // multi-table query - ABORT_IF_OOM((yyvsp[(2) - (5)].node)); - ABORT_IF_OOM((yyvsp[(3) - (5)].node)); - ABORT_IF_OOM((yyvsp[(5) - (5)].node)); - (yyval.node) = (yyvsp[(2) - (5)].node); - (yyval.node)->_lhs = (yyvsp[(3) - (5)].node); - (yyval.node)->_rhs = (yyvsp[(5) - (5)].node); + ABORT_IF_OOM((yyvsp[(2) - (6)].node)); + ABORT_IF_OOM((yyvsp[(3) - (6)].node)); + ABORT_IF_OOM((yyvsp[(6) - (6)].node)); + (yyval.node) = (yyvsp[(2) - (6)].node); + (yyval.node)->_lhs = (yyvsp[(3) - (6)].node); + (yyval.node)->_rhs = (yyvsp[(6) - (6)].node); - QLParseContextAddElement(context, (yyvsp[(2) - (5)].node)); + QLParseContextAddElement(context, (yyvsp[(2) - (6)].node)); ;} break; case 13: /* Line 1455 of yacc.c */ -#line 194 "QL/parser.y" +#line 196 "QL/parser.y" { (yyval.node) = 0; ;} @@ -1783,7 +1810,32 @@ yyreduce: case 14: /* Line 1455 of yacc.c */ -#line 197 "QL/parser.y" +#line 199 "QL/parser.y" + { + ;} + break; + + case 15: + +/* Line 1455 of yacc.c */ +#line 201 "QL/parser.y" + { + ;} + break; + + case 16: + +/* Line 1455 of yacc.c */ +#line 207 "QL/parser.y" + { + (yyval.node) = 0; + ;} + break; + + case 17: + +/* Line 1455 of yacc.c */ +#line 210 "QL/parser.y" { // where condition set ABORT_IF_OOM((yyvsp[(2) - (2)].node)); @@ -1791,19 +1843,19 @@ yyreduce: ;} break; - case 15: + case 18: /* Line 1455 of yacc.c */ -#line 205 "QL/parser.y" +#line 218 "QL/parser.y" { (yyval.node) = 0; ;} break; - case 16: + case 19: /* Line 1455 of yacc.c */ -#line 208 "QL/parser.y" +#line 221 "QL/parser.y" { // order by part of a query QL_ast_node_t* list = QLAstNodeCreate(context, QLNodeContainerList); @@ -1812,40 +1864,40 @@ yyreduce: ;} break; - case 17: + case 20: /* Line 1455 of yacc.c */ -#line 213 "QL/parser.y" +#line 226 "QL/parser.y" { (yyval.node) = QLParseContextPop(context); ABORT_IF_OOM((yyval.node)); ;} break; - case 18: + case 21: /* Line 1455 of yacc.c */ -#line 220 "QL/parser.y" +#line 233 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(1) - (1)].node)); QLParseContextAddElement(context, (yyvsp[(1) - (1)].node)); ;} break; - case 19: + case 22: /* Line 1455 of yacc.c */ -#line 224 "QL/parser.y" +#line 237 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(3) - (3)].node)); QLParseContextAddElement(context, (yyvsp[(3) - (3)].node)); ;} break; - case 20: + case 23: /* Line 1455 of yacc.c */ -#line 231 "QL/parser.y" +#line 244 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeContainerOrderElement); ABORT_IF_OOM((yyval.node)); @@ -1856,10 +1908,10 @@ yyreduce: ;} break; - case 21: + case 24: /* Line 1455 of yacc.c */ -#line 242 "QL/parser.y" +#line 255 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeValueOrderDirection); ABORT_IF_OOM((yyval.node)); @@ -1867,10 +1919,10 @@ yyreduce: ;} break; - case 22: + case 25: /* Line 1455 of yacc.c */ -#line 247 "QL/parser.y" +#line 260 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeValueOrderDirection); ABORT_IF_OOM((yyval.node)); @@ -1878,10 +1930,10 @@ yyreduce: ;} break; - case 23: + case 26: /* Line 1455 of yacc.c */ -#line 252 "QL/parser.y" +#line 265 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeValueOrderDirection); ABORT_IF_OOM((yyval.node)); @@ -1889,18 +1941,18 @@ yyreduce: ;} break; - case 24: + case 27: /* Line 1455 of yacc.c */ -#line 260 "QL/parser.y" +#line 273 "QL/parser.y" { ;} break; - case 25: + case 28: /* Line 1455 of yacc.c */ -#line 262 "QL/parser.y" +#line 275 "QL/parser.y" { // limit value int64_t d = TRI_Int64String((yyvsp[(2) - (2)].strval)); @@ -1916,10 +1968,10 @@ yyreduce: ;} break; - case 26: + case 29: /* Line 1455 of yacc.c */ -#line 275 "QL/parser.y" +#line 288 "QL/parser.y" { // limit - value int64_t d = TRI_Int64String((yyvsp[(3) - (3)].strval)); @@ -1935,10 +1987,10 @@ yyreduce: ;} break; - case 27: + case 30: /* Line 1455 of yacc.c */ -#line 288 "QL/parser.y" +#line 301 "QL/parser.y" { // limit value, value int64_t d1, d2; @@ -1961,10 +2013,10 @@ yyreduce: ;} break; - case 28: + case 31: /* Line 1455 of yacc.c */ -#line 308 "QL/parser.y" +#line 321 "QL/parser.y" { // limit value, -value int64_t d1, d2; @@ -1987,10 +2039,10 @@ yyreduce: ;} break; - case 29: + case 32: /* Line 1455 of yacc.c */ -#line 331 "QL/parser.y" +#line 344 "QL/parser.y" { // document is a reference to a collection (by using its alias) ABORT_IF_OOM((yyvsp[(1) - (1)].node)); @@ -1998,10 +2050,10 @@ yyreduce: ;} break; - case 30: + case 33: /* Line 1455 of yacc.c */ -#line 336 "QL/parser.y" +#line 349 "QL/parser.y" { // empty document (yyval.node) = QLAstNodeCreate(context, QLNodeValueDocument); @@ -2009,10 +2061,10 @@ yyreduce: ;} break; - case 31: + case 34: /* Line 1455 of yacc.c */ -#line 341 "QL/parser.y" +#line 354 "QL/parser.y" { // listing of document attributes QL_ast_node_t* list = QLAstNodeCreate(context, QLNodeContainerList); @@ -2021,10 +2073,10 @@ yyreduce: ;} break; - case 32: + case 35: /* Line 1455 of yacc.c */ -#line 346 "QL/parser.y" +#line 359 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeValueDocument); ABORT_IF_OOM((yyval.node)); @@ -2032,58 +2084,59 @@ yyreduce: ;} break; - case 33: + case 36: /* Line 1455 of yacc.c */ -#line 354 "QL/parser.y" +#line 367 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(1) - (1)].node)); QLParseContextAddElement(context, (yyvsp[(1) - (1)].node)); ;} break; - case 34: + case 37: /* Line 1455 of yacc.c */ -#line 358 "QL/parser.y" +#line 371 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(3) - (3)].node)); QLParseContextAddElement(context, (yyvsp[(3) - (3)].node)); ;} break; - case 35: + case 38: /* Line 1455 of yacc.c */ -#line 365 "QL/parser.y" +#line 378 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(1) - (1)].node)); (yyval.node) = (yyvsp[(1) - (1)].node); ;} break; - case 36: + case 39: /* Line 1455 of yacc.c */ -#line 372 "QL/parser.y" +#line 385 "QL/parser.y" { - QL_ast_node_t* identifier = QLAstNodeCreate(context, QLNodeValueIdentifier); - ABORT_IF_OOM(identifier); + size_t outLength; + QL_ast_node_t* str = QLAstNodeCreate(context, QLNodeValueString); + ABORT_IF_OOM(str); ABORT_IF_OOM((yyvsp[(1) - (3)].strval)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); - identifier->_value._stringValue = (yyvsp[(1) - (3)].strval); + str->_value._stringValue = QLParseRegisterString(context, TRI_UnescapeUtf8String((yyvsp[(1) - (3)].strval), strlen((yyvsp[(1) - (3)].strval)), &outLength)); (yyval.node) = QLAstNodeCreate(context, QLNodeValueNamedValue); ABORT_IF_OOM((yyval.node)); - (yyval.node)->_lhs = identifier; + (yyval.node)->_lhs = str; (yyval.node)->_rhs = (yyvsp[(3) - (3)].node); ;} break; - case 37: + case 40: /* Line 1455 of yacc.c */ -#line 384 "QL/parser.y" +#line 398 "QL/parser.y" { size_t outLength; QL_ast_node_t* str = QLAstNodeCreate(context, QLNodeValueString); @@ -2099,10 +2152,10 @@ yyreduce: ;} break; - case 38: + case 41: /* Line 1455 of yacc.c */ -#line 400 "QL/parser.y" +#line 414 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(1) - (2)].node)); ABORT_IF_OOM((yyvsp[(1) - (2)].node)->_value._stringValue); @@ -2133,122 +2186,92 @@ yyreduce: ;} break; - case 39: - -/* Line 1455 of yacc.c */ -#line 432 "QL/parser.y" - { - (yyval.node) = QLAstNodeCreate(context, QLNodeValueIdentifier); - ABORT_IF_OOM((yyval.node)); - ABORT_IF_OOM((yyvsp[(1) - (1)].strval)); - (yyval.node)->_value._stringValue = (yyvsp[(1) - (1)].strval); - ;} - break; - - case 40: - -/* Line 1455 of yacc.c */ -#line 438 "QL/parser.y" - { - size_t outLength; - (yyval.node) = QLAstNodeCreate(context, QLNodeValueIdentifier); - ABORT_IF_OOM((yyval.node)); - ABORT_IF_OOM((yyvsp[(1) - (1)].strval)); - (yyval.node)->_value._stringValue = QLParseRegisterString(context, TRI_UnescapeUtf8String((yyvsp[(1) - (1)].strval) + 1, strlen((yyvsp[(1) - (1)].strval)) - 2, &outLength)); - ;} - break; - - case 41: - -/* Line 1455 of yacc.c */ -#line 448 "QL/parser.y" - { - (yyval.node) = QLAstNodeCreate(context, QLNodeReferenceCollectionAlias); - ABORT_IF_OOM((yyval.node)); - ABORT_IF_OOM((yyvsp[(1) - (1)].strval)); - (yyval.node)->_value._stringValue = (yyvsp[(1) - (1)].strval); - ;} - break; - case 42: /* Line 1455 of yacc.c */ -#line 454 "QL/parser.y" +#line 446 "QL/parser.y" { - size_t outLength; - (yyval.node) = QLAstNodeCreate(context, QLNodeReferenceCollectionAlias); + (yyval.node) = QLAstNodeCreate(context, QLNodeValueIdentifier); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (1)].strval)); - (yyval.node)->_value._stringValue = QLParseRegisterString(context, TRI_UnescapeUtf8String((yyvsp[(1) - (1)].strval) + 1, strlen((yyvsp[(1) - (1)].strval)) - 2, &outLength)); + (yyval.node)->_value._stringValue = (yyvsp[(1) - (1)].strval); ;} break; case 43: /* Line 1455 of yacc.c */ -#line 464 "QL/parser.y" +#line 452 "QL/parser.y" { - ABORT_IF_OOM((yyvsp[(1) - (1)].node)); - (yyval.node) = (yyvsp[(1) - (1)].node); + size_t outLength; + (yyval.node) = QLAstNodeCreate(context, QLNodeValueIdentifier); + ABORT_IF_OOM((yyval.node)); + ABORT_IF_OOM((yyvsp[(1) - (1)].strval)); + (yyval.node)->_value._stringValue = QLParseRegisterString(context, TRI_UnescapeUtf8String((yyvsp[(1) - (1)].strval) + 1, strlen((yyvsp[(1) - (1)].strval)) - 2, &outLength)); ;} break; case 44: /* Line 1455 of yacc.c */ -#line 468 "QL/parser.y" +#line 462 "QL/parser.y" { - ABORT_IF_OOM((yyvsp[(1) - (1)].node)); - (yyval.node) = (yyvsp[(1) - (1)].node); + (yyval.node) = QLAstNodeCreate(context, QLNodeReferenceCollectionAlias); + ABORT_IF_OOM((yyval.node)); + ABORT_IF_OOM((yyvsp[(1) - (1)].strval)); + (yyval.node)->_value._stringValue = (yyvsp[(1) - (1)].strval); ;} break; case 45: /* Line 1455 of yacc.c */ -#line 472 "QL/parser.y" +#line 468 "QL/parser.y" { - ABORT_IF_OOM((yyvsp[(1) - (1)].node)); - (yyval.node) = (yyvsp[(1) - (1)].node); + size_t outLength; + (yyval.node) = QLAstNodeCreate(context, QLNodeReferenceCollectionAlias); + ABORT_IF_OOM((yyval.node)); + ABORT_IF_OOM((yyvsp[(1) - (1)].strval)); + (yyval.node)->_value._stringValue = QLParseRegisterString(context, TRI_UnescapeUtf8String((yyvsp[(1) - (1)].strval) + 1, strlen((yyvsp[(1) - (1)].strval)) - 2, &outLength)); ;} break; case 46: /* Line 1455 of yacc.c */ -#line 479 "QL/parser.y" +#line 478 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeJoinList); - ABORT_IF_OOM((yyval.node)); + ABORT_IF_OOM((yyvsp[(1) - (1)].node)); + (yyval.node) = (yyvsp[(1) - (1)].node); ;} break; case 47: /* Line 1455 of yacc.c */ -#line 486 "QL/parser.y" +#line 482 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeJoinInner); - ABORT_IF_OOM((yyval.node)); + ABORT_IF_OOM((yyvsp[(1) - (1)].node)); + (yyval.node) = (yyvsp[(1) - (1)].node); ;} break; case 48: /* Line 1455 of yacc.c */ -#line 490 "QL/parser.y" +#line 486 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeJoinInner); - ABORT_IF_OOM((yyval.node)); + ABORT_IF_OOM((yyvsp[(1) - (1)].node)); + (yyval.node) = (yyvsp[(1) - (1)].node); ;} break; case 49: /* Line 1455 of yacc.c */ -#line 497 "QL/parser.y" +#line 493 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeJoinLeft); + (yyval.node) = QLAstNodeCreate(context, QLNodeJoinList); ABORT_IF_OOM((yyval.node)); ;} break; @@ -2256,9 +2279,9 @@ yyreduce: case 50: /* Line 1455 of yacc.c */ -#line 501 "QL/parser.y" +#line 500 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeJoinLeft); + (yyval.node) = QLAstNodeCreate(context, QLNodeJoinInner); ABORT_IF_OOM((yyval.node)); ;} break; @@ -2266,9 +2289,9 @@ yyreduce: case 51: /* Line 1455 of yacc.c */ -#line 505 "QL/parser.y" +#line 504 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeJoinRight); + (yyval.node) = QLAstNodeCreate(context, QLNodeJoinInner); ABORT_IF_OOM((yyval.node)); ;} break; @@ -2276,9 +2299,9 @@ yyreduce: case 52: /* Line 1455 of yacc.c */ -#line 509 "QL/parser.y" +#line 511 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeJoinRight); + (yyval.node) = QLAstNodeCreate(context, QLNodeJoinLeft); ABORT_IF_OOM((yyval.node)); ;} break; @@ -2286,47 +2309,47 @@ yyreduce: case 53: /* Line 1455 of yacc.c */ -#line 516 "QL/parser.y" +#line 515 "QL/parser.y" { - ABORT_IF_OOM((yyvsp[(2) - (3)].node)); - (yyval.node) = (yyvsp[(2) - (3)].node); + (yyval.node) = QLAstNodeCreate(context, QLNodeJoinLeft); + ABORT_IF_OOM((yyval.node)); ;} break; case 54: /* Line 1455 of yacc.c */ -#line 520 "QL/parser.y" +#line 519 "QL/parser.y" { - ABORT_IF_OOM((yyvsp[(1) - (1)].node)); - (yyval.node) = (yyvsp[(1) - (1)].node); + (yyval.node) = QLAstNodeCreate(context, QLNodeJoinRight); + ABORT_IF_OOM((yyval.node)); ;} break; case 55: /* Line 1455 of yacc.c */ -#line 524 "QL/parser.y" +#line 523 "QL/parser.y" { - ABORT_IF_OOM((yyvsp[(1) - (1)].node)); - (yyval.node) = (yyvsp[(1) - (1)].node); + (yyval.node) = QLAstNodeCreate(context, QLNodeJoinRight); + ABORT_IF_OOM((yyval.node)); ;} break; case 56: /* Line 1455 of yacc.c */ -#line 528 "QL/parser.y" +#line 530 "QL/parser.y" { - ABORT_IF_OOM((yyvsp[(1) - (1)].node)); - (yyval.node) = (yyvsp[(1) - (1)].node); + ABORT_IF_OOM((yyvsp[(2) - (3)].node)); + (yyval.node) = (yyvsp[(2) - (3)].node); ;} break; case 57: /* Line 1455 of yacc.c */ -#line 532 "QL/parser.y" +#line 534 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(1) - (1)].node)); (yyval.node) = (yyvsp[(1) - (1)].node); @@ -2336,31 +2359,27 @@ yyreduce: case 58: /* Line 1455 of yacc.c */ -#line 536 "QL/parser.y" - { - QL_ast_node_t* list = QLAstNodeCreate(context, QLNodeContainerList); - ABORT_IF_OOM(list); - QLParseContextPush(context, list); +#line 538 "QL/parser.y" + { + ABORT_IF_OOM((yyvsp[(1) - (1)].node)); + (yyval.node) = (yyvsp[(1) - (1)].node); ;} break; case 59: /* Line 1455 of yacc.c */ -#line 540 "QL/parser.y" +#line 542 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeContainerMemberAccess); - ABORT_IF_OOM((yyval.node)); - ABORT_IF_OOM((yyvsp[(1) - (3)].node)); - (yyval.node)->_lhs = (yyvsp[(1) - (3)].node); - QLPopIntoRhs((yyval.node), context); + ABORT_IF_OOM((yyvsp[(1) - (1)].node)); + (yyval.node) = (yyvsp[(1) - (1)].node); ;} break; case 60: /* Line 1455 of yacc.c */ -#line 547 "QL/parser.y" +#line 546 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(1) - (1)].node)); (yyval.node) = (yyvsp[(1) - (1)].node); @@ -2370,8 +2389,8 @@ yyreduce: case 61: /* Line 1455 of yacc.c */ -#line 551 "QL/parser.y" - { +#line 550 "QL/parser.y" + { QL_ast_node_t* list = QLAstNodeCreate(context, QLNodeContainerList); ABORT_IF_OOM(list); QLParseContextPush(context, list); @@ -2381,7 +2400,7 @@ yyreduce: case 62: /* Line 1455 of yacc.c */ -#line 555 "QL/parser.y" +#line 554 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeContainerMemberAccess); ABORT_IF_OOM((yyval.node)); @@ -2394,17 +2413,17 @@ yyreduce: case 63: /* Line 1455 of yacc.c */ -#line 562 "QL/parser.y" +#line 561 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(1) - (1)].node)); - (yyval.node) = (yyvsp[(1) - (1)].node); + (yyval.node) = (yyvsp[(1) - (1)].node); ;} break; case 64: /* Line 1455 of yacc.c */ -#line 566 "QL/parser.y" +#line 565 "QL/parser.y" { QL_ast_node_t* list = QLAstNodeCreate(context, QLNodeContainerList); ABORT_IF_OOM(list); @@ -2415,7 +2434,7 @@ yyreduce: case 65: /* Line 1455 of yacc.c */ -#line 570 "QL/parser.y" +#line 569 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeContainerMemberAccess); ABORT_IF_OOM((yyval.node)); @@ -2428,17 +2447,51 @@ yyreduce: case 66: /* Line 1455 of yacc.c */ -#line 577 "QL/parser.y" +#line 576 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(1) - (1)].node)); - (yyval.node) = (yyvsp[(1) - (1)].node); + (yyval.node) = (yyvsp[(1) - (1)].node); ;} break; case 67: /* Line 1455 of yacc.c */ -#line 585 "QL/parser.y" +#line 580 "QL/parser.y" + { + QL_ast_node_t* list = QLAstNodeCreate(context, QLNodeContainerList); + ABORT_IF_OOM(list); + QLParseContextPush(context, list); + ;} + break; + + case 68: + +/* Line 1455 of yacc.c */ +#line 584 "QL/parser.y" + { + (yyval.node) = QLAstNodeCreate(context, QLNodeContainerMemberAccess); + ABORT_IF_OOM((yyval.node)); + ABORT_IF_OOM((yyvsp[(1) - (3)].node)); + (yyval.node)->_lhs = (yyvsp[(1) - (3)].node); + QLPopIntoRhs((yyval.node), context); + ;} + break; + + case 69: + +/* Line 1455 of yacc.c */ +#line 591 "QL/parser.y" + { + ABORT_IF_OOM((yyvsp[(1) - (1)].node)); + (yyval.node) = (yyvsp[(1) - (1)].node); + ;} + break; + + case 70: + +/* Line 1455 of yacc.c */ +#line 599 "QL/parser.y" { QL_ast_node_t* name = QLAstNodeCreate(context, QLNodeValueIdentifier); ABORT_IF_OOM(name); @@ -2448,20 +2501,20 @@ yyreduce: ;} break; - case 68: + case 71: /* Line 1455 of yacc.c */ -#line 592 "QL/parser.y" +#line 606 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(2) - (2)].node)); QLParseContextAddElement(context, (yyvsp[(2) - (2)].node)); ;} break; - case 69: + case 72: /* Line 1455 of yacc.c */ -#line 596 "QL/parser.y" +#line 610 "QL/parser.y" { QL_ast_node_t* name = QLAstNodeCreate(context, QLNodeValueIdentifier); ABORT_IF_OOM(name); @@ -2471,10 +2524,10 @@ yyreduce: ;} break; - case 70: + case 73: /* Line 1455 of yacc.c */ -#line 603 "QL/parser.y" +#line 617 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2482,10 +2535,10 @@ yyreduce: ;} break; - case 71: + case 74: /* Line 1455 of yacc.c */ -#line 611 "QL/parser.y" +#line 625 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeUnaryOperatorPlus); ABORT_IF_OOM((yyval.node)); @@ -2494,10 +2547,10 @@ yyreduce: ;} break; - case 72: + case 75: /* Line 1455 of yacc.c */ -#line 617 "QL/parser.y" +#line 631 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeUnaryOperatorMinus); ABORT_IF_OOM((yyval.node)); @@ -2506,10 +2559,10 @@ yyreduce: ;} break; - case 73: + case 76: /* Line 1455 of yacc.c */ -#line 623 "QL/parser.y" +#line 637 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeUnaryOperatorNot); ABORT_IF_OOM((yyval.node)); @@ -2518,54 +2571,12 @@ yyreduce: ;} break; - case 74: - -/* Line 1455 of yacc.c */ -#line 632 "QL/parser.y" - { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorOr); - ABORT_IF_OOM((yyval.node)); - ABORT_IF_OOM((yyvsp[(1) - (3)].node)); - ABORT_IF_OOM((yyvsp[(3) - (3)].node)); - (yyval.node)->_lhs = (yyvsp[(1) - (3)].node); - (yyval.node)->_rhs = (yyvsp[(3) - (3)].node); - ;} - break; - - case 75: - -/* Line 1455 of yacc.c */ -#line 640 "QL/parser.y" - { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorAnd); - ABORT_IF_OOM((yyval.node)); - ABORT_IF_OOM((yyvsp[(1) - (3)].node)); - ABORT_IF_OOM((yyvsp[(3) - (3)].node)); - (yyval.node)->_lhs = (yyvsp[(1) - (3)].node); - (yyval.node)->_rhs = (yyvsp[(3) - (3)].node); - ;} - break; - - case 76: - -/* Line 1455 of yacc.c */ -#line 648 "QL/parser.y" - { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorAdd); - ABORT_IF_OOM((yyval.node)); - ABORT_IF_OOM((yyvsp[(1) - (3)].node)); - ABORT_IF_OOM((yyvsp[(3) - (3)].node)); - (yyval.node)->_lhs = (yyvsp[(1) - (3)].node); - (yyval.node)->_rhs = (yyvsp[(3) - (3)].node); - ;} - break; - case 77: /* Line 1455 of yacc.c */ -#line 656 "QL/parser.y" +#line 646 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorSubtract); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorOr); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2577,23 +2588,23 @@ yyreduce: case 78: /* Line 1455 of yacc.c */ -#line 664 "QL/parser.y" +#line 654 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorMultiply); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorAnd); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); (yyval.node)->_lhs = (yyvsp[(1) - (3)].node); - (yyval.node)->_rhs = (yyvsp[(3) - (3)].node); + (yyval.node)->_rhs = (yyvsp[(3) - (3)].node); ;} break; case 79: /* Line 1455 of yacc.c */ -#line 672 "QL/parser.y" +#line 662 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorDivide); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorAdd); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2605,9 +2616,9 @@ yyreduce: case 80: /* Line 1455 of yacc.c */ -#line 680 "QL/parser.y" +#line 670 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorModulus); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorSubtract); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2619,9 +2630,9 @@ yyreduce: case 81: /* Line 1455 of yacc.c */ -#line 688 "QL/parser.y" +#line 678 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorIdentical); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorMultiply); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2633,9 +2644,9 @@ yyreduce: case 82: /* Line 1455 of yacc.c */ -#line 696 "QL/parser.y" +#line 686 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorUnidentical); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorDivide); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2647,9 +2658,9 @@ yyreduce: case 83: /* Line 1455 of yacc.c */ -#line 704 "QL/parser.y" +#line 694 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorEqual); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorModulus); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2661,9 +2672,9 @@ yyreduce: case 84: /* Line 1455 of yacc.c */ -#line 712 "QL/parser.y" +#line 702 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorUnequal); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorIdentical); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2675,9 +2686,9 @@ yyreduce: case 85: /* Line 1455 of yacc.c */ -#line 720 "QL/parser.y" +#line 710 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorLess); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorUnidentical); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2689,9 +2700,9 @@ yyreduce: case 86: /* Line 1455 of yacc.c */ -#line 728 "QL/parser.y" +#line 718 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorGreater); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorEqual); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2703,9 +2714,9 @@ yyreduce: case 87: /* Line 1455 of yacc.c */ -#line 736 "QL/parser.y" +#line 726 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorLessEqual); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorUnequal); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2717,9 +2728,9 @@ yyreduce: case 88: /* Line 1455 of yacc.c */ -#line 744 "QL/parser.y" +#line 734 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorGreaterEqual); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorLess); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2731,9 +2742,9 @@ yyreduce: case 89: /* Line 1455 of yacc.c */ -#line 752 "QL/parser.y" +#line 742 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorIn); + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorGreater); ABORT_IF_OOM((yyval.node)); ABORT_IF_OOM((yyvsp[(1) - (3)].node)); ABORT_IF_OOM((yyvsp[(3) - (3)].node)); @@ -2745,7 +2756,49 @@ yyreduce: case 90: /* Line 1455 of yacc.c */ -#line 763 "QL/parser.y" +#line 750 "QL/parser.y" + { + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorLessEqual); + ABORT_IF_OOM((yyval.node)); + ABORT_IF_OOM((yyvsp[(1) - (3)].node)); + ABORT_IF_OOM((yyvsp[(3) - (3)].node)); + (yyval.node)->_lhs = (yyvsp[(1) - (3)].node); + (yyval.node)->_rhs = (yyvsp[(3) - (3)].node); + ;} + break; + + case 91: + +/* Line 1455 of yacc.c */ +#line 758 "QL/parser.y" + { + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorGreaterEqual); + ABORT_IF_OOM((yyval.node)); + ABORT_IF_OOM((yyvsp[(1) - (3)].node)); + ABORT_IF_OOM((yyvsp[(3) - (3)].node)); + (yyval.node)->_lhs = (yyvsp[(1) - (3)].node); + (yyval.node)->_rhs = (yyvsp[(3) - (3)].node); + ;} + break; + + case 92: + +/* Line 1455 of yacc.c */ +#line 766 "QL/parser.y" + { + (yyval.node) = QLAstNodeCreate(context, QLNodeBinaryOperatorIn); + ABORT_IF_OOM((yyval.node)); + ABORT_IF_OOM((yyvsp[(1) - (3)].node)); + ABORT_IF_OOM((yyvsp[(3) - (3)].node)); + (yyval.node)->_lhs = (yyvsp[(1) - (3)].node); + (yyval.node)->_rhs = (yyvsp[(3) - (3)].node); + ;} + break; + + case 93: + +/* Line 1455 of yacc.c */ +#line 777 "QL/parser.y" { QL_ast_node_t* node = QLAstNodeCreate(context, QLNodeContainerTernarySwitch); ABORT_IF_OOM(node); @@ -2762,20 +2815,20 @@ yyreduce: ;} break; - case 91: + case 94: /* Line 1455 of yacc.c */ -#line 780 "QL/parser.y" +#line 794 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(1) - (1)].node)); (yyval.node) = (yyvsp[(1) - (1)].node); ;} break; - case 92: + case 95: /* Line 1455 of yacc.c */ -#line 787 "QL/parser.y" +#line 801 "QL/parser.y" { QL_ast_node_t* name = QLAstNodeCreate(context, QLNodeValueIdentifier); ABORT_IF_OOM(name); @@ -2790,10 +2843,10 @@ yyreduce: ;} break; - case 93: + case 96: /* Line 1455 of yacc.c */ -#line 799 "QL/parser.y" +#line 813 "QL/parser.y" { QL_ast_node_t* list = QLAstNodeCreate(context, QLNodeContainerList); ABORT_IF_OOM(list); @@ -2801,10 +2854,10 @@ yyreduce: ;} break; - case 94: + case 97: /* Line 1455 of yacc.c */ -#line 803 "QL/parser.y" +#line 817 "QL/parser.y" { QL_ast_node_t* name = QLAstNodeCreate(context, QLNodeValueIdentifier); ABORT_IF_OOM(name); @@ -2818,39 +2871,39 @@ yyreduce: ;} break; - case 95: + case 98: /* Line 1455 of yacc.c */ -#line 817 "QL/parser.y" +#line 831 "QL/parser.y" { QLParseContextAddElement(context, (yyvsp[(1) - (1)].node)); ;} break; - case 96: + case 99: /* Line 1455 of yacc.c */ -#line 820 "QL/parser.y" +#line 834 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(3) - (3)].node)); QLParseContextAddElement(context, (yyvsp[(3) - (3)].node)); ;} break; - case 97: + case 100: /* Line 1455 of yacc.c */ -#line 827 "QL/parser.y" +#line 841 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeValueArray); ABORT_IF_OOM((yyval.node)); ;} break; - case 98: + case 101: /* Line 1455 of yacc.c */ -#line 831 "QL/parser.y" +#line 845 "QL/parser.y" { QL_ast_node_t* list = QLAstNodeCreate(context, QLNodeContainerList); ABORT_IF_OOM(list); @@ -2858,10 +2911,10 @@ yyreduce: ;} break; - case 99: + case 102: /* Line 1455 of yacc.c */ -#line 835 "QL/parser.y" +#line 849 "QL/parser.y" { (yyval.node) = QLAstNodeCreate(context, QLNodeValueArray); ABORT_IF_OOM((yyval.node)); @@ -2869,29 +2922,29 @@ yyreduce: ;} break; - case 100: + case 103: /* Line 1455 of yacc.c */ -#line 843 "QL/parser.y" +#line 857 "QL/parser.y" { QLParseContextAddElement(context, (yyvsp[(1) - (1)].node)); ;} break; - case 101: + case 104: /* Line 1455 of yacc.c */ -#line 846 "QL/parser.y" +#line 860 "QL/parser.y" { ABORT_IF_OOM((yyvsp[(3) - (3)].node)); QLParseContextAddElement(context, (yyvsp[(3) - (3)].node)); ;} break; - case 102: + case 105: /* Line 1455 of yacc.c */ -#line 853 "QL/parser.y" +#line 867 "QL/parser.y" { size_t outLength; (yyval.node) = QLAstNodeCreate(context, QLNodeValueString); @@ -2901,10 +2954,10 @@ yyreduce: ;} break; - case 103: + case 106: /* Line 1455 of yacc.c */ -#line 860 "QL/parser.y" +#line 874 "QL/parser.y" { double d = TRI_DoubleString((yyvsp[(1) - (1)].strval)); if (TRI_errno() != TRI_ERROR_NO_ERROR && d != 0.0) { @@ -2918,45 +2971,13 @@ yyreduce: ;} break; - case 104: - -/* Line 1455 of yacc.c */ -#line 871 "QL/parser.y" - { - (yyval.node) = QLAstNodeCreate(context, QLNodeValueNull); - ABORT_IF_OOM((yyval.node)); - ;} - break; - - case 105: - -/* Line 1455 of yacc.c */ -#line 875 "QL/parser.y" - { - (yyval.node) = QLAstNodeCreate(context, QLNodeValueUndefined); - ABORT_IF_OOM((yyval.node)); - ;} - break; - - case 106: - -/* Line 1455 of yacc.c */ -#line 879 "QL/parser.y" - { - (yyval.node) = QLAstNodeCreate(context, QLNodeValueBool); - ABORT_IF_OOM((yyval.node)); - (yyval.node)->_value._boolValue = true; - ;} - break; - case 107: /* Line 1455 of yacc.c */ -#line 884 "QL/parser.y" +#line 885 "QL/parser.y" { - (yyval.node) = QLAstNodeCreate(context, QLNodeValueBool); + (yyval.node) = QLAstNodeCreate(context, QLNodeValueNull); ABORT_IF_OOM((yyval.node)); - (yyval.node)->_value._boolValue = false; ;} break; @@ -2964,6 +2985,38 @@ yyreduce: /* Line 1455 of yacc.c */ #line 889 "QL/parser.y" + { + (yyval.node) = QLAstNodeCreate(context, QLNodeValueUndefined); + ABORT_IF_OOM((yyval.node)); + ;} + break; + + case 109: + +/* Line 1455 of yacc.c */ +#line 893 "QL/parser.y" + { + (yyval.node) = QLAstNodeCreate(context, QLNodeValueBool); + ABORT_IF_OOM((yyval.node)); + (yyval.node)->_value._boolValue = true; + ;} + break; + + case 110: + +/* Line 1455 of yacc.c */ +#line 898 "QL/parser.y" + { + (yyval.node) = QLAstNodeCreate(context, QLNodeValueBool); + ABORT_IF_OOM((yyval.node)); + (yyval.node)->_value._boolValue = false; + ;} + break; + + case 111: + +/* Line 1455 of yacc.c */ +#line 903 "QL/parser.y" { // numbered parameter int64_t d = TRI_Int64String((yyvsp[(1) - (1)].strval)); @@ -2979,10 +3032,10 @@ yyreduce: ;} break; - case 109: + case 112: /* Line 1455 of yacc.c */ -#line 902 "QL/parser.y" +#line 916 "QL/parser.y" { // named parameter (yyval.node) = QLAstNodeCreate(context, QLNodeValueParameterNamed); @@ -2994,7 +3047,7 @@ yyreduce: /* Line 1455 of yacc.c */ -#line 2998 "QL/parser.c" +#line 3051 "QL/parser.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -3213,7 +3266,7 @@ yyreturn: /* Line 1675 of yacc.c */ -#line 910 "QL/parser.y" +#line 924 "QL/parser.y" diff --git a/QL/parser.h b/QL/parser.h index a973cd9df5..c1f18362a5 100644 --- a/QL/parser.h +++ b/QL/parser.h @@ -53,36 +53,38 @@ BY = 269, ASC = 270, DESC = 271, - LIMIT = 272, - AND = 273, - OR = 274, - NOT = 275, - IN = 276, - ASSIGNMENT = 277, - GREATER = 278, - LESS = 279, - GREATER_EQUAL = 280, - LESS_EQUAL = 281, - EQUAL = 282, - UNEQUAL = 283, - IDENTICAL = 284, - UNIDENTICAL = 285, - NULLX = 286, - TRUE = 287, - FALSE = 288, - UNDEFINED = 289, - IDENTIFIER = 290, - QUOTED_IDENTIFIER = 291, - PARAMETER = 292, - PARAMETER_NAMED = 293, - STRING = 294, - REAL = 295, - COLON = 296, - TERNARY = 297, - FCALL = 298, - UPLUS = 299, - UMINUS = 300, - MEMBER = 301 + WITHIN = 272, + NEAR = 273, + LIMIT = 274, + AND = 275, + OR = 276, + NOT = 277, + IN = 278, + ASSIGNMENT = 279, + GREATER = 280, + LESS = 281, + GREATER_EQUAL = 282, + LESS_EQUAL = 283, + EQUAL = 284, + UNEQUAL = 285, + IDENTICAL = 286, + UNIDENTICAL = 287, + NULLX = 288, + TRUE = 289, + FALSE = 290, + UNDEFINED = 291, + IDENTIFIER = 292, + QUOTED_IDENTIFIER = 293, + PARAMETER = 294, + PARAMETER_NAMED = 295, + STRING = 296, + REAL = 297, + COLON = 298, + TERNARY = 299, + FCALL = 300, + UPLUS = 301, + UMINUS = 302, + MEMBER = 303 }; #endif @@ -103,7 +105,7 @@ typedef union YYSTYPE /* Line 1676 of yacc.c */ -#line 107 "QL/parser.h" +#line 109 "QL/parser.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/QL/parser.y b/QL/parser.y index c0b491ac68..2ec6f09484 100644 --- a/QL/parser.y +++ b/QL/parser.y @@ -73,6 +73,7 @@ void QLerror (YYLTYPE *locp,QL_parser_context_t *context, const char *err) { %type collection_reference; %type collection_name; %type collection_alias; +%type geo_expression; %type where_clause; %type order_clause; %type order_list; @@ -95,6 +96,7 @@ void QLerror (YYLTYPE *locp,QL_parser_context_t *context, const char *err) { %token WHERE %token JOIN LIST INNER OUTER LEFT RIGHT ON %token ORDER BY ASC DESC +%token WITHIN NEAR %token LIMIT %token AND OR NOT IN %token ASSIGNMENT GREATER LESS GREATER_EQUAL LESS_EQUAL EQUAL UNEQUAL IDENTICAL UNIDENTICAL @@ -172,24 +174,35 @@ from_clause: ; from_list: - collection_reference { + collection_reference geo_expression { // single table query ABORT_IF_OOM($1); QLParseContextAddElement(context, $1); } - | from_list join_type collection_reference ON expression { + | from_list join_type collection_reference geo_expression ON expression { // multi-table query ABORT_IF_OOM($2); ABORT_IF_OOM($3); - ABORT_IF_OOM($5); + ABORT_IF_OOM($6); $$ = $2; $$->_lhs = $3; - $$->_rhs = $5; + $$->_rhs = $6; QLParseContextAddElement(context, $2); } ; +geo_expression: + /* empty */ { + $$ = 0; + } + | WITHIN collection_alias ASSIGNMENT '(' object_access ',' object_access ',' REAL ',' REAL ',' REAL ')' { + } + | NEAR collection_alias ASSIGNMENT '(' object_access ',' object_access ',' REAL ',' REAL ',' REAL ')' { + } + ; + + where_clause: /* empty */ { $$ = 0; @@ -370,15 +383,16 @@ attribute: named_attribute: IDENTIFIER COLON expression { - QL_ast_node_t* identifier = QLAstNodeCreate(context, QLNodeValueIdentifier); - ABORT_IF_OOM(identifier); + size_t outLength; + QL_ast_node_t* str = QLAstNodeCreate(context, QLNodeValueString); + ABORT_IF_OOM(str); ABORT_IF_OOM($1); ABORT_IF_OOM($3); - identifier->_value._stringValue = $1; + str->_value._stringValue = QLParseRegisterString(context, TRI_UnescapeUtf8String($1, strlen($1), &outLength)); $$ = QLAstNodeCreate(context, QLNodeValueNamedValue); ABORT_IF_OOM($$); - $$->_lhs = identifier; + $$->_lhs = str; $$->_rhs = $3; } | STRING COLON expression { diff --git a/QL/tokens.c b/QL/tokens.c index 0edfdf1676..bcf86407f6 100644 --- a/QL/tokens.c +++ b/QL/tokens.c @@ -446,8 +446,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); yyg->yy_c_buf_p = yy_cp; /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ -#define YY_NUM_RULES 45 -#define YY_END_OF_BUFFER 46 +#define YY_NUM_RULES 47 +#define YY_END_OF_BUFFER 48 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -455,23 +455,24 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[139] = +static yyconst flex_int16_t yy_accept[147] = { 0, - 0, 0, 46, 44, 43, 43, 23, 44, 44, 44, - 38, 38, 25, 33, 35, 34, 24, 44, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 44, 44, 44, 43, 28, 0, 39, - 0, 21, 0, 40, 0, 0, 38, 31, 30, 29, - 32, 41, 41, 0, 36, 36, 13, 36, 36, 36, - 11, 36, 36, 36, 36, 10, 36, 36, 36, 36, - 36, 36, 36, 36, 0, 0, 0, 37, 22, 27, - 38, 26, 41, 0, 14, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 0, 0, 48, 46, 45, 45, 25, 46, 46, 46, + 40, 40, 27, 35, 37, 36, 26, 46, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 46, 46, 46, 45, 30, 0, 41, + 0, 23, 0, 42, 0, 0, 40, 33, 32, 31, + 34, 43, 43, 0, 38, 38, 13, 38, 38, 38, + 11, 38, 38, 38, 38, 38, 10, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 0, 0, 0, 39, + 24, 29, 40, 28, 43, 0, 14, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 36, 36, 36, 0, 42, 15, 36, 2, 36, 5, - 7, 36, 4, 17, 36, 36, 36, 36, 19, 36, - 36, 0, 38, 20, 6, 16, 12, 9, 8, 36, - 36, 3, 1, 36, 36, 36, 18, 0 + 38, 38, 38, 38, 38, 38, 38, 0, 44, 15, + 38, 2, 38, 5, 7, 38, 4, 22, 17, 38, + 38, 38, 38, 19, 38, 38, 38, 0, 40, 20, + 6, 16, 12, 9, 8, 38, 38, 3, 38, 1, + 38, 21, 38, 38, 18, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -517,47 +518,49 @@ static yyconst flex_int32_t yy_meta[63] = 3, 1 } ; -static yyconst flex_int16_t yy_base[148] = +static yyconst flex_int16_t yy_base[156] = { 0, - 0, 0, 254, 294, 61, 63, 239, 62, 245, 61, - 238, 60, 294, 58, 232, 231, 294, 64, 42, 41, - 0, 58, 63, 52, 52, 63, 51, 61, 62, 68, - 60, 64, 73, 203, 82, 180, 75, 185, 86, 294, - 183, 294, 96, 294, 141, 116, 119, 294, 294, 126, - 294, 294, 121, 0, 0, 104, 0, 77, 104, 104, - 106, 112, 116, 111, 113, 0, 122, 111, 123, 120, - 114, 130, 130, 143, 68, 116, 83, 294, 294, 294, - 167, 294, 169, 65, 0, 138, 127, 140, 144, 143, - 146, 159, 152, 159, 169, 170, 169, 173, 174, 176, + 0, 0, 266, 312, 61, 63, 251, 62, 257, 61, + 251, 60, 312, 58, 241, 182, 312, 64, 42, 41, + 0, 58, 63, 52, 52, 63, 72, 79, 61, 68, + 60, 66, 96, 152, 47, 103, 75, 139, 86, 312, + 147, 312, 85, 312, 140, 116, 119, 312, 312, 89, + 312, 312, 126, 0, 0, 97, 0, 98, 105, 107, + 109, 97, 119, 114, 131, 122, 0, 131, 119, 132, + 129, 123, 139, 139, 129, 158, 58, 131, 92, 312, + 312, 312, 168, 312, 178, 65, 0, 155, 149, 156, + 169, 162, 159, 169, 162, 167, 172, 180, 181, 179, - 167, 0, 191, 195, 294, 0, 186, 0, 174, 0, - 0, 177, 0, 0, 181, 184, 186, 204, 0, 202, - 204, 217, 223, 0, 0, 0, 0, 0, 0, 194, - 210, 0, 0, 207, 217, 220, 0, 294, 265, 269, - 272, 274, 276, 280, 283, 286, 289 + 183, 185, 186, 177, 186, 0, 202, 226, 312, 0, + 199, 0, 185, 0, 0, 190, 0, 0, 0, 197, + 205, 204, 202, 0, 217, 221, 218, 239, 241, 0, + 0, 0, 0, 0, 0, 212, 228, 0, 225, 0, + 226, 0, 236, 238, 0, 312, 283, 287, 290, 292, + 294, 298, 301, 304, 307 } ; -static yyconst flex_int16_t yy_def[148] = +static yyconst flex_int16_t yy_def[156] = { 0, - 138, 1, 138, 138, 138, 138, 138, 139, 138, 140, - 138, 138, 138, 138, 138, 138, 138, 141, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 143, 144, 138, 138, 138, 139, 138, - 139, 138, 140, 138, 140, 138, 138, 138, 138, 138, - 138, 138, 138, 145, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 146, 143, 144, 144, 138, 138, 138, - 138, 138, 138, 145, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 146, 1, 146, 146, 146, 146, 146, 147, 146, 148, + 146, 146, 146, 146, 146, 146, 146, 149, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 151, 152, 146, 146, 146, 147, 146, + 147, 146, 148, 146, 148, 146, 146, 146, 146, 146, + 146, 146, 146, 153, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 154, 151, 152, 152, 146, + 146, 146, 146, 146, 146, 153, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, - 142, 147, 146, 138, 138, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 138, 138, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 0, 138, 138, - 138, 138, 138, 138, 138, 138, 138 + 150, 150, 150, 150, 150, 155, 154, 146, 146, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 146, 146, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 0, 146, 146, 146, 146, + 146, 146, 146, 146, 146 } ; -static yyconst flex_int16_t yy_nxt[357] = +static yyconst flex_int16_t yy_nxt[375] = { 0, 4, 5, 6, 7, 8, 9, 10, 4, 4, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, @@ -567,40 +570,42 @@ static yyconst flex_int16_t yy_nxt[357] = 25, 26, 21, 27, 28, 29, 30, 31, 32, 33, 21, 36, 37, 37, 37, 37, 40, 44, 46, 47, 47, 48, 49, 52, 53, 56, 37, 37, 57, 58, - 59, 105, 61, 62, 63, 138, 65, 69, 64, 70, - 40, 66, 71, 67, 72, 60, 68, 73, 56, 45, + 59, 109, 61, 62, 63, 79, 70, 80, 64, 71, + 40, 44, 72, 65, 146, 60, 73, 77, 56, 45, - 41, 57, 44, 58, 59, 61, 62, 75, 63, 65, - 86, 69, 64, 70, 66, 71, 67, 72, 60, 68, - 77, 73, 78, 85, 41, 81, 81, 46, 47, 47, - 83, 83, 87, 86, 45, 88, 89, 90, 91, 82, - 92, 94, 95, 138, 93, 96, 97, 85, 98, 99, - 100, 101, 102, 102, 77, 87, 78, 106, 88, 89, - 107, 90, 91, 92, 94, 109, 95, 93, 96, 108, - 97, 98, 99, 110, 100, 101, 81, 81, 83, 83, - 111, 106, 102, 107, 112, 138, 113, 114, 104, 109, - 115, 116, 108, 117, 118, 119, 110, 120, 80, 121, + 41, 57, 84, 58, 59, 61, 62, 66, 63, 67, + 70, 68, 64, 71, 69, 72, 87, 65, 60, 73, + 74, 75, 92, 45, 41, 83, 83, 46, 47, 47, + 66, 88, 67, 89, 68, 85, 85, 69, 90, 91, + 87, 93, 146, 94, 74, 75, 92, 95, 96, 146, + 97, 98, 82, 99, 88, 100, 89, 101, 102, 103, + 104, 90, 91, 105, 81, 93, 94, 106, 106, 79, + 95, 80, 96, 97, 110, 98, 99, 83, 83, 100, + 101, 102, 111, 103, 104, 112, 105, 85, 85, 108, + 113, 77, 114, 115, 116, 51, 117, 106, 110, 118, - 102, 102, 122, 111, 123, 123, 125, 124, 112, 113, - 114, 126, 104, 127, 115, 116, 128, 117, 118, 119, - 129, 120, 121, 130, 131, 132, 123, 123, 133, 125, - 102, 124, 123, 123, 126, 134, 127, 135, 136, 128, - 137, 79, 75, 129, 51, 50, 46, 130, 131, 132, - 42, 133, 38, 138, 138, 138, 138, 138, 138, 134, - 135, 138, 136, 138, 137, 39, 39, 39, 39, 43, - 43, 43, 43, 54, 54, 55, 55, 55, 74, 74, - 76, 76, 76, 76, 84, 84, 84, 103, 103, 103, - 102, 102, 102, 3, 138, 138, 138, 138, 138, 138, + 119, 120, 121, 122, 123, 111, 124, 125, 112, 126, + 127, 106, 106, 108, 113, 114, 115, 131, 116, 117, + 130, 136, 118, 119, 132, 120, 121, 122, 123, 133, + 124, 125, 126, 128, 127, 129, 129, 134, 135, 137, + 131, 106, 138, 139, 130, 136, 140, 132, 129, 129, + 129, 129, 133, 141, 50, 142, 143, 144, 145, 46, + 134, 135, 42, 137, 38, 146, 138, 139, 146, 140, + 146, 146, 146, 146, 146, 146, 146, 141, 142, 143, + 146, 144, 145, 39, 39, 39, 39, 43, 43, 43, + 43, 54, 54, 55, 55, 55, 76, 76, 78, 78, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138 + 78, 78, 86, 86, 86, 107, 107, 107, 106, 106, + 106, 3, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146 } ; -static yyconst flex_int16_t yy_chk[357] = +static yyconst flex_int16_t yy_chk[375] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -610,53 +615,55 @@ static yyconst flex_int16_t yy_chk[357] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 6, 6, 8, 10, 12, 12, 12, 14, 14, 18, 18, 19, 37, 37, 20, 22, - 23, 84, 24, 25, 26, 77, 27, 29, 26, 30, - 39, 28, 31, 28, 32, 23, 28, 33, 19, 10, + 23, 86, 24, 25, 26, 35, 29, 35, 26, 30, + 39, 43, 31, 27, 79, 23, 32, 77, 19, 10, - 8, 20, 43, 22, 23, 24, 25, 75, 26, 27, - 58, 29, 26, 30, 28, 31, 28, 32, 23, 28, - 35, 33, 35, 56, 39, 46, 46, 47, 47, 47, - 53, 53, 59, 58, 43, 60, 61, 62, 63, 50, - 64, 65, 67, 45, 64, 68, 69, 56, 70, 71, - 72, 73, 74, 74, 76, 59, 76, 86, 60, 61, - 87, 62, 63, 64, 65, 89, 67, 64, 68, 88, - 69, 70, 71, 90, 72, 73, 81, 81, 83, 83, - 91, 86, 74, 87, 92, 41, 93, 94, 81, 89, - 95, 96, 88, 97, 98, 99, 90, 100, 38, 101, + 8, 20, 50, 22, 23, 24, 25, 27, 26, 28, + 29, 28, 26, 30, 28, 31, 56, 27, 23, 32, + 33, 33, 62, 43, 39, 46, 46, 47, 47, 47, + 27, 58, 28, 59, 28, 53, 53, 28, 60, 61, + 56, 63, 45, 64, 33, 33, 62, 64, 65, 41, + 66, 68, 38, 69, 58, 70, 59, 71, 72, 73, + 74, 60, 61, 75, 36, 63, 64, 76, 76, 78, + 64, 78, 65, 66, 88, 68, 69, 83, 83, 70, + 71, 72, 89, 73, 74, 90, 75, 85, 85, 83, + 91, 34, 92, 93, 94, 16, 95, 76, 88, 96, - 103, 103, 104, 91, 104, 104, 109, 107, 92, 93, - 94, 112, 81, 115, 95, 96, 116, 97, 98, 99, - 117, 100, 101, 118, 120, 121, 122, 122, 130, 109, - 103, 107, 123, 123, 112, 131, 115, 134, 135, 116, - 136, 36, 34, 117, 16, 15, 11, 118, 120, 121, - 9, 130, 7, 3, 0, 0, 0, 0, 0, 131, - 134, 0, 135, 0, 136, 139, 139, 139, 139, 140, - 140, 140, 140, 141, 141, 142, 142, 142, 143, 143, - 144, 144, 144, 144, 145, 145, 145, 146, 146, 146, - 147, 147, 147, 138, 138, 138, 138, 138, 138, 138, + 97, 98, 99, 100, 101, 89, 102, 103, 90, 104, + 105, 107, 107, 83, 91, 92, 93, 113, 94, 95, + 111, 123, 96, 97, 116, 98, 99, 100, 101, 120, + 102, 103, 104, 108, 105, 108, 108, 121, 122, 125, + 113, 107, 126, 127, 111, 123, 136, 116, 128, 128, + 129, 129, 120, 137, 15, 139, 141, 143, 144, 11, + 121, 122, 9, 125, 7, 3, 126, 127, 0, 136, + 0, 0, 0, 0, 0, 0, 0, 137, 139, 141, + 0, 143, 144, 147, 147, 147, 147, 148, 148, 148, + 148, 149, 149, 150, 150, 150, 151, 151, 152, 152, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138 + 152, 152, 153, 153, 153, 154, 154, 154, 155, 155, + 155, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[46] = +static yyconst flex_int32_t yy_rule_can_match_eol[48] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, - 1, 0, 0, 1, 0, 0, }; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 1, 1, 0, 0, 1, 0, 0, }; -static yyconst flex_int16_t yy_rule_linenum[45] = +static yyconst flex_int16_t yy_rule_linenum[47] = { 0, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 118, 122, 126, 130, - 139, 143, 147, 156, 160, 169, 173, 177, 181, 185, - 189, 193, 197, 201, 210, 219, 224, 229, 234, 239, - 249, 254, 264, 268 + 139, 143, 152, 156, 160, 169, 173, 182, 186, 190, + 194, 198, 202, 206, 210, 214, 223, 232, 237, 242, + 247, 252, 262, 267, 277, 281 } ; /* The intent behind this definition is that it'll catch @@ -1067,13 +1074,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 139 ) + if ( yy_current_state >= 147 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_current_state != 138 ); + while ( yy_current_state != 146 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; @@ -1104,13 +1111,13 @@ do_action: /* This label is used only to access EOF actions. */ { if ( yy_act == 0 ) fprintf( stderr, "--scanner backing up\n" ); - else if ( yy_act < 45 ) + else if ( yy_act < 47 ) fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", (long)yy_rule_linenum[yy_act], yytext ); - else if ( yy_act == 45 ) + else if ( yy_act == 47 ) fprintf( stderr, "--accepting default rule (\"%s\")\n", yytext ); - else if ( yy_act == 46 ) + else if ( yy_act == 48 ) fprintf( stderr, "--(end of buffer or a NUL)\n" ); else fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); @@ -1250,21 +1257,36 @@ YY_RULE_SETUP } YY_BREAK /* --------------------------------------------------------------------------- - * logical operators + * other keywords * --------------------------------------------------------------------------- */ case 21: YY_RULE_SETUP { - return AND; + return WITHIN; } YY_BREAK case 22: YY_RULE_SETUP +{ + return NEAR; +} + YY_BREAK +/* --------------------------------------------------------------------------- + * logical operators + * --------------------------------------------------------------------------- */ +case 23: +YY_RULE_SETUP +{ + return AND; +} + YY_BREAK +case 24: +YY_RULE_SETUP { return OR; } YY_BREAK -case 23: +case 25: YY_RULE_SETUP { return NOT; @@ -1273,13 +1295,13 @@ YY_RULE_SETUP /* --------------------------------------------------------------------------- * ternary operator * --------------------------------------------------------------------------- */ -case 24: +case 26: YY_RULE_SETUP { return TERNARY; } YY_BREAK -case 25: +case 27: YY_RULE_SETUP { return COLON; @@ -1288,55 +1310,55 @@ YY_RULE_SETUP /* --------------------------------------------------------------------------- * comparison operators * --------------------------------------------------------------------------- */ -case 26: +case 28: YY_RULE_SETUP { return IDENTICAL; } YY_BREAK -case 27: +case 29: YY_RULE_SETUP { return UNIDENTICAL; } YY_BREAK -case 28: -YY_RULE_SETUP -{ - return UNEQUAL; -} - YY_BREAK -case 29: -YY_RULE_SETUP -{ - return EQUAL; -} - YY_BREAK case 30: YY_RULE_SETUP -{ +{ return UNEQUAL; } YY_BREAK case 31: YY_RULE_SETUP { - return LESS_EQUAL; + return EQUAL; } YY_BREAK case 32: YY_RULE_SETUP { - return GREATER_EQUAL; + return UNEQUAL; } YY_BREAK case 33: YY_RULE_SETUP +{ + return LESS_EQUAL; +} + YY_BREAK +case 34: +YY_RULE_SETUP +{ + return GREATER_EQUAL; +} + YY_BREAK +case 35: +YY_RULE_SETUP { return LESS; } YY_BREAK -case 34: +case 36: YY_RULE_SETUP { return GREATER; @@ -1345,7 +1367,7 @@ YY_RULE_SETUP /* --------------------------------------------------------------------------- * assignment * --------------------------------------------------------------------------- */ -case 35: +case 37: YY_RULE_SETUP { return ASSIGNMENT; @@ -1354,38 +1376,38 @@ YY_RULE_SETUP /* --------------------------------------------------------------------------- * literals * --------------------------------------------------------------------------- */ -case 36: +case 38: YY_RULE_SETUP { yylval->strval = QLParseAllocString(yyextra, yytext); return IDENTIFIER; } YY_BREAK -case 37: -/* rule 37 can match eol */ -YY_RULE_SETUP -{ - yylval->strval = QLParseAllocString(yyextra, yytext); - return QUOTED_IDENTIFIER; -} - YY_BREAK -case 38: -YY_RULE_SETUP -{ - yylval->strval = QLParseAllocString(yyextra, yytext); - return REAL; -} - YY_BREAK case 39: /* rule 39 can match eol */ YY_RULE_SETUP { yylval->strval = QLParseAllocString(yyextra, yytext); - return STRING; + return QUOTED_IDENTIFIER; } YY_BREAK case 40: -/* rule 40 can match eol */ +YY_RULE_SETUP +{ + yylval->strval = QLParseAllocString(yyextra, yytext); + return REAL; +} + YY_BREAK +case 41: +/* rule 41 can match eol */ +YY_RULE_SETUP +{ + yylval->strval = QLParseAllocString(yyextra, yytext); + return STRING; +} + YY_BREAK +case 42: +/* rule 42 can match eol */ YY_RULE_SETUP { yylval->strval = QLParseAllocString(yyextra, yytext); @@ -1395,14 +1417,14 @@ YY_RULE_SETUP /* --------------------------------------------------------------------------- * parameters * --------------------------------------------------------------------------- */ -case 41: +case 43: YY_RULE_SETUP { yylval->strval = QLParseAllocString(yyextra, yytext + 1); return PARAMETER; } YY_BREAK -case 42: +case 44: YY_RULE_SETUP { yylval->strval = QLParseAllocString2(yyextra, yytext + 1 , strlen(yytext) - 2); @@ -1412,20 +1434,20 @@ YY_RULE_SETUP /* --------------------------------------------------------------------------- * whitespace etc. * --------------------------------------------------------------------------- */ -case 43: -/* rule 43 can match eol */ +case 45: +/* rule 45 can match eol */ YY_RULE_SETUP { /* whitespace */; } YY_BREAK -case 44: +case 46: YY_RULE_SETUP { return (int) yytext[0]; } YY_BREAK -case 45: +case 47: YY_RULE_SETUP ECHO; YY_BREAK @@ -1744,7 +1766,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 139 ) + if ( yy_current_state >= 147 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1778,11 +1800,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 139 ) + if ( yy_current_state >= 147 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 138); + yy_is_jam = (yy_current_state == 146); return yy_is_jam ? 0 : yy_current_state; } diff --git a/QL/tokens.l b/QL/tokens.l index d2f25606ff..1388bf9897 100644 --- a/QL/tokens.l +++ b/QL/tokens.l @@ -131,6 +131,19 @@ return FALSE; } + + /* --------------------------------------------------------------------------- + * other keywords + * --------------------------------------------------------------------------- */ + +(?i:within) { + return WITHIN; +} + +(?i:near) { + return NEAR; +} + /* --------------------------------------------------------------------------- * logical operators diff --git a/RestServer/AvocadoServer.cpp b/RestServer/AvocadoServer.cpp index 80209d8441..2949f65fb3 100644 --- a/RestServer/AvocadoServer.cpp +++ b/RestServer/AvocadoServer.cpp @@ -47,7 +47,7 @@ #include "Logger/Logger.h" #include "Rest/Initialise.h" #include "RestHandler/RestActionHandler.h" -#include "RestHandler/RestDocumentHandler.h" +#include "RestHandler/RestCollectionHandler.h" #include "RestHandler/RestSystemActionHandler.h" #include "RestServer/ActionDispatcherThread.h" #include "RestServer/AvocadoHttpServer.h" @@ -529,7 +529,7 @@ int AvocadoServer::startupServer () { _applicationAdminServer->addBasicHandlers(factory); - factory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator::createData, _vocbase); + factory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator::createData, _vocbase); factory->addPrefixHandler(RestVocbaseBaseHandler::ACTION_PATH, RestHandlerCreator::createData, _vocbase); _httpServer = _applicationHttpServer->buildServer(new AvocadoHttpServer(scheduler, dispatcher), factory, ports); @@ -548,7 +548,7 @@ int AvocadoServer::startupServer () { _applicationAdminServer->addBasicHandlers(adminFactory); _applicationAdminServer->addHandlers(adminFactory, "/admin"); - adminFactory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator::createData, _vocbase); + adminFactory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator::createData, _vocbase); adminFactory->addPrefixHandler(RestVocbaseBaseHandler::ACTION_PATH, RestHandlerCreator::createData, _vocbase); adminFactory->addPrefixHandler(RestVocbaseBaseHandler::SYSTEM_ACTION_PATH, RestHandlerCreator::createData, _vocbase); diff --git a/RestServer/avocado.cpp b/RestServer/avocado.cpp index 999460b292..24d237ff4d 100644 --- a/RestServer/avocado.cpp +++ b/RestServer/avocado.cpp @@ -47,14 +47,6 @@ using namespace triagens::avocado; ///
    ///
  1. @ref StartStop ///
  2. -///
  3. @ref AvocadoScript -///
      -///
    1. @ref GeoCoordinates -///
    2. -///
    3. @ref Pagination -///
    4. -///
    -///
  4. ///
  5. @ref HttpInterface ///
      ///
    1. @ref RestInterface @@ -63,6 +55,22 @@ using namespace triagens::avocado; ///
    2. ///
    ///
  6. +///
  7. @ref AQL +///
      +///
    1. @ref Optimizer +///
    2. +///
    3. @ref IndexUsage +///
    4. +///
    +///
  8. +///
  9. @ref AvocadoScript +///
      +///
    1. @ref GeoCoordinates +///
    2. +///
    3. @ref Pagination +///
    4. +///
    +///
  10. ///
  11. Vertices, Edges, and Graphs ///
      ///
    1. @ref Graphs @@ -183,11 +191,9 @@ using namespace triagens::avocado; /// @page InstallManual AvocadoDB Installation Manual /// ///
        -///
      1. Building the AvocadoDB from Scratch -///
          -///
        1. @ref Compiling -///
        2. -///
        +///
      2. @ref Installing +///
      3. +///
      4. @ref Compiling ///
      5. ///
      //////////////////////////////////////////////////////////////////////////////// diff --git a/RestServer/install.h b/RestServer/install.h index 25c5116f14..1d4dd3b0d7 100644 --- a/RestServer/install.h +++ b/RestServer/install.h @@ -25,6 +25,43 @@ /// @author Copyright 2012, triAGENS GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +/// @page InstallingTOC +/// +///
        +///
      1. @ref Installing +///
          +///
        1. @ref MacOSX +///
            +///
          1. @ref MacOSXHomebrew +///
          +///
        2. +///
        +///
      2. +///
      +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @page Installing Installing the AvocadoDB +/// +///
      +/// @copydoc CompilingTOC +///
      +/// +/// @section MacOSX +/////////////////// +/// +/// @subsection MacOSXHomebrew +////////////////////////////// +/// +/// If you are using homebrew, +/// than you can install the AvocadoDB using @CODE{brew} as follows: +/// +/// @LIT{brew install https://raw.github.com/triAGENS/homebrew/master/Library/Formula/avocadodb.rb} +/// +/// This will install the AvocadoDB within your Homebrew tree. +//////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// /// @page CompilingTOC /// @@ -61,7 +98,7 @@ //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -/// @page Compiling Compiling the AvocadoDB +/// @page Compiling Compiling the AvocadoDB from scratch /// /// The following sections describe how to compile and build the AvocadoDB from /// scratch. The AvocadoDB will compile on most Linux and Mac OS X systems. It diff --git a/ShapedJson/shape-accessor.c b/ShapedJson/shape-accessor.c index cbbbe1baf0..d671b71b1a 100644 --- a/ShapedJson/shape-accessor.c +++ b/ShapedJson/shape-accessor.c @@ -220,6 +220,8 @@ static bool BytecodeShapeAccessor (TRI_shaper_t* shaper, TRI_shape_access_t* acc memcpy(cv.v, ops._buffer, ops._length * sizeof(void*)); + TRI_DestroyVectorPointer(&ops); + return true; } @@ -296,6 +298,18 @@ static bool ExecuteBytecodeShapeAccessor (TRI_shape_access_t const* accessor, /// @{ //////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +/// @brief free a shape accessor +//////////////////////////////////////////////////////////////////////////////// + +void TRI_FreeShapeAccessor (TRI_shape_access_t* accessor) { + assert(accessor); + if (accessor->_code) { + TRI_Free((void*) accessor->_code); + } + TRI_Free(accessor); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief creates a shape accessor //////////////////////////////////////////////////////////////////////////////// @@ -307,15 +321,19 @@ TRI_shape_access_t* TRI_ShapeAccessor (TRI_shaper_t* shaper, bool ok; accessor = TRI_Allocate(sizeof(TRI_shape_access_t)); + if (!accessor) { + return NULL; + } accessor->_sid = sid; accessor->_pid = pid; + accessor->_code = NULL; ok = BytecodeShapeAccessor(shaper, accessor); if (ok) { return accessor; } - TRI_Free(accessor); + TRI_FreeShapeAccessor(accessor); return NULL; } diff --git a/ShapedJson/shape-accessor.h b/ShapedJson/shape-accessor.h index 544740ffdb..f2da656c0c 100644 --- a/ShapedJson/shape-accessor.h +++ b/ShapedJson/shape-accessor.h @@ -84,6 +84,12 @@ TRI_shape_ac_bc_e; /// @{ //////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +/// @brief free a shape accessor +//////////////////////////////////////////////////////////////////////////////// + +void TRI_FreeShapeAccessor (TRI_shape_access_t*); + //////////////////////////////////////////////////////////////////////////////// /// @brief creates a shape accessor //////////////////////////////////////////////////////////////////////////////// diff --git a/ShapedJson/shaped-json.c b/ShapedJson/shaped-json.c index 6445502f2f..df948ccf4a 100644 --- a/ShapedJson/shaped-json.c +++ b/ShapedJson/shaped-json.c @@ -1816,6 +1816,9 @@ TRI_shaped_json_t* TRI_ShapedJsonJson (TRI_shaper_t* shaper, TRI_json_t const* j #endif shaped = TRI_Allocate(sizeof(TRI_shaped_json_t)); + if (!shaped) { + return NULL; + } shaped->_sid = dst._sid; shaped->_data.length = (uint32_t) dst._size; diff --git a/V8/v8-actions.cpp b/V8/v8-actions.cpp index c24d4b91fc..c7fba7ef25 100644 --- a/V8/v8-actions.cpp +++ b/V8/v8-actions.cpp @@ -29,6 +29,7 @@ #include "Basics/ReadLocker.h" #include "Basics/WriteLocker.h" +#include "Basics/StringUtils.h" #include "BasicsC/conversions.h" #include "BasicsC/logging.h" #include "Rest/HttpRequest.h" @@ -435,6 +436,24 @@ HttpResponse* TRI_ExecuteActionVocBase (TRI_vocbase_t* vocbase, // check if we know a callback map::iterator i = actions->find(name); + size_t pos = request->suffix().size(); + + if (i == actions->end()) { + // no direct callback found + + vector tmpSuffix(request->suffix()); + + // find longest prefix + while(tmpSuffix.size() > 1 && i == actions->end()) { + tmpSuffix.pop_back(); + --pos; + string tmpName = StringUtils::join(tmpSuffix, '/'); + LOG_DEBUG("find prefix '%s' for category %d", tmpName.c_str(), (int) category); + i = actions->find(tmpName); + } + + } + if (i == actions->end()) { LOG_DEBUG("unknown action '%s' for category %d", name.c_str(), (int) category); return new HttpResponse(HttpResponse::NOT_FOUND); @@ -442,9 +461,71 @@ HttpResponse* TRI_ExecuteActionVocBase (TRI_vocbase_t* vocbase, action_t* cb = (action_t*) i->second; - // that up the request + // setup the request v8::Handle req = v8::Object::New(); +// Example: +// { +// "_suffix":[ +// "suffix1", +// "suffix2" +// ], +// "_headers": +// { +// "accept":"text/html", +// "accept-encoding":"gzip, deflate", +// "accept-language":"de-de,en-us;q=0.7,en;q=0.3", +// "user-agent":"Mozilla/5.0" +// }, +// "_requestType":"GET", +// "_requestBody":"... only for PUT and POST ...", +// } + + // copy suffix + v8::Handle v8SuffixArray = v8::Array::New(); + vector const& suffix = request->suffix(); + int index = 0; + for (size_t s = pos; s < suffix.size(); ++s) { + v8SuffixArray->Set(index++, v8::String::New(suffix[s].c_str())); + } + req->Set(v8::Handle(v8::String::New("_suffix")), v8SuffixArray); + + // copy header fields + v8::Handle v8HeaderfildsObject = v8::Object::New(); + map const& headers = request->headers(); + map::const_iterator iter = headers.begin(); + for (; iter != headers.end(); ++iter) { + v8HeaderfildsObject->Set(v8::String::New(iter->first.c_str()), v8::String::New(iter->second.c_str())); + } + req->Set(v8::Handle(v8::String::New("_headers")), v8HeaderfildsObject); + + switch (request->requestType()) { + case HttpRequest::HTTP_REQUEST_POST: + req->Set(v8::Handle(v8::String::New("_requestType")), + v8::Handle(v8::String::New("POST"))); + req->Set(v8::Handle(v8::String::New("_requestBody")), + v8::Handle(v8::String::New(request->body().c_str()))); + break; + case HttpRequest::HTTP_REQUEST_PUT: + req->Set(v8::Handle(v8::String::New("_requestType")), + v8::Handle(v8::String::New("PUT"))); + req->Set(v8::Handle(v8::String::New("_requestBody")), + v8::Handle(v8::String::New(request->body().c_str()))); + break; + case HttpRequest::HTTP_REQUEST_DELETE: + req->Set(v8::Handle(v8::String::New("_requestType")), + v8::Handle(v8::String::New("DELETE"))); + break; + case HttpRequest::HTTP_REQUEST_HEAD: + req->Set(v8::Handle(v8::String::New("_requestType")), + v8::Handle(v8::String::New("HEAD"))); + break; + default: + req->Set(v8::Handle(v8::String::New("_requestType")), + v8::Handle(v8::String::New("GET"))); + } + + map values = request->values(); for (map::iterator i = values.begin(); i != values.end(); ++i) { @@ -539,6 +620,18 @@ HttpResponse* TRI_ExecuteActionVocBase (TRI_vocbase_t* vocbase, response->body().appendText(TRI_ObjectToString(res->Get(v8g->BodyKey))); } + if (res->Has(v8g->HeadersKey)) { + v8::Handle val = res->Get(v8g->HeadersKey); + v8::Handle v8Headers = val.As(); + if (v8Headers->IsObject()) { + v8::Handle props = v8Headers->GetPropertyNames(); + for (size_t i = 0; i < props->Length(); i++) { + v8::Handle key = props->Get(v8::Integer::New(i)); + response->setHeader(TRI_ObjectToString(key), TRI_ObjectToString(v8Headers->Get(key))); + } + } + } + return response; } } @@ -576,6 +669,7 @@ void TRI_InitV8Actions (v8::Handle context) { // ............................................................................. v8g->BodyKey = v8::Persistent::New(v8::String::New("body")); + v8g->HeadersKey = v8::Persistent::New(v8::String::New("headers")); v8g->ContentType = v8::Persistent::New(v8::String::New("contentType")); v8g->ParametersKey = v8::Persistent::New(v8::String::New("parameters")); v8g->ResponseCodeKey = v8::Persistent::New(v8::String::New("responseCode")); diff --git a/V8/v8-conv.cpp b/V8/v8-conv.cpp index 16a4c86da8..64a9c83162 100644 --- a/V8/v8-conv.cpp +++ b/V8/v8-conv.cpp @@ -1307,7 +1307,7 @@ bool TRI_ObjectDocumentPointer (TRI_doc_collection_t* collection, v8::Handle TRI_ArrayResultSet (TRI_result_set_t* rs) { v8::Handle array = v8::Array::New(); - TRI_doc_collection_t* collection = rs->_containerElement->_container->_collection; + TRI_doc_collection_t* collection = rs->_barrier->_container->_collection; TRI_shaper_t* shaper = collection->_shaper; size_t pos; diff --git a/V8/v8-conv.h b/V8/v8-conv.h index 0baad8dfaf..9cb17788bb 100644 --- a/V8/v8-conv.h +++ b/V8/v8-conv.h @@ -31,8 +31,9 @@ #include "V8/v8-globals.h" #include "BasicsC/json.h" -#include "VocBase/simple-collection.h" #include "V8/v8-c-utils.h" +#include "VocBase/result-set.h" +#include "VocBase/simple-collection.h" // ----------------------------------------------------------------------------- // --SECTION-- CONVERSION FUNCTIONS diff --git a/V8/v8-globals.h b/V8/v8-globals.h index 15896dbba3..1574d87b81 100644 --- a/V8/v8-globals.h +++ b/V8/v8-globals.h @@ -277,6 +277,12 @@ typedef struct TRI_v8_global_s { v8::Persistent BodyKey; +//////////////////////////////////////////////////////////////////////////////// +/// @brief "headers" key name +//////////////////////////////////////////////////////////////////////////////// + + v8::Persistent HeadersKey; + //////////////////////////////////////////////////////////////////////////////// /// @brief "_id" key name //////////////////////////////////////////////////////////////////////////////// diff --git a/V8/v8-utils.cpp b/V8/v8-utils.cpp index b4ae778b46..5be8395d14 100644 --- a/V8/v8-utils.cpp +++ b/V8/v8-utils.cpp @@ -461,16 +461,15 @@ bool TRI_ExecuteRefExecutionContext (TRI_js_exec_context_t context, TRI_json_t* v8::Handle parameter = obj->Get(position++); if (parameter->IsNumber()) { v8::Handle numberParameter = parameter->ToNumber(); - TRI_PushBackListJson(r, TRI_CreateNumberJson(numberParameter->Value())); + TRI_PushBack2ListJson(r, TRI_CreateNumberJson(numberParameter->Value())); } else if (parameter->IsString() ) { v8::Handle stringParameter= parameter->ToString(); v8::String::Utf8Value str(stringParameter); - TRI_PushBackListJson(r, TRI_CreateStringCopyJson(*str)); + TRI_PushBack2ListJson(r, TRI_CreateStringCopyJson(*str)); } else { continue; - return false; } } diff --git a/V8/v8-vocbase.cpp b/V8/v8-vocbase.cpp index 6c36af31d2..3452d87208 100644 --- a/V8/v8-vocbase.cpp +++ b/V8/v8-vocbase.cpp @@ -1095,7 +1095,7 @@ static v8::Handle JS_NextQuery (v8::Arguments const& argv) { } if (rs->hasNext(rs)) { - TRI_doc_collection_t* collection = rs->_containerElement->_container->_collection; + TRI_doc_collection_t* collection = rs->_barrier->_container->_collection; TRI_shaper_t* shaper = collection->_shaper; TRI_rs_entry_t const* entry = rs->next(rs); @@ -1130,7 +1130,7 @@ static v8::Handle JS_NextRefQuery (v8::Arguments const& argv) { } if (rs->hasNext(rs)) { - TRI_doc_collection_t* collection = rs->_containerElement->_container->_collection; + TRI_doc_collection_t* collection = rs->_barrier->_container->_collection; TRI_rs_entry_t const* entry = rs->next(rs); string ref = StringUtils::itoa(collection->base._cid) + ":" + StringUtils::itoa(entry->_did); @@ -2862,7 +2862,7 @@ static v8::Handle JS_EnsureHashIndexVocbaseCol (v8::Arguments const& ok = false; break; } - + memcpy(cArgument, *argumentString, argumentString.length()); TRI_PushBackVector(&attributes,&cArgument); } @@ -2873,7 +2873,7 @@ static v8::Handle JS_EnsureHashIndexVocbaseCol (v8::Arguments const& // ............................................................................. for (size_t j = 0; j < attributes._length; ++j) { - char* left = *((char**) (TRI_AtVector(&attributes, j))); + char* left = *((char**) (TRI_AtVector(&attributes, j))); for (size_t k = j + 1; k < attributes._length; ++k) { char* right = *((char**) (TRI_AtVector(&attributes, k))); if (strcmp(left,right) == 0) { @@ -2881,7 +2881,7 @@ static v8::Handle JS_EnsureHashIndexVocbaseCol (v8::Arguments const& //printf("%s:%s:%u:%s:%s\n",__FILE__,__FUNCTION__,__LINE__,left,right); ok = false; break; - } + } } } @@ -3025,7 +3025,7 @@ static v8::Handle JS_EnsureMultiHashIndexVocbaseCol (v8::Arguments co ok = false; break; } - + memcpy(cArgument, *argumentString, argumentString.length()); TRI_PushBackVector(&attributes,&cArgument); } @@ -3036,14 +3036,14 @@ static v8::Handle JS_EnsureMultiHashIndexVocbaseCol (v8::Arguments co // ............................................................................. for (size_t j = 0; j < attributes._length; ++j) { - char* left = *((char**) (TRI_AtVector(&attributes, j))); + char* left = *((char**) (TRI_AtVector(&attributes, j))); for (size_t k = j + 1; k < attributes._length; ++k) { char* right = *((char**) (TRI_AtVector(&attributes, k))); if (strcmp(left,right) == 0) { errorString = "duplicate parameters sent to ensureMultiHashIndex(...) command"; ok = false; break; - } + } } } diff --git a/VocBase/barrier.c b/VocBase/barrier.c new file mode 100644 index 0000000000..14f11cd851 --- /dev/null +++ b/VocBase/barrier.c @@ -0,0 +1,199 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief delete barriers for datafiles +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2010-2011 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 Dr. Frank Celler +/// @author Copyright 2011, triagens GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "barrier.h" + +#include "VocBase/document-collection.h" + +// ----------------------------------------------------------------------------- +// --SECTION-- BARRIER +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup VocBase +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief initialises a result set container +//////////////////////////////////////////////////////////////////////////////// + +void TRI_InitBarrierList (TRI_barrier_list_t* container, TRI_doc_collection_t* collection) { + container->_collection = collection; + + TRI_InitSpin(&container->_lock); + + container->_begin = NULL; + container->_end = NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief destroys a result set container +//////////////////////////////////////////////////////////////////////////////// + +void TRI_DestroyBarrierList (TRI_barrier_list_t* container) { + TRI_barrier_t* ptr; + TRI_barrier_t* next; + + ptr = container->_begin; + + while (ptr != NULL) { + next = ptr->_next; + ptr->_container = NULL; + ptr = next; + } + + TRI_DestroySpin(&container->_lock); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a new barrier element +//////////////////////////////////////////////////////////////////////////////// + +TRI_barrier_t* TRI_CreateBarrierElement (TRI_barrier_list_t* container) { + TRI_barrier_t* element; + + element = TRI_Allocate(sizeof(TRI_barrier_t)); + + element->_type = TRI_BARRIER_ELEMENT; + element->_container = container; + element->_datafile = NULL; + element->datafileCallback = NULL; + + TRI_LockSpin(&container->_lock); + + // empty list + if (container->_end == NULL) { + element->_next = NULL; + element->_prev = NULL; + + container->_begin = element; + container->_end = element; + } + + // add to the end + else { + element->_next = NULL; + element->_prev = container->_end; + + container->_end->_next = element; + container->_end = element; + } + + TRI_UnlockSpin(&container->_lock); + + return element; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a new datafile deletion barrier +//////////////////////////////////////////////////////////////////////////////// + +TRI_barrier_t* TRI_CreateBarrierDatafile (TRI_barrier_list_t* container, + TRI_datafile_t* datafile, + void (*callback) (struct TRI_datafile_s*, void*), + void* data) { + TRI_barrier_t* element; + + element = TRI_Allocate(sizeof(TRI_barrier_t)); + + element->_type = TRI_BARRIER_DATAFILE; + element->_container = container; + element->_datafile = datafile; + element->_datafileData = data; + element->datafileCallback = callback; + + TRI_LockSpin(&container->_lock); + + // empty list + if (container->_end == NULL) { + element->_next = NULL; + element->_prev = NULL; + + container->_begin = element; + container->_end = element; + } + + // add to the end + else { + element->_next = NULL; + element->_prev = container->_end; + + container->_end->_next = element; + container->_end = element; + } + + TRI_UnlockSpin(&container->_lock); + + return element; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief removes and frees a barrier element or datafile deletion marker +//////////////////////////////////////////////////////////////////////////////// + +void TRI_FreeBarrier (TRI_barrier_t* element) { + TRI_barrier_list_t* container; + + container = element->_container; + + TRI_LockSpin(&container->_lock); + + // element is at the beginning of the chain + if (element->_prev == NULL) { + container->_begin = element->_next; + } + else { + element->_prev->_next = element->_next; + } + + // element is at the end of the chain + if (element->_next == NULL) { + container->_end = element->_prev; + } + else { + element->_next->_prev = element->_prev; + } + + TRI_UnlockSpin(&container->_lock); + + // free the element + TRI_Free(element); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/VocBase/barrier.h b/VocBase/barrier.h new file mode 100644 index 0000000000..a3e5f08789 --- /dev/null +++ b/VocBase/barrier.h @@ -0,0 +1,154 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief delete barriers for datafiles +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2010-2011 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 Dr. Frank Celler +/// @author Copyright 2011, triagens GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_DURHAM_VOC_BASE_BARRIER_H +#define TRIAGENS_DURHAM_VOC_BASE_BARRIER_H 1 + +#include "BasicsC/locks.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ----------------------------------------------------------------------------- +// --SECTION-- forward declarations +// ----------------------------------------------------------------------------- + +struct TRI_doc_collection_s; +struct TRI_datafile_s; + +// ----------------------------------------------------------------------------- +// --SECTION-- public types +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup VocBase +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief barrier element type +//////////////////////////////////////////////////////////////////////////////// + +typedef enum { + TRI_BARRIER_ELEMENT, + TRI_BARRIER_DATAFILE +} +TRI_barrier_type_e; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief barrier element +//////////////////////////////////////////////////////////////////////////////// + +typedef struct TRI_barrier_s { + struct TRI_barrier_s* _prev; + struct TRI_barrier_s* _next; + + struct TRI_barrier_list_s* _container; + + TRI_barrier_type_e _type; + + struct TRI_datafile_s* _datafile; + void* _datafileData; + void (*datafileCallback) (struct TRI_datafile_s*, void*); +} +TRI_barrier_t; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief doubly linked list of barriers +//////////////////////////////////////////////////////////////////////////////// + +typedef struct TRI_barrier_list_s { + struct TRI_doc_collection_s* _collection; + + TRI_spin_t _lock; + + TRI_barrier_t* _begin; + TRI_barrier_t* _end; +} +TRI_barrier_list_t; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup VocBase +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief initialises a result set container +//////////////////////////////////////////////////////////////////////////////// + +void TRI_InitBarrierList (TRI_barrier_list_t* container, struct TRI_doc_collection_s* collection); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief destroys a result set container +//////////////////////////////////////////////////////////////////////////////// + +void TRI_DestroyBarrierList (TRI_barrier_list_t* container); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a new barrier element +//////////////////////////////////////////////////////////////////////////////// + +TRI_barrier_t* TRI_CreateBarrierElement (TRI_barrier_list_t* container); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a new datafile deletion barrier +//////////////////////////////////////////////////////////////////////////////// + +TRI_barrier_t* TRI_CreateBarrierDatafile (TRI_barrier_list_t* container, + struct TRI_datafile_s* datafile, + void (*callback) (struct TRI_datafile_s*, void*), + void* data); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief removes and frees a barrier element or datafile deletion marker +//////////////////////////////////////////////////////////////////////////////// + +void TRI_FreeBarrier (TRI_barrier_t* element); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/VocBase/compactor.c b/VocBase/compactor.c index 51abf9a1a3..34cdc367f7 100644 --- a/VocBase/compactor.c +++ b/VocBase/compactor.c @@ -368,7 +368,7 @@ static void CompactifyDatafile (TRI_sim_collection_t* collection, TRI_voc_fid_t } // add a deletion marker to the result set container - TRI_AddDatafileRSContainer(&collection->base._resultSets, df, RemoveDatafileCallback, &collection->base.base); + TRI_CreateBarrierDatafile(&collection->base._barrierList, df, RemoveDatafileCallback, &collection->base.base); } //////////////////////////////////////////////////////////////////////////////// @@ -429,16 +429,16 @@ static void CompactifySimCollection (TRI_sim_collection_t* collection) { //////////////////////////////////////////////////////////////////////////////// static void CleanupSimCollection (TRI_sim_collection_t* collection) { - TRI_rs_container_t* container; - TRI_rs_container_element_t* element; + TRI_barrier_list_t* container; + TRI_barrier_t* element; - container = &collection->base._resultSets; + container = &collection->base._barrierList; element = NULL; // check and remove a datafile element at the beginning of the list TRI_LockSpin(&container->_lock); - if (container->_begin != NULL && container->_begin->_type == TRI_RSCE_DATAFILE) { + if (container->_begin != NULL && container->_begin->_type == TRI_BARRIER_DATAFILE) { element = container->_begin; container->_begin = element->_next; diff --git a/VocBase/data-feeder.c b/VocBase/data-feeder.c index dde8d57368..1737d7333a 100644 --- a/VocBase/data-feeder.c +++ b/VocBase/data-feeder.c @@ -276,9 +276,11 @@ static void RewindFeederPrimaryLookup (TRI_data_feeder_t* feeder) { true); if (TRI_ExecuteRefExecutionContext (state->_context, parameters)) { if (parameters->_type != TRI_JSON_LIST) { + TRI_FreeJson(parameters); return; } if (parameters->_value._objects._length != 1) { + TRI_FreeJson(parameters); return; } @@ -408,6 +410,7 @@ static void InitFeederHashLookup (TRI_data_feeder_t* feeder) { QL_optimize_range_t* range; TRI_data_feeder_hash_lookup_t* state; TRI_json_t* parameters; + TRI_json_t* doc; TRI_string_buffer_t* buffer; size_t i; @@ -416,6 +419,7 @@ static void InitFeederHashLookup (TRI_data_feeder_t* feeder) { state->_context = NULL; state->_position = 0; + state->_hashElements = NULL; state->_index = TRI_IndexSimCollection((TRI_sim_collection_t*) feeder->_collection, feeder->_indexId); if (!state->_index) { @@ -465,16 +469,20 @@ static void InitFeederHashLookup (TRI_data_feeder_t* feeder) { for (i = 0; i < feeder->_ranges->_length; i++) { range = (QL_optimize_range_t*) feeder->_ranges->_buffer[i]; if (range->_valueType == RANGE_TYPE_STRING) { - TRI_PushBackListJson(parameters, + TRI_PushBack2ListJson(parameters, TRI_CreateStringCopyJson(range->_minValue._stringValue)); } else if (range->_valueType == RANGE_TYPE_DOUBLE) { - TRI_PushBackListJson(parameters, + TRI_PushBack2ListJson(parameters, TRI_CreateNumberJson(range->_minValue._doubleValue)); } else if (range->_valueType == RANGE_TYPE_JSON) { - TRI_PushBackListJson(parameters, - TRI_JsonString(range->_minValue._stringValue)); + doc = TRI_JsonString(range->_minValue._stringValue); + if (!doc) { + TRI_FreeJson(parameters); + return; + } + TRI_PushBackListJson(parameters, doc); } } state->_hashElements = TRI_LookupHashIndex(state->_index, parameters); @@ -494,9 +502,14 @@ static void RewindFeederHashLookup (TRI_data_feeder_t* feeder) { state = (TRI_data_feeder_hash_lookup_t*) feeder->_state; state->_position = 0; - state->_hashElements = NULL; if (feeder->_accessType == ACCESS_REF) { + if (state->_hashElements) { + TRI_Free(state->_hashElements->_elements); + TRI_Free(state->_hashElements); + } + state->_hashElements = NULL; + if (!state->_context) { return; } @@ -511,6 +524,7 @@ static void RewindFeederHashLookup (TRI_data_feeder_t* feeder) { if (TRI_ExecuteRefExecutionContext (state->_context, parameters)) { state->_hashElements = TRI_LookupHashIndex(state->_index, parameters); } + TRI_FreeJson(parameters); } } @@ -563,6 +577,10 @@ static void FreeFeederHashLookup (TRI_data_feeder_t* feeder) { TRI_data_feeder_hash_lookup_t* state; state = (TRI_data_feeder_hash_lookup_t*) feeder->_state; + if (state->_hashElements) { + TRI_Free(state->_hashElements->_elements); + TRI_Free(state->_hashElements); + } if (state->_context) { TRI_FreeExecutionContext(state->_context); diff --git a/VocBase/data-feeder.h b/VocBase/data-feeder.h index b770cfdc8c..d0d46c955a 100644 --- a/VocBase/data-feeder.h +++ b/VocBase/data-feeder.h @@ -42,12 +42,7 @@ extern "C" { #endif //////////////////////////////////////////////////////////////////////////////// -/// @addtogroup VocBase -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @page indexusage Index usage +/// @page IndexUsage Index usage /// /// When executing a query, the database will automatically check if it can use /// an index to speed up the query. It will check all available indexes for the @@ -66,8 +61,23 @@ extern "C" { /// /// An index can only be used if the WHERE/JOIN conditions refer to indexed /// attributes. It depends on the index type what kinds of comparisons are allowed -/// in order to use the index. It also depends on the index type whether just a +/// in order to use the index. For example, the primary index and hash indexes +/// only support equality comparisons whereas other index types might allow +/// range queries as well. It also depends on the index type whether just a /// subset of the indexed attributes is sufficient in order to use an index. +/// +/// The query optimizer needs to detect that an index can actually be used, and +/// it will only allow using indexes if the indexed attributes are not used in +/// combination with logical @LIT{||} or logical @LIT{!}. Furthermore, the +/// optimizer currently cannot make use of indexes if the same attribute is +/// compared to multiple values at the same time (i.e. a so-called in-list +/// comparison). For example, the following condition would not allow to use +/// an index: @LIT{WHERE users.id == 3 || users.id == 4 || users.id == 9} +/// +/// There is no way to explicitly specify which index to use/prefer/reject in a +/// query as there sometimes is in other database products. +/// +/// @section Index types /// /// There are the following index types: /// - primary index (automatically created for the "_id" attribute of a collection) @@ -119,9 +129,11 @@ extern "C" { /// - If no index can be used to access the documents in a collection, a full /// collection scan will be done. /// -/// There is no way to explicitly specify which index to use/prefer/reject in a -/// query as there sometimes is in other database products. -/// +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup VocBase +/// @{ //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// diff --git a/VocBase/document-collection.c b/VocBase/document-collection.c index 3b10364e7a..c8f7d62f95 100644 --- a/VocBase/document-collection.c +++ b/VocBase/document-collection.c @@ -446,7 +446,7 @@ void TRI_InitDocCollection (TRI_doc_collection_t* collection, collection->figures = Figures; - TRI_InitRSContainer(&collection->_resultSets, collection); + TRI_InitBarrierList(&collection->_barrierList, collection); TRI_InitAssociativePointer(&collection->_datafileInfo, HashKeyDatafile, @@ -465,7 +465,7 @@ void TRI_DestroyDocCollection (TRI_doc_collection_t* collection) { } TRI_DestroyAssociativePointer(&collection->_datafileInfo); - TRI_DestroyRSContainer(&collection->_resultSets); + TRI_DestroyBarrierList(&collection->_barrierList); TRI_DestroyCollection(&collection->base); } diff --git a/VocBase/document-collection.h b/VocBase/document-collection.h index 5daff3828c..4364eed0df 100644 --- a/VocBase/document-collection.h +++ b/VocBase/document-collection.h @@ -32,7 +32,7 @@ #include "BasicsC/json.h" #include "ShapedJson/json-shaper.h" -#include "VocBase/result-set.h" +#include "VocBase/barrier.h" #ifdef __cplusplus extern "C" { @@ -239,7 +239,7 @@ typedef struct TRI_doc_collection_s { TRI_collection_t base; TRI_shaper_t* _shaper; - TRI_rs_container_t _resultSets; + TRI_barrier_list_t _barrierList; TRI_associative_pointer_t _datafileInfo; bool (*beginRead) (struct TRI_doc_collection_s*); diff --git a/VocBase/fluent-query.c b/VocBase/fluent-query.c index c7475bdc54..e3c1797e39 100644 --- a/VocBase/fluent-query.c +++ b/VocBase/fluent-query.c @@ -2798,7 +2798,7 @@ TRI_fluent_query_t* TRI_CreateWithinQuery (TRI_fluent_query_t* operand, TRI_result_set_t* TRI_ExecuteQuery (TRI_fluent_query_t* query) { TRI_doc_collection_t* collection = query->_collection->_collection; - TRI_rs_container_element_t* ce; + TRI_barrier_t* ce; TRI_fluent_query_result_t result; TRI_result_set_t* rs; TRI_rs_info_t info; @@ -2824,7 +2824,7 @@ TRI_result_set_t* TRI_ExecuteQuery (TRI_fluent_query_t* query) { collection->beginRead(collection); - ce = TRI_AddResultSetRSContainer(&collection->_resultSets); + ce = TRI_CreateBarrierElement(&collection->_barrierList); query->execute(query, &result); @@ -2845,8 +2845,6 @@ TRI_result_set_t* TRI_ExecuteQuery (TRI_fluent_query_t* query) { result._total); } - ce->_resultSet = rs; - collection->endRead(collection); // ............................................................................. diff --git a/VocBase/index.c b/VocBase/index.c index 3c916dd198..7f0886f7cb 100644 --- a/VocBase/index.c +++ b/VocBase/index.c @@ -153,13 +153,43 @@ bool TRI_SaveIndex (TRI_doc_collection_t* collection, TRI_index_t* idx) { return true; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief free an existing index definition +//////////////////////////////////////////////////////////////////////////////// + +void TRI_FreeIndexDefinition (TRI_index_definition_t* definition) { + TRI_DestroyVectorString(&definition->_fields); + TRI_Free(definition); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief free an existing index definitions vector +//////////////////////////////////////////////////////////////////////////////// + +void TRI_FreeIndexDefinitions (TRI_vector_pointer_t* definitions) { + TRI_index_definition_t* definition; + size_t i; + + if (!definitions) { + return; + } + + for (i = 0; i < definitions->_length; i++) { + definition = (TRI_index_definition_t*) definitions->_buffer[i]; + assert(definition); + TRI_FreeIndexDefinition(definition); + } + + TRI_FreeVectorPointer(definitions); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief gets the definitions of all index files for a collection //////////////////////////////////////////////////////////////////////////////// -TRI_vector_pointer_t TRI_GetCollectionIndexes(const TRI_vocbase_t* vocbase, - const char* collectionName) { - TRI_vector_pointer_t indexes; +TRI_vector_pointer_t* TRI_GetCollectionIndexes(const TRI_vocbase_t* vocbase, + const char* collectionName) { + TRI_vector_pointer_t* indexes; TRI_index_definition_t* indexDefinition; TRI_vector_string_t indexFiles; TRI_json_t* json; @@ -177,7 +207,12 @@ TRI_vector_pointer_t TRI_GetCollectionIndexes(const TRI_vocbase_t* vocbase, uint32_t j; assert(vocbase); - TRI_InitVectorPointer(&indexes); + + indexes = (TRI_vector_pointer_t*) TRI_Allocate(sizeof(TRI_vector_pointer_t)); + if (!indexes) { + return NULL; + } + TRI_InitVectorPointer(indexes); // add "pseudo" primary index indexDefinition = (TRI_index_definition_t*) TRI_Allocate(sizeof(TRI_index_definition_t)); @@ -187,8 +222,11 @@ TRI_vector_pointer_t TRI_GetCollectionIndexes(const TRI_vocbase_t* vocbase, indexDefinition->_type = TRI_IDX_TYPE_PRIMARY_INDEX; indexDefinition->_isUnique = true; // primary index is always unique - TRI_PushBackVectorString(&indexDefinition->_fields, "_id"); // name of field - TRI_PushBackVectorPointer(&indexes, indexDefinition); + temp3 = TRI_DuplicateString("_id"); + if (temp3) { + TRI_PushBackVectorString(&indexDefinition->_fields, temp3); // name of field + } + TRI_PushBackVectorPointer(indexes, indexDefinition); } // get all index filenames @@ -257,7 +295,8 @@ TRI_vector_pointer_t TRI_GetCollectionIndexes(const TRI_vocbase_t* vocbase, } // create the index definition - indexDefinition = (TRI_index_definition_t*) TRI_Allocate(sizeof(TRI_index_definition_t)); + indexDefinition = + (TRI_index_definition_t*) TRI_Allocate(sizeof(TRI_index_definition_t)); if (indexDefinition) { TRI_InitVectorString(&indexDefinition->_fields); indexDefinition->_iid = indexId; @@ -287,7 +326,7 @@ TRI_vector_pointer_t TRI_GetCollectionIndexes(const TRI_vocbase_t* vocbase, TRI_Free(indexDefinition); } else { - TRI_PushBackVectorPointer(&indexes, indexDefinition); + TRI_PushBackVectorPointer(indexes, indexDefinition); } } @@ -977,7 +1016,7 @@ HashIndexElements* TRI_LookupHashIndex(TRI_index_t* idx, TRI_json_t* parameterLi element.fields = TRI_Allocate( sizeof(TRI_json_t) * element.numFields); if (element.fields == NULL) { LOG_WARNING("out-of-memory in LookupHashIndex"); - return false; + return NULL; } hashIndex = (TRI_hash_index_t*) idx; @@ -985,8 +1024,9 @@ HashIndexElements* TRI_LookupHashIndex(TRI_index_t* idx, TRI_json_t* parameterLi for (size_t j = 0; j < element.numFields; ++j) { TRI_json_t* jsonObject = (TRI_json_t*) (TRI_AtVector(&(parameterList->_value._objects),j)); - TRI_shaped_json_t* shapedObject = TRI_ShapedJsonJson(shaper,jsonObject); + TRI_shaped_json_t* shapedObject = TRI_ShapedJsonJson(shaper, jsonObject); element.fields[j] = *shapedObject; + TRI_Free(shapedObject); } if (hashIndex->_unique) { @@ -994,10 +1034,11 @@ HashIndexElements* TRI_LookupHashIndex(TRI_index_t* idx, TRI_json_t* parameterLi } else { result = MultiHashIndex_find(hashIndex->_hashIndex, &element); - for (int j = 0; j < result->_numElements; ++j) { - } } - + + for (size_t j = 0; j < element.numFields; ++j) { + TRI_DestroyShapedJson(element.fields + j); + } TRI_Free(element.fields); return result; @@ -1037,6 +1078,9 @@ static bool HashIndexHelper(const TRI_hash_index_t* hashIndex, // .......................................................................... acc = TRI_ShapeAccessor(hashIndex->base._collection->_shaper, shapedDoc->_sid, shape); if (acc == NULL || acc->_shape == NULL) { + if (acc != NULL) { + TRI_FreeShapeAccessor(acc); + } TRI_Free(hashElement->fields); return false; } @@ -1046,7 +1090,7 @@ static bool HashIndexHelper(const TRI_hash_index_t* hashIndex, // Extract the field // .......................................................................... if (! TRI_ExecuteShapeAccessor(acc, shapedDoc, &shapedObject)) { - TRI_Free(acc); + TRI_FreeShapeAccessor(acc); TRI_Free(hashElement->fields); return false; } @@ -1056,7 +1100,7 @@ static bool HashIndexHelper(const TRI_hash_index_t* hashIndex, // Store the json shaped Object -- this is what will be hashed // .......................................................................... hashElement->fields[j] = shapedObject; - TRI_Free(acc); + TRI_FreeShapeAccessor(acc); } // end of for loop } @@ -1082,6 +1126,9 @@ static bool HashIndexHelper(const TRI_hash_index_t* hashIndex, // .......................................................................... acc = TRI_ShapeAccessor(hashIndex->base._collection->_shaper, document->_document._sid, shape); if (acc == NULL || acc->_shape == NULL) { + if (acc != NULL) { + TRI_FreeShapeAccessor(acc); + } TRI_Free(hashElement->fields); return false; } @@ -1091,7 +1138,7 @@ static bool HashIndexHelper(const TRI_hash_index_t* hashIndex, // Extract the field // .......................................................................... if (! TRI_ExecuteShapeAccessor(acc, &(document->_document), &shapedObject)) { - TRI_Free(acc); + TRI_FreeShapeAccessor(acc); TRI_Free(hashElement->fields); return false; } @@ -1114,7 +1161,7 @@ static bool HashIndexHelper(const TRI_hash_index_t* hashIndex, // Store the field // .......................................................................... hashElement->fields[j] = shapedObject; - TRI_Free(acc); + TRI_FreeShapeAccessor(acc); } // end of for loop } diff --git a/VocBase/index.h b/VocBase/index.h index a3f97e4293..1d1bbc4903 100644 --- a/VocBase/index.h +++ b/VocBase/index.h @@ -161,12 +161,24 @@ bool TRI_RemoveIndex (struct TRI_doc_collection_s* collection, TRI_index_t* idx) bool TRI_SaveIndex (struct TRI_doc_collection_s*, TRI_index_t*); +//////////////////////////////////////////////////////////////////////////////// +/// @brief free an existing index definition +//////////////////////////////////////////////////////////////////////////////// + +void TRI_FreeIndexDefinition (TRI_index_definition_t*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief free an existing index definitions vector +//////////////////////////////////////////////////////////////////////////////// + +void TRI_FreeIndexDefinitions (TRI_vector_pointer_t*); + //////////////////////////////////////////////////////////////////////////////// /// @brief gets the definitions of all index files for a collection //////////////////////////////////////////////////////////////////////////////// -TRI_vector_pointer_t TRI_GetCollectionIndexes(const TRI_vocbase_t* vocbase, - const char* collectionName); +TRI_vector_pointer_t* TRI_GetCollectionIndexes(const TRI_vocbase_t* vocbase, + const char* collectionName); //////////////////////////////////////////////////////////////////////////////// /// @brief gets the names of all index files for a collection diff --git a/VocBase/join-execute.c b/VocBase/join-execute.c index ba62957886..7c230f2a5c 100644 --- a/VocBase/join-execute.c +++ b/VocBase/join-execute.c @@ -37,9 +37,9 @@ static TRI_data_feeder_t* DetermineIndexUsage (const TRI_vocbase_t* vocbase, const TRI_select_join_t* join, const size_t level, const TRI_join_part_t* part) { - TRI_vector_pointer_t indexDefinitions; + TRI_vector_pointer_t* indexDefinitions; TRI_index_definition_t* indexDefinition; - TRI_data_feeder_t* feeder; + TRI_data_feeder_t* feeder = NULL; QL_optimize_range_t* range; TRI_vector_pointer_t matches; size_t i, j, k; @@ -50,13 +50,17 @@ static TRI_data_feeder_t* DetermineIndexUsage (const TRI_vocbase_t* vocbase, if (part->_ranges) { TRI_InitVectorPointer(&matches); indexDefinitions = TRI_GetCollectionIndexes(vocbase, part->_collectionName); + if (!indexDefinitions) { + goto EXIT2; + } // enum all indexes - for (i = 0; i < indexDefinitions._length; i++) { - indexDefinition = (TRI_index_definition_t*) indexDefinitions._buffer[i]; + for (i = 0; i < indexDefinitions->_length; i++) { + indexDefinition = (TRI_index_definition_t*) indexDefinitions->_buffer[i]; // reset compare state if (matches._length) { + TRI_DestroyVectorPointer(&matches); TRI_InitVectorPointer(&matches); } numFields = 0; @@ -173,10 +177,12 @@ static TRI_data_feeder_t* DetermineIndexUsage (const TRI_vocbase_t* vocbase, } EXIT: - TRI_DestroyVectorPointer(&indexDefinitions); + TRI_FreeIndexDefinitions(indexDefinitions); TRI_DestroyVectorPointer(&matches); } +EXIT2: + if (!feeder) { // if no index can be used, we'll do a full table scan feeder = TRI_CreateDataFeederTableScan((TRI_doc_collection_t*) part->_collection, diff --git a/VocBase/query.c b/VocBase/query.c index d029b27e09..6574e4a691 100644 --- a/VocBase/query.c +++ b/VocBase/query.c @@ -1090,11 +1090,11 @@ void TRI_ReadUnlockCollectionsQuery (TRI_query_t* query) { void TRI_AddCollectionsCursor (TRI_rc_cursor_t* cursor, TRI_query_t* query) { TRI_join_part_t* part; - TRI_rs_container_element_t* ce; + TRI_barrier_t* ce; size_t i; if (query->_joins == NULL) { - ce = TRI_AddResultSetRSContainer(&query->_primary->_resultSets); + ce = TRI_CreateBarrierElement(&query->_primary->_barrierList); TRI_PushBackVectorPointer(&cursor->_containers, ce); return; } @@ -1104,7 +1104,7 @@ void TRI_AddCollectionsCursor (TRI_rc_cursor_t* cursor, TRI_query_t* query) { for (i = 0; i < query->_joins->_parts._length; i++) { part = (TRI_join_part_t*) query->_joins->_parts._buffer[i]; assert(part->_collection); - ce = TRI_AddResultSetRSContainer(&part->_collection->_resultSets); + ce = TRI_CreateBarrierElement(&part->_collection->_barrierList); TRI_PushBackVectorPointer(&cursor->_containers, ce); } } @@ -1115,13 +1115,13 @@ void TRI_AddCollectionsCursor (TRI_rc_cursor_t* cursor, TRI_query_t* query) { //////////////////////////////////////////////////////////////////////////////// void TRI_RemoveCollectionsCursor (TRI_rc_cursor_t* cursor) { - TRI_rs_container_element_t* ce; + TRI_barrier_t* ce; size_t i; for (i = 0; i < cursor->_containers._length; ++i) { ce = cursor->_containers._buffer[i]; - TRI_RemoveRSContainer(ce); + TRI_FreeBarrier(ce); } cursor->_containers._length = 0; diff --git a/VocBase/result-set.c b/VocBase/result-set.c index 1dfb51caf9..5fcd2ab39e 100644 --- a/VocBase/result-set.c +++ b/VocBase/result-set.c @@ -32,12 +32,6 @@ #include -// ----------------------------------------------------------------------------- -// --SECTION-- forward declarations -// ----------------------------------------------------------------------------- - -static void RemoveContainerElement (TRI_result_set_t* rs); - // ----------------------------------------------------------------------------- // --SECTION-- SINGLE RESULT SETS // ----------------------------------------------------------------------------- @@ -123,7 +117,7 @@ static TRI_voc_size_t CountRSSingle (TRI_result_set_t* rs, bool current) { //////////////////////////////////////////////////////////////////////////////// static void FreeRSSingle (TRI_result_set_t* rs) { - RemoveContainerElement(rs); + TRI_FreeBarrier(rs->_barrier); TRI_Free(rs->_info._cursor); TRI_Free(rs); @@ -147,7 +141,7 @@ static void FreeRSSingle (TRI_result_set_t* rs) { //////////////////////////////////////////////////////////////////////////////// TRI_result_set_t* TRI_CreateRSSingle (TRI_doc_collection_t* collection, - TRI_rs_container_element_t* containerElement, + TRI_barrier_t* barrier, TRI_doc_mptr_t const* header, TRI_voc_size_t total) { doc_rs_single_t* rs; @@ -162,7 +156,7 @@ TRI_result_set_t* TRI_CreateRSSingle (TRI_doc_collection_t* collection, rs->base.free = FreeRSSingle; rs->base._id = TRI_NewTickVocBase(); - rs->base._containerElement = containerElement; + rs->base._barrier = barrier; if (header == NULL) { rs->_empty = true; @@ -299,7 +293,7 @@ static void FreeRSVector (TRI_result_set_t* rs) { rss = (doc_rs_vector_t*) rs; - RemoveContainerElement(rs); + TRI_FreeBarrier(rs->_barrier); if (rss->_entries != NULL) { ptr = rss->_entries; @@ -334,7 +328,7 @@ static void FreeRSVector (TRI_result_set_t* rs) { //////////////////////////////////////////////////////////////////////////////// TRI_result_set_t* TRI_CreateRSVector (TRI_doc_collection_t* collection, - TRI_rs_container_element_t* containerElement, + TRI_barrier_t* barrier, TRI_doc_mptr_t const** header, TRI_json_t const* augmented, TRI_voc_size_t length, @@ -355,7 +349,7 @@ TRI_result_set_t* TRI_CreateRSVector (TRI_doc_collection_t* collection, rs->base.free = FreeRSVector; rs->base._id = TRI_NewTickVocBase(); - rs->base._containerElement = containerElement; + rs->base._barrier = barrier; if (length == 0) { rs->_length = 0; @@ -409,233 +403,6 @@ TRI_result_set_t* TRI_CreateRSVector (TRI_doc_collection_t* collection, /// @} //////////////////////////////////////////////////////////////////////////////// -// ----------------------------------------------------------------------------- -// --SECTION-- RESULT SETS CONTAINER -// ----------------------------------------------------------------------------- - -// ----------------------------------------------------------------------------- -// --SECTION-- private functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup VocBase -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @brief removes a result set from the doubly linked list -//////////////////////////////////////////////////////////////////////////////// - -static void RemoveContainerElement (TRI_result_set_t* rs) { - TRI_rs_container_t* container; - TRI_rs_container_element_t* element; - - element = rs->_containerElement; - container = element->_container; - - TRI_LockSpin(&container->_lock); - - // element is at the beginning of the chain - if (element->_prev == NULL) { - container->_begin = element->_next; - } - else { - element->_prev->_next = element->_next; - } - - // element is at the end of the chain - if (element->_next == NULL) { - container->_end = element->_prev; - } - else { - element->_next->_prev = element->_prev; - } - - TRI_UnlockSpin(&container->_lock); - - // free the element - TRI_Free(element); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- constructors and destructors -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup VocBase -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @brief initialises a result set container -//////////////////////////////////////////////////////////////////////////////// - -void TRI_InitRSContainer (TRI_rs_container_t* container, TRI_doc_collection_t* collection) { - container->_collection = collection; - - TRI_InitSpin(&container->_lock); - - container->_begin = NULL; - container->_end = NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief destroys a result set container -//////////////////////////////////////////////////////////////////////////////// - -void TRI_DestroyRSContainer (TRI_rs_container_t* container) { - TRI_rs_container_element_t* ptr; - TRI_rs_container_element_t* next; - - ptr = container->_begin; - - while (ptr != NULL) { - next = ptr->_next; - ptr->_container = NULL; - ptr = next; - } - - TRI_DestroySpin(&container->_lock); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- public functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup VocBase -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @brief adds a result set to the end of the doubly linked list -//////////////////////////////////////////////////////////////////////////////// - -TRI_rs_container_element_t* TRI_AddResultSetRSContainer (TRI_rs_container_t* container) { - TRI_rs_container_element_t* element; - - element = TRI_Allocate(sizeof(TRI_rs_container_element_t)); - - element->_type = TRI_RSCE_RESULT_SET; - element->_container = container; - element->_resultSet = NULL; - element->_datafile = NULL; - element->datafileCallback = NULL; - - TRI_LockSpin(&container->_lock); - - // empty list - if (container->_end == NULL) { - element->_next = NULL; - element->_prev = NULL; - - container->_begin = element; - container->_end = element; - } - - // add to the end - else { - element->_next = NULL; - element->_prev = container->_end; - - container->_end->_next = element; - container->_end = element; - } - - TRI_UnlockSpin(&container->_lock); - - return element; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief adds an callback to the result set container -//////////////////////////////////////////////////////////////////////////////// - -TRI_rs_container_element_t* TRI_AddDatafileRSContainer (TRI_rs_container_t* container, - TRI_datafile_t* datafile, - void (*callback) (struct TRI_datafile_s*, void*), - void* data) { - TRI_rs_container_element_t* element; - - element = TRI_Allocate(sizeof(TRI_rs_container_element_t)); - - element->_type = TRI_RSCE_DATAFILE; - element->_container = container; - element->_resultSet = NULL; - element->_datafile = datafile; - element->_datafileData = data; - element->datafileCallback = callback; - - TRI_LockSpin(&container->_lock); - - // empty list - if (container->_end == NULL) { - element->_next = NULL; - element->_prev = NULL; - - container->_begin = element; - container->_end = element; - } - - // add to the end - else { - element->_next = NULL; - element->_prev = container->_end; - - container->_end->_next = element; - container->_end = element; - } - - TRI_UnlockSpin(&container->_lock); - - return element; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief removes a result set from the doubly linked list -//////////////////////////////////////////////////////////////////////////////// - -void TRI_RemoveRSContainer (TRI_rs_container_element_t* element) { - TRI_rs_container_t* container; - - container = element->_container; - - TRI_LockSpin(&container->_lock); - - // element is at the beginning of the chain - if (element->_prev == NULL) { - container->_begin = element->_next; - } - else { - element->_prev->_next = element->_next; - } - - // element is at the end of the chain - if (element->_next == NULL) { - container->_end = element->_prev; - } - else { - element->_next->_prev = element->_prev; - } - - TRI_UnlockSpin(&container->_lock); - - // free the element - TRI_Free(element); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - // Local Variables: // mode: outline-minor // outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" diff --git a/VocBase/result-set.h b/VocBase/result-set.h index c7ff95bfd9..512f9950ef 100644 --- a/VocBase/result-set.h +++ b/VocBase/result-set.h @@ -45,8 +45,8 @@ extern "C" { struct TRI_doc_collection_s; struct TRI_doc_mptr_s; -struct TRI_rs_container_s; -struct TRI_rs_container_element_s; +struct TRI_barrier_list_s; +struct TRI_barrier_s; // ----------------------------------------------------------------------------- // --SECTION-- public types @@ -106,7 +106,7 @@ typedef struct TRI_result_set_s { TRI_rs_id_t _id; TRI_rs_info_t _info; - struct TRI_rs_container_element_s* _containerElement; + struct TRI_barrier_s* _barrier; char* _error; @@ -118,50 +118,6 @@ typedef struct TRI_result_set_s { } TRI_result_set_t; -//////////////////////////////////////////////////////////////////////////////// -/// @brief result set container element type -//////////////////////////////////////////////////////////////////////////////// - -typedef enum { - TRI_RSCE_RESULT_SET, - TRI_RSCE_DATAFILE -} -TRI_rs_container_element_type_e; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief result set container element -//////////////////////////////////////////////////////////////////////////////// - -typedef struct TRI_rs_container_element_s { - struct TRI_rs_container_element_s* _prev; - struct TRI_rs_container_element_s* _next; - - struct TRI_rs_container_s* _container; - - TRI_rs_container_element_type_e _type; - - TRI_result_set_t* _resultSet; - - struct TRI_datafile_s* _datafile; - void* _datafileData; - void (*datafileCallback) (struct TRI_datafile_s*, void*); -} -TRI_rs_container_element_t; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief a result set container for all result sets of a collection -//////////////////////////////////////////////////////////////////////////////// - -typedef struct TRI_rs_container_s { - struct TRI_doc_collection_s* _collection; - - TRI_spin_t _lock; - - TRI_rs_container_element_t* _begin; - TRI_rs_container_element_t* _end; -} -TRI_rs_container_t; - //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// @@ -175,24 +131,12 @@ TRI_rs_container_t; /// @{ //////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -/// @brief initialises a result set container -//////////////////////////////////////////////////////////////////////////////// - -void TRI_InitRSContainer (TRI_rs_container_t*, struct TRI_doc_collection_s*); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief destroys a result set container -//////////////////////////////////////////////////////////////////////////////// - -void TRI_DestroyRSContainer (TRI_rs_container_t*); - //////////////////////////////////////////////////////////////////////////////// /// @brief creates a single result set //////////////////////////////////////////////////////////////////////////////// TRI_result_set_t* TRI_CreateRSSingle (struct TRI_doc_collection_s* collection, - TRI_rs_container_element_t* containerElement, + struct TRI_barrier_s* containerElement, struct TRI_doc_mptr_s const* header, TRI_voc_size_t total); @@ -201,7 +145,7 @@ TRI_result_set_t* TRI_CreateRSSingle (struct TRI_doc_collection_s* collection, //////////////////////////////////////////////////////////////////////////////// TRI_result_set_t* TRI_CreateRSVector (struct TRI_doc_collection_s* collection, - TRI_rs_container_element_t* containerElement, + struct TRI_barrier_s* containerElement, struct TRI_doc_mptr_s const** header, TRI_json_t const* augmented, TRI_voc_size_t length, @@ -211,40 +155,6 @@ TRI_result_set_t* TRI_CreateRSVector (struct TRI_doc_collection_s* collection, /// @} //////////////////////////////////////////////////////////////////////////////// -// ----------------------------------------------------------------------------- -// --SECTION-- public functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup VocBase -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @brief adds a result set to the end of the doubly linked list -//////////////////////////////////////////////////////////////////////////////// - -TRI_rs_container_element_t* TRI_AddResultSetRSContainer (TRI_rs_container_t* container); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief adds an callback to the result set container -//////////////////////////////////////////////////////////////////////////////// - -TRI_rs_container_element_t* TRI_AddDatafileRSContainer (TRI_rs_container_t* container, - struct TRI_datafile_s* datafile, - void (*callback) (struct TRI_datafile_s*, void*), - void*); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief removes a result set from the doubly linked list -//////////////////////////////////////////////////////////////////////////////// - -void TRI_RemoveRSContainer (TRI_rs_container_element_t* element); - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - #ifdef __cplusplus } #endif diff --git a/VocBase/shadow-data.c b/VocBase/shadow-data.c new file mode 100644 index 0000000000..efd92cc2d4 --- /dev/null +++ b/VocBase/shadow-data.c @@ -0,0 +1,83 @@ +TRI_shadow_t* TRI_CreateShadowData (TRI_shadow_store_t* store, TRI_vocbase_t* vocbase, TRI_voc_cid_t cid, TRI_voc_did_t did) { + TRI_vocbase_col_t const* col; + + // extract the collection + col = TRI_LookupCollectionByIdVocBase(vocbase, cid); + + if (col == NULL ...) { + return NULL; + } + + collection = col->...; + + // lock the collection + collection->beginRead(collection); + + // find the document + mptr = collection->read(collection, did); + + if (mptr == NULL) { + collection->endRead(collection); + return NULL; + } + + // check if we already know a parsed version + TRI_LockMutex(&store->_lock); + + element = LookupElement(store, cid, did); + + if (element != NULL) { + ok = store->verify(store, collection, mptr, element); + + if (ok) { + ++element->_counter; + + TRI_UnlockMutex(&store->_lock); + collection->endRead(collection); + + return element; + } + else { + RemoveElement(store, element); + } + } + + // parse the document + parsed = store->parse(store, collection, mptr); + + if (parsed == NULL) { + TRI_UnlockMutex(&store->_lock); + collection->endRead(collection); + return NULL; + } + + // enter the parsed document into the store + element = CreateElement(store, parsed); + + // use element, unlock the store and the collection + ++element->_counter; + + TRI_UnlockMutex(&store->_lock); + collection->endRead(collection); + + // and return the element + return element; +} + + + +void TRI_ReleaseShadowData (TRI_shadow_store_t* store, TRI_shadow_t* element) { + TRI_LockMutex(&store->_lock); + + // release the element + --element->_counter; + + // need to destroy the element + if (element->_counter < 1) { + RemoveElement(store, element); + DestroyElement(store, element); + } + + TRI_UnlockMutex(&store->_lock); +} + diff --git a/VocBase/shadow-data.h b/VocBase/shadow-data.h new file mode 100644 index 0000000000..d0e91f120f --- /dev/null +++ b/VocBase/shadow-data.h @@ -0,0 +1,16 @@ +typedef struct TRI_shadow_store_s { + TRI_mutex_t _lock; + + TRI_associative_pointer_t _data; + + void* (*parse) (struct TRI_shadow_store_s*, struct TRI_doc_collection_s*, struct TRI_doc_mptr_s*); +} +TRI_shadow_store_t; + + + +typdef struct TRI_shadow_s { + int64_t _rc; + void* _data; +} +TRI_shadow_t; diff --git a/VocBase/simple-collection.c b/VocBase/simple-collection.c index 990be556e0..3c9514baf7 100644 --- a/VocBase/simple-collection.c +++ b/VocBase/simple-collection.c @@ -259,10 +259,9 @@ static void CreateHeader (TRI_doc_collection_t* c, size_t markerSize, TRI_doc_mptr_t* header, void const* additional) { - - const TRI_doc_document_marker_t* marker; + TRI_doc_document_marker_t const* marker; - marker = (const TRI_doc_document_marker_t*) m; + marker = (TRI_doc_document_marker_t const*) m; header->_did = marker->_did; header->_rid = marker->_rid; @@ -271,7 +270,7 @@ static void CreateHeader (TRI_doc_collection_t* c, header->_data = marker; header->_document._sid = marker->_shape; header->_document._data.length = marker->base._size - markerSize; - header->_document._data.data = ((const char*) marker) + markerSize; + header->_document._data.data = ((char*) marker) + markerSize; } //////////////////////////////////////////////////////////////////////////////// @@ -2278,7 +2277,7 @@ static TRI_index_t* CreateHashIndexSimCollection (TRI_sim_collection_t* collecti // Determine the shape ids for the attributes // ........................................................................... for (size_t j = 0; j < attributes->_length; ++j) { - char* shapeString = *((char**)(TRI_AtVector(attributes,j))); + char* shapeString = *((char**)(TRI_AtVector(attributes,j))); TRI_shape_pid_t shape = shaper->findAttributePathByName(shaper, shapeString); TRI_PushBackVector(&shapes,&shape); } @@ -2412,7 +2411,7 @@ TRI_index_t* TRI_LookupGeoIndex2SimCollection (TRI_sim_collection_t* collection, TRI_index_t* TRI_LookupHashIndexSimCollection (TRI_sim_collection_t* collection, const TRI_vector_t* shapes) { - TRI_index_t* matchedIndex = NULL; + TRI_index_t* matchedIndex = NULL; // ........................................................................... // Note: This function does NOT differentiate between non-unique and unique @@ -2430,26 +2429,26 @@ TRI_index_t* TRI_LookupHashIndexSimCollection (TRI_sim_collection_t* collection, TRI_hash_index_t* hashIndex = (TRI_hash_index_t*) idx; bool found = true; - + // ......................................................................... - // check that the type of the index is in fact a hash index + // check that the type of the index is in fact a hash index // ......................................................................... - + if (idx->_type != TRI_IDX_TYPE_HASH_INDEX) { continue; } - + // ......................................................................... // check that the number of shapes (fields) in the hash index matches that // of the number of attributes // ......................................................................... - + if (shapes->_length != hashIndex->_shapeList->_length) { continue; } - - + + // ......................................................................... // Go through all the attributes and see if they match // ......................................................................... @@ -2459,10 +2458,10 @@ TRI_index_t* TRI_LookupHashIndexSimCollection (TRI_sim_collection_t* collection, TRI_shape_pid_t shape = *((TRI_shape_pid_t*)(TRI_AtVector(shapes,k))); if (field != shape) { found = false; - break; - } + break; + } } - + if (found) { matchedIndex = idx; diff --git a/js/actions/api.js b/js/actions/api.js new file mode 100644 index 0000000000..7201dd079b --- /dev/null +++ b/js/actions/api.js @@ -0,0 +1,120 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns an error +/// +/// @FUN{actionResultError(@FA{req}, @FA{res}, @FA{httpReturnCode}, @FA{errorNum}, @FA{errorMessage}, @FA{headers})} +/// +/// The functions returns an error json object. The returned object is an array +/// with an attribute @LIT{errorMessage} containing the error message +/// @FA{errorMessage}. +//////////////////////////////////////////////////////////////////////////////// + +function actionResultError (req, res, httpReturnCode, errorNum, errorMessage, headers) { + res.responseCode = httpReturnCode; + res.contentType = "application/json"; + + var result = { + "error" : true, + "code" : httpReturnCode, + "errorNum" : errorNum, + "errorMessage" : errorMessage + } + + res.body = JSON.stringify(result); + + if (headers != undefined) { + res.headers = headers; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns an error for unsupported methods +/// +/// @FUN{actionResultUnsupported(@FA{req}, @FA{res}, @FA{headers})} +/// +/// The functions returns an error json object. The returned object is an array +/// with an attribute @LIT{errorMessage} containing the error message +/// @FA{errorMessage}. +//////////////////////////////////////////////////////////////////////////////// + +function actionResultUnsupported (req, res, headers) { + actionResultError(req, res, 405, 405, "Unsupported method", headers); +} + + + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns a result +/// +/// @FUN{actionResultOK(@FA{req}, @FA{res}, @FA{httpReturnCode}, @FA{result}, @FA{headers}})} +/// +//////////////////////////////////////////////////////////////////////////////// + +function actionResultOK (req, res, httpReturnCode, result, headers) { + res.responseCode = httpReturnCode; + res.contentType = "application/json"; + + // add some default attributes to result: + result.error = false; + result.code = httpReturnCode; + + res.body = JSON.stringify(result); + + if (headers != undefined) { + res.headers = headers; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief error codes +//////////////////////////////////////////////////////////////////////////////// + +var queryNotFound = 10404; +var queryNotModified = 10304; + +var collectionNotFound = 20404; +var documentNotFound = 30404; +var documentNotModified = 30304; + +var cursorNotFound = 40404; +var cursorNotModified = 40304; + +var myApiRequests = {}; + +myApiRequests.cursor = { + "POST /_api/cursor" : "create and execute query. (creates a cursor)", + "PUT /_api/cursor/" : "get next results", + "DELETE /_api/cursor/" : "delete cursor" +} + +myApiRequests.collection = { + "GET /_api/collections" : "get list of collections", + "GET /_api/collection/" : "get all elements of collection" +} + +myApiRequests.document = { + "POST /_api/document/" : "create new document", + "PUT /_api/document//" : "update document", + "GET /_api/document//" : "get a document", + "DELETE /_api/document//" : "delete a document" +} + +myApiRequests.query = { + "POST /_api/query" : "create a query", + "GET /_api/query/" : "get query", + "PUT /_api/query/" : "change query", + "DELETE /_api/query/" : "delete query" +} + +defineAction("help", + function (req, res) { + var result = { + "requests":myApiRequests + } + + actionResultOK(req, res, 200, result); + }, + { + parameters : { + } + } +); diff --git a/js/actions/collection.js b/js/actions/collection.js new file mode 100644 index 0000000000..fd232a1e36 --- /dev/null +++ b/js/actions/collection.js @@ -0,0 +1,83 @@ +function getCollections(req, res) { + var colls; + var coll; + var result; + + colls = db._collections(); + result = { + path : db._path, + collections : {} + }; + + for (var i = 0; i < colls.length; ++i) { + coll = colls[i]; + + result.collections[coll._name] = { + id : coll._id, + name : coll._name, + status : coll.status(), + figures : coll.figures() + }; + } + + actionResultOK(req, res, 200, result); +} + +function getCollection(req, res) { + if (req._suffix.length != 1) { + actionResultError (req, res, 404, collectionNotFound, "Collection not found"); + return; + } + + try { + var name = decodeURIComponent(req._suffix[0]); + var result = { + "name" : name, + "documents" : {} + }; + + result.documents = db[name].all().toArray(); + actionResultOK(req, res, 200, result); + } + catch (e) { + actionResultError (req, res, 404, collectionNotFound, "Collection not found") + } +} + +defineAction("_api/collections", + function (req, res) { + + switch (req._requestType) { + case ("GET") : + getCollections(req, res); + break; + default: + actionResultError (req, res, 405, 405, "Unsupported method"); + } + + }, + { + parameters : { + } + } +); + +defineAction("_api/collection", + function (req, res) { + + switch (req._requestType) { + case ("GET") : + getCollection(req, res); + break; + default: + actionResultUnsupported(req, res); + } + + }, + { + parameters : { + blocksize : "number", + page : "number" + } + } +); diff --git a/js/actions/cursor.js b/js/actions/cursor.js new file mode 100644 index 0000000000..efa7072871 --- /dev/null +++ b/js/actions/cursor.js @@ -0,0 +1,105 @@ + +function postCursor(req, res) { + if (req._suffix.length != 0) { + actionResultError (req, res, 404, cursorNotModified, "Cursor not created") + return; + } + + try { + var json = JSON.parse(req._requestBody); + + if (json.qid == undefined) { + actionResultError (req, res, 404, cursorNotModified, "Missing query identifier"); + return; + } + + var cid = db.cursor.save(json); + + // req.bindParameter + // req.skip + // req.count + // query.execute(...) + + var result = { + "result" : [{"found":"nothing"}], + "cid" : cid, + "count" : 1, + "hasMore" : false + }; + + actionResultOK(req, res, 201, result); + } + catch (e) { + actionResultError (req, res, 404, cursorNotModified, "Cursor not created") + } +} + +function putCursor(req, res) { + if (req._suffix.length != 1) { + actionResultError (req, res, 404, cursorNotFound, "Cursor not found") + return; + } + + try { + var cid = decodeURIComponent(req._suffix[0]); + var data = db.cursor.document_wrapped(qid); + + // TODO + + var result = { + "result" : [{"found":"nothing"}], + "count" : 1, + "cid" : cid, + "hasMore" : false + }; + + actionResultOK(req, res, 200, result); + } + catch (e) { + actionResultError (req, res, 404, cursorNotFound, "Cursor not found") + } +} + +function deleteCursor(req, res) { + if (req._suffix.length != 1) { + actionResultError (req, res, 404, cursorNotFound, "Cursor not found") + return; + } + + try { + var cid = decodeURIComponent(req._suffix[0]); + if(db.cursor.delete(qid)) { + actionResultOK(req, res, 202, {"cid" : cid}); + } + else { + actionResultError (req, res, 404, cursorNotFound, "Cursor not found") + } + } + catch (e) { + actionResultError (req, res, 404, cursorNotFound, "Cursor not found") + } +} + +defineAction("_api/cursor", + function (req, res) { + + switch (req._requestType) { + case ("POST") : + postCursor(req, res); + break; + case ("PUT") : + putCursor(req, res); + break; + case ("DELETE") : + deleteCursor(req, res); + break; + default: + actionResultUnsupported(req, res); + } + + }, + { + parameters : { + } + } +); diff --git a/js/actions/document.js b/js/actions/document.js new file mode 100644 index 0000000000..338c258ac9 --- /dev/null +++ b/js/actions/document.js @@ -0,0 +1,125 @@ +function getDocument(req, res) { + if (req._suffix.length != 2) { + actionResultError (req, res, 404, documentNotFound, "Document not found"); + return; + } + + try { + var collection = decodeURIComponent(req._suffix[0]); + var documentId = decodeURIComponent(req._suffix[1]); + var result = { + "collection" : collection, + "documentId" : documentId, + "document" : {} + }; + + + result.document = db[collection].document_wrapped(documentId); + actionResultOK(req, res, 200, result); + } + catch (e) { + actionResultError (req, res, 404, documentNotFound, "Document not found: " + e); + } +} + +function deleteDocument(req, res) { + if (req._suffix.length != 2) { + actionResultError (req, res, 404, documentNotFound, "Document not found"); + return; + } + + try { + var collection = decodeURIComponent(req._suffix[0]); + var documentId = decodeURIComponent(req._suffix[1]); + var result = { + "collection" : collection, + "documentId" : documentId + }; + + + if (db[collection].delete(documentId)) { + result.document = undefined; + actionResultOK(req, res, 200, result); + } + else { + actionResultError (req, res, 304, documentNotModified, "Document not deleted"); + } + } + catch (e) { + actionResultError(req, res, 304, documentNotModified, "Document not deleted: " + e); + } +} + +function postDocument(req, res) { + if (req._suffix.length != 1) { + actionResultError (req, res, 404, collectionNotFound, "Collection not found"); + return; + } + + try { + var collection = decodeURIComponent(req._suffix[0]); + var json = JSON.parse(req._requestBody); + var id = db[collection].save(json); + + var result = { + "collection" : collection, + "documentId" : id + }; + + actionResultOK(req, res, 201, result); + } + catch (e) { + actionResultError (req, res, 404, documentNotModified, "Document not saved: " + e); + } +} + +function putDocument(req, res) { + if (req._suffix.length != 2) { + actionResultError (req, res, 404, documentNotFound, "Document not found"); + return; + } + + try { + var collection = decodeURIComponent(req._suffix[0]); + var documentId = decodeURIComponent(req._suffix[1]); + var json = JSON.parse(req._requestBody); + var id = db[collection].replace(documentId, json); + + var result = { + "collection" : collection, + "documentId" : id + }; + + actionResultOK(req, res, 202, result); + } + catch (e) { + actionResultError (req, res, 404, documentNotModified, "Document not changed: " + e); + } +} + +defineAction("_api/document", + function (req, res) { + + switch (req._requestType) { + case ("GET") : + getDocument(req, res); + break; + case ("POST") : + postDocument(req, res); + break; + case ("PUT") : + putDocument(req, res); + break; + case ("DELETE") : + deleteDocument(req, res); + break; + default: + actionResultUnsupported(req, res); + } + + }, + { + parameters : { + } + } +); diff --git a/js/actions/query.js b/js/actions/query.js new file mode 100644 index 0000000000..6cea88fa49 --- /dev/null +++ b/js/actions/query.js @@ -0,0 +1,132 @@ +function getQuery(req, res) { + if (req._suffix.length != 1) { + actionResultError (req, res, 404, queryNotFound, "Query not found") + return; + } + + try { + var qid = decodeURIComponent(req._suffix[0]); + var result = db.query.document_wrapped(qid); + + var result = { + "query" : doc.query + }; + + actionResultOK(req, res, 200, result); + } + catch (e) { + actionResultError (req, res, 404, queryNotFound, "Query not found") + } +} + +function postQuery(req, res) { + if (req._suffix.length != 0) { + actionResultError(req, res, 404, queryNotModified, "Query not created") + return; + } + + try { + var json = JSON.parse(req._requestBody); + + if (json.query == undefined) { + actionResultError(req, res, 404, queryNotModified, "Document has no query.") + return; + } + + var q = { + "query":json.query + } + + var id = db.query.save(q); + + var result = { + "qid" : id + }; + + actionResultOK(req, res, 201, result); + } + catch (e) { + actionResultError (req, res, 404, queryNotModified, "Query not created") + } +} + +function putQuery(req, res) { + if (req._suffix.length != 1) { + actionResultError (req, res, 404, queryNotFound, "Query not found"); + return; + } + + try { + var qid = decodeURIComponent(req._suffix[0]); + var json = JSON.parse(req._requestBody); + + if (json.query == undefined) { + actionResultError(req, res, 404, queryNotModified, "Document has no query.") + return; + } + + var q = { + "query":json.query + } + + var id = db.query.replace(qid, q); + + var result = { + "qid" : id + }; + + actionResultOK(req, res, 202, result); + } + catch (e) { + actionResultError (req, res, 404, queryNotModified, "Query not changed") + } +} + +function deleteQuery(req, res) { + if (req._suffix.length != 1) { + actionResultError (req, res, 404, queryNotFound, "Query not found"); + return; + } + + try { + var qid = decodeURIComponent(req._suffix[0]); + + if (db.query.delete(qid)) { + actionResultOK(req, res, 202, {"qid" : qid}); + } + else { + actionResultError (req, res, 404, queryNotModified, "Query not changed") + } + + } + catch (e) { + actionResultError (req, res, 404, queryNotModified, "Query not changed") + } +} + +defineAction("_api/query", + function (req, res) { + + switch (req._requestType) { + case ("GET") : + getQuery(req, res); + break; + case ("POST") : + postQuery(req, res); + break; + case ("PUT") : + putQuery(req, res); + break; + case ("DELETE") : + deleteQuery(req, res); + break; + default: + actionResultUnsupported(req, res); + } + + }, + { + parameters : { + } + } +);