diff --git a/CMakeLists.txt b/CMakeLists.txt index e0fda19867..8803747263 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -691,7 +691,7 @@ if (OPENSSL_LIB_PATH) endif () ################################################################################ -### @brief READLINE or LINENOISE +### @brief LINENOISE ################################################################################ if (MSVC) diff --git a/Documentation/Books/Users/IndexHandling/WhichIndex.mdpp b/Documentation/Books/Users/IndexHandling/WhichIndex.mdpp index 1d8803519c..c062047125 100644 --- a/Documentation/Books/Users/IndexHandling/WhichIndex.mdpp +++ b/Documentation/Books/Users/IndexHandling/WhichIndex.mdpp @@ -54,14 +54,14 @@ different usage scenarios: Geo indexes will only be invoked via special functions. -- full-text index: a full-text index can be used to index all words contained in +- fulltext index: a fulltext index can be used to index all words contained in a specific attribute of all documents in a collection. Only words with a (specifiable) minimum length are indexed. Word tokenization is done using the word boundary analysis provided by libicu, which is taking into account the selected language provided at server start. The index supports complete match queries (full words) and prefix queries. - Full-text indexes will only be invoked via special functions. + Fulltext indexes will only be invoked via special functions. - cap constraint: the cap constraint provided by ArangoDB indexes documents not to speed up search queries, but to limit (cap) the number or size of @@ -114,7 +114,7 @@ the lookup value cannot be `null`, a sparse index may be used. When uncertain, t will not make use of a sparse index in a query in order to produce correct results. For example, the following queries cannot use a sparse index on `attr` because the optimizer -will not know beforehand whether the comparison values for `doc.attr` will include `null`: +will not know beforehand whether the values which are compared to `doc.attr` will include `null`: FOR doc In collection FILTER doc.attr == SOME_FUNCTION(...) diff --git a/LICENSES-OTHER-COMPONENTS.md b/LICENSES-OTHER-COMPONENTS.md index 8a2c0bbaec..b01b122f98 100644 --- a/LICENSES-OTHER-COMPONENTS.md +++ b/LICENSES-OTHER-COMPONENTS.md @@ -19,7 +19,7 @@ ### zlib -* free as-is license +* [free as-is license](https://github.com/arangodb/arangodb/blob/devel/3rdParty/zlib-1.2.7/README#L85) ### Valgrind @@ -31,12 +31,6 @@ * http://www.boost.org/ * [boost software license](http://www.boost.org/LICENSE_1_0.txt) -### readline - -* http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html -* GNU GPL -* alternatively linenoise can be used - ### linenoise * https://github.com/antirez/linenoise @@ -57,9 +51,8 @@ ### Bison * https://www.gnu.org/software/bison/ -* GNU GPL3 * only used to generate code, not part of the distribution -* see https://github.com/arangodb/arangodb/blob/devel/arangod/Aql/grammar.cpp#L20 +* parts used see https://github.com/arangodb/arangodb/blob/devel/arangod/Aql/grammar.cpp#L20 ### Flex @@ -79,27 +72,27 @@ #### Jasmine * https://jasmine.github.io -* MIT License +* [MIT License](https://raw.githubusercontent.com/jasmine/jasmine/master/MIT.LICENSE) #### JSUnity * https://github.com/atesgoral/jsunity -* MIT License +* [MIT License](http://www.opensource.org/licenses/mit-license.php) #### ArangoDB Query Builder * https://github.com/arangodb/aqbjs -* Apache 2 +* [Apache 2](https://raw.githubusercontent.com/arangodb/aqbjs/master/LICENSE) #### Chai * http://chaijs.com -* MIT License +* [MIT License](https://github.com/chaijs/chai/blob/master/README.md) #### CoffeeScript * http://coffeescript.org -* MIT License +* [MIT License](https://www.npmjs.com/package/coffee-script) #### stacktrace.js @@ -109,72 +102,72 @@ #### expect.js * https://github.com/Automattic/expect.js -* MIT License +* [MIT License](https://github.com/Automattic/expect.js/blob/master/README.md) #### extendible * https://github.com/3rd-Eden/extendible -* MIT License +* [MIT License](https://github.com/bigpipe/extendible/blob/master/README.md) #### Foxx Generator * https://github.com/moonglum/foxx_generator -* Apache 2 License +* [Apache 2 License](https://raw.githubusercontent.com/moonglum/foxx_generator/master/LICENSE) #### highlight.js * https://highlightjs.org -* BSD 3-Clause License +* [BSD 3-Clause License](https://raw.githubusercontent.com/isagalaev/highlight.js/master/LICENSE) #### http-errors * https://github.com/jshttp/http-errors -* MIT License +* [MIT License](https://raw.githubusercontent.com/jshttp/http-errors/master/LICENSE) #### i * https://github.com/pksunkara/inflect -* MIT License +* [MIT License](https://raw.githubusercontent.com/pksunkara/inflect/master/LICENSE) #### Joi * https://github.com/hapijs/joi -* BSD 3-Clause License +* [BSD 3-Clause License](https://raw.githubusercontent.com/hapijs/joi/master/LICENSE) #### Ace * https://github.com/ajaxorg/ace -* BSD 3-Clause License +* [BSD 3-Clause License](https://raw.githubusercontent.com/ajaxorg/ace/master/LICENSE) #### YAML * https://github.com/nodeca/js-yaml -* MIT License +* [MIT License](https://raw.githubusercontent.com/nodeca/js-yaml/master/LICENSE) #### JSHint * http://jshint.com -* MIT License +* [MIT License](https://raw.githubusercontent.com/jshint/jshint/master/LICENSE) #### minimatch * https://github.com/isaacs/minimatch -* MIT License +* [MIT License](https://raw.githubusercontent.com/isaacs/minimatch/master/LICENSE) #### mocha * http://mochajs.org -* MIT License +* [MIT License](https://raw.githubusercontent.com/mochajs/mocha/master/LICENSE) #### qs * https://github.com/hapijs/qs -* BSD 3-Clause License +* [BSD 3-Clause License](https://raw.githubusercontent.com/hapijs/hapi/master/LICENSE) #### Ramda * http://ramdajs.com -* MIT License +* [MIT License](https://raw.githubusercontent.com/ramda/ramda/master/LICENSE.txt) #### semver @@ -184,109 +177,111 @@ #### Sinon.JS * http://sinonjs.org -* BSD 3-Clause License +* [BSD 3-Clause License](https://www.npmjs.com/package/sinon) #### underscore * http://underscorejs.org -* MIT License +* [MIT License](https://github.com/jashkenas/underscore/blob/master/LICENSE) ### Frontend libraries #### swagger * http://swagger.io -* Apache 2 License +* [Apache 2 License](https://raw.githubusercontent.com/swagger-api/swagger-js/master/LICENSE) #### Backbone.js * http://backbonejs.org -* MIT License +* [MIT License](https://raw.githubusercontent.com/jashkenas/backbone/master/LICENSE) #### Bootstrap * http://getbootstrap.com -* MIT License +* [MIT License](https://github.com/twbs/bootstrap/blob/master/LICENSE) #### D3js * http://d3js.org -* BSD 3-Clause License +* [BSD 3-Clause License](https://raw.githubusercontent.com/mbostock/d3/master/LICENSE) #### dygraph * http://dygraphs.com -* MIT License +* [MIT License](https://www.npmjs.com/package/dygraphs) #### EJS * http://www.embeddedjs.com -* MIT License +* [MIT License](http://www.embeddedjs.com/) under Highlights #### jqconsole * https://github.com/replit/jq-console -* MIT License +* [MIT License](https://github.com/replit/jq-console/blob/master/README.md) #### jQuery * http://jquery.com -* MIT License +* [MIT License](https://raw.githubusercontent.com/jquery/jquery/master/LICENSE.txt) #### jQuery UI * http://jqueryui.com -* MIT License +* [MIT License](https://raw.githubusercontent.com/jquery/jquery-ui/master/LICENSE.txt) #### jQuery Snippet * http://steamdev.com/snippet -* MIT License +* [MIT License](https://web.archive.org/web/20150817084109/http://steamdev.com/snippet/) in "section 5" #### jQuery Hotkeys -* https://github.com/jeresig/jquery.hotkeys -* MIT License or GPL Version 2 License +* https://code.google.com/p/js-hotkeys/ +* [MIT License](https://code.google.com/p/js-hotkeys/) under "Code license" #### jQuery Contextmenu * https://github.com/swisnl/jQuery-contextMenu -* MIT License +* [MIT License](https://github.com/swisnl/jQuery-contextMenu) under "License" #### jQuery Form * https://github.com/malsup/form/ -* MIT License or GPL Version 2 License +* [MIT License](https://github.com/malsup/form/) under "Copyright and License" #### jQuery UploadFile * https://github.com/hayageek/jquery-upload-file/ -* MIT License +* [MIT License](https://raw.githubusercontent.com/hayageek/jquery-upload-file/master/MIT-License.txt) #### jQuery Textfill * https://github.com/jquery-textfill/jquery-textfill -* MIT License +* [MIT License](https://raw.githubusercontent.com/jquery-textfill/jquery-textfill/master/COPYING.md) #### jQuery Strftime * https://github.com/samsonjs/strftime -* MIT License +* [MIT License](https://github.com/samsonjs/strftime) under "License" #### nvd3 * https://github.com/novus/nvd3 -* Apache 2 License +* [Apache 2 License](https://github.com/novus/nvd3/blob/master/LICENSE.md) under "nvd3.js" #### jsoneditor.js -* Apache 2 License +* https://github.com/josdejong/jsoneditor/ +* [Apache 2 License](https://raw.githubusercontent.com/josdejong/jsoneditor/master/LICENSE) #### Crypto.js * https://github.com/brix/crypto-js -* MIT License / BSD 3-Clause License +* [MIT License](https://github.com/brix/crypto-js) under "License" #### select2 -* Apache 2 License +* https://github.com/select2/select2 +* [Apache 2 License](https://github.com/select2/select2) diff --git a/Makefile.am b/Makefile.am index 2a8adad87d..9a90dae9fa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -118,7 +118,6 @@ AM_CPPFLAGS = \ @LIBEV_CPPFLAGS@ \ @MATH_CPPFLAGS@ \ @OPENSSL_CPPFLAGS@ \ - @READLINE_CPPFLAGS@ \ @ICU_CPPFLAGS@ \ @ZLIB_CPPFLAGS@ \ @V8_CPPFLAGS@ @@ -131,7 +130,6 @@ AM_LDFLAGS = \ @LIBEV_LDFLAGS@ \ @MATH_LDFLAGS@ \ @OPENSSL_LDFLAGS@ \ - @READLINE_LDFLAGS@ \ @ICU_LDFLAGS@ \ @ZLIB_LDFLAGS@ \ @V8_LDFLAGS@ @@ -147,8 +145,7 @@ LIBS = \ @MATH_LIBS@ \ @OPENSSL_LIBS@ \ @ICU_LIBS@ \ - @ZLIB_LIBS@ \ - @READLINE_LIBS@ + @ZLIB_LIBS@ ## ----------------------------------------------------------------------------- ## --SECTION-- LIBRARIES & PROGRAMS @@ -528,11 +525,6 @@ cmake-setup: -D OPENSSL_LIBS= \ -D OPENSSL_VERSION= \ \ - -D READLINE_INCLUDE= \ - -D READLINE_LIB_PATH= \ - -D READLINE_LIBS= \ - -D READLINE_VERSION= \ - \ -D V8_INCLUDE= \ -D V8_LIB_PATH= \ -D V8_LIBS= \ diff --git a/arangod/Aql/Ast.cpp b/arangod/Aql/Ast.cpp index 01bb51e5d6..6e0b2e5a1b 100644 --- a/arangod/Aql/Ast.cpp +++ b/arangod/Aql/Ast.cpp @@ -1756,8 +1756,12 @@ AstNode* Ast::clone (AstNode const* node) { // recursively clone subnodes size_t const n = node->numMembers(); - for (size_t i = 0; i < n; ++i) { - copy->addMember(clone(node->getMemberUnchecked(i))); + if (n > 0) { + copy->members.reserve(n); + + for (size_t i = 0; i < n; ++i) { + copy->addMember(clone(node->getMemberUnchecked(i))); + } } return copy; diff --git a/arangod/Aql/IndexBlock.cpp b/arangod/Aql/IndexBlock.cpp index 75597d0f6c..26df363d31 100644 --- a/arangod/Aql/IndexBlock.cpp +++ b/arangod/Aql/IndexBlock.cpp @@ -403,7 +403,7 @@ bool IndexBlock::readIndex (size_t atMost) { size_t lastIndexNr = _indexes.size() - 1; bool isReverse = (static_cast(getPlanNode()))->_reverse; - bool isLastIndex = (_currentIndex == lastIndexNr && !isReverse) || (_currentIndex == 0 && isReverse); + bool isLastIndex = (_currentIndex == lastIndexNr && ! isReverse) || (_currentIndex == 0 && isReverse); try { size_t nrSent = 0; while (nrSent < atMost && _iterator != nullptr) { diff --git a/arangod/CMakeLists.txt b/arangod/CMakeLists.txt index b2c52e5693..6e3609045a 100644 --- a/arangod/CMakeLists.txt +++ b/arangod/CMakeLists.txt @@ -279,7 +279,6 @@ target_link_libraries( ${ICU_LIBS} ${BT_LIBS} ${ZLIB_LIBS} - ${READLINE_LIBS} ${OPENSSL_LIBS} ${CMAKE_THREAD_LIBS_INIT} ${MSVC_LIBS} diff --git a/arangod/Indexes/HashIndex.cpp b/arangod/Indexes/HashIndex.cpp index 48c10db7a9..8c68caced4 100644 --- a/arangod/Indexes/HashIndex.cpp +++ b/arangod/Indexes/HashIndex.cpp @@ -812,7 +812,7 @@ IndexIterator* HashIndex::iteratorForCondition (IndexIteratorContext* context, triagens::aql::Ast* ast, triagens::aql::AstNode const* node, triagens::aql::Variable const* reference, - bool const reverse) const { + bool reverse) const { TRI_ASSERT(node->type == aql::NODE_TYPE_OPERATOR_NARY_AND); SimpleAttributeEqualityMatcher matcher(fields()); @@ -824,13 +824,17 @@ IndexIterator* HashIndex::iteratorForCondition (IndexIteratorContext* context, std::vector permutationStates; permutationStates.reserve(n); size_t maxPermutations = 1; + + std::pair> paramPair; for (size_t i = 0; i < n; ++i) { - std::pair> paramPair; auto comp = allVals->getMemberUnchecked(i); auto attrNode = comp->getMember(0); auto valNode = comp->getMember(1); + paramPair.first = nullptr; + paramPair.second.clear(); + if (! attrNode->isAttributeAccessForVariable(paramPair) || paramPair.first != reference) { attrNode = comp->getMember(1); valNode = comp->getMember(0); diff --git a/arangod/Indexes/HashIndex.h b/arangod/Indexes/HashIndex.h index cbbab0dc00..a3fba97814 100644 --- a/arangod/Indexes/HashIndex.h +++ b/arangod/Indexes/HashIndex.h @@ -192,7 +192,7 @@ namespace triagens { triagens::aql::Ast*, triagens::aql::AstNode const*, triagens::aql::Variable const*, - bool const) const override; + bool) const override; triagens::aql::AstNode* specializeCondition (triagens::aql::AstNode*, triagens::aql::Variable const*) const override; diff --git a/arangod/Indexes/Index.cpp b/arangod/Indexes/Index.cpp index 9dab1e75e9..7bae137913 100644 --- a/arangod/Indexes/Index.cpp +++ b/arangod/Indexes/Index.cpp @@ -553,7 +553,8 @@ triagens::aql::AstNode* Index::specializeCondition (triagens::aql::AstNode* node bool Index::canUseConditionPart (triagens::aql::AstNode const* access, triagens::aql::AstNode const* other, triagens::aql::AstNode const* op, - triagens::aql::Variable const* reference) const { + triagens::aql::Variable const* reference, + bool isExecution) const { if (_sparse) { if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_NIN) { @@ -614,6 +615,11 @@ bool Index::canUseConditionPart (triagens::aql::AstNode const* access, } } + if (isExecution) { + // in execution phase, we do not need to check the variable usage again + return true; + } + // test if the reference variable is contained on both side of the expression std::unordered_set variables; if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN && diff --git a/arangod/Indexes/Index.h b/arangod/Indexes/Index.h index 0ed33abb03..13ea06b363 100644 --- a/arangod/Indexes/Index.h +++ b/arangod/Indexes/Index.h @@ -370,7 +370,8 @@ namespace triagens { bool canUseConditionPart (triagens::aql::AstNode const* access, triagens::aql::AstNode const* other, triagens::aql::AstNode const* op, - triagens::aql::Variable const* reference) const; + triagens::aql::Variable const* reference, + bool) const; // ----------------------------------------------------------------------------- // --SECTION-- protected variables diff --git a/arangod/Indexes/SimpleAttributeEqualityMatcher.cpp b/arangod/Indexes/SimpleAttributeEqualityMatcher.cpp index c1e230ccab..c165785c92 100644 --- a/arangod/Indexes/SimpleAttributeEqualityMatcher.cpp +++ b/arangod/Indexes/SimpleAttributeEqualityMatcher.cpp @@ -72,8 +72,8 @@ bool SimpleAttributeEqualityMatcher::matchOne (triagens::arango::Index const* in if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_EQ) { TRI_ASSERT(op->numMembers() == 2); // EQ is symmetric - if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference) || - accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference)) { + if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference, false) || + accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference, false)) { // we can use the index calculateIndexCosts(index, itemsInIndex, estimatedItems, estimatedCost); return true; @@ -81,7 +81,7 @@ bool SimpleAttributeEqualityMatcher::matchOne (triagens::arango::Index const* in } else if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN) { TRI_ASSERT(op->numMembers() == 2); - if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference)) { + if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference, false)) { // we can use the index // use slightly different cost calculation for IN that for EQ calculateIndexCosts(index, itemsInIndex, estimatedItems, estimatedCost); @@ -118,8 +118,8 @@ bool SimpleAttributeEqualityMatcher::matchAll (triagens::arango::Index const* in if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_EQ) { TRI_ASSERT(op->numMembers() == 2); - if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference) || - accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference)) { + if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference, false) || + accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference, false)) { if (_found.size() == _attributes.size()) { // got enough attributes break; @@ -129,7 +129,7 @@ bool SimpleAttributeEqualityMatcher::matchAll (triagens::arango::Index const* in else if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN) { TRI_ASSERT(op->numMembers() == 2); - if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference)) { + if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference, false)) { auto m = op->getMember(1); if (m->type != triagens::aql::NODE_TYPE_EXPANSION && m->numMembers() > 1) { // attr IN [ a, b, c ] => this will produce multiple items, so count them! @@ -182,10 +182,10 @@ triagens::aql::AstNode* SimpleAttributeEqualityMatcher::getOne (triagens::aql::A op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN) { TRI_ASSERT(op->numMembers() == 2); // note: accessFitsIndex will increase _found in case of a condition match - bool matches = accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference); + bool matches = accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference, true); if (! matches && op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_EQ) { - matches = accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference); + matches = accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference, true); } if (matches) { @@ -223,11 +223,11 @@ triagens::aql::AstNode* SimpleAttributeEqualityMatcher::getAll (triagens::aql::A op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN) { TRI_ASSERT(op->numMembers() == 2); // note: accessFitsIndex will increase _found in case of a condition match - bool matches = accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference); + bool matches = accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference, true); if (! matches && op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_EQ) { // EQ is symmetric - matches = accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference); + matches = accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference, true); } if (matches) { @@ -238,14 +238,14 @@ triagens::aql::AstNode* SimpleAttributeEqualityMatcher::getAll (triagens::aql::A if (_found.size() == _attributes.size()) { // got enough matches - std::unique_ptr node(ast->createNodeNaryOperator(triagens::aql::NODE_TYPE_OPERATOR_NARY_AND)); + auto node = ast->createNodeNaryOperator(triagens::aql::NODE_TYPE_OPERATOR_NARY_AND); for (auto& it : parts) { - node->addMember(ast->clone(it)); + node->addMember(it); } // done - return node.release(); + return node; } } } @@ -274,8 +274,8 @@ triagens::aql::AstNode* SimpleAttributeEqualityMatcher::specializeOne (triagens: if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_EQ) { TRI_ASSERT(op->numMembers() == 2); // EQ is symmetric - if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference) || - accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference)) { + if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference, false) || + accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference, false)) { // we can use the index // now return only the child node we need while (node->numMembers() > 0) { @@ -289,7 +289,7 @@ triagens::aql::AstNode* SimpleAttributeEqualityMatcher::specializeOne (triagens: else if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN) { TRI_ASSERT(op->numMembers() == 2); - if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference)) { + if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference, false)) { // we can use the index // now return only the child node we need while (node->numMembers() > 0) { @@ -325,8 +325,8 @@ triagens::aql::AstNode* SimpleAttributeEqualityMatcher::specializeAll (triagens: if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_EQ) { TRI_ASSERT(op->numMembers() == 2); - if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference) || - accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference)) { + if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference, false) || + accessFitsIndex(index, op->getMember(1), op->getMember(0), op, reference, false)) { children.emplace_back(op); TRI_IF_FAILURE("SimpleAttributeMatcher::specializeAllChildrenEQ") { THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG); @@ -339,7 +339,7 @@ triagens::aql::AstNode* SimpleAttributeEqualityMatcher::specializeAll (triagens: } else if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN) { TRI_ASSERT(op->numMembers() == 2); - if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference)) { + if (accessFitsIndex(index, op->getMember(0), op->getMember(1), op, reference, false)) { children.emplace_back(op); TRI_IF_FAILURE("SimpleAttributeMatcher::specializeAllChildrenIN") { THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG); @@ -433,8 +433,9 @@ bool SimpleAttributeEqualityMatcher::accessFitsIndex (triagens::arango::Index co triagens::aql::AstNode const* access, triagens::aql::AstNode const* other, triagens::aql::AstNode const* op, - triagens::aql::Variable const* reference) { - if (! index->canUseConditionPart(access, other, op, reference)) { + triagens::aql::Variable const* reference, + bool isExecution) { + if (! index->canUseConditionPart(access, other, op, reference, isExecution)) { return false; } diff --git a/arangod/Indexes/SimpleAttributeEqualityMatcher.h b/arangod/Indexes/SimpleAttributeEqualityMatcher.h index b3ae6a2997..fd481a7822 100644 --- a/arangod/Indexes/SimpleAttributeEqualityMatcher.h +++ b/arangod/Indexes/SimpleAttributeEqualityMatcher.h @@ -157,7 +157,8 @@ namespace triagens { triagens::aql::AstNode const*, triagens::aql::AstNode const*, triagens::aql::AstNode const*, - triagens::aql::Variable const*); + triagens::aql::Variable const*, + bool); // ----------------------------------------------------------------------------- // --SECTION-- private variables diff --git a/arangod/Indexes/SkiplistIndex.cpp b/arangod/Indexes/SkiplistIndex.cpp index a7f2c7abd3..8cb5312b12 100644 --- a/arangod/Indexes/SkiplistIndex.cpp +++ b/arangod/Indexes/SkiplistIndex.cpp @@ -1047,8 +1047,9 @@ bool SkiplistIndex::accessFitsIndex (triagens::aql::AstNode const* access, triagens::aql::AstNode const* other, triagens::aql::AstNode const* op, triagens::aql::Variable const* reference, - std::unordered_map>& found) const { - if (! this->canUseConditionPart(access, other, op, reference)) { + std::unordered_map>& found, + bool isExecution) const { + if (! this->canUseConditionPart(access, other, op, reference, isExecution)) { return false; } @@ -1100,7 +1101,8 @@ bool SkiplistIndex::accessFitsIndex (triagens::aql::AstNode const* access, void SkiplistIndex::matchAttributes (triagens::aql::AstNode const* node, triagens::aql::Variable const* reference, std::unordered_map>& found, - size_t& values) const { + size_t& values, + bool isExecution) const { for (size_t i = 0; i < node->numMembers(); ++i) { auto op = node->getMember(i); @@ -1111,12 +1113,12 @@ void SkiplistIndex::matchAttributes (triagens::aql::AstNode const* node, case triagens::aql::NODE_TYPE_OPERATOR_BINARY_GT: case triagens::aql::NODE_TYPE_OPERATOR_BINARY_GE: TRI_ASSERT(op->numMembers() == 2); - accessFitsIndex(op->getMember(0), op->getMember(1), op, reference, found); - accessFitsIndex(op->getMember(1), op->getMember(0), op, reference, found); + accessFitsIndex(op->getMember(0), op->getMember(1), op, reference, found, isExecution); + accessFitsIndex(op->getMember(1), op->getMember(0), op, reference, found, isExecution); break; case triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN: - if (accessFitsIndex(op->getMember(0), op->getMember(1), op, reference, found)) { + if (accessFitsIndex(op->getMember(0), op->getMember(1), op, reference, found, isExecution)) { auto m = op->getMember(1); if (m->type != triagens::aql::NODE_TYPE_EXPANSION && m->numMembers() > 1) { // attr IN [ a, b, c ] => this will produce multiple items, so count them! @@ -1124,7 +1126,7 @@ void SkiplistIndex::matchAttributes (triagens::aql::AstNode const* node, } } else { - accessFitsIndex(op->getMember(1), op->getMember(0), op, reference, found); + accessFitsIndex(op->getMember(1), op->getMember(0), op, reference, found, isExecution); } break; @@ -1141,7 +1143,7 @@ bool SkiplistIndex::supportsFilterCondition (triagens::aql::AstNode const* node, double& estimatedCost) const { std::unordered_map> found; size_t values = 0; - matchAttributes(node, reference, found, values); + matchAttributes(node, reference, found, values, false); bool lastContainsEquality = true; size_t attributesCovered = 0; @@ -1276,7 +1278,7 @@ IndexIterator* SkiplistIndex::iteratorForCondition (IndexIteratorContext* contex triagens::aql::Ast* ast, triagens::aql::AstNode const* node, triagens::aql::Variable const* reference, - bool const reverse) const { + bool reverse) const { // Create the skiplistOperator for the IndexLookup if (node == nullptr) { @@ -1295,7 +1297,7 @@ IndexIterator* SkiplistIndex::iteratorForCondition (IndexIteratorContext* contex } std::unordered_map> found; size_t unused = 0; - matchAttributes(node, reference, found, unused); + matchAttributes(node, reference, found, unused, true); // found contains all attributes that are relevant for this node. // It might be less than fields(). @@ -1537,7 +1539,7 @@ triagens::aql::AstNode* SkiplistIndex::specializeCondition (triagens::aql::AstNo triagens::aql::Variable const* reference) const { std::unordered_map> found; size_t values = 0; - matchAttributes(node, reference, found, values); + matchAttributes(node, reference, found, values, false); std::vector children; bool lastContainsEquality = true; diff --git a/arangod/Indexes/SkiplistIndex.h b/arangod/Indexes/SkiplistIndex.h index e6196679ad..2e30672f47 100644 --- a/arangod/Indexes/SkiplistIndex.h +++ b/arangod/Indexes/SkiplistIndex.h @@ -319,7 +319,7 @@ namespace triagens { triagens::aql::Ast*, triagens::aql::AstNode const*, triagens::aql::Variable const*, - bool const) const override; + bool) const override; triagens::aql::AstNode* specializeCondition (triagens::aql::AstNode*, triagens::aql::Variable const*) const override; @@ -344,12 +344,14 @@ namespace triagens { triagens::aql::AstNode const*, triagens::aql::AstNode const*, triagens::aql::Variable const*, - std::unordered_map>&) const; + std::unordered_map>&, + bool) const; void matchAttributes (triagens::aql::AstNode const*, triagens::aql::Variable const*, std::unordered_map>&, - size_t&) const; + size_t&, + bool) const; // ----------------------------------------------------------------------------- // --SECTION-- private variables diff --git a/arangosh/ArangoShell/ArangoClient.h b/arangosh/ArangoShell/ArangoClient.h index ffeb1db9f6..9ffac58587 100644 --- a/arangosh/ArangoShell/ArangoClient.h +++ b/arangosh/ArangoShell/ArangoClient.h @@ -98,7 +98,6 @@ namespace triagens { /// /// This sequence must be used before any non-visible characters in the prompt. /// -/// From readline/display.c: /// \\001 (^A) start non-visible characters /// \\002 (^B) end non-visible characters /// diff --git a/arangosh/CMakeLists.txt b/arangosh/CMakeLists.txt index cf38e0a7f9..c3372b642d 100644 --- a/arangosh/CMakeLists.txt +++ b/arangosh/CMakeLists.txt @@ -48,7 +48,6 @@ target_link_libraries( ${ICU_LIBS} ${BT_LIBS} ${ZLIB_LIBS} - ${READLINE_LIBS} ${OPENSSL_LIBS} ${MSVC_LIBS} ) @@ -98,7 +97,6 @@ target_link_libraries( ${ICU_LIBS} ${BT_LIBS} ${ZLIB_LIBS} - ${READLINE_LIBS} ${OPENSSL_LIBS} ${MSVC_LIBS} ) @@ -149,7 +147,6 @@ target_link_libraries( ${ICU_LIBS} ${BT_LIBS} ${ZLIB_LIBS} - ${READLINE_LIBS} ${OPENSSL_LIBS} ${MSVC_LIBS} ) @@ -198,7 +195,6 @@ target_link_libraries( ${ICU_LIBS} ${BT_LIBS} ${ZLIB_LIBS} - ${READLINE_LIBS} ${OPENSSL_LIBS} ${MSVC_LIBS} ) @@ -251,7 +247,6 @@ target_link_libraries( ${BT_LIBS} ${ICU_LIBS} ${ZLIB_LIBS} - ${READLINE_LIBS} ${OPENSSL_LIBS} ${MSVC_LIBS} ) diff --git a/arangosh/V8Client/arangosh.cpp b/arangosh/V8Client/arangosh.cpp index ade52d201d..69dd9721be 100644 --- a/arangosh/V8Client/arangosh.cpp +++ b/arangosh/V8Client/arangosh.cpp @@ -1548,20 +1548,10 @@ static void RunShell (v8::Isolate* isolate, v8::Handle context, boo #ifdef TRI_HAVE_LINENOISE // linenoise doesn't need escape sequences for escape sequences + // TODO: this should be a function defined in "console" goodPrompt = TRI_SHELL_COLOR_BOLD_GREEN + dynamicPrompt + TRI_SHELL_COLOR_RESET; badPrompt = TRI_SHELL_COLOR_BOLD_RED + dynamicPrompt + TRI_SHELL_COLOR_RESET; -#else - // readline does... - goodPrompt = string() - + ArangoClient::PROMPT_IGNORE_START + TRI_SHELL_COLOR_BOLD_GREEN + ArangoClient::PROMPT_IGNORE_END - + dynamicPrompt - + ArangoClient::PROMPT_IGNORE_START + TRI_SHELL_COLOR_RESET + ArangoClient::PROMPT_IGNORE_END; - - badPrompt = string() - + ArangoClient::PROMPT_IGNORE_START + TRI_SHELL_COLOR_BOLD_RED + ArangoClient::PROMPT_IGNORE_END - + dynamicPrompt - + ArangoClient::PROMPT_IGNORE_START + TRI_SHELL_COLOR_RESET + ArangoClient::PROMPT_IGNORE_END; #endif } else { diff --git a/configure.ac b/configure.ac index b029d1f4f9..7e111114b5 100644 --- a/configure.ac +++ b/configure.ac @@ -207,168 +207,9 @@ dnl ---------------------------------------------------------------------------- m4_include([m4/external.math]) dnl ---------------------------------------------------------------------------- -dnl READLINE +dnl REPL dnl ---------------------------------------------------------------------------- -AC_MSG_NOTICE([--------------------------------------------------------------------------------]) -AC_MSG_NOTICE([CHECKING FOR READLINE]) -AC_MSG_NOTICE([--------------------------------------------------------------------------------]) - -AC_LANG(C) - -AC_ARG_ENABLE(readline, - AS_HELP_STRING([--enable-readline], [enable readline support (default: yes)]), - tr_READLINE="$enableval", - tr_READLINE="maybe" -) - -if test "x$tr_DARWIN" = xyes; then - READLINE=/usr/local/opt/readline - READLINE_CPPFLAGS="-I$READLINE/include" - READLINE_INCLUDE="$READLINE/include" - READLINE_LDFLAGS="-L$READLINE/lib" - READLINE_LIB_PATH="$READLINE/lib" -fi - -AC_ARG_WITH(readline, - AS_HELP_STRING([--with-readline=DIR], [where the readline library and includes are located]), - [READLINE_CPPFLAGS="-I$withval/include" - READLINE_INCLUDE="$withval/include" - READLINE_LDFLAGS="-L$withval/lib" - READLINE_LIB_PATH="$withval/lib" - READLINE="$withval"] -) - -AC_ARG_WITH(readline-lib, - AS_HELP_STRING([--with-readline-lib=DIR], [where the readline library is located]), - [READLINE_LDFLAGS="-L$withval" - READLINE_LIB_PATH="$withval"] -) - -dnl checks for the READLINE library - -if test "x$READLINE_CPPFLAGS" != x; then - TR_INCLUDE([READLINE_CPPFLAGS]) -fi - -dnl save flags - -SAVE_CPPFLAGS="$CPPFLAGS" -CPPFLAGS="$CPPFLAGS $READLINE_CPPFLAGS" - -SAVE_LDFLAGS="$LDFLAGS" -LDFLAGS="$LDFLAGS $READLINE_LDFLAGS" - -SAVE_LIBS="$LIBS" - -dnl check for header and library - -if test "x$tr_READLINE" = xyes -o "x$tr_READLINE" = xmaybe; then - ch_READLINE="$tr_READLINE" - - AC_CHECK_HEADERS(readline/readline.h, [tr_READLINE="yes"], [tr_READLINE="no"]) - - if test "x$tr_READLINE" = xyes; then - AC_CHECK_LIB([readline], [readline], [READLINE_LIBS="-lreadline" tr_READLINE="yes"], [tr_READLINE="no"]) - fi - - AC_MSG_CHECKING([READLINE support]) - - if test "x$tr_READLINE" != xyes; then - AC_MSG_RESULT([not found]) - - if test "x$ch_READLINE" = xyes; then - AC_MSG_ERROR([Please install readline support]) - fi - else - AC_MSG_RESULT([readline]) - fi -else - AC_MSG_CHECKING([READLINE support]) - AC_MSG_RESULT([disabled]) -fi - -dnl grep readline version number - -if test "x$tr_READLINE" = xyes; then - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -main () { -#if defined(RL_VERSION_MAJOR) && defined(RL_VERSION_MINOR) - long sdnhg36ed = RL_VERSION_MAJOR RL_VERSION_MINOR ; -#else - long sdnhg36ed = RL_READLINE_VERSION hex ; -#endif -} - -_ACEOF - - AC_MSG_CHECKING([READLINE version]) - eval "$ac_cpp conftest.$ac_ext" | fgrep "long sdnhg36ed" | awk '{print $4 "." $5}' > conftest.output - READLINE_VERSION=`cat conftest.output` - - if test -z "$READLINE_VERSION"; then - AC_MSG_ERROR([Readline support is not working. Please re-install readline support]) - fi - - AC_MSG_RESULT([$READLINE_VERSION]) - rm -f conftest* - - if test "x$tr_DARWIN" = xyes; then - case "$READLINE_VERSION" in - 6.*|5.*) - ;; - - *) - AC_MSG_ERROR([Please install readline 6 from brew. If you have a non-standard brew location, use "--with-readline".]) - ;; - esac - fi -fi - -dnl restore flags and set readline flags - -LIBS="$SAVE_LIBS" -LDFLAGS="$SAVE_LDFLAGS" -CPPFLAGS="$SAVE_CPPFLAGS" - -if test "x$tr_READLINE" = xyes; then - CPPFLAGS="$CPPFLAGS -DHAVE_READLINE=1" - READLINE_CPPFLAGS="${READLINE_CPPFLAGS} -DTRI_READLINE_VERSION='\"${READLINE_VERSION}\"'" -fi - -AM_CONDITIONAL(ENABLE_READLINE, test "x$tr_READLINE" = xyes) - -if test "x$tr_READLINE" = xyes; then - AC_DEFINE_UNQUOTED(TRI_HAVE_READLINE, 1, [true if readline is used]) -fi - -dnl add substitutions - -AC_SUBST(READLINE_VERSION) -AC_SUBST(READLINE_CPPFLAGS) -AC_SUBST(READLINE_INCLUDE) -AC_SUBST(READLINE_LDFLAGS) -AC_SUBST(READLINE_LIB_PATH) -AC_SUBST(READLINE_LIBS) - -dnl informational output - -if test "x$tr_READLINE" = xyes; then - LIB_INFO="$LIB_INFO|READLINE VERSION: ${READLINE_VERSION}" - - LIB_INFO="$LIB_INFO|READLINE_CPPFLAGS: ${READLINE_CPPFLAGS}" - LIB_INFO="$LIB_INFO|READLINE_LDFLAGS: ${READLINE_LDFLAGS}" - LIB_INFO="$LIB_INFO|READLINE_LIBS: ${READLINE_LIBS}" -else - LIB_INFO="$LIB_INFO|READLINE VERSION: disabled" -fi - -LIB_INFO="$LIB_INFO|." - dnl ---------------------------------------------------------------------------- dnl OPENSSL dnl ---------------------------------------------------------------------------- diff --git a/lib/Basics/local-configuration.h.in b/lib/Basics/local-configuration.h.in index 311690fc9c..01d6886fe9 100644 --- a/lib/Basics/local-configuration.h.in +++ b/lib/Basics/local-configuration.h.in @@ -66,12 +66,6 @@ #undef TRI_ENABLE_FAILURE_TESTS -//////////////////////////////////////////////////////////////////////////////// -/// @brief enable readline -//////////////////////////////////////////////////////////////////////////////// - -#undef TRI_HAVE_READLINE - //////////////////////////////////////////////////////////////////////////////// /// @brief enable linenoise //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index a4615d5808..98d9de63a7 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -35,7 +35,6 @@ else () Basics/terminal-utils-posix.cpp Basics/threads-posix.cpp Rest/EndpointUnixDomain.cpp - Utilities/ReadlineShell.cpp ) endif () diff --git a/lib/Makefile.files b/lib/Makefile.files index c6faf8f138..d241922834 100644 --- a/lib/Makefile.files +++ b/lib/Makefile.files @@ -97,13 +97,6 @@ lib_libarango_a_SOURCES = \ lib/Zip/unzip.cpp \ lib/Zip/zip.cpp -if ENABLE_READLINE - -lib_libarango_a_SOURCES += \ - lib/Utilities/ReadlineShell.cpp - -endif - ################################################################################ ### @brief library "libarango.a", client part ################################################################################ diff --git a/lib/Rest/Version.cpp b/lib/Rest/Version.cpp index 73c8fb1b7d..6185174fb4 100644 --- a/lib/Rest/Version.cpp +++ b/lib/Rest/Version.cpp @@ -79,10 +79,6 @@ void Version::initialize () { Values["maintainer-mode"] = "false"; #endif -#ifdef TRI_READLINE_VERSION - Values["readline-version"] = getReadlineVersion(); -#endif - #ifdef TRI_HAVE_TCMALLOC Values["tcmalloc"] = "true"; #else @@ -182,19 +178,11 @@ std::string Version::getZLibVersion () { } //////////////////////////////////////////////////////////////////////////////// -/// @brief get readline version +/// @brief get REPL version //////////////////////////////////////////////////////////////////////////////// -std::string Version::getReadlineVersion () { -#ifdef TRI_READLINE_VERSION - std::string const value(TRI_READLINE_VERSION); - - if (value.size() >= 2) { - return value; - } - // fallthrough -#endif - return std::string("unknown version"); +std::string Version::getReplVersion () { + return std::string("dummy shell"); } //////////////////////////////////////////////////////////////////////////////// @@ -282,9 +270,7 @@ std::string Version::getVerboseVersionString () { #endif << "ICU " << getICUVersion() << ", " << "V8 " << getV8Version() << ", " -#ifdef TRI_READLINE_VERSION - << "Readline " << getReadlineVersion() << ", " -#endif + << "REPL " << getReplVersion() << ", " << getOpenSSLVersion(); return version.str(); diff --git a/lib/Rest/Version.h b/lib/Rest/Version.h index 46c3064f32..42e83c24d4 100644 --- a/lib/Rest/Version.h +++ b/lib/Rest/Version.h @@ -112,10 +112,10 @@ namespace triagens { static std::string getZLibVersion (); //////////////////////////////////////////////////////////////////////////////// -/// @brief get readline version +/// @brief get repl version //////////////////////////////////////////////////////////////////////////////// - static std::string getReadlineVersion (); + static std::string getReplVersion (); //////////////////////////////////////////////////////////////////////////////// /// @brief get ICU version diff --git a/lib/Utilities/ReadlineShell.cpp b/lib/Utilities/ReadlineShell.cpp deleted file mode 100644 index 7ff755b2c6..0000000000 --- a/lib/Utilities/ReadlineShell.cpp +++ /dev/null @@ -1,382 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// @brief line editor using readline -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany -/// Copyright 2004-2014 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 ArangoDB GmbH, Cologne, Germany -/// -/// @author Dr. Frank Celler -/// @author Jan Steemann -/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany -/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -#include "ReadlineShell.h" - -#include "Basics/tri-strings.h" -#include "Utilities/Completer.h" -#include "Utilities/LineEditor.h" - -#include -#include -#include - -using namespace std; -using namespace triagens; -using namespace arangodb; - -// ----------------------------------------------------------------------------- -// --SECTION-- private functions -// ----------------------------------------------------------------------------- - -namespace { - Completer* COMPLETER; -} - -static char WordBreakCharacters[] = { - ' ', '\t', '\n', '"', '\\', '\'', '`', '@', - '<', '>', '=', ';', '|', '&', '{', '}', '(', ')', - '\0' -}; - -static char* CompletionGenerator (char const* text, int state) { - static size_t currentIndex; - static vector result; - - // compute the possible completion - if (state == 0) { - result = COMPLETER->alternatives(text); - LineEditor::sortAlternatives(result); - } - - if (currentIndex < result.size()) { - return TRI_SystemDuplicateString(result[currentIndex++].c_str()); - } - - currentIndex = 0; - result.clear(); - return nullptr; -} - -static char** AttemptedCompletion (char const* text, int start, int end) { - char** result = rl_completion_matches(text, CompletionGenerator); - rl_attempted_completion_over = true; - - if (result != nullptr && result[0] != nullptr && result[1] == nullptr) { - size_t n = strlen(result[0]); - - if (result[0][n - 1] == ')') { - result[0][n - 1] = '\0'; - } - } - -#if RL_READLINE_VERSION >= 0x0500 - // issue #289 - rl_completion_suppress_append = 1; -#endif - - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief callback function that readline calls periodically while waiting -/// for input and being idle -//////////////////////////////////////////////////////////////////////////////// - -static int ReadlineIdle () { - auto instance = ReadlineShell::instance(); - - if (instance != nullptr && instance->getLoopState() == 2) { - rl_done = 1; - } - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief callback function that readline calls when the input is completed -//////////////////////////////////////////////////////////////////////////////// - -static void ReadlineInputCompleted (char* value) { - // if we don't clear the prompt here, readline will display it instantly - // the user pressed the return key. this is not desired because when we - // wait for input afterwards, readline will display the prompt again - rl_set_prompt(""); - - auto instance = ReadlineShell::instance(); - - if (instance != nullptr) { - if (instance->getLoopState() == 2) { - - // CTRL-C received - rl_done = 1; - - // replace current input with nothing - rl_replace_line("", 0); - - instance->setLastInput(""); - } - else if (value == nullptr) { - rl_done = 1; - rl_replace_line("", 0); - instance->setLoopState(3); - instance->setLastInput(""); - } - else { - instance->setLoopState(1); - instance->setLastInput(value == 0 ? "" : value); - } - } - - if (value != nullptr) { - // avoid memleak - TRI_SystemFree(value); - } -} - -// ----------------------------------------------------------------------------- -// --SECTION-- class ReadlineShell -// ----------------------------------------------------------------------------- - -// ----------------------------------------------------------------------------- -// --SECTION-- private variables -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @brief (sole) instance of a ReadlineShell -//////////////////////////////////////////////////////////////////////////////// - -std::atomic ReadlineShell::_instance(nullptr); - -// ----------------------------------------------------------------------------- -// --SECTION-- constructors and destructors -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @brief constructs a new editor -//////////////////////////////////////////////////////////////////////////////// - -ReadlineShell::ReadlineShell (std::string const& history, Completer* completer) - : ShellImplementation(history, completer), - _loopState(0), - _lastInput(), - _lastInputWasEmpty(false) { - - COMPLETER = completer; - - rl_initialize(); - - rl_attempted_completion_function = AttemptedCompletion; - rl_completer_word_break_characters = WordBreakCharacters; - - // register ourselves - TRI_ASSERT(_instance == nullptr); - _instance = this; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief destructor -//////////////////////////////////////////////////////////////////////////////// - -ReadlineShell::~ReadlineShell () { - // unregister ourselves - _instance = nullptr; -} - -// ----------------------------------------------------------------------------- -// --SECTION-- ShellImplementation methods -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @brief handle a signal -//////////////////////////////////////////////////////////////////////////////// - -void ReadlineShell::signal () { - // set the global state, so the readline input loop can react on it - setLoopState(2); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief line editor open -//////////////////////////////////////////////////////////////////////////////// - -bool ReadlineShell::open (bool autoComplete) { - if (autoComplete) { - - // issue #289: do not append a space after completion - rl_completion_append_character = '\0'; - - // works only in Readline 4.2+ -#if RL_READLINE_VERSION >= 0x0500 - // enable this to turn on the visual bell - evil! - // rl_variable_bind("prefer-visible-bell", "1"); - - // use this for single-line editing as in mongodb shell - // rl_variable_bind("horizontal-scroll-mode", "1"); - - // show matching parentheses - rl_set_paren_blink_timeout(300 * 1000); - rl_variable_bind("blink-matching-paren", "1"); - - // show selection list when completion is ambiguous. not setting this - // variable will turn the selection list off at least on Ubuntu - rl_variable_bind("show-all-if-ambiguous", "1"); - - // use readline's built-in page-wise completer - rl_variable_bind("page-completions", "1"); -#endif - - rl_bind_key('\t', rl_complete); - } - - using_history(); - //stifle_history(MAX_HISTORY_ENTRIES); - stifle_history(1000); - - _state = STATE_OPENED; - return read_history(historyPath().c_str()) == 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief line editor shutdown -//////////////////////////////////////////////////////////////////////////////// - -bool ReadlineShell::close () { - if (_state != STATE_OPENED) { - // avoid duplicate saving of history - return true; - } - - _state = STATE_CLOSED; - - bool res = writeHistory(); - - clear_history(); - - HIST_ENTRY** hist = history_list(); - - if (hist != nullptr) { - TRI_SystemFree(hist); - } - - return res; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief get the history file path -//////////////////////////////////////////////////////////////////////////////// - -string ReadlineShell::historyPath () { - string path; - - if (getenv("HOME")) { - path.append(getenv("HOME")); - path += '/'; - } - - path.append(_historyFilename); - - return path; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief add to history -//////////////////////////////////////////////////////////////////////////////// - -void ReadlineShell::addHistory (const string& str) { - if (str.empty()) { - return; - } - - history_set_pos(history_length - 1); - - if (current_history()) { - do { - if (strcmp(current_history()->line, str.c_str()) == 0) { - HIST_ENTRY* e = remove_history(where_history()); - - if (e != nullptr) { - free_history_entry(e); - } - - break; - } - } - while (previous_history()); - } - - add_history(str.c_str()); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief save history -//////////////////////////////////////////////////////////////////////////////// - -bool ReadlineShell::writeHistory () { - return (write_history(historyPath().c_str()) == 0); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief read a line from the input -//////////////////////////////////////////////////////////////////////////////// - -string ReadlineShell::getLine (const string& prompt, bool& eof) { - setLoopState(0); - - rl_event_hook = ReadlineIdle; - rl_callback_handler_install(prompt.c_str(), ReadlineInputCompleted); - - int state; - - eof = false; - - do { - rl_callback_read_char(); - state = getLoopState(); - } - while (state == 0); - - rl_callback_handler_remove(); - - if (state == 2) { - setLastInput(""); - - if (_lastInputWasEmpty) { - eof = true; - } - else { - _lastInputWasEmpty = true; - } - } - else if (state == 3) { - setLastInput(""); - eof = true; - _lastInputWasEmpty = false; - } - else { - _lastInputWasEmpty = false; - } - - return _lastInput; -} - -// ----------------------------------------------------------------------------- -// --SECTION-- END-OF-FILE -// ----------------------------------------------------------------------------- diff --git a/lib/Utilities/ReadlineShell.h b/lib/Utilities/ReadlineShell.h deleted file mode 100644 index b51020ee4f..0000000000 --- a/lib/Utilities/ReadlineShell.h +++ /dev/null @@ -1,210 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// @brief a basis class for concrete implementations for a shell -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany -/// Copyright 2004-2014 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 ArangoDB GmbH, Cologne, Germany -/// -/// @author Esteban Lombeyda -/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany -/// @author Copyright 2011-2014, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -#ifndef ARANGODB_UTILITIES_READLINE_SHELL_H -#define ARANGODB_UTILITIES_READLINE_SHELL_H 1 - -#include "Utilities/ShellImplementation.h" - -#include "Utilities/Completer.h" - -namespace arangodb { - -// ----------------------------------------------------------------------------- -// --SECTION-- class ReadlineShell -// ----------------------------------------------------------------------------- - - class ReadlineShell : public ShellImplementation { - -// ----------------------------------------------------------------------------- -// --SECTION-- static public methods -// ----------------------------------------------------------------------------- - - public: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the currently active shell instance -//////////////////////////////////////////////////////////////////////////////// - - static ReadlineShell* instance () { - return _instance.load(); - } - -// ----------------------------------------------------------------------------- -// --SECTION-- constructors and destructors -// ----------------------------------------------------------------------------- - - public: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief constructor -//////////////////////////////////////////////////////////////////////////////// - - ReadlineShell (std::string const& history, Completer*); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief destructor -//////////////////////////////////////////////////////////////////////////////// - - ~ReadlineShell (); - -// ----------------------------------------------------------------------------- -// --SECTION-- ShellImplementation methods -// ----------------------------------------------------------------------------- - - public: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief line editor open -//////////////////////////////////////////////////////////////////////////////// - - bool open (bool autoComplete) override final; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief line editor shutdown -//////////////////////////////////////////////////////////////////////////////// - - bool close () override final; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief get the history file path -/// -/// The path is "$HOME" plus _historyFilename, if $HOME is set. Else -/// the local file _historyFilename. -//////////////////////////////////////////////////////////////////////////////// - - std::string historyPath () override final; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief add to history -//////////////////////////////////////////////////////////////////////////////// - - void addHistory (const std::string&) override final; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief save the history -//////////////////////////////////////////////////////////////////////////////// - - bool writeHistory () override final; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief read a line from the input -//////////////////////////////////////////////////////////////////////////////// - - std::string getLine (const std::string& prompt, bool& eof) override final; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief handle a signal -//////////////////////////////////////////////////////////////////////////////// - - void signal () override final; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief whether or not the shell implementation supports colors -//////////////////////////////////////////////////////////////////////////////// - - bool supportsColors () override final { - return true; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief whether or not the shell supports a CTRL-C handler -//////////////////////////////////////////////////////////////////////////////// - - bool supportsCtrlCHandler () override final { - return true; - } - -// ----------------------------------------------------------------------------- -// --SECTION-- public methods -// ----------------------------------------------------------------------------- - - public: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief set the last input value -//////////////////////////////////////////////////////////////////////////////// - - void setLastInput (const std::string& input) { - _lastInput = input; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief get the current input loop state -//////////////////////////////////////////////////////////////////////////////// - - int getLoopState () const { - return _loopState; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief set the current input loop state -//////////////////////////////////////////////////////////////////////////////// - - void setLoopState (int state) { - _loopState = state; - } - -// ----------------------------------------------------------------------------- -// --SECTION-- private variables -// ----------------------------------------------------------------------------- - - private: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief current state of input loop (may be affected by out-of-band signals) -//////////////////////////////////////////////////////////////////////////////// - - std::atomic _loopState; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief last value entered by user. -//////////////////////////////////////////////////////////////////////////////// - - std::string _lastInput; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief whether or not the input from the previous invocation was a CTRL-C -//////////////////////////////////////////////////////////////////////////////// - - bool _lastInputWasEmpty; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief system-wide instance of the ReadlineShell -//////////////////////////////////////////////////////////////////////////////// - - static std::atomic _instance; - }; -} - -#endif - -// ----------------------------------------------------------------------------- -// --SECTION-- END-OF-FILE -// ----------------------------------------------------------------------------- diff --git a/lib/Utilities/ShellImplFactory.cpp b/lib/Utilities/ShellImplFactory.cpp index 9a67ce2964..43eac99ff0 100644 --- a/lib/Utilities/ShellImplFactory.cpp +++ b/lib/Utilities/ShellImplFactory.cpp @@ -33,8 +33,6 @@ #include "LinenoiseShell.h" #elif defined TRI_HAVE_LINENOISE #include "LinenoiseShell.h" -#elif defined TRI_HAVE_READLINE -#include "ReadlineShell.h" #endif #include "DummyShell.h" @@ -63,12 +61,9 @@ ShellImplementation* ShellImplFactory::buildShell (std::string const& history, } #ifdef _WIN32 - // under Windows the readline is not compilable return new LinenoiseShell(history, completer); #elif defined TRI_HAVE_LINENOISE return new LinenoiseShell(history, completer); -#elif defined TRI_HAVE_READLINE - return new ReadlineShell(history, completer); #else // last resort! return new DummyShell(history, completer); @@ -85,12 +80,9 @@ bool ShellImplFactory::hasCtrlCHandler () { } #ifdef _WIN32 - // under Windows the readline is not compilable return false; #elif defined TRI_HAVE_LINENOISE return false; -#elif defined TRI_HAVE_READLINE - return true; #else return false; #endif