8000 Added some more Array Indexing tests. And improved the pathbased inde… · jameswei/arangodb@52e372a · GitHub
[go: up one dir, main page]

Skip to content

Commit 52e372a

Browse files
committed
Added some more Array Indexing tests. And improved the pathbased index. Now it is checked when trying to array-index a non-array value. And if non existing attributes are added to the index or not.
1 parent d9eb549 commit 52e372a

File tree

2 files changed

+209
-3
lines changed

2 files changed

+209
-3
lines changed

arangod/Indexes/PathBasedIndex.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,16 @@ void PathBasedIndex::buildIndexValues (TRI_shaped_json_t const* documentShape,
309309

310310
if (! check || shape == nullptr || shapedJson._sid == BasicShapes::TRI_SHAPE_SID_NULL) {
311311
// attribute not, found
312-
if (expand) {
312+
bool expandAnywhere = false;
313+
for (size_t k = 0; k < n; ++k) {
314+
if (_paths[level][k].second) {
315+
expandAnywhere = true;
316+
break;
317+
}
318+
}
319+
if (expandAnywhere && (i < n - 1 || ! check || shape == nullptr ) ) {
320+
// We have an array index and we are not evaluating the indexed attribute.
321+
// Do not index this attribute at all
313322
if (level == 0) {
314323
// If we expand at the first position and this is not set we cannot index anything
315324
return;
@@ -327,8 +336,9 @@ void PathBasedIndex::buildIndexValues (TRI_shaped_json_t const* documentShape,
327336
currentShape._data.length = 0;
328337
break;
329338
}
330-
if (_sparse) {
331-
// If sparse we do not have to index
339+
if (!expandAnywhere && _sparse) {
340+
// If sparse we do not have to index.
341+
// If we are in an array we index null
332342
return;
333343
}
334344

js/server/tests/aql-queries-array.js

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,85 @@ function arrayIndexNonArraySuite () {
588588
assertEqual(actual[0], "null2");
589589
},
590590

591+
testHashIndexMultipleAttributeMiddleArraySub : function () {
592+
var inserted = 0;
593+
col.ensureHashIndex("b", "a[*].d", "c");
594+
col.save({}); // a is not set, no indexing
595+
checkElementsInIndex(inserted);
596+
col.save({b: 1}); // a is not set, no indexing
597+
checkElementsInIndex(inserted);
598+
col.save({b: 1, c: 1}); // a is not set, no indexing
599+
checkElementsInIndex(inserted);
600+
col.save({ a: "This is no array" }); // a is illegal, no indexing
601+
checkElementsInIndex(inserted);
602+
col.save({ a: "This is no array", b: 1 }); // no indexing
603+
checkElementsInIndex(inserted);
604+
col.save({ a: "This is no array", b: 1, c: 1}); // no indexing
605+
checkElementsInIndex(inserted);
606+
col.save({ a: {b: [42] } }); // no indexing
607+
checkElementsInIndex(inserted);
608+
col.save({ a: {b: [42] }, b: 1 }); // no indexing
609+
checkElementsInIndex(inserted);
610+
col.save({ a: {b: [42] }, b: 1, c: 1 }); // no indexing
611+
checkElementsInIndex(inserted);
612+
col.save({ a: [] }); // Empty Array. no indexing
613+
checkElementsInIndex(inserted);
614+
col.save({ a: [], b: 1 }); // Empty Array. no indexing
615+
checkElementsInIndex(inserted);
616+
col.save({ a: [], b: 1, c: 1 }); // Empty Array. no indexing
617+
checkElementsInIndex(inserted);
618+
619+
col.save({ a: [1, 2, 3, 3, 2, 1] }); // a does not have any nested value. Handled equal to a: []
620+
checkElementsInIndex(inserted);
621+
622+
col.save({ a: [1, 2, 3, 3, 2, 1], b: 1 }); // a does not have any nested value. Handled equal to a: []
623+
checkElementsInIndex(inserted);
624+
625+
col.save({ a: [1, 2, 3, 3, 2, 1], b: 1, c: 1 }); // a does not have any nested value. Handled equal to a: []
626+
checkElementsInIndex(inserted);
627+
628+
col.save({ a: [{d: 1}, {d: 2}, {d: 3}, {d: 3}, {d: 2}, {d: 1}] });
629+
inserted += 3; // We index b: null and 3 values for a[*].d
630+
checkElementsInIndex(inserted);
631+
632+
col.save({ a: [{d: 1}, {d: 2}, {d: 3}, {d: 3}, {d: 2}, {d: 1}], b: 1 });
633+
inserted += 3; // We index b: 1 and 3 values for a[*].d
634+
checkElementsInIndex(inserted);
635+
636+
col.save({ a: [{d: 1}, {d: 2}, {d: 3}, {d: 3}, {d: 2}, {d: 1}], b: 1, c: 1 });
637+
inserted += 3; // We index b: 1, c: 1 and 3 values for a[*].d
638+
checkElementsInIndex(inserted);
639+
640+
col.save({_key: "null1", a: [{d: null}, {d: "a"}, {d: "b"}, {d: "c"}, {d: "b"}, {d: "a"}, {d: null}] });
641+
inserted += 4;
642+
checkElementsInIndex(inserted); // b: null a: "a", "b", "c", null c:null
643+
644+
col.save({_key: "null2", a: [{d: null}, {d: "a"}, {d: "b"}, {d: "c"}, {d: "b"}, {d: "a"}, {d: null}], b: 1 });
645+
inserted += 4;
646+
checkElementsInIndex(inserted);
647+
648+
col.save({_key: "null3", a: [{d: null}, {d: "a"}, {d: "b"}, {d: "c"}, {d: "b"}, {d: "a"}, {d: null}], b: 1, c: 1 });
649+
inserted += 4;
650+
checkElementsInIndex(inserted);
651+
652+
const query = `FOR x IN ${cName} FILTER @tag IN x.a[*].d && 1 == x.b && 1 == x.c SORT x._key RETURN x._key`;
653+
var actual = AQL_EXECUTE(query, { tag : null }).json;
654+
// We expect that we can only find the Array that has stored exactly the null value
655+
assertEqual(actual.length, 1);
656+
assertEqual(actual[0], "null3");
657+
},
658+
659+
testHashIndexSubAttributeArray : function () {
660+
col.ensureHashIndex("b", "a.d[*]", "c");
661+
col.save({b: 1, a:[ {d: [1, 2]}, {d: 3} ], c: 1});
662+
checkElementsInIndex(0);
663+
664+
const query = `FOR x IN ${cName} FILTER @tag IN x.a[*].d && 1 == x.b SORT x._key RETURN x._key`;
665+
var actual = AQL_EXECUTE(query, { tag : null }).json;
666+
assertEqual(actual.length, 0);
667+
// Do not find anything
668+
},
669+
591670
testSkiplistSingleAttribute : function () {
592671
col.ensureSkiplist("a[*]");
593672
col.save({}); // a is not set
@@ -747,6 +826,123 @@ function arrayIndexNonArraySuite () {
747826
assertEqual(actual.length, inserted - insertedB);
748827
},
749828

829+
testSkiplistMultipleAttributeMiddleArraySub : function () {
830+
var inserted = 0;
831+
var insertedB = 0;
832+
col.ensureSkiplist("b", "a[*].d", "c");
833+
col.save({}); // a is not set, we index b: null
834+
inserted += 1;
835+
checkElementsInIndex(inserted);
836+
col.save({b: 1}); // a is not set, but we can index b only
837+
inserted += 1;
838+
insertedB += 1;
839+
checkElementsInIndex(inserted);
840+
col.save({b: 1, c: 1}); // a is not set, but we can index b only
841+
inserted += 1;
842+
insertedB += 1;
843+
checkElementsInIndex(inserted);
844+
col.save({ a: "This is no array" }); // a is illegal. But we can index b only
845+
inserted += 1;
846+
checkElementsInIndex(inserted);
847+
col.save({ a: "This is no array", b: 1 }); // We can index b only
848+
inserted += 1;
849+
insertedB += 1;
850+
checkElementsInIndex(inserted);
851+
col.save({ a: "This is no array", b: 1, c: 1}); // We can index b only
852+
inserted += 1;
853+
insertedB += 1;
854+
checkElementsInIndex(inserted);
855+
col.save({ a: {b: [42] } }); // We can index b only
856+
inserted += 1;
857+
checkElementsInIndex(inserted);
858+
col.save({ a: {b: [42] }, b: 1 }); // We can index b only
859+
inserted += 1;
860+
insertedB += 1;
861+
checkElementsInIndex(inserted);
862+
col.save({ a: {b: [42] }, b: 1, c: 1 }); // We can index b only
863+
inserted += 1;
864+
insertedB += 1;
865+
checkElementsInIndex(inserted);
866+
col.save({ a: [] }); // Empty Array. Nothing for a but index b
867+
inserted += 1;
868+
checkElementsInIndex(inserted);
869+
col.save({ a: [], b: 1 }); // Empty Array. Nothing for a but index b
870+
inserted += 1;
871+
insertedB += 1;
872+
checkElementsInIndex(inserted);
873+
col.save({ a: [], b: 1, c: 1 }); // Empty Array. Nothing for a but index b
874+
inserted += 1;
875+
insertedB += 1;
876+
checkElementsInIndex(inserted);
877+
878+
col.save({ a: [1, 2, 3, 3, 2, 1] });
879+
inserted += 1; // We index b: null But a does not have any nested value. Handled equal to a: []
880+
checkElementsInIndex(inserted);
881+
882+
col.save({ a: [1, 2, 3, 3, 2, 1], b: 1 }); // b: 1 a: 1,2,3 c: null
883+
inserted += 1; // We index b: 1 But a does not have any nested value. Handled equal to a: []
884+
insertedB += 1;
885+
checkElementsInIndex(inserted);
886+
887+
col.save({ a: [1, 2, 3, 3, 2, 1], b: 1, c: 1 });
888+
inserted += 1; // We index b: 1, c: 1 But a does not have any nested value. Handled equal to a: []
889+
insertedB += 1;
890+
checkElementsInIndex(inserted);
891+
892+
col.save({ a: [{d: 1}, {d: 2}, {d: 3}, {d: 3}, {d: 2}, {d: 1}] });
893+
inserted += 3; // We index b: null and 3 values for a[*].d
894+
checkElementsInIndex(inserted);
895+
896+
col.save({ a: [{d: 1}, {d: 2}, {d: 3}, {d: 3}, {d: 2}, {d: 1}], b: 1 });
897+
inserted += 3; // We index b: 1 and 3 values for a[*].d
898+
insertedB += 3;
899+
checkElementsInIndex(inserted);
900+
901+
col.save({ a: [{d: 1}, {d: 2}, {d: 3}, {d: 3}, {d: 2}, {d: 1}], b: 1, c: 1 });
902+
inserted += 3; // We index b: 1, c: 1 and 3 values for a[*].d
903+
insertedB += 3;
904+
checkElementsInIndex(inserted);
905+
906+
col.save({_key: "null1", a: [{d: null}, {d: "a"}, {d: "b"}, {d: "c"}, {d: "b"}, {d: "a"}, {d: null}] });
907+
inserted += 4;
908+
checkElementsInIndex(inserted); // b: null a: "a", "b", "c", null c:null
909+
910+
col.save({_key: "null2", a: [{d: null}, {d: "a"}, {d: "b"}, {d: "c"}, {d: "b"}, {d: "a"}, {d: null}], b: 1 });
911+
inserted += 4;
912+
insertedB += 4;
913+
checkElementsInIndex(inserted);
914+
915+
col.save({_key: "null3", a: [{d: null}, {d: "a"}, {d: "b"}, {d: "c"}, {d: "b"}, {d: "a"}, {d: null}], b: 1, c: 1 });
916+
inserted += 4;
917+
insertedB += 4;
918+
checkElementsInIndex(inserted);
919+
920+
const query = `FOR x IN ${cName} FILTER @tag IN x.a[*].d && 1 == x.b SORT x._key RETURN x._key`;
921+
var actual = AQL_EXECUTE(query, { tag : null }).json;
922+
// We expect that we can only find the Array that has stored exactly the null value
923+
assertEqual(actual.length, 2);
924+
assertEqual(actual[0], "null2");
925+
assertEqual(actual[1], "null3");
926+
927+
const query2 = `FOR x IN ${cName} FILTER 1 == x.b RETURN x._key`;
928+
actual = AQL_EXECUTE(query2).json;
929+
assertEqual(actual.length, insertedB);
930+
const query3 = `FOR x IN ${cName} FILTER null == x.b RETURN x._key`;
931+
actual = AQL_EXECUTE(query3).json;
932+
assertEqual(actual.length, inserted - insertedB);
933+
},
934+
935+
testSkiplistIndexSubAttributeArray : function () {
936+
col.ensureSkiplist("b", "a.d[*]", "c");
937+
col.save({b: 1, a:[ {d: [1, 2]}, {d: 3} ], c: 1});
938+
// We do only index b: 1 here
939+
checkElementsInIndex(1);
940+
941+
const query = `FOR x IN ${cName} FILTER @tag IN x.a[*].d && 1 == x.b SORT x._key RETURN x._key`;
942+
var actual = AQL_EXECUTE(query, { tag : null }).json;
943+
assertEqual(actual.length, 0);
944+
// Do not find anything
945+
}
750946

751947
};
752948

0 commit comments

Comments
 (0)
0