1
0
Fork 0
This commit is contained in:
Frank Celler 2012-02-24 18:43:09 +01:00
parent 16051bc6a1
commit 258952bc9f
52 changed files with 2503 additions and 1294 deletions

View File

@ -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, &copy);
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;

View File

@ -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;
}

View File

@ -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

View File

@ -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 \

View File

@ -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
################################################################################
################################################################################

View File

@ -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;
}

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -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));

View File

@ -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.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

View File

@ -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;
}
}

View File

@ -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*);
////////////////////////////////////////////////////////////////////////////////
/// @}

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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 {

View File

@ -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;
}

View File

@ -131,6 +131,19 @@
return FALSE;
}
/* ---------------------------------------------------------------------------
* other keywords
* --------------------------------------------------------------------------- */
(?i:within) {
return WITHIN;
}
(?i:near) {
return NEAR;
}
/* ---------------------------------------------------------------------------
* logical operators

View File

@ -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);

View File

@ -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>
////////////////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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;
}

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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;

View File

@ -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"));

View File

@ -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;

View File

@ -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

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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;
}
}

View File

@ -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;
}
}
}
}

199
VocBase/barrier.c Normal file
View File

@ -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:

154
VocBase/barrier.h Normal file
View File

@ -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:

View File

@ -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;

View File

@ -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);

View File

@ -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
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

View File

@ -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);
}

View File

@ -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*);

View File

@ -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);
// .............................................................................

View File

@ -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
}

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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--\\|/// @\\}\\)"

View File

@ -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

83
VocBase/shadow-data.c Normal file
View File

@ -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);
}

16
VocBase/shadow-data.h Normal file
View File

@ -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;

View File

@ -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;

120
js/actions/api.js Normal file
View File

@ -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 : {
}
}
);

83
js/actions/collection.js Normal file
View File

@ -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"
}
}
);

105
js/actions/cursor.js Normal file
View File

@ -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 : {
}
}
);

125
js/actions/document.js Normal file
View File

@ -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 : {
}
}
);

132
js/actions/query.js Normal file
View File

@ -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 : {
}
}
);