mirror of https://gitee.com/bigwinds/arangodb
1751 lines
61 KiB
C
1751 lines
61 KiB
C
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief query
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2010-2012 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 2012, triAGENS GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "query.h"
|
|
|
|
#include "BasicsC/logging.h"
|
|
#include "BasicsC/string-buffer.h"
|
|
#include "BasicsC/strings.h"
|
|
#include "V8/v8-c-utils.h"
|
|
#include "VocBase/query-cursor.h"
|
|
#include "VocBase/query-join-execute.h"
|
|
#include "VocBase/simple-collection.h"
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- SELECT DOCUMENT
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief clones a query selection for unaltered documents - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_qry_select_t* CloneQuerySelectDocument (TRI_qry_select_t const* s) {
|
|
return TRI_CreateQuerySelectDocument();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief frees a query selection for unaltered documents - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeQuerySelectDocument (TRI_qry_select_t* s) {
|
|
TRI_qry_select_direct_t* selectClause;
|
|
|
|
selectClause = (TRI_qry_select_direct_t*) s;
|
|
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, selectClause);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief converts result to JavaScript - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool ToJavaScriptSelectDocument (TRI_qry_select_t* s,
|
|
TRI_rc_result_t* result,
|
|
void* storage) {
|
|
|
|
TRI_doc_mptr_t masterPointer;
|
|
TRI_doc_mptr_t* document;
|
|
TRI_select_size_t* numPtr;
|
|
TRI_select_size_t num;
|
|
TRI_select_result_t* selectResult = result->_selectResult;
|
|
TRI_select_datapart_t* part = (TRI_select_datapart_t*) selectResult->_dataParts->_buffer[0];
|
|
|
|
numPtr = (TRI_select_size_t*) result->_dataPtr;
|
|
num = *numPtr++;
|
|
assert(num == 1);
|
|
document = *((TRI_sr_documents_t*) numPtr);
|
|
TRI_MarkerMasterPointer(document, &masterPointer);
|
|
|
|
return TRI_ObjectDocumentPointer(part->_collection, &masterPointer, storage);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- constructors and destructors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a query selection for unaltered documents - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_qry_select_t* TRI_CreateQuerySelectDocument () {
|
|
TRI_qry_select_direct_t* result;
|
|
|
|
result = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_qry_select_direct_t), false);
|
|
|
|
result->base._type = TRI_QRY_SELECT_DOCUMENT;
|
|
|
|
result->base.clone = CloneQuerySelectDocument;
|
|
result->base.free = FreeQuerySelectDocument;
|
|
result->base.toJavaScript = ToJavaScriptSelectDocument;
|
|
|
|
return &result->base;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- SELECT GENERAL
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief clones a query selection for general documents - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_qry_select_t* CloneQuerySelectGeneral (TRI_qry_select_t const* s) {
|
|
TRI_qry_select_general_t* selectClause;
|
|
|
|
selectClause = (TRI_qry_select_general_t*) s;
|
|
|
|
return TRI_CreateQuerySelectGeneral(selectClause->_code);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief frees a query selection for general documents - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeQuerySelectGeneral (TRI_qry_select_t* s) {
|
|
TRI_qry_select_general_t* selectClause;
|
|
|
|
selectClause = (TRI_qry_select_general_t*) s;
|
|
|
|
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, selectClause->_code);
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, selectClause);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief converts result to JavaScript - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool ToJavaScriptSelectGeneral (TRI_qry_select_t* s,
|
|
TRI_rc_result_t* result,
|
|
void* storage) {
|
|
TRI_rc_context_t* context;
|
|
TRI_js_exec_context_t* execContext;
|
|
|
|
context = result->_context;
|
|
execContext = context->_selectClause;
|
|
|
|
if (execContext == NULL) {
|
|
LOG_ERROR("no JavaScript context for select is known");
|
|
return false;
|
|
}
|
|
|
|
// first define the augumentation, they might get overwritten
|
|
if (result->_augmention._type == TRI_JSON_ARRAY) {
|
|
TRI_DefineJsonArrayExecutionContext(execContext, &result->_augmention);
|
|
}
|
|
|
|
// define the documents
|
|
TRI_DefineSelectExecutionContext(execContext, result);
|
|
|
|
// execute everything
|
|
return TRI_ExecuteExecutionContext(execContext, storage);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- constructors and destructors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a query selection for general, generated documents - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_qry_select_t* TRI_CreateQuerySelectGeneral (char const* clause) {
|
|
TRI_qry_select_general_t* result;
|
|
|
|
result = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_qry_select_general_t), false);
|
|
|
|
result->base._type = TRI_QRY_SELECT_GENERAL;
|
|
|
|
result->base.clone = CloneQuerySelectGeneral;
|
|
result->base.free = FreeQuerySelectGeneral;
|
|
result->base.toJavaScript = ToJavaScriptSelectGeneral;
|
|
|
|
result->_code = TRI_DuplicateString(clause);
|
|
|
|
return &result->base;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- DOCUMENTS LIST
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private types
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief list of all documents - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef struct collection_cursor_s {
|
|
TRI_rc_cursor_t base;
|
|
|
|
TRI_select_size_t _length;
|
|
TRI_select_size_t _currentRow;
|
|
|
|
TRI_doc_mptr_t* _documents;
|
|
TRI_doc_mptr_t* _current;
|
|
TRI_doc_mptr_t* _end;
|
|
|
|
TRI_json_t* _augmentions;
|
|
TRI_json_t* _currentAugmention;
|
|
|
|
TRI_rc_result_t _result;
|
|
|
|
void* _iterator;
|
|
}
|
|
collection_cursor_t;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief fill function - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef void (*cond_fptr) (collection_cursor_t*,
|
|
TRI_sim_collection_t*,
|
|
TRI_rc_context_t*,
|
|
TRI_qry_where_t*,
|
|
TRI_voc_size_t,
|
|
TRI_voc_ssize_t);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns the next element - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_rc_result_t* NextCollectionCursor (TRI_rc_cursor_t* c) {
|
|
collection_cursor_t* cursor;
|
|
|
|
cursor = (collection_cursor_t*) c;
|
|
if (cursor->_currentRow < cursor->_length) {
|
|
cursor->_result._dataPtr =
|
|
cursor->_result._selectResult->getAt(cursor->_result._selectResult, cursor->_currentRow++);
|
|
|
|
if (cursor->_augmentions != NULL) {
|
|
cursor->_result._augmention = *cursor->_currentAugmention++;
|
|
}
|
|
|
|
return &cursor->_result;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool ToJavaScriptHashDocument (TRI_qry_select_t* s,
|
|
TRI_rc_result_t* result,
|
|
void* storage) {
|
|
|
|
TRI_doc_mptr_t* document;
|
|
TRI_doc_collection_t* collection;
|
|
|
|
collection = result->_context->_primary;
|
|
|
|
document = (TRI_doc_mptr_t*) result->_dataPtr;
|
|
return TRI_ObjectDocumentPointer(collection, document, storage);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_rc_result_t* NextHashCollectionCursor (TRI_rc_cursor_t* c) {
|
|
collection_cursor_t* cursor;
|
|
|
|
cursor = (collection_cursor_t*) c;
|
|
|
|
if (cursor->_currentRow == cursor->_length) {
|
|
return NULL;
|
|
}
|
|
|
|
cursor->_current = &(cursor->_documents[cursor->_currentRow]);
|
|
cursor->_result._dataPtr = (TRI_sr_documents_t*) (cursor->_current);
|
|
++(cursor->_currentRow);
|
|
|
|
return &cursor->_result;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool ToJavaScriptPQDocument (TRI_qry_select_t* s,
|
|
TRI_rc_result_t* result,
|
|
void* storage) {
|
|
|
|
TRI_doc_mptr_t* document;
|
|
TRI_doc_collection_t* collection;
|
|
|
|
collection = result->_context->_primary;
|
|
|
|
document = (TRI_doc_mptr_t*) result->_dataPtr;
|
|
return TRI_ObjectDocumentPointer(collection, document, storage);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_rc_result_t* NextPQCollectionCursor (TRI_rc_cursor_t* c) {
|
|
collection_cursor_t* cursor;
|
|
|
|
cursor = (collection_cursor_t*) c;
|
|
|
|
if (cursor->_currentRow == cursor->_length) {
|
|
return NULL;
|
|
}
|
|
|
|
cursor->_current = &(cursor->_documents[cursor->_currentRow]);
|
|
cursor->_result._dataPtr = (TRI_sr_documents_t*) (cursor->_current);
|
|
++(cursor->_currentRow);
|
|
|
|
return &cursor->_result;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// For a collection, advances a given cursor by one. Cursor is associated with
|
|
// a skip list index. Note: for now the <void* _iterator> field will store
|
|
// the iterator which is associated with a skip list index. There is no
|
|
// notion of the number of documents -- these have to be counted. So whenever
|
|
// a count() request is received, the iterator advances to the end of the
|
|
// interval.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_rc_result_t* NextSkiplistCollectionCursor (TRI_rc_cursor_t* c) {
|
|
collection_cursor_t* cursor;
|
|
SkiplistIndexElement* element;
|
|
TRI_skiplist_iterator_t* iterator;
|
|
|
|
cursor = (collection_cursor_t*)(c);
|
|
if (cursor == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
iterator = (TRI_skiplist_iterator_t*)(cursor->_iterator);
|
|
if (iterator == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
element = (SkiplistIndexElement*)(iterator->_next(iterator));
|
|
if (element == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
cursor->_current = element->data;
|
|
cursor->_result._dataPtr = (TRI_sr_documents_t*) (cursor->_current);
|
|
++(cursor->_currentRow);
|
|
return &cursor->_result;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief checks if the cursor is exhausted - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool HasNextSkiplistCollectionCursor (TRI_rc_cursor_t* c) {
|
|
collection_cursor_t* cursor;
|
|
TRI_skiplist_iterator_t* iterator;
|
|
|
|
cursor = (collection_cursor_t*)(c);
|
|
if (cursor == NULL) {
|
|
return false;
|
|
}
|
|
|
|
iterator = (TRI_skiplist_iterator_t*)(cursor->_iterator);
|
|
if (iterator == NULL) {
|
|
return false;
|
|
}
|
|
|
|
return (iterator->_hasNext(iterator));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief checks if the cursor associated with is exhausted
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool HasNextCollectionCursor (TRI_rc_cursor_t* c) {
|
|
collection_cursor_t* cursor;
|
|
|
|
cursor = (collection_cursor_t*) c;
|
|
|
|
return cursor->_currentRow < cursor->_length;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief frees a cursor - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeCollectionCursor (TRI_rc_cursor_t* c) {
|
|
collection_cursor_t* cursor;
|
|
TRI_qry_select_t* slct;
|
|
size_t i;
|
|
|
|
cursor = (collection_cursor_t*) c;
|
|
|
|
// free result set
|
|
if (cursor->_result._selectResult != NULL) {
|
|
cursor->_result._selectResult->free(cursor->_result._selectResult);
|
|
}
|
|
|
|
// free select
|
|
slct = cursor->base._select;
|
|
slct->free(slct);
|
|
|
|
TRI_RemoveCollectionsCursor(&cursor->base);
|
|
|
|
TRI_DestroyVectorPointer(&cursor->base._containers);
|
|
|
|
TRI_FreeContextQuery(cursor->base._context);
|
|
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, cursor->_documents);
|
|
|
|
if (cursor->_augmentions != NULL) {
|
|
for (i = 0; i < cursor->_length; ++i) {
|
|
TRI_DestroyJson(TRI_UNKNOWN_MEM_ZONE, &cursor->_augmentions[i]);
|
|
}
|
|
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, cursor->_augmentions);
|
|
}
|
|
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, cursor);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief apply a skip and limit on the result set
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool TransformDataSkipLimit (TRI_rc_result_t* result,
|
|
TRI_voc_size_t skip,
|
|
TRI_voc_ssize_t limit) {
|
|
|
|
TRI_select_result_t* _result = result->_selectResult;
|
|
|
|
// return nothing
|
|
if (limit == 0 || _result->_numRows <= skip) {
|
|
return TRI_SliceSelectResult(_result, 0, 0);
|
|
}
|
|
|
|
// positive limit, skip and slice from front
|
|
if (limit > 0) {
|
|
if (_result->_numRows - skip < limit) {
|
|
return TRI_SliceSelectResult(_result, skip, _result->_numRows - skip);
|
|
}
|
|
|
|
return TRI_SliceSelectResult(_result, skip, limit);
|
|
}
|
|
|
|
// negative limit, slice from back
|
|
if (_result->_numRows - skip < -limit) {
|
|
return TRI_SliceSelectResult(_result, 0, _result->_numRows - skip);
|
|
}
|
|
|
|
return TRI_SliceSelectResult(_result, _result->_numRows - skip + limit, -limit);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- WHERE BOOLEAN
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief clones a query condition for constant conditions - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_qry_where_t* CloneQueryWhereBoolean (TRI_qry_where_t const* w) {
|
|
TRI_qry_where_boolean_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_boolean_t*) w;
|
|
|
|
return TRI_CreateQueryWhereBoolean(whereClause->_value);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief frees a query condition for constant conditions - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeQueryWhereBoolean (TRI_qry_where_t* w) {
|
|
TRI_qry_where_boolean_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_boolean_t*) w;
|
|
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, whereClause);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- constructors and destructors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a query condition for constant conditions - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_qry_where_t* TRI_CreateQueryWhereBoolean (bool where) {
|
|
TRI_qry_where_boolean_t* result;
|
|
|
|
result = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_qry_where_boolean_t), false);
|
|
|
|
result->base.base._type = TRI_QRY_WHERE_BOOLEAN;
|
|
|
|
result->base.base.clone = CloneQueryWhereBoolean;
|
|
result->base.base.free = FreeQueryWhereBoolean;
|
|
|
|
result->_value = where;
|
|
|
|
return &result->base.base;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- WHERE PRIMARY INDEX WITH CONSTANT
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief clones a query condition using the primary index and a constant - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_qry_where_t* CloneQueryWherePrimaryConstant (TRI_qry_where_t const* w) {
|
|
TRI_qry_where_primary_const_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_primary_const_t*) w;
|
|
|
|
return TRI_CreateQueryWherePrimaryConstant(whereClause->_did);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief frees a query condition using the primary index and a constant - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeQueryWherePrimaryConstant (TRI_qry_where_t* w) {
|
|
TRI_qry_where_primary_const_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_primary_const_t*) w;
|
|
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, whereClause);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns document identifier for a constant - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_voc_did_t DidQueryWherePrimaryConstant (TRI_qry_where_primary_t* w,
|
|
TRI_rc_context_t* context) {
|
|
TRI_qry_where_primary_const_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_primary_const_t*) w;
|
|
|
|
return whereClause->_did;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- constructors and destructors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a query condition using the primary index and a constant - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_qry_where_t* TRI_CreateQueryWherePrimaryConstant (TRI_voc_did_t did) {
|
|
TRI_qry_where_primary_const_t* result;
|
|
|
|
result = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_qry_where_primary_const_t), false);
|
|
|
|
result->base.base._type = TRI_QRY_WHERE_PRIMARY_CONSTANT;
|
|
|
|
result->base.base.clone = CloneQueryWherePrimaryConstant;
|
|
result->base.base.free = FreeQueryWherePrimaryConstant;
|
|
|
|
result->base.did = DidQueryWherePrimaryConstant;
|
|
|
|
result->_did = did;
|
|
|
|
return &result->base.base;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- WHERE GENERAL
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief clones a query condition for general, JavaScript conditions - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_qry_where_t* CloneQueryWhereGeneral (TRI_qry_where_t const* w) {
|
|
TRI_qry_where_general_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_general_t*) w;
|
|
|
|
return TRI_CreateQueryWhereGeneral(whereClause->_code);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief frees a query condition for general, JavaScript conditions - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeQueryWhereGeneral (TRI_qry_where_t* w) {
|
|
TRI_qry_where_general_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_general_t*) w;
|
|
|
|
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, whereClause->_code);
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, whereClause);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- constructors and destructors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a query condition for general, JavaScript conditions - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_qry_where_t* TRI_CreateQueryWhereGeneral (char const* clause) {
|
|
TRI_qry_where_general_t* result;
|
|
|
|
result = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_qry_where_general_t), false);
|
|
|
|
result->base.base._type = TRI_QRY_WHERE_GENERAL;
|
|
|
|
result->base.base.clone = CloneQueryWhereGeneral;
|
|
result->base.base.free = FreeQueryWhereGeneral;
|
|
|
|
//result->base.checkCondition = CheckConditionWhereGeneral;
|
|
|
|
result->_code = TRI_DuplicateString(clause);
|
|
|
|
return &result->base.base;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- WHERE WITHIN GEO INDEX
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief clones a query condition using the geo index and constants - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_qry_where_t* CloneQueryWhereHashConstant (const TRI_qry_where_t* w) {
|
|
TRI_qry_where_hash_const_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_hash_const_t*) w;
|
|
|
|
return TRI_CreateQueryWhereHashConstant(whereClause->_iid, whereClause->_parameters);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief clones a query condition - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_qry_where_t* CloneQueryWherePQConstant (const TRI_qry_where_t* w) {
|
|
TRI_qry_where_priorityqueue_const_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_priorityqueue_const_t*) w;
|
|
|
|
return TRI_CreateQueryWherePQConstant(whereClause->_iid, whereClause->_parameters);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_qry_where_t* CloneQueryWhereSkiplistConstant (const TRI_qry_where_t* w) {
|
|
const TRI_qry_where_skiplist_const_t* whereClause;
|
|
|
|
whereClause = (const TRI_qry_where_skiplist_const_t*) w;
|
|
|
|
return TRI_CreateQueryWhereSkiplistConstant(whereClause->_iid, whereClause->_operator);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static TRI_qry_where_t* CloneQueryWhereWithinConstant (const TRI_qry_where_t* w) {
|
|
const TRI_qry_where_within_const_t* whereClause;
|
|
|
|
whereClause = (const TRI_qry_where_within_const_t*) w;
|
|
|
|
return TRI_CreateQueryWhereWithinConstant(whereClause->base._iid,
|
|
whereClause->base._nameDistance,
|
|
whereClause->_coordinates[0],
|
|
whereClause->_coordinates[1],
|
|
whereClause->_radius);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief frees a query condition using the geo index and constants - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeQueryWhereHashConstant (TRI_qry_where_t* w) {
|
|
TRI_qry_where_hash_const_t* whereClause;
|
|
whereClause = (TRI_qry_where_hash_const_t*) w;
|
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, whereClause->_parameters);
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, whereClause);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief frees a query condition priority queue - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeQueryWherePQConstant (TRI_qry_where_t* w) {
|
|
TRI_qry_where_priorityqueue_const_t* whereClause;
|
|
whereClause = (TRI_qry_where_priorityqueue_const_t*) w;
|
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, whereClause->_parameters);
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, whereClause);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeQueryWhereSkiplistConstant (TRI_qry_where_t* w) {
|
|
TRI_qry_where_skiplist_const_t* whereClause;
|
|
whereClause = (TRI_qry_where_skiplist_const_t*) w;
|
|
TRI_FreeSLOperator(whereClause->_operator);
|
|
}
|
|
|
|
static void FreeQueryWhereWithinConstant (TRI_qry_where_t* w) {
|
|
TRI_qry_where_within_const_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_within_const_t*) w;
|
|
|
|
if (whereClause->base._nameDistance != NULL) {
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, whereClause->base._nameDistance);
|
|
}
|
|
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, whereClause);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns the latitude and longitude for constants - probably DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static double* CoordinatesQueryWhereWithinConstant (TRI_qry_where_within_t* w,
|
|
TRI_rc_context_t* context) {
|
|
TRI_qry_where_within_const_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_within_const_t*) w;
|
|
|
|
return whereClause->_coordinates;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns the radius for constants - probably DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static double RadiusQueryWhereWithinConstant (TRI_qry_where_within_t* w,
|
|
TRI_rc_context_t* context) {
|
|
TRI_qry_where_within_const_t* whereClause;
|
|
|
|
whereClause = (TRI_qry_where_within_const_t*) w;
|
|
|
|
return whereClause->_radius;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- constructors and destructors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a query condition using the geo index and a constant - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_qry_where_t* TRI_CreateQueryWhereWithinConstant (TRI_idx_iid_t iid,
|
|
char const* nameDistance,
|
|
double latitiude,
|
|
double longitude,
|
|
double radius) {
|
|
TRI_qry_where_within_const_t* result;
|
|
|
|
result = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_qry_where_within_const_t), false);
|
|
|
|
result->base.base._type = TRI_QRY_WHERE_WITHIN_CONSTANT;
|
|
|
|
result->base.base.clone = CloneQueryWhereWithinConstant;
|
|
result->base.base.free = FreeQueryWhereWithinConstant;
|
|
|
|
result->base.coordinates = CoordinatesQueryWhereWithinConstant;
|
|
result->base.radius = RadiusQueryWhereWithinConstant;
|
|
|
|
result->base._iid = iid;
|
|
result->base._nameDistance = nameDistance == NULL ? NULL : TRI_DuplicateString(nameDistance);
|
|
|
|
result->_coordinates[0] = latitiude;
|
|
result->_coordinates[1] = longitude;
|
|
result->_radius = radius;
|
|
|
|
return &result->base.base;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a query condition for hash index - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_qry_where_t* TRI_CreateQueryWhereHashConstant (TRI_idx_iid_t iid, TRI_json_t* parameters) {
|
|
TRI_qry_where_hash_const_t* result;
|
|
result = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_qry_where_hash_const_t), false);
|
|
result->base._type = TRI_QRY_WHERE_HASH_CONSTANT;
|
|
result->base.clone = CloneQueryWhereHashConstant;
|
|
result->base.free = FreeQueryWhereHashConstant;
|
|
result->_iid = iid;
|
|
result->_parameters = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, parameters);
|
|
return &result->base;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a query condition for priority queue index - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_qry_where_t* TRI_CreateQueryWherePQConstant (TRI_idx_iid_t iid, TRI_json_t* parameters) {
|
|
TRI_qry_where_priorityqueue_const_t* result;
|
|
result = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_qry_where_priorityqueue_const_t), false);
|
|
result->base._type = TRI_QRY_WHERE_PRIORITY_QUEUE_CONSTANT;
|
|
result->base.clone = CloneQueryWherePQConstant;
|
|
result->base.free = FreeQueryWherePQConstant;
|
|
result->_iid = iid;
|
|
result->_parameters = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, parameters);
|
|
return &result->base;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a query condition for skiplist index - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
TRI_qry_where_t* TRI_CreateQueryWhereSkiplistConstant (TRI_idx_iid_t iid, TRI_sl_operator_t* slOperator) {
|
|
TRI_qry_where_skiplist_const_t* result;
|
|
|
|
result = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_qry_where_skiplist_const_t), false);
|
|
result->base._type = TRI_QRY_WHERE_SKIPLIST_CONSTANT;
|
|
result->base.clone = CloneQueryWhereSkiplistConstant;
|
|
result->base.free = FreeQueryWhereSkiplistConstant;
|
|
result->_iid = iid;
|
|
result->_operator = CopySLOperator(slOperator);
|
|
return &result->base;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- QUERY
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- constructors and destructors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool InitCollectionsQuery (TRI_query_t* query) {
|
|
TRI_vocbase_col_t* collection;
|
|
size_t i;
|
|
|
|
assert(query->_vocbase);
|
|
|
|
for (i = 0 ; i < query->_joins->_parts._length; i++) {
|
|
TRI_join_part_t* part;
|
|
|
|
part = (TRI_join_part_t*) query->_joins->_parts._buffer[i];
|
|
assert(part->_collection == NULL);
|
|
assert(part->_alias);
|
|
collection = TRI_UseCollectionByNameVocBase(query->_vocbase, part->_collectionName);
|
|
if (!collection) {
|
|
size_t j;
|
|
|
|
// unlock collections again
|
|
for (j = 0; j < i; ++j) {
|
|
part = (TRI_join_part_t*) query->_joins->_parts._buffer[j];
|
|
if (part->_collection) {
|
|
TRI_ReleaseCollectionVocBase(query->_vocbase, part->_collection);
|
|
part->_collection = NULL;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
part->_collection = collection;
|
|
if (part->_type == JOIN_TYPE_PRIMARY) {
|
|
query->_primary = collection->_collection;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a hash query - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_query_t* TRI_CreateHashQuery(const TRI_qry_where_t* whereStmt,
|
|
TRI_doc_collection_t* collection) {
|
|
TRI_query_t* query;
|
|
|
|
query = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_query_t), false);
|
|
if (!query) {
|
|
return NULL;
|
|
}
|
|
|
|
query->_where = ( whereStmt == NULL ? NULL : whereStmt->clone(whereStmt));
|
|
query->_skip = TRI_QRY_NO_SKIP;
|
|
query->_limit = TRI_QRY_NO_LIMIT;
|
|
query->_primary = collection;
|
|
query->_joins = NULL;
|
|
query->_select = TRI_CreateQuerySelectDocument();
|
|
return query;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a priority queue query - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_query_t* TRI_CreatePriorityQueueQuery(const TRI_qry_where_t* whereStmt,
|
|
TRI_doc_collection_t* collection) {
|
|
TRI_query_t* query;
|
|
|
|
query = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_query_t), false);
|
|
if (!query) {
|
|
return NULL;
|
|
}
|
|
|
|
query->_where = ( whereStmt == NULL ? NULL : whereStmt->clone(whereStmt));
|
|
query->_skip = TRI_QRY_NO_SKIP;
|
|
query->_limit = TRI_QRY_NO_LIMIT;
|
|
query->_primary = collection;
|
|
query->_joins = NULL;
|
|
query->_select = TRI_CreateQuerySelectDocument();
|
|
return query;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a skiplist query - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_query_t* TRI_CreateSkiplistQuery(const TRI_qry_where_t* whereStmt,
|
|
TRI_doc_collection_t* collection) {
|
|
TRI_query_t* query;
|
|
|
|
query = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_query_t), false);
|
|
if (!query) {
|
|
return NULL;
|
|
}
|
|
|
|
query->_where = ( whereStmt == NULL ? NULL : whereStmt->clone(whereStmt));
|
|
query->_skip = TRI_QRY_NO_SKIP;
|
|
query->_limit = TRI_QRY_NO_LIMIT;
|
|
query->_primary = collection;
|
|
query->_joins = NULL;
|
|
query->_select = TRI_CreateQuerySelectDocument();
|
|
return query;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a query - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_query_t* TRI_CreateQuery (TRI_vocbase_t* vocbase,
|
|
TRI_qry_select_t* selectStmt,
|
|
TRI_qry_where_t* whereStmt,
|
|
TRI_select_join_t* joins,
|
|
TRI_voc_size_t skip,
|
|
TRI_voc_ssize_t limit) {
|
|
TRI_query_t* query;
|
|
|
|
query = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_query_t), false);
|
|
if (!query) {
|
|
return NULL;
|
|
}
|
|
|
|
query->_vocbase = vocbase;
|
|
query->_select = selectStmt;
|
|
query->_where = whereStmt;
|
|
query->_joins = joins;
|
|
query->_skip = skip;
|
|
query->_limit = limit;
|
|
|
|
if (!InitCollectionsQuery(query)) {
|
|
TRI_FreeQuery(query);
|
|
return NULL;
|
|
}
|
|
|
|
return query;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief frees a query - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_FreeQuery (TRI_query_t* query) {
|
|
query->_select->free(query->_select);
|
|
|
|
if (query->_where != NULL) {
|
|
query->_where->free(query->_where);
|
|
}
|
|
if (query->_joins != NULL) {
|
|
TRI_join_part_t* part;
|
|
size_t i;
|
|
|
|
// unlock collections
|
|
for (i = 0; i < query->_joins->_parts._length; ++i) {
|
|
part = (TRI_join_part_t*) query->_joins->_parts._buffer[i];
|
|
if (part->_collection) {
|
|
TRI_ReleaseCollectionVocBase(query->_vocbase, part->_collection);
|
|
}
|
|
}
|
|
|
|
query->_joins->free(query->_joins);
|
|
}
|
|
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, query);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a context - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_rc_context_t* TRI_CreateContextQuery (TRI_query_t* query) {
|
|
TRI_rc_context_t* context;
|
|
TRI_qry_select_general_t* selectGeneral;
|
|
TRI_qry_where_general_t* whereGeneral;
|
|
|
|
context = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_rc_context_t), false);
|
|
|
|
context->_primary = query->_primary;
|
|
|
|
// check if we need a JavaScript execution context
|
|
if (query->_select->_type == TRI_QRY_SELECT_GENERAL) {
|
|
selectGeneral = (TRI_qry_select_general_t*) query->_select;
|
|
|
|
context->_selectClause = TRI_CreateExecutionContext(selectGeneral->_code);
|
|
|
|
if (context->_selectClause == NULL) {
|
|
TRI_FreeContextQuery(context);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (query->_where != NULL && query->_where->_type == TRI_QRY_WHERE_GENERAL) {
|
|
whereGeneral = (TRI_qry_where_general_t*) query->_where;
|
|
|
|
context->_whereClause = TRI_CreateExecutionContext(whereGeneral->_code);
|
|
|
|
if (context->_whereClause == NULL) {
|
|
TRI_FreeContextQuery(context);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return context;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief frees a context - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_FreeContextQuery (TRI_rc_context_t* context) {
|
|
if (context->_selectClause != NULL) {
|
|
TRI_FreeExecutionContext(context->_selectClause);
|
|
}
|
|
|
|
if (context->_whereClause != NULL) {
|
|
TRI_FreeExecutionContext(context->_whereClause);
|
|
}
|
|
|
|
if (context->_orderClause != NULL) {
|
|
TRI_FreeExecutionContext(context->_orderClause);
|
|
}
|
|
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, context);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- public methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup VocBase
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief read locks all collections of a query - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_ReadLockCollectionsQuery (TRI_query_t* query) {
|
|
TRI_join_part_t* part;
|
|
size_t i;
|
|
|
|
if (query->_joins == NULL) {
|
|
query->_primary->beginRead(query->_primary);
|
|
return;
|
|
}
|
|
|
|
|
|
// note: the same collection might be read-locked multiple times here
|
|
for (i = 0; i < query->_joins->_parts._length; i++) {
|
|
part = (TRI_join_part_t*) query->_joins->_parts._buffer[i];
|
|
assert(part->_collection);
|
|
part->_collection->_collection->beginRead(part->_collection->_collection);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief read unlocks all collections of a query - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_ReadUnlockCollectionsQuery (TRI_query_t* query) {
|
|
TRI_join_part_t* part;
|
|
size_t i;
|
|
|
|
if (query->_joins == NULL) {
|
|
query->_primary->endRead(query->_primary);
|
|
return;
|
|
}
|
|
|
|
// note: the same collection might be read-unlocked multiple times here
|
|
i = query->_joins->_parts._length;
|
|
while (i > 0) {
|
|
i--;
|
|
part = (TRI_join_part_t*) query->_joins->_parts._buffer[i];
|
|
assert(part->_collection);
|
|
part->_collection->_collection->endRead(part->_collection->_collection);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief adds a gc marker for all collections - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_AddCollectionsCursor (TRI_rc_cursor_t* cursor, TRI_query_t* query) {
|
|
TRI_join_part_t* part;
|
|
TRI_barrier_t* ce;
|
|
size_t i;
|
|
|
|
if (query->_joins == NULL) {
|
|
ce = TRI_CreateBarrierElement(&query->_primary->_barrierList);
|
|
TRI_PushBackVectorPointer(&cursor->_containers, ce);
|
|
return;
|
|
}
|
|
|
|
|
|
// note: the same collection might be added multiple times here
|
|
for (i = 0; i < query->_joins->_parts._length; i++) {
|
|
part = (TRI_join_part_t*) query->_joins->_parts._buffer[i];
|
|
assert(part->_collection);
|
|
ce = TRI_CreateBarrierElement(&part->_collection->_collection->_barrierList);
|
|
TRI_PushBackVectorPointer(&cursor->_containers, ce);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief removes the gc markers for all collections of a query - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TRI_RemoveCollectionsCursor (TRI_rc_cursor_t* cursor) {
|
|
size_t i;
|
|
|
|
for (i = 0; i < cursor->_containers._length; ++i) {
|
|
TRI_barrier_t* ce = cursor->_containers._buffer[i];
|
|
assert(ce);
|
|
TRI_FreeBarrier(ce);
|
|
}
|
|
|
|
cursor->_containers._length = 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief executes a query - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FilterDataHashQuery(collection_cursor_t* cursor,TRI_query_t* query,
|
|
TRI_rc_context_t* context) {
|
|
|
|
bool ok;
|
|
TRI_index_t* idx;
|
|
TRI_qry_where_hash_const_t* where;
|
|
TRI_sim_collection_t* collection;
|
|
HashIndexElements* hashElements;
|
|
TRI_doc_mptr_t* wtr;
|
|
TRI_doc_mptr_t* doc;
|
|
size_t j;
|
|
|
|
cursor->base._context = context;
|
|
cursor->base._select = query->_select->clone(query->_select);
|
|
|
|
cursor->base.next = NextHashCollectionCursor;
|
|
cursor->base.hasNext = HasNextCollectionCursor;
|
|
cursor->base.free = FreeCollectionCursor;
|
|
cursor->_result._selectResult = NULL;
|
|
|
|
cursor->_result._context = context;
|
|
cursor->_result._dataPtr = NULL;
|
|
|
|
cursor->base._select->toJavaScript = ToJavaScriptHashDocument;
|
|
|
|
TRI_InitVectorPointer(&cursor->base._containers, TRI_UNKNOWN_MEM_ZONE);
|
|
|
|
TRI_ReadLockCollectionsQuery(query);
|
|
|
|
TRI_AddCollectionsCursor(&cursor->base, query);
|
|
|
|
ok = (query->_primary->base._type == TRI_COL_TYPE_SIMPLE_DOCUMENT);
|
|
|
|
if (ok) {
|
|
where = (TRI_qry_where_hash_const_t*)(query->_where);
|
|
ok = (where->base._type == TRI_QRY_WHERE_HASH_CONSTANT);
|
|
}
|
|
|
|
if (ok) {
|
|
collection = (TRI_sim_collection_t*) query->_primary;
|
|
idx = TRI_IndexSimCollection(collection, where->_iid);
|
|
ok = (idx != NULL);
|
|
}
|
|
|
|
if (ok) {
|
|
hashElements = TRI_LookupHashIndex(idx,where->_parameters);
|
|
ok = (hashElements != NULL);
|
|
}
|
|
|
|
|
|
if (ok) {
|
|
cursor->_documents = (TRI_doc_mptr_t*) (TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_doc_mptr_t) * hashElements->_numElements, false));
|
|
|
|
wtr = cursor->_documents;
|
|
cursor->_length = 0;
|
|
cursor->base._matchedDocuments = 0;
|
|
cursor->_current = 0;
|
|
cursor->_currentRow = 0;
|
|
|
|
for (j = 0; j < hashElements->_numElements; ++j) {
|
|
// should not be necessary to check that documents have not been deleted
|
|
doc = (TRI_doc_mptr_t*)((hashElements->_elements[j]).data);
|
|
if (doc->_deletion) {
|
|
continue;
|
|
}
|
|
if (cursor->_current == 0) {
|
|
cursor->_current = wtr;
|
|
}
|
|
++cursor->base._matchedDocuments;
|
|
++cursor->_length;
|
|
*wtr = *doc;
|
|
++wtr;
|
|
}
|
|
|
|
|
|
if (hashElements->_elements != NULL) {
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, hashElements->_elements);
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, hashElements);
|
|
}
|
|
}
|
|
|
|
TRI_ReadUnlockCollectionsQuery(query);
|
|
|
|
if (!ok) {
|
|
cursor->_length = 0;
|
|
cursor->_currentRow = 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief executes a query - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FilterDataPQQuery(collection_cursor_t* cursor,TRI_query_t* query,
|
|
TRI_rc_context_t* context) {
|
|
|
|
bool ok;
|
|
TRI_index_t* idx;
|
|
TRI_qry_where_priorityqueue_const_t* where;
|
|
TRI_sim_collection_t* collection;
|
|
PQIndexElements* pqElements;
|
|
TRI_doc_mptr_t* wtr;
|
|
TRI_doc_mptr_t* doc;
|
|
size_t j;
|
|
|
|
cursor->base._context = context;
|
|
cursor->base._select = query->_select->clone(query->_select);
|
|
|
|
cursor->base.next = NextPQCollectionCursor;
|
|
cursor->base.hasNext = HasNextCollectionCursor;
|
|
cursor->base.free = FreeCollectionCursor;
|
|
cursor->_result._selectResult = NULL;
|
|
|
|
cursor->_result._context = context;
|
|
cursor->_result._dataPtr = NULL;
|
|
|
|
cursor->base._select->toJavaScript = ToJavaScriptPQDocument;
|
|
|
|
TRI_InitVectorPointer(&cursor->base._containers, TRI_UNKNOWN_MEM_ZONE);
|
|
|
|
TRI_ReadLockCollectionsQuery(query);
|
|
|
|
TRI_AddCollectionsCursor(&cursor->base, query);
|
|
|
|
|
|
ok = (query->_primary->base._type == TRI_COL_TYPE_SIMPLE_DOCUMENT);
|
|
|
|
if (ok) {
|
|
where = (TRI_qry_where_priorityqueue_const_t*)(query->_where);
|
|
ok = (where->base._type == TRI_QRY_WHERE_PRIORITY_QUEUE_CONSTANT);
|
|
}
|
|
|
|
if (ok) {
|
|
collection = (TRI_sim_collection_t*) query->_primary;
|
|
idx = TRI_IndexSimCollection(collection, where->_iid);
|
|
ok = (idx != NULL);
|
|
}
|
|
|
|
if (ok) {
|
|
pqElements = TRI_LookupPriorityQueueIndex(idx,where->_parameters);
|
|
ok = (pqElements != NULL);
|
|
}
|
|
|
|
|
|
if (ok) {
|
|
cursor->_documents = (TRI_doc_mptr_t*) (TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_doc_mptr_t) * pqElements->_numElements, false));
|
|
|
|
wtr = cursor->_documents;
|
|
cursor->_length = 0;
|
|
cursor->base._matchedDocuments = 0;
|
|
cursor->_current = 0;
|
|
cursor->_currentRow = 0;
|
|
|
|
for (j = 0; j < pqElements->_numElements; ++j) {
|
|
// should not be necessary to check that documents have not been deleted
|
|
doc = (TRI_doc_mptr_t*)((pqElements->_elements[j]).data);
|
|
if (doc->_deletion) {
|
|
continue;
|
|
}
|
|
if (cursor->_current == 0) {
|
|
cursor->_current = wtr;
|
|
}
|
|
++cursor->base._matchedDocuments;
|
|
++cursor->_length;
|
|
*wtr = *doc;
|
|
++wtr;
|
|
}
|
|
|
|
|
|
if (pqElements->_elements != NULL) {
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, pqElements->_elements);
|
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, pqElements);
|
|
}
|
|
}
|
|
|
|
TRI_ReadUnlockCollectionsQuery(query);
|
|
|
|
if (!ok) {
|
|
cursor->_length = 0;
|
|
cursor->_currentRow = 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FilterDataSLQuery(collection_cursor_t* cursor,TRI_query_t* query,
|
|
TRI_rc_context_t* context) {
|
|
|
|
bool ok;
|
|
TRI_index_t* idx;
|
|
TRI_qry_where_skiplist_const_t* where;
|
|
TRI_sim_collection_t* collection;
|
|
TRI_skiplist_iterator_t* skiplistIterator;
|
|
|
|
cursor->base._context = context;
|
|
cursor->base._select = query->_select->clone(query->_select);
|
|
|
|
cursor->base.next = NextSkiplistCollectionCursor;
|
|
cursor->base.hasNext = HasNextSkiplistCollectionCursor;
|
|
cursor->base.free = FreeCollectionCursor;
|
|
cursor->_result._selectResult = NULL;
|
|
|
|
cursor->_result._context = context;
|
|
cursor->_result._dataPtr = NULL;
|
|
|
|
cursor->base._select->toJavaScript = ToJavaScriptHashDocument;
|
|
|
|
TRI_InitVectorPointer(&cursor->base._containers, TRI_UNKNOWN_MEM_ZONE);
|
|
|
|
TRI_ReadLockCollectionsQuery(query);
|
|
|
|
TRI_AddCollectionsCursor(&cursor->base, query);
|
|
|
|
ok = (query->_primary->base._type == TRI_COL_TYPE_SIMPLE_DOCUMENT);
|
|
|
|
if (ok) {
|
|
where = (TRI_qry_where_skiplist_const_t*)(query->_where);
|
|
ok = (where->base._type == TRI_QRY_WHERE_SKIPLIST_CONSTANT);
|
|
}
|
|
|
|
if (ok) {
|
|
collection = (TRI_sim_collection_t*) query->_primary;
|
|
idx = TRI_IndexSimCollection(collection, where->_iid);
|
|
ok = (idx != NULL);
|
|
}
|
|
|
|
if (ok) {
|
|
skiplistIterator = TRI_LookupSkiplistIndex(idx,where->_operator);
|
|
ok = (skiplistIterator != NULL);
|
|
}
|
|
|
|
|
|
if (ok) {
|
|
cursor->_documents = NULL;
|
|
cursor->_length = 0;
|
|
cursor->base._matchedDocuments = 0;
|
|
cursor->_current = 0;
|
|
cursor->_currentRow = 0;
|
|
cursor->_iterator = skiplistIterator;
|
|
}
|
|
|
|
TRI_ReadUnlockCollectionsQuery(query);
|
|
|
|
if (!ok) {
|
|
cursor->_length = 0;
|
|
cursor->_currentRow = 0;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief executes a query - DEPRECATED
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_rc_cursor_t* TRI_ExecuteQueryAql (TRI_query_t* query, TRI_rc_context_t* context) {
|
|
TRI_qry_where_t* where;
|
|
TRI_voc_size_t skip;
|
|
TRI_voc_ssize_t limit;
|
|
TRI_select_result_t* selectResult;
|
|
collection_cursor_t* cursor;
|
|
bool applyPostSkipLimit;
|
|
bool emptyQuery;
|
|
|
|
skip = query->_skip;
|
|
limit = query->_limit;
|
|
applyPostSkipLimit = false;
|
|
|
|
if (limit < 0) {
|
|
limit = TRI_QRY_NO_LIMIT;
|
|
skip = 0;
|
|
applyPostSkipLimit = true;
|
|
}
|
|
|
|
// set up where condition
|
|
emptyQuery = false;
|
|
where = 0;
|
|
|
|
if (query->_where != NULL) {
|
|
|
|
where = query->_where;
|
|
|
|
if (where->_type == TRI_QRY_WHERE_BOOLEAN) {
|
|
TRI_qry_where_boolean_t* b;
|
|
b = (TRI_qry_where_boolean_t*) where;
|
|
if (!b->_value) {
|
|
emptyQuery = true;
|
|
}
|
|
where = NULL;
|
|
}
|
|
|
|
else if (where->_type == TRI_QRY_WHERE_PRIMARY_CONSTANT) {
|
|
assert(false);
|
|
}
|
|
|
|
else if (where->_type == TRI_QRY_WHERE_WITHIN_CONSTANT) {
|
|
assert(false);
|
|
}
|
|
|
|
else if (where->_type == TRI_QRY_WHERE_HASH_CONSTANT) {
|
|
cursor = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(collection_cursor_t), false);
|
|
if (cursor == NULL) {
|
|
return NULL;
|
|
}
|
|
FilterDataHashQuery(cursor,query,context);
|
|
return &cursor->base;
|
|
}
|
|
|
|
else if (where->_type == TRI_QRY_WHERE_PRIORITY_QUEUE_CONSTANT) {
|
|
cursor = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(collection_cursor_t), false);
|
|
if (cursor == NULL) {
|
|
return NULL;
|
|
}
|
|
FilterDataPQQuery(cursor,query,context);
|
|
return &cursor->base;
|
|
}
|
|
|
|
else if (where->_type == TRI_QRY_WHERE_SKIPLIST_CONSTANT) {
|
|
cursor = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(collection_cursor_t), false);
|
|
if (cursor == NULL) {
|
|
return NULL;
|
|
}
|
|
FilterDataSLQuery(cursor,query,context);
|
|
return &cursor->base;
|
|
}
|
|
}
|
|
|
|
// create a select result container for the joins
|
|
selectResult = TRI_JoinSelectResultX(query->_vocbase, query->_joins);
|
|
if (!selectResult) {
|
|
return NULL;
|
|
}
|
|
|
|
// .............................................................................
|
|
// construct a collection subset
|
|
// .............................................................................
|
|
|
|
cursor = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(collection_cursor_t), false);
|
|
if (!cursor) {
|
|
selectResult->free(selectResult);
|
|
return NULL;
|
|
}
|
|
cursor->base._context = context;
|
|
cursor->base._select = query->_select->clone(query->_select);
|
|
cursor->base.next = NextCollectionCursor;
|
|
cursor->base.hasNext = HasNextCollectionCursor;
|
|
cursor->base.free = FreeCollectionCursor;
|
|
cursor->_result._selectResult = selectResult;
|
|
cursor->_result._dataPtr = NULL;
|
|
cursor->_result._context = context;
|
|
cursor->_result._augmention._type = TRI_JSON_UNUSED;
|
|
|
|
TRI_InitVectorPointer(&cursor->base._containers, TRI_UNKNOWN_MEM_ZONE);
|
|
|
|
// .............................................................................
|
|
// inside a read transaction
|
|
// .............................................................................
|
|
|
|
TRI_ReadLockCollectionsQuery(query);
|
|
TRI_AddCollectionsCursor(&cursor->base, query);
|
|
|
|
// Execute joins
|
|
if (!emptyQuery) {
|
|
TRI_ExecuteJoinsX(selectResult, query->_joins, where, context, skip, limit);
|
|
}
|
|
|
|
TRI_ReadUnlockCollectionsQuery(query);
|
|
|
|
// .............................................................................
|
|
// outside a read transaction
|
|
// .............................................................................
|
|
|
|
// apply a negative limit or a limit after ordering
|
|
if (applyPostSkipLimit) {
|
|
TransformDataSkipLimit(&cursor->_result, query->_skip, query->_limit);
|
|
}
|
|
|
|
// adjust cursor length
|
|
cursor->_length = selectResult->_numRows;
|
|
cursor->_currentRow = 0;
|
|
|
|
return &cursor->base;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Local Variables:
|
|
// mode: outline-minor
|
|
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
|
// End:
|
|
|