mirror of https://gitee.com/bigwinds/arangodb
more QL
This commit is contained in:
parent
16051bc6a1
commit
258952bc9f
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
19
Makefile.in
19
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
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
1199
QL/parser.c
1199
QL/parser.c
File diff suppressed because it is too large
Load Diff
64
QL/parser.h
64
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 */
|
||||
|
|
30
QL/parser.y
30
QL/parser.y
|
@ -73,6 +73,7 @@ void QLerror (YYLTYPE *locp,QL_parser_context_t *context, const char *err) {
|
|||
%type <node> collection_reference;
|
||||
%type <node> collection_name;
|
||||
%type <node> collection_alias;
|
||||
%type <node> geo_expression;
|
||||
%type <node> where_clause;
|
||||
%type <node> order_clause;
|
||||
%type <node> 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 {
|
||||
|
|
362
QL/tokens.c
362
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;
|
||||
}
|
||||
|
|
13
QL/tokens.l
13
QL/tokens.l
|
@ -131,6 +131,19 @@
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* other keywords
|
||||
* --------------------------------------------------------------------------- */
|
||||
|
||||
(?i:within) {
|
||||
return WITHIN;
|
||||
}
|
||||
|
||||
(?i:near) {
|
||||
return NEAR;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* logical operators
|
||||
|
|
|
@ -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<RestDocumentHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
factory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator<RestCollectionHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
factory->addPrefixHandler(RestVocbaseBaseHandler::ACTION_PATH, RestHandlerCreator<RestActionHandler>::createData<TRI_vocbase_t*>, _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<RestDocumentHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
adminFactory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator<RestCollectionHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
adminFactory->addPrefixHandler(RestVocbaseBaseHandler::ACTION_PATH, RestHandlerCreator<RestActionHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
adminFactory->addPrefixHandler(RestVocbaseBaseHandler::SYSTEM_ACTION_PATH, RestHandlerCreator<RestSystemActionHandler>::createData<TRI_vocbase_t*>, _vocbase);
|
||||
|
||||
|
|
|
@ -47,14 +47,6 @@ using namespace triagens::avocado;
|
|||
/// <ol>
|
||||
/// <li>@ref StartStop
|
||||
/// </li>
|
||||
/// <li>@ref AvocadoScript
|
||||
/// <ol>
|
||||
/// <li>@ref GeoCoordinates
|
||||
/// </li>
|
||||
/// <li>@ref Pagination
|
||||
/// </li>
|
||||
/// </ol>
|
||||
/// </li>
|
||||
/// <li>@ref HttpInterface
|
||||
/// <ol>
|
||||
/// <li>@ref RestInterface
|
||||
|
@ -63,6 +55,22 @@ using namespace triagens::avocado;
|
|||
/// </li>
|
||||
/// </ol>
|
||||
/// </li>
|
||||
/// <li>@ref AQL
|
||||
/// <ol>
|
||||
/// <li>@ref Optimizer
|
||||
/// </li>
|
||||
/// <li>@ref IndexUsage
|
||||
/// </li>
|
||||
/// </ol>
|
||||
/// </li>
|
||||
/// <li>@ref AvocadoScript
|
||||
/// <ol>
|
||||
/// <li>@ref GeoCoordinates
|
||||
/// </li>
|
||||
/// <li>@ref Pagination
|
||||
/// </li>
|
||||
/// </ol>
|
||||
/// </li>
|
||||
/// <li>Vertices, Edges, and Graphs
|
||||
/// <ol>
|
||||
/// <li>@ref Graphs
|
||||
|
@ -183,11 +191,9 @@ using namespace triagens::avocado;
|
|||
/// @page InstallManual AvocadoDB Installation Manual
|
||||
///
|
||||
/// <ol>
|
||||
/// <li>Building the AvocadoDB from Scratch
|
||||
/// <ol>
|
||||
/// <li>@ref Compiling
|
||||
/// </li>
|
||||
/// </ol>
|
||||
/// <li>@ref Installing
|
||||
/// <li>
|
||||
/// <li>@ref Compiling
|
||||
/// </li>
|
||||
/// </ol>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -25,6 +25,43 @@
|
|||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page InstallingTOC
|
||||
///
|
||||
/// <ol>
|
||||
/// <li>@ref Installing
|
||||
/// <ol>
|
||||
/// <li>@ref MacOSX
|
||||
/// <ol>
|
||||
/// <li>@ref MacOSXHomebrew
|
||||
/// </ol>
|
||||
/// </li>
|
||||
/// </ol>
|
||||
/// </li>
|
||||
/// </ol>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page Installing Installing the AvocadoDB
|
||||
///
|
||||
/// <hr>
|
||||
/// @copydoc CompilingTOC
|
||||
/// <hr>
|
||||
///
|
||||
/// @section MacOSX
|
||||
///////////////////
|
||||
///
|
||||
/// @subsection MacOSXHomebrew
|
||||
//////////////////////////////
|
||||
///
|
||||
/// If you are using <a href="http://mxcl.github.com/homebrew/">homebrew</a>,
|
||||
/// 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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<string, void*>::iterator i = actions->find(name);
|
||||
|
||||
size_t pos = request->suffix().size();
|
||||
|
||||
if (i == actions->end()) {
|
||||
// no direct callback found
|
||||
|
||||
vector<string> 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<v8::Object> 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<v8::Array> v8SuffixArray = v8::Array::New();
|
||||
vector<string> 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>(v8::String::New("_suffix")), v8SuffixArray);
|
||||
|
||||
// copy header fields
|
||||
v8::Handle<v8::Object> v8HeaderfildsObject = v8::Object::New();
|
||||
map<string, string> const& headers = request->headers();
|
||||
map<string, string>::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>(v8::String::New("_headers")), v8HeaderfildsObject);
|
||||
|
||||
switch (request->requestType()) {
|
||||
case HttpRequest::HTTP_REQUEST_POST:
|
||||
req->Set(v8::Handle<v8::String>(v8::String::New("_requestType")),
|
||||
v8::Handle<v8::String>(v8::String::New("POST")));
|
||||
req->Set(v8::Handle<v8::String>(v8::String::New("_requestBody")),
|
||||
v8::Handle<v8::String>(v8::String::New(request->body().c_str())));
|
||||
break;
|
||||
case HttpRequest::HTTP_REQUEST_PUT:
|
||||
req->Set(v8::Handle<v8::String>(v8::String::New("_requestType")),
|
||||
v8::Handle<v8::String>(v8::String::New("PUT")));
|
||||
req->Set(v8::Handle<v8::String>(v8::String::New("_requestBody")),
|
||||
v8::Handle<v8::String>(v8::String::New(request->body().c_str())));
|
||||
break;
|
||||
case HttpRequest::HTTP_REQUEST_DELETE:
|
||||
req->Set(v8::Handle<v8::String>(v8::String::New("_requestType")),
|
||||
v8::Handle<v8::String>(v8::String::New("DELETE")));
|
||||
break;
|
||||
case HttpRequest::HTTP_REQUEST_HEAD:
|
||||
req->Set(v8::Handle<v8::String>(v8::String::New("_requestType")),
|
||||
v8::Handle<v8::String>(v8::String::New("HEAD")));
|
||||
break;
|
||||
default:
|
||||
req->Set(v8::Handle<v8::String>(v8::String::New("_requestType")),
|
||||
v8::Handle<v8::String>(v8::String::New("GET")));
|
||||
}
|
||||
|
||||
|
||||
map<string, string> values = request->values();
|
||||
|
||||
for (map<string, string>::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<v8::Value> val = res->Get(v8g->HeadersKey);
|
||||
v8::Handle<v8::Object> v8Headers = val.As<v8::Object>();
|
||||
if (v8Headers->IsObject()) {
|
||||
v8::Handle<v8::Array> props = v8Headers->GetPropertyNames();
|
||||
for (size_t i = 0; i < props->Length(); i++) {
|
||||
v8::Handle<v8::Value> 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<v8::Context> context) {
|
|||
// .............................................................................
|
||||
|
||||
v8g->BodyKey = v8::Persistent<v8::String>::New(v8::String::New("body"));
|
||||
v8g->HeadersKey = v8::Persistent<v8::String>::New(v8::String::New("headers"));
|
||||
v8g->ContentType = v8::Persistent<v8::String>::New(v8::String::New("contentType"));
|
||||
v8g->ParametersKey = v8::Persistent<v8::String>::New(v8::String::New("parameters"));
|
||||
v8g->ResponseCodeKey = v8::Persistent<v8::String>::New(v8::String::New("responseCode"));
|
||||
|
|
|
@ -1307,7 +1307,7 @@ bool TRI_ObjectDocumentPointer (TRI_doc_collection_t* collection,
|
|||
v8::Handle<v8::Array> TRI_ArrayResultSet (TRI_result_set_t* rs) {
|
||||
v8::Handle<v8::Array> 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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -277,6 +277,12 @@ typedef struct TRI_v8_global_s {
|
|||
|
||||
v8::Persistent<v8::String> BodyKey;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief "headers" key name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Persistent<v8::String> HeadersKey;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief "_id" key name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -461,16 +461,15 @@ bool TRI_ExecuteRefExecutionContext (TRI_js_exec_context_t context, TRI_json_t*
|
|||
v8::Handle<v8::Value> parameter = obj->Get(position++);
|
||||
if (parameter->IsNumber()) {
|
||||
v8::Handle<v8::Number> numberParameter = parameter->ToNumber();
|
||||
TRI_PushBackListJson(r, TRI_CreateNumberJson(numberParameter->Value()));
|
||||
TRI_PushBack2ListJson(r, TRI_CreateNumberJson(numberParameter->Value()));
|
||||
}
|
||||
else if (parameter->IsString() ) {
|
||||
v8::Handle<v8::String> stringParameter= parameter->ToString();
|
||||
v8::String::Utf8Value str(stringParameter);
|
||||
TRI_PushBackListJson(r, TRI_CreateStringCopyJson(*str));
|
||||
TRI_PushBack2ListJson(r, TRI_CreateStringCopyJson(*str));
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1095,7 +1095,7 @@ static v8::Handle<v8::Value> 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<v8::Value> 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<v8::Value> JS_EnsureHashIndexVocbaseCol (v8::Arguments const&
|
|||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
memcpy(cArgument, *argumentString, argumentString.length());
|
||||
TRI_PushBackVector(&attributes,&cArgument);
|
||||
}
|
||||
|
@ -2873,7 +2873,7 @@ static v8::Handle<v8::Value> 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<v8::Value> 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<v8::Value> JS_EnsureMultiHashIndexVocbaseCol (v8::Arguments co
|
|||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
memcpy(cArgument, *argumentString, argumentString.length());
|
||||
TRI_PushBackVector(&attributes,&cArgument);
|
||||
}
|
||||
|
@ -3036,14 +3036,14 @@ static v8::Handle<v8::Value> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
|
@ -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:
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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);
|
||||
|
||||
// .............................................................................
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -32,12 +32,6 @@
|
|||
|
||||
#include <VocBase/document-collection.h>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --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--\\|/// @\\}\\)"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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/<cursor-id>" : "get next results",
|
||||
"DELETE /_api/cursor/<cursor-id>" : "delete cursor"
|
||||
}
|
||||
|
||||
myApiRequests.collection = {
|
||||
"GET /_api/collections" : "get list of collections",
|
||||
"GET /_api/collection/<collection-id>" : "get all elements of collection"
|
||||
}
|
||||
|
||||
myApiRequests.document = {
|
||||
"POST /_api/document/<collection-id>" : "create new document",
|
||||
"PUT /_api/document/<collection-id>/<document-id>" : "update document",
|
||||
"GET /_api/document/<collection-id>/<document-id>" : "get a document",
|
||||
"DELETE /_api/document/<collection-id>/<document-id>" : "delete a document"
|
||||
}
|
||||
|
||||
myApiRequests.query = {
|
||||
"POST /_api/query" : "create a query",
|
||||
"GET /_api/query/<query-id>" : "get query",
|
||||
"PUT /_api/query/<query-id>" : "change query",
|
||||
"DELETE /_api/query/<query-id>" : "delete query"
|
||||
}
|
||||
|
||||
defineAction("help",
|
||||
function (req, res) {
|
||||
var result = {
|
||||
"requests":myApiRequests
|
||||
}
|
||||
|
||||
actionResultOK(req, res, 200, result);
|
||||
},
|
||||
{
|
||||
parameters : {
|
||||
}
|
||||
}
|
||||
);
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
);
|
|
@ -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 : {
|
||||
}
|
||||
}
|
||||
);
|
|
@ -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 : {
|
||||
}
|
||||
}
|
||||
);
|
|
@ -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 : {
|
||||
}
|
||||
}
|
||||
);
|
Loading…
Reference in New Issue