mirror of https://gitee.com/bigwinds/arangodb
added limited AQL support for bit indexes
This commit is contained in:
parent
d632fb820b
commit
8847d87580
|
@ -0,0 +1,35 @@
|
|||
> curl --data @- -X POST --dump - http://localhost:8529/_api/index?collection=109061392
|
||||
{ "type" : "skiplist", "unique" : false, "fields" : [ "x", [0,1,[]], "y", ["a","b",[]] ] }
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
content-type: application/json
|
||||
|
||||
{
|
||||
"fields": [
|
||||
[
|
||||
"x",
|
||||
[
|
||||
0,
|
||||
1,
|
||||
[
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"y",
|
||||
[
|
||||
"a",
|
||||
"b",
|
||||
[
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"id": "109061392/173166777",
|
||||
"type": "bitarray",
|
||||
"isNewlyCreated": true,
|
||||
"unique": false,
|
||||
"undefined": false,
|
||||
"code": 201,
|
||||
"error": false
|
||||
}
|
|
@ -1088,6 +1088,88 @@ static void GenerateSkiplistAccess (TRI_aql_codegen_js_t* const generator,
|
|||
ScopeOutput(generator, " })");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate code for bitarray access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void GenerateBitarrayAccess (TRI_aql_codegen_js_t* const generator,
|
||||
const TRI_aql_index_t* const idx,
|
||||
const TRI_aql_collection_t* const collection,
|
||||
const char* const collectionName) {
|
||||
size_t i, n;
|
||||
|
||||
n = idx->_fieldAccesses->_length;
|
||||
assert(n >= 1);
|
||||
|
||||
|
||||
if (n == 1) {
|
||||
// peek at first element and check if it is a list access
|
||||
TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) TRI_AtVectorPointer(idx->_fieldAccesses, 0);
|
||||
|
||||
if (fieldAccess->_type == TRI_AQL_ACCESS_LIST) {
|
||||
assert(false);
|
||||
ScopeOutput(generator, "AHUACATL_GET_DOCUMENTS_BITARRAY_LIST('");
|
||||
ScopeOutput(generator, collectionName);
|
||||
ScopeOutput(generator, "', ");
|
||||
ScopeOutputIndexId(generator, collection, idx);
|
||||
ScopeOutput(generator, ", ");
|
||||
ScopeOutputQuoted2(generator, fieldAccess->_fullName + fieldAccess->_variableNameLength + 1);
|
||||
ScopeOutput(generator, ", ");
|
||||
ScopeOutputJson(generator, fieldAccess->_value._value);
|
||||
ScopeOutput(generator, ")");
|
||||
return;
|
||||
}
|
||||
// fall through to other access types
|
||||
}
|
||||
|
||||
ScopeOutput(generator, "AHUACATL_GET_DOCUMENTS_BITARRAY('");
|
||||
ScopeOutput(generator, collectionName);
|
||||
ScopeOutput(generator, "', ");
|
||||
ScopeOutputIndexId(generator, collection, idx);
|
||||
ScopeOutput(generator, ", { \"==\" : {"); // only support the equality operator for now
|
||||
|
||||
|
||||
// ..................................................................................
|
||||
// Construct the javascript object which will eventually be used to generate
|
||||
// the index operator. The object is in the form: {"==": {"x":0}}
|
||||
// ..................................................................................
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) TRI_AtVectorPointer(idx->_fieldAccesses, i);
|
||||
|
||||
// ................................................................................
|
||||
// Only implement equality operator for now
|
||||
// ................................................................................
|
||||
|
||||
ScopeOutputQuoted2(generator, fieldAccess->_fullName + fieldAccess->_variableNameLength + 1);
|
||||
ScopeOutput(generator, " : ");
|
||||
|
||||
switch (fieldAccess->_type) {
|
||||
|
||||
case TRI_AQL_ACCESS_EXACT: {
|
||||
ScopeOutputJson(generator, fieldAccess->_value._value);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRI_AQL_ACCESS_REFERENCE: {
|
||||
ProcessAttributeAccess(generator, fieldAccess->_value._reference._ref._node);
|
||||
}
|
||||
|
||||
default: {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (i < (n-1)) {
|
||||
ScopeOutput(generator, ", ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ScopeOutput(generator, "} })");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate code for a reference (the name of a variable)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1287,7 +1369,6 @@ static void ProcessCollectionHinted (TRI_aql_codegen_js_t* const generator,
|
|||
case TRI_IDX_TYPE_GEO2_INDEX:
|
||||
case TRI_IDX_TYPE_PRIORITY_QUEUE_INDEX:
|
||||
case TRI_IDX_TYPE_CAP_CONSTRAINT:
|
||||
case TRI_IDX_TYPE_BITARRAY_INDEX:
|
||||
// these index types are not yet supported
|
||||
generator->_errorCode = TRI_ERROR_INTERNAL;
|
||||
break;
|
||||
|
@ -1303,6 +1384,11 @@ static void ProcessCollectionHinted (TRI_aql_codegen_js_t* const generator,
|
|||
case TRI_IDX_TYPE_SKIPLIST_INDEX:
|
||||
GenerateSkiplistAccess(generator, hint->_index, hint->_collection, collectionName);
|
||||
break;
|
||||
|
||||
case TRI_IDX_TYPE_BITARRAY_INDEX: {
|
||||
GenerateBitarrayAccess(generator, hint->_index, hint->_collection, collectionName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -335,6 +335,7 @@ bool TRI_BindQueryContextAql (TRI_aql_context_t* const context,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_OptimiseQueryContextAql (TRI_aql_context_t* const context) {
|
||||
|
||||
// do some basic optimisations in the AST
|
||||
if (!TRI_OptimiseAql(context)) {
|
||||
// constant folding failed
|
||||
|
|
|
@ -104,7 +104,7 @@ static TRI_aql_index_t* PickIndex (TRI_aql_context_t* const context,
|
|||
TRI_aql_index_t* pickedIndex,
|
||||
const TRI_index_t* const idx,
|
||||
TRI_vector_pointer_t* fieldAccesses) {
|
||||
bool isBetter;
|
||||
bool isBetter = false;
|
||||
|
||||
assert(idx);
|
||||
assert(fieldAccesses);
|
||||
|
@ -121,21 +121,98 @@ static TRI_aql_index_t* PickIndex (TRI_aql_context_t* const context,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// If we do not have an index yet, then this index will do. As has been said
|
||||
// before 'any index is better than none'
|
||||
// ...........................................................................
|
||||
|
||||
if (pickedIndex->_idx == NULL) {
|
||||
// any index is better than none
|
||||
pickedIndex->_idx = (TRI_index_t*) idx;
|
||||
pickedIndex->_fieldAccesses = TRI_CopyVectorPointer(TRI_UNKNOWN_MEM_ZONE, fieldAccesses);
|
||||
return pickedIndex;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// We have previously selected an index, if it happens to be the primary then
|
||||
// we stick with it.
|
||||
// ...........................................................................
|
||||
|
||||
if (pickedIndex->_idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX) {
|
||||
return pickedIndex;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Now go through the various possibilities if we have not located something
|
||||
// better.
|
||||
// ...........................................................................
|
||||
|
||||
if ( (isBetter == false) && (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX) ) {
|
||||
// .........................................................................
|
||||
// If we can used the primary index, then this is better than any other
|
||||
// index so use it.
|
||||
// .........................................................................
|
||||
isBetter = true;
|
||||
}
|
||||
else {
|
||||
isBetter = idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX || // primary index is better than any others
|
||||
(idx->_type == TRI_IDX_TYPE_HASH_INDEX && pickedIndex->_idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) || // hash is better than skiplist
|
||||
(idx->_unique && !pickedIndex->_idx->_unique) || // unique indexes are better than non-unique ones
|
||||
(fieldAccesses->_length < pickedIndex->_fieldAccesses->_length && idx->_unique) || // shorter indexes are better if unique
|
||||
(fieldAccesses->_length > pickedIndex->_fieldAccesses->_length && !idx->_unique); // longer indexes are better if non-unique
|
||||
|
||||
// if we have already picked the primary index, we won't overwrite it with any other index
|
||||
isBetter &= (pickedIndex->_idx->_type != TRI_IDX_TYPE_PRIMARY_INDEX);
|
||||
|
||||
if ( (isBetter == false) && (idx->_type == TRI_IDX_TYPE_HASH_INDEX) ) {
|
||||
// .........................................................................
|
||||
// If the index type is a hash index, use this -- but only if we have NOT
|
||||
// located something better BEFORE.
|
||||
// .........................................................................
|
||||
isBetter = true;
|
||||
}
|
||||
|
||||
|
||||
if ( (isBetter == false) && (idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) &&
|
||||
(pickedIndex->_idx->_type != TRI_IDX_TYPE_HASH_INDEX) ) {
|
||||
// .........................................................................
|
||||
// If the index type is a skiplist index, use this -- but only if we have NOT
|
||||
// located something better BEFORE.
|
||||
// .........................................................................
|
||||
isBetter = true;
|
||||
}
|
||||
|
||||
|
||||
if ( (isBetter == false) && (idx->_type == TRI_IDX_TYPE_BITARRAY_INDEX) &&
|
||||
(pickedIndex->_idx->_type != TRI_IDX_TYPE_HASH_INDEX) &&
|
||||
(pickedIndex->_idx->_type != TRI_IDX_TYPE_SKIPLIST_INDEX) ) {
|
||||
// .........................................................................
|
||||
// If the index type is a bitarray index, use this -- but only if we have NOT
|
||||
// located something better BEFORE.
|
||||
// .........................................................................
|
||||
isBetter = true;
|
||||
}
|
||||
|
||||
|
||||
if ( (isBetter == false) && (idx->_unique == true) && (pickedIndex->_idx->_unique == false) ) {
|
||||
// .........................................................................
|
||||
// If the index is a unique one and the picked index is non-unique, then
|
||||
// replace it with the unique overriding the preferences above. E.g. if
|
||||
// we have a non-unique hash index (which we have chosen) and now we are
|
||||
// testing a unique skiplist, replace it with the skiplist.
|
||||
// .........................................................................
|
||||
isBetter = true;
|
||||
}
|
||||
|
||||
|
||||
if ( (isBetter == false) &&
|
||||
(fieldAccesses->_length < pickedIndex->_fieldAccesses->_length ) &&
|
||||
(idx->_unique == true) ) {
|
||||
isBetter = true;
|
||||
}
|
||||
|
||||
|
||||
if ( (isBetter == false) &&
|
||||
(fieldAccesses->_length > pickedIndex->_fieldAccesses->_length ) &&
|
||||
(idx->_unique == false) ) {
|
||||
isBetter = true;
|
||||
}
|
||||
|
||||
|
||||
if (isBetter) {
|
||||
if (pickedIndex->_fieldAccesses != NULL) {
|
||||
TRI_FreeVectorPointer(TRI_UNKNOWN_MEM_ZONE, pickedIndex->_fieldAccesses);
|
||||
|
@ -207,12 +284,12 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
|
|||
case TRI_IDX_TYPE_GEO2_INDEX:
|
||||
case TRI_IDX_TYPE_PRIORITY_QUEUE_INDEX:
|
||||
case TRI_IDX_TYPE_CAP_CONSTRAINT:
|
||||
case TRI_IDX_TYPE_BITARRAY_INDEX:
|
||||
// ignore all these index types for now
|
||||
continue;
|
||||
case TRI_IDX_TYPE_PRIMARY_INDEX:
|
||||
case TRI_IDX_TYPE_HASH_INDEX:
|
||||
case TRI_IDX_TYPE_SKIPLIST_INDEX:
|
||||
case TRI_IDX_TYPE_BITARRAY_INDEX:
|
||||
// these indexes are valid candidates
|
||||
break;
|
||||
}
|
||||
|
@ -239,6 +316,7 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
|
|||
for (k = 0; k < candidates->_length; ++k) {
|
||||
TRI_aql_field_access_t* candidate = (TRI_aql_field_access_t*) TRI_AtVectorPointer(candidates, k);
|
||||
|
||||
|
||||
if (candidate->_type == TRI_AQL_ACCESS_IMPOSSIBLE ||
|
||||
candidate->_type == TRI_AQL_ACCESS_ALL) {
|
||||
// wrong index type, doesn't help us at all
|
||||
|
@ -260,6 +338,7 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
|
|||
|
||||
TRI_PushBackVectorPointer(&matches, candidate);
|
||||
}
|
||||
|
||||
else if (idx->_type == TRI_IDX_TYPE_HASH_INDEX) {
|
||||
if (!IsExactCandidate(candidate)) {
|
||||
// wrong access type for hash index
|
||||
|
@ -273,6 +352,21 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
|
|||
|
||||
TRI_PushBackVectorPointer(&matches, candidate);
|
||||
}
|
||||
|
||||
else if (idx->_type == TRI_IDX_TYPE_BITARRAY_INDEX) {
|
||||
if (!IsExactCandidate(candidate)) {
|
||||
// wrong access type for hash index
|
||||
continue;
|
||||
}
|
||||
|
||||
if (candidate->_type == TRI_AQL_ACCESS_LIST) {
|
||||
// we found a list, but the index covers multiple attributes. that means we cannot use list access
|
||||
continue;
|
||||
}
|
||||
|
||||
TRI_PushBackVectorPointer(&matches, candidate);
|
||||
}
|
||||
|
||||
else if (idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
|
||||
bool candidateIsExact;
|
||||
|
||||
|
|
|
@ -96,8 +96,7 @@ typedef struct
|
|||
/* "points" lists the slotid of the points. This is */
|
||||
/* only used for a leaf pot. */
|
||||
/* =================================================== */
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
int LorLeaf;
|
||||
int RorPoints;
|
||||
GeoString middle;
|
||||
|
@ -125,8 +124,7 @@ typedef struct
|
|||
/* There is no provision at present for the index to */
|
||||
/* get smaller when the majority of points are deleted */
|
||||
/* =================================================== */
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
GeoIndexFixed fixed; /* fixed point data */
|
||||
int potct; /* pots allocated */
|
||||
int slotct; /* slots allocated */
|
||||
|
@ -369,8 +367,7 @@ int GeoIndexNewPot(GeoIx * gix)
|
|||
/* GeoString values of real (latitude, longitude) */
|
||||
/* points */
|
||||
/* =================================================== */
|
||||
GeoIndex * GeoIndex_new(void)
|
||||
{
|
||||
GeoIndex * GeoIndex_new(void) {
|
||||
GeoIx * gix;
|
||||
int i,j;
|
||||
double lat, lon, x, y, z;
|
||||
|
@ -576,8 +573,7 @@ GeoIndex * GeoIndex_new(void)
|
|||
/* objects that may have been pointed to by the user's */
|
||||
/* data pointers are (of course) not freed by this call*/
|
||||
/* =================================================== */
|
||||
void GeoIndex_free(GeoIndex * gi)
|
||||
{
|
||||
void GeoIndex_free(GeoIndex * gi) {
|
||||
GeoIx * gix;
|
||||
|
||||
if (gi == NULL) {
|
||||
|
@ -2275,6 +2271,7 @@ int GeoIndex_INDEXVALID(GeoIndex * gi)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int GeoIndex_assignMethod(void* methodHandle, TRI_index_method_assignment_type_e methodType) {
|
||||
|
||||
switch (methodType) {
|
||||
|
||||
case TRI_INDEX_METHOD_ASSIGNMENT_FREE : {
|
||||
|
|
|
@ -102,7 +102,7 @@ int GeoIndex_assignMethod (void*, TRI_index_method_assignment_type_e);
|
|||
// Allows one or more call back functions to be assigned
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int GeoIndexIndex_assignMethod (void*, TRI_index_method_assignment_type_e);
|
||||
int GeoIndex_assignMethod (void*, TRI_index_method_assignment_type_e);
|
||||
|
||||
GeoIndex * GeoIndex_new(void);
|
||||
void GeoIndex_free(GeoIndex * gi);
|
||||
|
|
|
@ -519,54 +519,51 @@ static TRI_index_operator_t* SetupConditionsBitarrayHelper (TRI_index_t* idx,
|
|||
// Check the various operator conditions
|
||||
// ........................................................................
|
||||
|
||||
|
||||
// ........................................................................
|
||||
// Check for an 'AND' condition. The following are acceptable: '&', '&&' 'and'
|
||||
// ........................................................................
|
||||
if (condition->HasOwnProperty(v8::String::New("&"))) {
|
||||
operatorType = TRI_AND_INDEX_OPERATOR;
|
||||
value = condition->Get(v8::String::New("&"));
|
||||
}
|
||||
else if (condition->HasOwnProperty(v8::String::New("&&"))) {
|
||||
operatorType = TRI_AND_INDEX_OPERATOR;
|
||||
if (!value->IsArray()) {
|
||||
// wrong data type for AND condition -- we require [leftOperation,rightOperation]
|
||||
return 0;
|
||||
value = condition->Get(v8::String::New("&&"));
|
||||
}
|
||||
}
|
||||
if (condition->HasOwnProperty(v8::String::New("and"))) {
|
||||
else if (condition->HasOwnProperty(v8::String::New("and"))) {
|
||||
operatorType = TRI_AND_INDEX_OPERATOR;
|
||||
value = condition->Get(v8::String::New("and"));
|
||||
operatorType = TRI_AND_INDEX_OPERATOR;
|
||||
if (!value->IsArray()) {
|
||||
// wrong data type for AND condition -- we require [leftOperation,rightOperation]
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// ........................................................................
|
||||
// Check for an 'OR' condition. The following are acceptable: '|', '||' 'or'
|
||||
// ........................................................................
|
||||
else if (condition->HasOwnProperty(v8::String::New("|"))) {
|
||||
value = condition->Get(v8::String::New("|"));
|
||||
operatorType = TRI_OR_INDEX_OPERATOR;
|
||||
if (!value->IsArray()) {
|
||||
// wrong data type for OR condition -- we require [leftOperation,rightOperation]
|
||||
return 0;
|
||||
}
|
||||
else if (condition->HasOwnProperty(v8::String::New("||"))) {
|
||||
value = condition->Get(v8::String::New("||"));
|
||||
operatorType = TRI_OR_INDEX_OPERATOR;
|
||||
}
|
||||
else if (condition->HasOwnProperty(v8::String::New("or"))) {
|
||||
value = condition->Get(v8::String::New("or"));
|
||||
operatorType = TRI_OR_INDEX_OPERATOR;
|
||||
if (!value->IsArray()) {
|
||||
// wrong data type for OR condition -- we require [leftOperation,rightOperation]
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// ........................................................................
|
||||
// Check for an 'NOT' condition. The following are acceptable: '!', 'not'
|
||||
// ........................................................................
|
||||
else if (condition->HasOwnProperty(v8::String::New("!"))) {
|
||||
value = condition->Get(v8::String::New("!"));
|
||||
operatorType = TRI_NOT_INDEX_OPERATOR;
|
||||
if (!value->IsObject()) {
|
||||
// wrong data type for NOT condition -- we require {condition...} ]
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (condition->HasOwnProperty(v8::String::New("not"))) {
|
||||
value = condition->Get(v8::String::New("!"));
|
||||
value = condition->Get(v8::String::New("not"));
|
||||
operatorType = TRI_NOT_INDEX_OPERATOR;
|
||||
if (!value->IsObject()) {
|
||||
// wrong data type for NOT condition -- we require {condition...} ]
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// ........................................................................
|
||||
// Check for an 'EQUAL' condition. The following are acceptable: '=', '==', 'eq'
|
||||
// ........................................................................
|
||||
else if (condition->HasOwnProperty(v8::String::New("=="))) {
|
||||
value = condition->Get(v8::String::New("=="));
|
||||
operatorType = TRI_EQ_INDEX_OPERATOR;
|
||||
|
@ -575,33 +572,79 @@ static TRI_index_operator_t* SetupConditionsBitarrayHelper (TRI_index_t* idx,
|
|||
value = condition->Get(v8::String::New("="));
|
||||
operatorType = TRI_EQ_INDEX_OPERATOR;
|
||||
}
|
||||
else if (condition->HasOwnProperty(v8::String::New("eq"))) {
|
||||
value = condition->Get(v8::String::New("eq"));
|
||||
operatorType = TRI_EQ_INDEX_OPERATOR;
|
||||
}
|
||||
// ........................................................................
|
||||
// Check for an 'NOT EQUAL' condition. The following are acceptable: '!=', '<>, 'ne'
|
||||
// ........................................................................
|
||||
else if (condition->HasOwnProperty(v8::String::New("!="))) {
|
||||
value = condition->Get(v8::String::New("!="));
|
||||
operatorType = TRI_NE_INDEX_OPERATOR;
|
||||
}
|
||||
else if (condition->HasOwnProperty(v8::String::New("<>"))) {
|
||||
value = condition->Get(v8::String::New("<>"));
|
||||
operatorType = TRI_NE_INDEX_OPERATOR;
|
||||
}
|
||||
else if (condition->HasOwnProperty(v8::String::New("ne"))) {
|
||||
value = condition->Get(v8::String::New("ne"));
|
||||
operatorType = TRI_NE_INDEX_OPERATOR;
|
||||
}
|
||||
// ........................................................................
|
||||
// Check for an 'LESS THAN OR EQUAL' condition. The following are acceptable: '<=', 'le'
|
||||
// ........................................................................
|
||||
else if (condition->HasOwnProperty(v8::String::New("<="))) {
|
||||
value = condition->Get(v8::String::New("<="));
|
||||
operatorType = TRI_LE_INDEX_OPERATOR;
|
||||
}
|
||||
else if (condition->HasOwnProperty(v8::String::New("le"))) {
|
||||
value = condition->Get(v8::String::New("le"));
|
||||
operatorType = TRI_LE_INDEX_OPERATOR;
|
||||
}
|
||||
// ........................................................................
|
||||
// Check for an 'LESS THAN ' condition. The following are acceptable: '<', 'lt'
|
||||
// ........................................................................
|
||||
else if (condition->HasOwnProperty(v8::String::New("<"))) {
|
||||
value = condition->Get(v8::String::New("<"));
|
||||
operatorType = TRI_LT_INDEX_OPERATOR;
|
||||
}
|
||||
else if (condition->HasOwnProperty(v8::String::New("lt"))) {
|
||||
value = condition->Get(v8::String::New("lt"));
|
||||
operatorType = TRI_LT_INDEX_OPERATOR;
|
||||
}
|
||||
// ........................................................................
|
||||
// Check for an 'GREATER THAN OR EQUAL' condition. The following are acceptable: '>=', 'ge'
|
||||
// ........................................................................
|
||||
else if (condition->HasOwnProperty(v8::String::New(">="))) {
|
||||
value = condition->Get(v8::String::New(">="));
|
||||
operatorType = TRI_GE_INDEX_OPERATOR;
|
||||
}
|
||||
else if (condition->HasOwnProperty(v8::String::New("ge"))) {
|
||||
value = condition->Get(v8::String::New("ge"));
|
||||
operatorType = TRI_GE_INDEX_OPERATOR;
|
||||
}
|
||||
// ........................................................................
|
||||
// Check for an 'GREATER THAN ' condition. The following are acceptable: '>', 'gt'
|
||||
// ........................................................................
|
||||
else if (condition->HasOwnProperty(v8::String::New(">"))) {
|
||||
value = condition->Get(v8::String::New(">"));
|
||||
operatorType = TRI_GT_INDEX_OPERATOR;
|
||||
}
|
||||
else if (condition->HasOwnProperty(v8::String::New("gt"))) {
|
||||
value = condition->Get(v8::String::New("gt"));
|
||||
operatorType = TRI_GT_INDEX_OPERATOR;
|
||||
}
|
||||
// ........................................................................
|
||||
// We received an invalid condition. Most likely we are really expressing
|
||||
// a condition {"x":1} which should be BY_EXAMPLE rather than BY_CONDITION
|
||||
// ........................................................................
|
||||
else { // invalid operator index condition
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ........................................................................
|
||||
// Since we have a valid condition condition, act upon it
|
||||
// Since we have a valid condition, act upon it
|
||||
// may require recursion
|
||||
// ........................................................................
|
||||
|
||||
|
@ -609,7 +652,41 @@ static TRI_index_operator_t* SetupConditionsBitarrayHelper (TRI_index_t* idx,
|
|||
|
||||
case TRI_AND_INDEX_OPERATOR:
|
||||
case TRI_OR_INDEX_OPERATOR: {
|
||||
|
||||
// ....................................................................
|
||||
// For both the 'AND' and 'OR' index operators, we require an array
|
||||
// with 2 elements for the value of the condition object. E.g. we
|
||||
// expect: {"&": [{"x":0},{"x":1}]} <-- this is a special "and" call
|
||||
// see the ensureBitarray doc for
|
||||
// more information.
|
||||
// More common is
|
||||
// expect: {"or": [{"x":0},{"x":1}]} <-- which means return all docs
|
||||
// where attribute "x" has the
|
||||
// value of 0 or 1.
|
||||
// To have "x" = 0 or "x" = 1 or "x" = 2 we expect:
|
||||
// {"or":[{"x":0},{"or":[{"x":1},{"x":2}]}]} or any valid iteration
|
||||
// of this. TODO: shortcut this with the "list" index operator
|
||||
// ....................................................................
|
||||
|
||||
// ....................................................................
|
||||
// wrong data type for this condition -- we require [leftOperation,rightOperation]
|
||||
// ....................................................................
|
||||
|
||||
if (!value->IsArray()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
v8::Handle<v8::Array> andValues = v8::Handle<v8::Array>::Cast(value);
|
||||
|
||||
|
||||
// ....................................................................
|
||||
// Check the length of the array to ensure that it is exactly 2
|
||||
// ....................................................................
|
||||
|
||||
if (andValues->Length() != 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> leftValue = andValues->Get(0);
|
||||
v8::Handle<v8::Value> rightValue = andValues->Get(1);
|
||||
|
||||
|
@ -620,6 +697,11 @@ static TRI_index_operator_t* SetupConditionsBitarrayHelper (TRI_index_t* idx,
|
|||
v8::Handle<v8::Object> leftObject = v8::Handle<v8::Object>::Cast(leftValue);
|
||||
v8::Handle<v8::Object> rightObject = v8::Handle<v8::Object>::Cast(rightValue);
|
||||
|
||||
|
||||
// ....................................................................
|
||||
// recurse the left and right operators
|
||||
// ....................................................................
|
||||
|
||||
TRI_index_operator_t* leftOp = SetupConditionsBitarrayHelper(idx, shaper, leftObject);
|
||||
TRI_index_operator_t* rightOp = SetupConditionsBitarrayHelper(idx, shaper, rightObject);
|
||||
|
||||
|
@ -634,7 +716,22 @@ static TRI_index_operator_t* SetupConditionsBitarrayHelper (TRI_index_t* idx,
|
|||
}
|
||||
|
||||
case TRI_NOT_INDEX_OPERATOR: {
|
||||
|
||||
// ....................................................................
|
||||
// wrong data type for this condition -- we require {...} which becomes
|
||||
// the left object for not operator.
|
||||
// ....................................................................
|
||||
|
||||
if (!value->IsObject()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
v8::Handle<v8::Object> leftObject = v8::Handle<v8::Object>::Cast(value);
|
||||
|
||||
|
||||
// ....................................................................
|
||||
// recurse the left and only operator
|
||||
// ....................................................................
|
||||
TRI_index_operator_t* leftOp = SetupConditionsBitarrayHelper(idx, shaper, leftObject);
|
||||
|
||||
if (leftOp == 0) {
|
||||
|
@ -651,6 +748,7 @@ static TRI_index_operator_t* SetupConditionsBitarrayHelper (TRI_index_t* idx,
|
|||
case TRI_LT_INDEX_OPERATOR:
|
||||
case TRI_GE_INDEX_OPERATOR:
|
||||
case TRI_GT_INDEX_OPERATOR: {
|
||||
|
||||
v8::Handle<v8::Object> leftObject = v8::Handle<v8::Object>::Cast(value);
|
||||
TRI_json_t* parameters = SetupBitarrayAttributeValuesHelper(idx, leftObject);
|
||||
|
||||
|
@ -1166,6 +1264,7 @@ static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv, st
|
|||
|
||||
else {
|
||||
LOG_WARNING("index iterator returned with a NULL value in ExecuteBitarrayQuery");
|
||||
// return an empty list
|
||||
}
|
||||
|
||||
collection->_collection->endRead(collection->_collection);
|
||||
|
|
|
@ -1338,6 +1338,7 @@ static v8::Handle<v8::Value> ExecuteQueryNativeAhuacatl (TRI_aql_context_t* cons
|
|||
// bind values
|
||||
// optimise
|
||||
// lock
|
||||
|
||||
if (!TRI_ValidateQueryContextAql(context) ||
|
||||
!TRI_BindQueryContextAql(context, parameters) ||
|
||||
!TRI_LockQueryContextAql(context) ||
|
||||
|
@ -2088,7 +2089,6 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
const string queryString = TRI_ObjectToString(queryArg);
|
||||
|
||||
// return number of total records in cursor?
|
||||
bool doCount = false;
|
||||
// maximum number of results to return at once
|
||||
|
@ -2781,7 +2781,7 @@ static v8::Handle<v8::Value> EnsureBitarray (v8::Arguments const& argv, bool sup
|
|||
if ( (argv.Length() < 2) || (argv.Length() % 2 != 0) ) {
|
||||
LOG_WARNING("bitarray index creation failed -- invalid parameters (require key_1,values_1,...,key_n,values_n)");
|
||||
TRI_ReleaseCollection(collection);
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_ILLEGAL_OPTION, "usage: ensureBitarray(<path>, <list of values>, ...)")));
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_ILLEGAL_OPTION, "usage: ensureBitarray(path 1, <list of values 1>, <path 2>, <list of values 2>, ...)")));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1017,6 +1017,7 @@ TRI_index_t* TRI_CreateGeo1Index (struct TRI_doc_collection_s* collection,
|
|||
bool ignoreNull) {
|
||||
TRI_geo_index_t* geo;
|
||||
char* ln;
|
||||
int result;
|
||||
|
||||
geo = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_geo_index_t), false);
|
||||
|
||||
|
@ -1048,12 +1049,31 @@ TRI_index_t* TRI_CreateGeo1Index (struct TRI_doc_collection_s* collection,
|
|||
geo->_constraint = constraint;
|
||||
geo->_geoIndex = GeoIndex_new();
|
||||
|
||||
if (geo->_geoIndex == NULL) { // oops out of memory?
|
||||
LOG_WARNING("geo index creation failed -- internal error when creating new goe index structure");
|
||||
TRI_DestroyVectorString(&geo->base._fields);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, geo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
geo->_variant = geoJson ? INDEX_GEO_COMBINED_LAT_LON : INDEX_GEO_COMBINED_LON_LAT;
|
||||
geo->_location = location;
|
||||
geo->_latitude = 0;
|
||||
geo->_longitude = 0;
|
||||
geo->_geoJson = geoJson;
|
||||
|
||||
result = GeoIndex_assignMethod(&(geo->base.indexQuery), TRI_INDEX_METHOD_ASSIGNMENT_QUERY);
|
||||
result = result || GeoIndex_assignMethod(&(geo->base.indexQueryFree), TRI_INDEX_METHOD_ASSIGNMENT_FREE);
|
||||
result = result || GeoIndex_assignMethod(&(geo->base.indexQueryResult), TRI_INDEX_METHOD_ASSIGNMENT_RESULT);
|
||||
|
||||
if (result != TRI_ERROR_NO_ERROR) {
|
||||
TRI_DestroyVectorString(&geo->base._fields);
|
||||
GeoIndex_free(geo->_geoIndex);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, geo);
|
||||
LOG_WARNING("geo index creation failed -- internal error when assigning function calls");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &geo->base;
|
||||
}
|
||||
|
||||
|
@ -1071,6 +1091,7 @@ TRI_index_t* TRI_CreateGeo2Index (struct TRI_doc_collection_s* collection,
|
|||
TRI_geo_index_t* geo;
|
||||
char* lat;
|
||||
char* lon;
|
||||
int result;
|
||||
|
||||
geo = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_geo_index_t), false);
|
||||
|
||||
|
@ -1103,11 +1124,30 @@ TRI_index_t* TRI_CreateGeo2Index (struct TRI_doc_collection_s* collection,
|
|||
geo->_constraint = constraint;
|
||||
geo->_geoIndex = GeoIndex_new();
|
||||
|
||||
if (geo->_geoIndex == NULL) { // oops out of memory?
|
||||
LOG_WARNING("geo index creation failed -- internal error when creating new goe index structure");
|
||||
TRI_DestroyVectorString(&geo->base._fields);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, geo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
geo->_variant = INDEX_GEO_INDIVIDUAL_LAT_LON;
|
||||
geo->_location = 0;
|
||||
geo->_latitude = latitude;
|
||||
geo->_longitude = longitude;
|
||||
|
||||
result = GeoIndex_assignMethod(&(geo->base.indexQuery), TRI_INDEX_METHOD_ASSIGNMENT_QUERY);
|
||||
result = result || GeoIndex_assignMethod(&(geo->base.indexQueryFree), TRI_INDEX_METHOD_ASSIGNMENT_FREE);
|
||||
result = result || GeoIndex_assignMethod(&(geo->base.indexQueryResult), TRI_INDEX_METHOD_ASSIGNMENT_RESULT);
|
||||
|
||||
if (result != TRI_ERROR_NO_ERROR) {
|
||||
TRI_DestroyVectorString(&geo->base._fields);
|
||||
GeoIndex_free(geo->_geoIndex);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, geo);
|
||||
LOG_WARNING("geo index creation failed -- internal error when assigning function calls");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &geo->base;
|
||||
}
|
||||
|
||||
|
@ -1732,7 +1772,7 @@ TRI_index_t* TRI_CreateHashIndex (struct TRI_doc_collection_s* collection,
|
|||
hashIndex->_hashIndex = MultiHashIndex_new();
|
||||
}
|
||||
|
||||
if (hashIndex->_hashIndex == NULL) {
|
||||
if (hashIndex->_hashIndex == NULL) { // oops out of memory?
|
||||
TRI_DestroyVector(&hashIndex->_paths);
|
||||
TRI_DestroyVectorString(&hashIndex->base._fields);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, hashIndex);
|
||||
|
@ -1750,7 +1790,8 @@ TRI_index_t* TRI_CreateHashIndex (struct TRI_doc_collection_s* collection,
|
|||
if (result != TRI_ERROR_NO_ERROR) {
|
||||
TRI_DestroyVector(&hashIndex->_paths);
|
||||
TRI_DestroyVectorString(&hashIndex->base._fields);
|
||||
TRI_FreeBitarrayIndex(&hashIndex->base);
|
||||
HashIndex_free(hashIndex->_hashIndex);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, hashIndex);
|
||||
LOG_WARNING("hash index creation failed -- internal error when assigning function calls");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3484,6 +3525,15 @@ TRI_index_t* TRI_CreateSkiplistIndex (struct TRI_doc_collection_s* collection,
|
|||
skiplistIndex->_skiplistIndex = MultiSkiplistIndex_new();
|
||||
}
|
||||
|
||||
if (skiplistIndex->_skiplistIndex == NULL) {
|
||||
TRI_DestroyVector(&skiplistIndex->_paths);
|
||||
TRI_DestroyVectorString(&skiplistIndex->base._fields);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, skiplistIndex);
|
||||
LOG_WARNING("skiplist index creation failed -- internal error when creating skiplist structure");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Assign the function calls used by the query engine
|
||||
// ...........................................................................
|
||||
|
@ -3495,7 +3545,8 @@ TRI_index_t* TRI_CreateSkiplistIndex (struct TRI_doc_collection_s* collection,
|
|||
if (result != TRI_ERROR_NO_ERROR) {
|
||||
TRI_DestroyVector(&skiplistIndex->_paths);
|
||||
TRI_DestroyVectorString(&skiplistIndex->base._fields);
|
||||
TRI_FreeBitarrayIndex(&skiplistIndex->base);
|
||||
SkiplistIndex_free(skiplistIndex->_skiplistIndex);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, skiplistIndex);
|
||||
LOG_WARNING("skiplist index creation failed -- internal error when assigning function calls");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4384,7 +4435,6 @@ TRI_index_t* TRI_CreateBitarrayIndex (struct TRI_doc_collection_s* collection,
|
|||
createContext = NULL;
|
||||
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Check that the attributes have not been repeated
|
||||
// ...........................................................................
|
||||
|
@ -4403,7 +4453,7 @@ TRI_index_t* TRI_CreateBitarrayIndex (struct TRI_doc_collection_s* collection,
|
|||
if (value == NULL) {
|
||||
TRI_DestroyVector(&baIndex->_paths);
|
||||
TRI_DestroyVector(&baIndex->_values);
|
||||
TRI_FreeBitarrayIndex(&baIndex->base);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE,baIndex);
|
||||
LOG_WARNING("bitarray index creation failed -- list of values for index undefined");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4428,7 +4478,7 @@ TRI_index_t* TRI_CreateBitarrayIndex (struct TRI_doc_collection_s* collection,
|
|||
if (cardinality > 64) {
|
||||
TRI_DestroyVector(&baIndex->_paths);
|
||||
TRI_DestroyVector(&baIndex->_values);
|
||||
TRI_FreeBitarrayIndex(&baIndex->base);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE,baIndex);
|
||||
LOG_WARNING("bitarray index creation failed -- more than 64 possible values");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4437,7 +4487,7 @@ TRI_index_t* TRI_CreateBitarrayIndex (struct TRI_doc_collection_s* collection,
|
|||
if (cardinality < 1 ) {
|
||||
TRI_DestroyVector(&baIndex->_paths);
|
||||
TRI_DestroyVector(&baIndex->_values);
|
||||
TRI_FreeBitarrayIndex(&baIndex->base);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE,baIndex);
|
||||
LOG_WARNING("bitarray index creation failed -- no index values defined");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4455,7 +4505,7 @@ TRI_index_t* TRI_CreateBitarrayIndex (struct TRI_doc_collection_s* collection,
|
|||
if (result != TRI_ERROR_NO_ERROR) {
|
||||
TRI_DestroyVector(&baIndex->_paths);
|
||||
TRI_DestroyVector(&baIndex->_values);
|
||||
TRI_FreeBitarrayIndex(&baIndex->base);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE,baIndex);
|
||||
LOG_WARNING("bitarray index creation failed -- internal error when assigning function calls");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4471,6 +4521,7 @@ TRI_index_t* TRI_CreateBitarrayIndex (struct TRI_doc_collection_s* collection,
|
|||
TRI_DestroyVector(&baIndex->_paths);
|
||||
TRI_DestroyVector(&baIndex->_values);
|
||||
TRI_FreeBitarrayIndex(&baIndex->base);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE,baIndex);
|
||||
LOG_WARNING("bitarray index creation failed -- your guess as good as mine");
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1356,6 +1356,32 @@ function ArangoCollection (database, data) {
|
|||
return true;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a bitarray index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ArangoCollection.prototype.ensureBitarray = function () {
|
||||
var i;
|
||||
var body;
|
||||
var fields = [];
|
||||
|
||||
for (i = 0; i < arguments.length; ++i) {
|
||||
fields.push(arguments[i]);
|
||||
}
|
||||
|
||||
body = { type : "bitarray", unique : false, fields : fields };
|
||||
|
||||
var requestResult = this._database._connection.POST(
|
||||
"/_api/index?collection=" + encodeURIComponent(this._id),
|
||||
JSON.stringify(body));
|
||||
|
||||
client.checkRequestResult(requestResult);
|
||||
|
||||
return requestResult;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a cap constraint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1357,6 +1357,32 @@ static string JS_client_client =
|
|||
" return true;\n"
|
||||
" };\n"
|
||||
"\n"
|
||||
" \n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief adds a bitarray index\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
" ArangoCollection.prototype.ensureBitarray = function () {\n"
|
||||
" var i;\n"
|
||||
" var body;\n"
|
||||
" var fields = [];\n"
|
||||
"\n"
|
||||
" for (i = 0; i < arguments.length; ++i) {\n"
|
||||
" fields.push(arguments[i]);\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" body = { type : \"bitarray\", unique : false, fields : fields };\n"
|
||||
"\n"
|
||||
" var requestResult = this._database._connection.POST(\n"
|
||||
" \"/_api/index?collection=\" + encodeURIComponent(this._id),\n"
|
||||
" JSON.stringify(body));\n"
|
||||
"\n"
|
||||
" client.checkRequestResult(requestResult);\n"
|
||||
"\n"
|
||||
" return requestResult;\n"
|
||||
" };\n"
|
||||
"\n"
|
||||
" \n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief adds a cap constraint\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
|
|
|
@ -455,6 +455,40 @@ function AHUACATL_GET_DOCUMENTS_HASH_LIST (collection, idx, attribute, values) {
|
|||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get documents from the specified collection using a bitarray
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function AHUACATL_GET_DOCUMENTS_BITARRAY (collection, idx, example) {
|
||||
return internal.db[collection].BY_CONDITION_BITARRAY(idx, example).documents;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get documents from the specified collection using a bitarray
|
||||
/// (multiple index values) TODO: replace by 'IN index operator'
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function AHUACATL_GET_DOCUMENTS_BITARRAY_LIST (collection, idx, attribute, values) {
|
||||
var result = [ ];
|
||||
|
||||
for (var i in values) {
|
||||
var value = values[i];
|
||||
var example = { };
|
||||
|
||||
example[attribute] = value;
|
||||
|
||||
var documents = internal.db[collection].BY_EXAMPLE_BITARRAY(idx, example).documents;
|
||||
for (var j in documents) {
|
||||
result.push(documents[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get documents from the specified collection using a skiplist
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -457,6 +457,40 @@ static string JS_server_ahuacatl =
|
|||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief get documents from the specified collection using a bitarray\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"function AHUACATL_GET_DOCUMENTS_BITARRAY (collection, idx, example) {\n"
|
||||
" return internal.db[collection].BY_CONDITION_BITARRAY(idx, example).documents;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief get documents from the specified collection using a bitarray\n"
|
||||
"/// (multiple index values) TODO: replace by 'IN index operator'\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"function AHUACATL_GET_DOCUMENTS_BITARRAY_LIST (collection, idx, attribute, values) {\n"
|
||||
" var result = [ ];\n"
|
||||
"\n"
|
||||
" for (var i in values) {\n"
|
||||
" var value = values[i];\n"
|
||||
" var example = { };\n"
|
||||
"\n"
|
||||
" example[attribute] = value;\n"
|
||||
"\n"
|
||||
" var documents = internal.db[collection].BY_EXAMPLE_BITARRAY(idx, example).documents;\n"
|
||||
" for (var j in documents) {\n"
|
||||
" result.push(documents[j]);\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" return result;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief get documents from the specified collection using a skiplist\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
|
|
Loading…
Reference in New Issue