From ee15b97153d5481448cc598e3caa6693a061d008 Mon Sep 17 00:00:00 2001 From: Heiko Kernbach Date: Mon, 21 May 2012 11:11:49 +0200 Subject: [PATCH 1/5] bugfix sourceview --- html/admin/index.html | 2 +- html/admin/js/master.js | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/html/admin/index.html b/html/admin/index.html index e6b21157a0..7094b3771e 100644 --- a/html/admin/index.html +++ b/html/admin/index.html @@ -151,7 +151,7 @@ Add Document - diff --git a/html/admin/js/master.js b/html/admin/js/master.js index d492e56d0f..1626140f5e 100644 --- a/html/admin/js/master.js +++ b/html/admin/js/master.js @@ -12,6 +12,8 @@ var globalCollectionID; var globalCollectionRev; var checkCollectionName; var open = false; +var rowCounter = 0; + $(document).ready(function() { showCursor(); @@ -764,11 +766,7 @@ var logTable = $('#logTableID').dataTable({ var collectionID; var boxContent = $('#documentEditSourceBox').val(); var jsonContent = JSON.parse(boxContent); - $.each(jsonContent, function(row1, row2) { - if ( row1 == '_id') { - collectionID = row2; - } - }); + collectionID = globalCollectionID; $.ajax({ type: "PUT", @@ -812,7 +810,8 @@ var logTable = $('#logTableID').dataTable({ $('#addEditedDocRowButton').live('click', function () { if (tableView == true) { - documentEditTable.fnAddData(['', "somevalue", value2html("editme"), JSON.stringify("editme")]); + rowCounter = rowCounter + 1; + documentEditTable.fnAddData(['', "somekey" + rowCounter, value2html("editme"), JSON.stringify("editme")]); documentTableMakeEditable('#documentEditTableID'); showCursor(); } @@ -886,7 +885,8 @@ var logTable = $('#logTableID').dataTable({ $('#addNewDocButton').live('click', function () { if (tableView == true) { - newDocumentTable.fnAddData(['', "somevalue", value2html("editme"), JSON.stringify("editme")]); + rowCounter = rowCounter + 1; + newDocumentTable.fnAddData(['', "somekey" + rowCounter, value2html("editme"), JSON.stringify("editme")]); documentTableMakeEditable('#NewDocumentTableID'); showCursor(); } @@ -1166,7 +1166,7 @@ var logTable = $('#logTableID').dataTable({ $('#avocshWindow').append('' + client + ''); try { - var server = "" + JSON.stringify(eval(data)); + var server = "" + eval(data); $('#avocshWindow').append('

' + server + '

'); } catch(e) { From f7593506246ae2cebf0ffcc8cae46a4b9cfda6b8 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Mon, 21 May 2012 14:16:44 +0200 Subject: [PATCH 2/5] added --create option for arangoimp --- V8Client/ImportHelper.cpp | 20 ++++++++++++++++++-- V8Client/ImportHelper.h | 12 ++++++++++++ V8Client/arangoimp.cpp | 7 +++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/V8Client/ImportHelper.cpp b/V8Client/ImportHelper.cpp index 41e1dc93cb..8a55ca81f6 100644 --- a/V8Client/ImportHelper.cpp +++ b/V8Client/ImportHelper.cpp @@ -72,6 +72,7 @@ namespace triagens { _outputBuffer(TRI_UNKNOWN_MEM_ZONE) { _quote = '"'; _separator = ','; + _createCollection = false; regcomp(&_doubleRegex, "^[-+]?([0-9]+\\.?[0-9]*|\\.[0-9]+)([eE][-+]?[0-8]+)?$", REG_ICASE | REG_EXTENDED); regcomp(&_intRegex, "^[-+]?([0-9]+)$", REG_ICASE | REG_EXTENDED); _hasError = false; @@ -229,6 +230,20 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// /// private functions //////////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////////////// + /// @brief return the collection-related URL part + //////////////////////////////////////////////////////////////////////////////// + + string ImportHelper::getCollectionUrlPart () { + string part("collection=" + StringUtils::urlEncode(_collectionName)); + + if (_createCollection) { + part += "&createCollection=yes"; + } + + return part; + } //////////////////////////////////////////////////////////////////////////////// /// @brief start a new csv line @@ -359,13 +374,14 @@ namespace triagens { } + void ImportHelper::sendCsvBuffer () { if (_hasError) { return; } map headerFields; - SimpleHttpResult* result = _client->request(SimpleHttpClient::POST, "/_api/import?collection=" + StringUtils::urlEncode(_collectionName), _outputBuffer.c_str(), _outputBuffer.length(), headerFields); + SimpleHttpResult* result = _client->request(SimpleHttpClient::POST, "/_api/import?" + getCollectionUrlPart(), _outputBuffer.c_str(), _outputBuffer.length(), headerFields); handleResult(result); @@ -378,7 +394,7 @@ namespace triagens { } map headerFields; - SimpleHttpResult* result = _client->request(SimpleHttpClient::POST, "/_api/import?type=documents&collection=" + StringUtils::urlEncode(_collectionName), str, len, headerFields); + SimpleHttpResult* result = _client->request(SimpleHttpClient::POST, "/_api/import?type=documents&" + getCollectionUrlPart(), str, len, headerFields); handleResult(result); } diff --git a/V8Client/ImportHelper.h b/V8Client/ImportHelper.h index b2ddb2af78..2d4d248baa 100644 --- a/V8Client/ImportHelper.h +++ b/V8Client/ImportHelper.h @@ -128,6 +128,16 @@ namespace triagens { _separator = separator; } + //////////////////////////////////////////////////////////////////////////////// + /// @brief sets the createCollection flag + /// + /// @param bool value create the collection if it does not exist + //////////////////////////////////////////////////////////////////////////////// + + void setCreateCollection (const bool value) { + _createCollection = value; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief get the number of read lines /// @@ -173,6 +183,7 @@ namespace triagens { static void ProcessCsvAdd (TRI_csv_parser_t* parser, char const* field, size_t row, size_t column, bool escaped); static void ProcessCsvEnd (TRI_csv_parser_t* parser, char const* field, size_t row, size_t column, bool escaped); + string getCollectionUrlPart (); void beginLine (size_t row); void addField (char const* field, size_t row, size_t column, bool escaped); void addLastField (char const* field, size_t row, size_t column, bool escaped); @@ -187,6 +198,7 @@ namespace triagens { char _quote; char _separator; + bool _createCollection; size_t _numberLines; size_t _numberOk; diff --git a/V8Client/arangoimp.cpp b/V8Client/arangoimp.cpp index d92fe37311..ed8c0e569c 100644 --- a/V8Client/arangoimp.cpp +++ b/V8Client/arangoimp.cpp @@ -91,6 +91,7 @@ static string SeparatorChar = ","; static string FileName = ""; static string CollectionName = ""; static string TypeImport = "json"; +static bool CreateCollection = false; //////////////////////////////////////////////////////////////////////////////// /// @} @@ -158,6 +159,7 @@ static void ParseProgramOptions (int argc, char* argv[]) { ("server", &ServerAddress, "server address and port") ("file", &FileName, "file name (\"-\" for STDIN)") ("collection", &CollectionName, "collection name") + ("create-collection", &CreateCollection, "create collection if it does not yet exist") ("type", &TypeImport, "type of file (\"csv\" or \"json\")") ("quote", &QuoteChar, "quote character") ("separator", &SeparatorChar, "separator character") @@ -238,6 +240,7 @@ int main (int argc, char* argv[]) { cout << "----------------------------------------" << endl; cout << "collection : " << CollectionName << endl; + cout << "create : " << (CreateCollection ? "yes" : "no") << endl; cout << "file : " << FileName << endl; cout << "type : " << TypeImport << endl; cout << "quote : " << QuoteChar << endl; @@ -245,6 +248,10 @@ int main (int argc, char* argv[]) { cout << "----------------------------------------" << endl; ImportHelper ih(clientConnection->getHttpClient(), maxUploadSize); + + if (CreateCollection) { + ih.setCreateCollection(true); + } if (QuoteChar.length() == 1) { ih.setQuote(QuoteChar[0]); From 24d829bb5c09e13ded32eb3026a982c4a69826ee Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Mon, 21 May 2012 14:46:59 +0200 Subject: [PATCH 3/5] added tests for skiplist queries --- Makefile.unittests | 1 + js/server/tests/ahuacatl-skiplist.js | 293 +++++++++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 js/server/tests/ahuacatl-skiplist.js diff --git a/Makefile.unittests b/Makefile.unittests index 61cc121a51..b04690878b 100644 --- a/Makefile.unittests +++ b/Makefile.unittests @@ -186,6 +186,7 @@ SHELL_SERVER_AHUACATL = @srcdir@/js/server/tests/ahuacatl-operators.js \ @srcdir@/js/server/tests/ahuacatl-relational.js \ @srcdir@/js/server/tests/ahuacatl-ternary.js \ @srcdir@/js/server/tests/ahuacatl-parse.js \ + @srcdir@/js/server/tests/ahuacatl-skiplist.js \ @srcdir@/js/server/tests/ahuacatl-queries-simple.js \ @srcdir@/js/server/tests/ahuacatl-queries-variables.js \ @srcdir@/js/server/tests/ahuacatl-queries-geo.js \ diff --git a/js/server/tests/ahuacatl-skiplist.js b/js/server/tests/ahuacatl-skiplist.js new file mode 100644 index 0000000000..c6448e58a5 --- /dev/null +++ b/js/server/tests/ahuacatl-skiplist.js @@ -0,0 +1,293 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief tests for Ahuacatl, skiplist index queries +/// +/// @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 Jan Steemann +/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +var internal = require("internal"); +var jsunity = require("jsunity"); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test suite +//////////////////////////////////////////////////////////////////////////////// + +function ahuacatlSkiplistTestSuite () { + var errors = internal.errors; + var skiplist; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief execute a given query +//////////////////////////////////////////////////////////////////////////////// + + function executeQuery (query, bindVars) { + var cursor = AHUACATL_RUN(query, bindVars); + return cursor; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief execute a given query and return the results as an array +//////////////////////////////////////////////////////////////////////////////// + + function getQueryResults (query, bindVars) { + var result = executeQuery(query, bindVars).getRows(); + var results = [ ]; + + for (var i in result) { + if (!result.hasOwnProperty(i)) { + continue; + } + + results.push(result[i]); + } + + return results; + } + + + return { + +//////////////////////////////////////////////////////////////////////////////// +/// @brief set up +//////////////////////////////////////////////////////////////////////////////// + + setUp : function () { + skiplist = internal.db.UnitTestsAhuacatlSkiplist; + + if (skiplist.count() == 0) { + for (var i = 1; i <= 5; ++i) { + for (var j = 1; j <= 5; ++j) { + skiplist.save({ "a" : i, "b": j }); + } + } + + skiplist.ensureSkiplist("a", "b"); + } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief tear down +//////////////////////////////////////////////////////////////////////////////// + + tearDown : function () { + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first skiplist index field with equality +//////////////////////////////////////////////////////////////////////////////// + + testEqSingle1 : function () { + var expected = [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 1, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a == 1 SORT v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first skiplist index field with equality +//////////////////////////////////////////////////////////////////////////////// + + testEqSingle2 : function () { + var expected = [ [ 5, 1 ], [ 5, 2 ], [ 5, 3 ], [ 5, 4 ], [ 5, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a == 5 SORT v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first skiplist index field with greater than +//////////////////////////////////////////////////////////////////////////////// + + testGtSingle : function () { + var expected = [ [ 5, 1 ], [ 5, 2 ], [ 5, 3 ], [ 5, 4 ], [ 5, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a > 4 SORT v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first skiplist index field with greater equal +//////////////////////////////////////////////////////////////////////////////// + + testGeSingle : function () { + var expected = [ [ 5, 1 ], [ 5, 2 ], [ 5, 3 ], [ 5, 4 ], [ 5, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a >= 5 SORT v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first skiplist index field with less than +//////////////////////////////////////////////////////////////////////////////// + + testLtSingle : function () { + var expected = [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 1, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a < 2 SORT v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first skiplist index field with greater equal +//////////////////////////////////////////////////////////////////////////////// + + testGeSingle : function () { + var expected = [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 1, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a <= 1 SORT v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first skiplist index field with a range access +//////////////////////////////////////////////////////////////////////////////// + + testRangeSingle1 : function () { + var expected = [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 1, 5 ], [ 2, 1 ], [ 2, 2 ], [ 2, 3 ], [ 2, 4 ], [ 2, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a >= 1 && v.a <= 2 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first skiplist index field with a range access +//////////////////////////////////////////////////////////////////////////////// + + testRangeSingle2 : function () { + var expected = [ ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a > 1 && v.a < 2 RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first skiplist index field with a range access +//////////////////////////////////////////////////////////////////////////////// + + testRangeSingle3 : function () { + var expected = [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 1, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a >= 1 && v.a < 2 SORT v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first skiplist index field with a range access +//////////////////////////////////////////////////////////////////////////////// + + testRangeSingle3 : function () { + var expected = [ [ 2, 1 ], [ 2, 2 ], [ 2, 3 ], [ 2, 4 ], [ 2, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a > 1 && v.a <= 2 SORT v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test two skiplist index fields with equality +//////////////////////////////////////////////////////////////////////////////// + + testEqMultiAll : function () { + for (var i = 1; i <= 5; ++i) { + for (var j = 1; j <=5; ++j) { + var expected = [ [ i, j ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a == @a && v.b == @b RETURN [ v.a, v.b ]", { "a" : i, "b" : j }); + + assertEqual(expected, actual); + } + } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test two skiplist index fields with different operators +//////////////////////////////////////////////////////////////////////////////// + + testEqGt1 : function () { + var expected = [ [ 1, 3 ], [ 1, 4 ], [ 1, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a == 1 && v.b > 2 SORT v.b RETURN [ v.a, v.b ]"); + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test two skiplist index fields with different operators +//////////////////////////////////////////////////////////////////////////////// + + testEqGt2 : function () { + var expected = [ [ 4, 4 ], [ 4, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a == 4 && v.b > 3 SORT v.b RETURN [ v.a, v.b ]"); + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test two skiplist index fields with different operators +//////////////////////////////////////////////////////////////////////////////// + + testEqLt1 : function () { + var expected = [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a == 1 && v.b < 4 SORT v.b RETURN [ v.a, v.b ]"); + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test two skiplist index fields with different operators +//////////////////////////////////////////////////////////////////////////////// + + testEqLt2 : function () { + var expected = [ [ 5, 1 ], [ 5, 2 ], [ 5, 3 ], [ 5, 4 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a == 5 && v.b < 5 SORT v.b RETURN [ v.a, v.b ]"); + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test two skiplist index fields with different operators +//////////////////////////////////////////////////////////////////////////////// + + testEqLe1 : function () { + var expected = [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a == 1 && v.b <= 3 SORT v.b RETURN [ v.a, v.b ]"); + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test two skiplist index fields with different operators +//////////////////////////////////////////////////////////////////////////////// + + testEqLe2 : function () { + var expected = [ [ 5, 1 ], [ 5, 2 ], [ 5, 3 ], [ 5, 4 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a == 5 && v.b <= 4 SORT v.b RETURN [ v.a, v.b ]"); + assertEqual(expected, actual); + }, + }; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief executes the test suite +//////////////////////////////////////////////////////////////////////////////// + +jsunity.run(ahuacatlSkiplistTestSuite); + +return jsunity.done(); + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)" +// End: From 46ea63a11ccbd93c7b63da93baa4069041fc318e Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Mon, 21 May 2012 14:57:49 +0200 Subject: [PATCH 4/5] more test cases --- js/server/tests/ahuacatl-skiplist.js | 235 ++++++++++++++++++++++++++- 1 file changed, 228 insertions(+), 7 deletions(-) diff --git a/js/server/tests/ahuacatl-skiplist.js b/js/server/tests/ahuacatl-skiplist.js index c6448e58a5..0789536711 100644 --- a/js/server/tests/ahuacatl-skiplist.js +++ b/js/server/tests/ahuacatl-skiplist.js @@ -203,7 +203,7 @@ function ahuacatlSkiplistTestSuite () { }, //////////////////////////////////////////////////////////////////////////////// -/// @brief test two skiplist index fields with equality +/// @brief test multiple skiplist fields with multiple operators //////////////////////////////////////////////////////////////////////////////// testEqMultiAll : function () { @@ -218,7 +218,7 @@ function ahuacatlSkiplistTestSuite () { }, //////////////////////////////////////////////////////////////////////////////// -/// @brief test two skiplist index fields with different operators +/// @brief test multiple skiplist fields with multiple operators //////////////////////////////////////////////////////////////////////////////// testEqGt1 : function () { @@ -228,7 +228,7 @@ function ahuacatlSkiplistTestSuite () { }, //////////////////////////////////////////////////////////////////////////////// -/// @brief test two skiplist index fields with different operators +/// @brief test multiple skiplist fields with multiple operators //////////////////////////////////////////////////////////////////////////////// testEqGt2 : function () { @@ -238,7 +238,7 @@ function ahuacatlSkiplistTestSuite () { }, //////////////////////////////////////////////////////////////////////////////// -/// @brief test two skiplist index fields with different operators +/// @brief test multiple skiplist fields with multiple operators //////////////////////////////////////////////////////////////////////////////// testEqLt1 : function () { @@ -248,7 +248,7 @@ function ahuacatlSkiplistTestSuite () { }, //////////////////////////////////////////////////////////////////////////////// -/// @brief test two skiplist index fields with different operators +/// @brief test multiple skiplist fields with multiple operators //////////////////////////////////////////////////////////////////////////////// testEqLt2 : function () { @@ -258,7 +258,7 @@ function ahuacatlSkiplistTestSuite () { }, //////////////////////////////////////////////////////////////////////////////// -/// @brief test two skiplist index fields with different operators +/// @brief test multiple skiplist fields with multiple operators //////////////////////////////////////////////////////////////////////////////// testEqLe1 : function () { @@ -268,7 +268,7 @@ function ahuacatlSkiplistTestSuite () { }, //////////////////////////////////////////////////////////////////////////////// -/// @brief test two skiplist index fields with different operators +/// @brief test multiple skiplist fields with multiple operators //////////////////////////////////////////////////////////////////////////////// testEqLe2 : function () { @@ -276,6 +276,227 @@ function ahuacatlSkiplistTestSuite () { var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a == 5 && v.b <= 4 SORT v.b RETURN [ v.a, v.b ]"); assertEqual(expected, actual); }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testLtlt : function () { + var expected = [ [ 1, 1 ], [ 1, 2 ], [ 2, 1 ], [ 2, 2 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a < 3 && v.b < 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testLeLe : function () { + var expected = [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 2, 1 ], [ 2, 2 ], [ 2, 3 ], [ 3, 1 ], [ 3, 2 ], [ 3, 3 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a <= 3 && v.b <= 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testLtLe : function () { + var expected = [ [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 2, 1 ], [ 2, 2 ], [ 2, 3 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a < 3 && v.b <= 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testLeLt : function () { + var expected = [ [ 1, 1 ], [ 1, 2 ], [ 2, 1 ], [ 2, 2 ], [ 3, 1 ], [ 3, 2 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a <= 3 && v.b < 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testLtEq : function () { + var expected = [ [ 1, 4 ], [ 2, 4 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a < 3 && v.b == 4 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testLeEq : function () { + var expected = [ [ 1, 4 ], [ 2, 4 ], [ 3, 4 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a <= 3 && v.b == 4 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testLtGt : function () { + var expected = [ [ 1, 4 ], [ 1, 5 ], [ 2, 4 ], [ 2, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a < 3 && v.b > 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testLeGe : function () { + var expected = [ [ 1, 3 ], [ 1, 4 ], [ 1, 5 ], [ 2, 3 ], [ 2, 4 ], [ 2, 5 ], [ 3, 3 ], [ 3, 4 ], [ 3, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a <= 3 && v.b >= 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testLtGe : function () { + var expected = [ [ 1, 3 ], [ 1, 4 ], [ 1, 5 ], [ 2, 3 ], [ 2, 4 ], [ 2, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a < 3 && v.b >= 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testLeGt : function () { + var expected = [ [ 1, 4 ], [ 1, 5 ], [ 2, 4 ], [ 2, 5 ], [ 3, 4 ], [ 3, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a <= 3 && v.b > 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testGtlt : function () { + var expected = [ [ 4, 1 ], [ 4, 2 ], [ 5, 1 ], [ 5, 2 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a > 3 && v.b < 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testGeLe : function () { + var expected = [ [ 3, 1 ], [ 3, 2 ], [ 3, 3 ], [ 4, 1 ], [ 4, 2 ], [ 4, 3 ], [ 5, 1 ], [ 5, 2 ], [ 5, 3 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a >= 3 && v.b <= 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testGtLe : function () { + var expected = [ [ 4, 1 ], [ 4, 2 ], [ 4, 3 ], [ 5, 1 ], [ 5, 2 ], [ 5, 3 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a > 3 && v.b <= 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testGeLt : function () { + var expected = [ [ 3, 1 ], [ 3, 2 ], [ 4, 1 ], [ 4, 2 ], [ 5, 1 ], [ 5, 2 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a >= 3 && v.b < 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testGtEq : function () { + var expected = [ [ 4, 4 ], [ 5, 4 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a > 3 && v.b == 4 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testGeEq : function () { + var expected = [ [ 3, 4 ], [ 4, 4 ], [ 5, 4 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a >= 3 && v.b == 4 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testGtGt : function () { + var expected = [ [ 4, 4 ], [ 4, 5 ], [ 5, 4 ], [ 5, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a > 3 && v.b > 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testGeGe : function () { + var expected = [ [ 3, 3 ], [ 3, 4 ], [ 3, 5 ], [ 4, 3 ], [ 4, 4 ], [ 4, 5 ], [ 5, 3 ], [ 5, 4 ], [ 5, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a >= 3 && v.b >= 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testGtGe : function () { + var expected = [ [ 4, 3 ], [ 4, 4 ], [ 4, 5 ], [ 5, 3 ], [ 5, 4 ], [ 5, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a > 3 && v.b >= 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple skiplist fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testGeGt : function () { + var expected = [ [ 3, 4 ], [ 3, 5 ], [ 4, 4 ], [ 4, 5 ], [ 5, 4 ], [ 5, 5 ] ]; + var actual = getQueryResults("FOR v IN " + skiplist.name() + " FILTER v.a >= 3 && v.b > 3 SORT v.a, v.b RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + }; } From 74ab2da22c2951fb58aadf86f9a42a703f183e42 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Mon, 21 May 2012 15:51:59 +0200 Subject: [PATCH 5/5] issue #67: skiplist interface does not support range operations and two different attributes. now, make such queries fail --- V8/v8-query.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/V8/v8-query.cpp b/V8/v8-query.cpp index 7b6dc076d2..95043c61ff 100644 --- a/V8/v8-query.cpp +++ b/V8/v8-query.cpp @@ -228,15 +228,15 @@ static TRI_sl_operator_t* SetupConditionsSkiplist (TRI_index_t* idx, TRI_sl_operator_t* lastOperator = 0; TRI_json_t* parameters = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE); size_t numEq = 0; - size_t numNonEq = 0; + size_t lastNonEq = 0; if (parameters == 0) { return 0; } // iterate over all index fields - for (size_t i = 0; i < idx->_fields._length; ++i) { - v8::Handle key = v8::String::New(idx->_fields._buffer[i]); + for (size_t i = 1; i <= idx->_fields._length; ++i) { + v8::Handle key = v8::String::New(idx->_fields._buffer[i - 1]); if (!conditions->HasOwnProperty(key)) { break; @@ -283,7 +283,7 @@ static TRI_sl_operator_t* SetupConditionsSkiplist (TRI_index_t* idx, if (opValue == "==") { // equality comparison - if (numNonEq > 0) { + if (lastNonEq > 0) { goto MEM_ERROR; } @@ -293,6 +293,12 @@ static TRI_sl_operator_t* SetupConditionsSkiplist (TRI_index_t* idx, break; } else { + if (lastNonEq > 0 && lastNonEq != i) { + // if we already had a range condition and a previous field, we cannot continue + // because the skiplist interface does not support such queries + goto MEM_ERROR; + } + TRI_sl_operator_type_e opType; if (opValue == ">") { opType = TRI_SL_GT_OPERATOR; @@ -311,7 +317,7 @@ static TRI_sl_operator_t* SetupConditionsSkiplist (TRI_index_t* idx, goto MEM_ERROR; } - ++numNonEq; + lastNonEq = i; TRI_json_t* cloned = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, parameters); if (cloned == 0) { @@ -363,7 +369,7 @@ static TRI_sl_operator_t* SetupConditionsSkiplist (TRI_index_t* idx, if (numEq) { // create equality operator if one is in queue assert(lastOperator == 0); - assert(numNonEq == 0); + assert(lastNonEq == 0); TRI_json_t* clonedParams = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, parameters); if (clonedParams == 0) {