diff --git a/arangod/BitIndexes/bitarray.c b/arangod/BitIndexes/bitarray.c index 785e0f11ed..e91855102d 100755 --- a/arangod/BitIndexes/bitarray.c +++ b/arangod/BitIndexes/bitarray.c @@ -407,6 +407,14 @@ int TRI_LookupBitMaskBitarray(TRI_bitarray_t* ba, TRI_bitarray_mask_t* mask, voi // .......................................................................... bitValues = bitValues & ~(mask->_ignoreMask); + + /* + if (j_bitNum == 0) { + debugPrintMask(ba,mask->_ignoreMask); + debugPrintMask(ba,mask->_mask); + debugPrintMask(ba,bitValues); + } + */ if (mask->_mask == 0 && bitValues != 0) { continue; @@ -711,9 +719,7 @@ static void setBitarrayMask(TRI_bitarray_t* ba, TRI_bitarray_mask_t* mask, TRI_m void debugPrintMask(TRI_bitarray_t* ba, uint64_t mask) { int j; - - return; - + printf("------------------- Bitarray mask --------------------------\n"); for (j = 0; j < ba->_numColumns; ++j) { if ((mask & ((uint64_t)(1) << j)) == 0) { diff --git a/arangod/BitIndexes/bitarrayIndex.c b/arangod/BitIndexes/bitarrayIndex.c index 37dec6cb95..3ed33e8e39 100755 --- a/arangod/BitIndexes/bitarrayIndex.c +++ b/arangod/BitIndexes/bitarrayIndex.c @@ -858,7 +858,7 @@ int generateBitMask(BitarrayIndex* baIndex, const BitarrayIndexElement* element, int generateEqualBitMask(BitarrayIndex* baIndex, const TRI_relation_index_operator_t* relationOperator, TRI_bitarray_mask_t* mask) { int j; int shiftLeft; - + int ignoreShiftLeft; // ........................................................................... // some safety checks first // ........................................................................... @@ -892,6 +892,7 @@ int generateEqualBitMask(BitarrayIndex* baIndex, const TRI_relation_index_operat mask->_mask = 0; mask->_ignoreMask = 0; shiftLeft = 0; + ignoreShiftLeft = 0; for (j = 0; j < baIndex->_values._length; ++j) { // loop over the number of attributes defined in the index TRI_json_t* valueList; @@ -905,62 +906,67 @@ int generateEqualBitMask(BitarrayIndex* baIndex, const TRI_relation_index_operat valueList = (TRI_json_t*)(TRI_AtVector(&(baIndex->_values),j)); + ignoreShiftLeft += valueList->_value._objects._length; + // ......................................................................... // client did not send us this attribute (hence undefined value), therefore // this particular column we ignore // ......................................................................... if (value->_type == TRI_JSON_UNUSED) { - tempMask = (uint64_t)(1) << (valueList->_value._objects._length - 1); - mask->_ignoreMask = mask->_ignoreMask | (tempMask << shiftLeft); - continue; + tempMask = ~((~(uint64_t)(0)) << ignoreShiftLeft); + other = (~(uint64_t)(0)) << (ignoreShiftLeft - valueList->_value._objects._length); + mask->_ignoreMask = mask->_ignoreMask | (tempMask & other); + other = 0; + tempMask = 0; } + - - other = 0; - tempMask = 0; - - for (i = 0; i < valueList->_value._objects._length; ++i) { - TRI_json_t* listEntry = (TRI_json_t*)(TRI_AtVector(&(valueList->_value._objects), i)); - int k; + else { + other = 0; + tempMask = 0; - // ....................................................................... - // if the ith possible set of values is not a list, do comparison - // ....................................................................... - - if (listEntry->_type != TRI_JSON_LIST) { - if (isEqualJson(value, listEntry)) { - tempMask = tempMask | (1 << i); - } - continue; + for (i = 0; i < valueList->_value._objects._length; ++i) { + TRI_json_t* listEntry = (TRI_json_t*)(TRI_AtVector(&(valueList->_value._objects), i)); + int k; + + // ....................................................................... + // if the ith possible set of values is not a list, do comparison + // ....................................................................... + + if (listEntry->_type != TRI_JSON_LIST) { + if (isEqualJson(value, listEntry)) { + tempMask = tempMask | (1 << i); + } + continue; + } + + + // ....................................................................... + // ith entry in the set of possible values is a list + // ....................................................................... + + // ....................................................................... + // Special case of an empty list -- this means all other values + // ....................................................................... + + if (listEntry->_value._objects._length == 0) { // special case + other = (1 << i); + continue; + } + + + for (k = 0; k < listEntry->_value._objects._length; k++) { + TRI_json_t* subListEntry; + subListEntry = (TRI_json_t*)(TRI_AtVector(&(listEntry->_value._objects), i)); + if (isEqualJson(value, subListEntry)) { + tempMask = tempMask | (1 << i); + break; + } + } + } - - - // ....................................................................... - // ith entry in the set of possible values is a list - // ....................................................................... - - // ....................................................................... - // Special case of an empty list -- this means all other values - // ....................................................................... - - if (listEntry->_value._objects._length == 0) { // special case - other = (1 << i); - continue; - } - - - for (k = 0; k < listEntry->_value._objects._length; k++) { - TRI_json_t* subListEntry; - subListEntry = (TRI_json_t*)(TRI_AtVector(&(listEntry->_value._objects), i)); - if (isEqualJson(value, subListEntry)) { - tempMask = tempMask | (1 << i); - break; - } - } - - } - + } // ............................................................................ // When we create a bitarray index, for example: ensureBitarray("x",[0,[],1,2,3]) diff --git a/arangod/V8Server/v8-query.cpp b/arangod/V8Server/v8-query.cpp index 68ef6948aa..dda7196fd5 100755 --- a/arangod/V8Server/v8-query.cpp +++ b/arangod/V8Server/v8-query.cpp @@ -477,7 +477,9 @@ static TRI_index_operator_t* SetupExampleBitarray (TRI_index_t* idx, TRI_shaper_ // The client may have sent values for all of the Attributes or for // a subset of them. If the value for an Attribute is missing, then we // assume that the client wishes to IGNORE the value of that Attribute. - // In the later case, we add the json object '{}' to indicate that + // In the later case, we add the json object 'TRI_JSON_UNUSED' to + // indicate that this attribute is to be ignored. Notice that it is + // possible to ignore all the attributes defined as part of the index. // ...................................................................... diff --git a/js/common/tests/shell-bitarray-index.js b/js/common/tests/shell-bitarray-index.js index fba14aa788..804ecb1f38 100755 --- a/js/common/tests/shell-bitarray-index.js +++ b/js/common/tests/shell-bitarray-index.js @@ -151,7 +151,82 @@ function BitarrayIndexSuite() { }, + // ........................................................................... + // In this test we have not specified a bitarray column for values outside + // the range 0-9. + // ........................................................................... + testLookupBitarrayIndex_2 : function () { + var idx; + var n = 1000; + var bitarrayValues = [0,1,2,3,4,5,6,7,8,9]; + var shelves = new Array(bitarrayValues.length + 2); + var docs = new Array(); + var result; + + + // ......................................................................... + // initialise our counters to 0 + // ......................................................................... + + for (var j = 0; j < shelves.length; ++j) { + shelves[j] = 0; + } + + // ......................................................................... + // Create a bit array index with one attribute + // ......................................................................... + + idx = collection.ensureBitarray("x",bitarrayValues); + + + // ......................................................................... + // Save n random records + // ......................................................................... + + print("Start writing",n," documents into index"); + + for (var j = 0; j < n; ++j) { + var value = Math.floor(Math.random()*(bitarrayValues.length + 5)); + var alpha = Math.floor(Math.random()*(bitarrayValues.length + 5)); + var doc; + + doc = collection.save({"x":value, "y":{"a":1,"z":String.fromCharCode(97 + alpha)} }); + docs.push(doc._id); + if (value > bitarrayValues[bitarrayValues.length - 1]) { + shelves[shelves.length - 2] = shelves[shelves.length - 2] + 1; + } + else { + shelves[value] = shelves[value] + 1; + } + } + + print("End writing",n," documents into index"); + + for (var j = 0; j < (shelves.length - 1) ; ++j) { + shelves[shelves.length - 1] = shelves[shelves.length - 1] + shelves[j]; + } + + // ......................................................................... + // Ensure that we have the total number of written documents stored in the + // last position + // ......................................................................... + + assertEqual(shelves[shelves.length - 1], n); + + + print("Start Lookup"); + print(shelves); + for (var j = 0; j < bitarrayValues.length; ++j) { + result = collection.BY_EXAMPLE_BITARRAY(idx.id,{"x":j,"y":6,"z":-1}, null, null); + assertEqual(result['total'],shelves[j]); + } + + result = collection.BY_EXAMPLE_BITARRAY(idx.id,{"x":"hi there"}, null, null); + assertEqual(result['total'],shelves[bitarrayValues.length]); + + print("End Lookup"); + return; },