diff --git a/Documentation/InstallationManual/Installing.md b/Documentation/InstallationManual/Installing.md index 2ecae8cbf3..60636514ad 100644 --- a/Documentation/InstallationManual/Installing.md +++ b/Documentation/InstallationManual/Installing.md @@ -36,7 +36,17 @@ Please use the @EXTREF_S{https://github.com/mgiken/portage-overlay/tree/master/dev-db/ArangoDB,portage} provided by @@mgiken. -### Linux-Mint {#InstallingDebian} +### Debian sid {#InstallingDebian} + +To use ArangoDB on Debian sid (the development version of Debian), a different version +of ICU is required. User basir provided the following instructions for getting ArangoDB 2.0.7 +to work on an x86_64: + +@EXTREF_S{https://github.com/triAGENS/ArangoDB/issues/865,link to Github issue} + +Other versions of ArangoDB or other architectures should work similarly. + +### Linux-Mint {#InstallingLinuxMint} Download and import GPG-PublicKey: diff --git a/Documentation/InstallationManual/InstallingTOC.md b/Documentation/InstallationManual/InstallingTOC.md index 568fd16578..ba974f042e 100644 --- a/Documentation/InstallationManual/InstallingTOC.md +++ b/Documentation/InstallationManual/InstallingTOC.md @@ -5,6 +5,7 @@ TOC {#InstallingTOC} - @ref InstallingLinux - @ref InstallingLinuxPackageManager - @ref InstallingDebian + - @ref InstallingLinuxMint - @ref InstallingMacOSX - @ref InstallingMacOSXHomebrew - @ref InstallingMacOSXAppStore diff --git a/UnitTests/Basics/structure-size-test.cpp b/UnitTests/Basics/structure-size-test.cpp index 7cccca5f60..4ff86b2d39 100644 --- a/UnitTests/Basics/structure-size-test.cpp +++ b/UnitTests/Basics/structure-size-test.cpp @@ -121,32 +121,6 @@ BOOST_AUTO_TEST_CASE (tst_df_footer_marker) { BOOST_CHECK_EQUAL(28, offsetof(struct TRI_df_footer_marker_s, _totalSize)); } -//////////////////////////////////////////////////////////////////////////////// -/// @brief test sizeof TRI_df_document_marker_t -//////////////////////////////////////////////////////////////////////////////// - -BOOST_AUTO_TEST_CASE (tst_df_document_marker) { - size_t s = sizeof(TRI_df_document_marker_t); - - BOOST_CHECK_EQUAL(24, s); // base + own size - BOOST_CHECK_EQUAL(true, s % 8 == 0); - - BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_df_document_marker_s, base)); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief test sizeof TRI_df_skip_marker_t -//////////////////////////////////////////////////////////////////////////////// - -BOOST_AUTO_TEST_CASE (tst_df_skip_marker) { - size_t s = sizeof(TRI_df_skip_marker_t); - - BOOST_CHECK_EQUAL(24, s); // base + own size - BOOST_CHECK_EQUAL(true, s % 8 == 0); - - BOOST_CHECK_EQUAL( 0, offsetof(struct TRI_df_skip_marker_s, base)); -} - //////////////////////////////////////////////////////////////////////////////// /// @brief test sizeof TRI_col_header_marker_t //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/VocBase/datafile.h b/arangod/VocBase/datafile.h index 35315b1c47..53fc59f984 100644 --- a/arangod/VocBase/datafile.h +++ b/arangod/VocBase/datafile.h @@ -415,15 +415,6 @@ typedef struct TRI_df_document_marker_s { } TRI_df_document_marker_t; -//////////////////////////////////////////////////////////////////////////////// -/// @brief datafile skip marker -//////////////////////////////////////////////////////////////////////////////// - -typedef struct TRI_df_skip_marker_s { - TRI_df_marker_t base; // 24 bytes -} -TRI_df_skip_marker_t; - //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/js/apps/system/aardvark/frontend/js/modules/org/arangodb/graph/traversal.js b/js/apps/system/aardvark/frontend/js/modules/org/arangodb/graph/traversal.js index bb11770548..11f48b7cb3 100644 --- a/js/apps/system/aardvark/frontend/js/modules/org/arangodb/graph/traversal.js +++ b/js/apps/system/aardvark/frontend/js/modules/org/arangodb/graph/traversal.js @@ -30,6 +30,7 @@ module.define("org/arangodb/graph/traversal", function(exports, module) { //////////////////////////////////////////////////////////////////////////////// var graph = require("org/arangodb/graph-blueprint"); +var generalGraph = require("org/arangodb/general-graph"); var arangodb = require("org/arangodb"); var BinaryHeap = require("org/arangodb/heap").BinaryHeap; var ArangoError = arangodb.ArangoError; @@ -159,6 +160,72 @@ function collectionDatasourceFactory (edgeCollection) { }; } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief general graph datasource +/// +/// This is a factory function that creates a datasource that operates on the +/// specified general graph. The vertices and edges are delivered by the +/// the general-graph module. +//////////////////////////////////////////////////////////////////////////////// + +function generalGraphDatasourceFactory (graph) { + var g = graph; + if (typeof g === 'string') { + g = generalGraph._graph(g); + } + + return { + graph: g, + + getVertexId: function (vertex) { + return vertex._id; + }, + + getPeerVertex: function (edge, vertex) { + if (edge._from === vertex._id) { + return db._document(edge._to); + } + + if (edge._to === vertex._id) { + return db._document(edge._from); + } + + return null; + }, + + getInVertex: function (edge) { + return db._document(edge._to); + }, + + getOutVertex: function (edge) { + return db._document(edge._from); + }, + + getEdgeId: function (edge) { + return edge._id; + }, + + getLabel: function (edge) { + return edge.$label; + }, + + getAllEdges: function (vertex) { + return this.graph._EDGES(vertex._id); + }, + + getInEdges: function (vertex) { + return this.graph._INEDGES(vertex._id); + }, + + getOutEdges: function (vertex) { + return this.graph._OUTEDGES(vertex._id); + } + }; +} + + + //////////////////////////////////////////////////////////////////////////////// /// @brief default Graph datasource /// @@ -1487,6 +1554,7 @@ ArangoTraverser.EXCLUDE = 'exclude'; //////////////////////////////////////////////////////////////////////////////// exports.collectionDatasourceFactory = collectionDatasourceFactory; +exports.generalGraphDatasourceFactory = generalGraphDatasourceFactory; exports.graphDatasourceFactory = graphDatasourceFactory; exports.outboundExpander = outboundExpander; diff --git a/js/apps/system/aardvark/frontend/js/templates/queryView.ejs b/js/apps/system/aardvark/frontend/js/templates/queryView.ejs index aa347531ba..a900c115ff 100644 --- a/js/apps/system/aardvark/frontend/js/templates/queryView.ejs +++ b/js/apps/system/aardvark/frontend/js/templates/queryView.ejs @@ -70,54 +70,4 @@ - - - - - diff --git a/js/apps/system/aardvark/frontend/js/views/documentsView.js b/js/apps/system/aardvark/frontend/js/views/documentsView.js index 7a32964bfc..7d08f970ae 100644 --- a/js/apps/system/aardvark/frontend/js/views/documentsView.js +++ b/js/apps/system/aardvark/frontend/js/views/documentsView.js @@ -168,7 +168,7 @@ this.buildCollectionLink( this.collectionContext.prev ), - { + { trigger: true } ); @@ -281,7 +281,7 @@ var num = ++this.filterId; $('#filterHeader').append('
'+ - ''+ ''+ - ''+ ' ' + '
'); @@ -432,6 +432,7 @@ this.collection.getDocuments(this.collection.collectionID, page); $('#docDeleteModal').modal('hide'); this.drawTable(); + this.renderPaginationElements(); } }, @@ -554,7 +555,7 @@ $('.modalImportTooltips').tooltip({ placement: "left" }); - + arangoHelper.fixTooltips(".icon_arangodb, .arangoicon", "top"); this.drawTable(); this.renderPaginationElements(); diff --git a/js/apps/system/aardvark/frontend/js/views/modalView.js b/js/apps/system/aardvark/frontend/js/views/modalView.js index 4b5ebfd573..b93759e8ae 100644 --- a/js/apps/system/aardvark/frontend/js/views/modalView.js +++ b/js/apps/system/aardvark/frontend/js/views/modalView.js @@ -13,7 +13,7 @@ }; }; - var createTextStub = function(type, label, value, info, placeholder, mandatory) { + var createTextStub = function(type, label, value, info, placeholder, mandatory, regexp) { var obj = { type: type, label: label @@ -30,6 +30,12 @@ if (mandatory) { obj.mandatory = mandatory; } + if (regexp){ + // returns true if the string contains the match + obj.validateInput = function(el){ + return regexp.test(el.val()); + }; + } return obj; }; @@ -161,8 +167,9 @@ return obj; }, - createTextEntry: function(id, label, value, info, placeholder, mandatory) { - var obj = createTextStub(this.tables.TEXT, label, value, info, placeholder, mandatory); + createTextEntry: function(id, label, value, info, placeholder, mandatory, regexp) { + var obj = createTextStub(this.tables.TEXT, label, value, info, placeholder, mandatory, + regexp); obj.id = id; return obj; }, @@ -270,6 +277,20 @@ }); } });//handle select2 + + self.testInput = (function(){ + _.each(tableContent,function(r){ + if(r.validateInput){ + $('#' + r.id).on('keyup', function(){ + if(r.validateInput($('#' + r.id))){ + $('#' + r.id).addClass('invalid-input'); + } else { + $('#' + r.id).removeClass('invalid-input'); + } + }); + } + }); + }()); if (events) { this.events = events; this.delegateEvents(); diff --git a/js/apps/system/aardvark/frontend/js/views/queryView.js b/js/apps/system/aardvark/frontend/js/views/queryView.js index f1ccaa63a0..75223df1fa 100644 --- a/js/apps/system/aardvark/frontend/js/views/queryView.js +++ b/js/apps/system/aardvark/frontend/js/views/queryView.js @@ -17,26 +17,6 @@ this.tableDescription.rows = this.customQueries; }, - updateTable: function () { - this.tableDescription.rows = this.customQueries; - - _.each(this.tableDescription.rows, function(k,v) { - k.thirdRow = ''; - }); - - this.$(this.id).html(this.table.render({content: this.tableDescription})); - }, - - editCustomQuery: function(e) { - var queryName = $(e.target).parent().children().first().text(); - var inputEditor = ace.edit("aqlEditor"); - inputEditor.setValue(this.getCustomQueryValueByName(queryName)); - this.deselect(inputEditor); - $('#querySelect').val(queryName); - this.switchTab("query-switch"); - }, - events: { "click #result-switch": "switchTab", "click #query-switch": "switchTab", @@ -57,10 +37,8 @@ 'click #clearQueryButton': 'clearInput', 'click #addAQL': 'addAQL', 'click #editAQL': 'editAQL', - 'click #save-query': 'saveAQL', - 'click #delete-edit-query': 'showDeleteField', + 'click #delete-edit-query': 'showDeleteFie/ld', 'click #abortDeleteQuery': 'hideDeleteField', - 'keyup #new-query-name': 'listenKey', 'change #queryModalSelect': 'updateEditSelect', 'change #querySelect': 'importSelected', 'change #querySize': 'changeSize', @@ -71,6 +49,46 @@ 'click #queryDiv .showHotkeyHelp': 'shortcutModal' }, + createCustomQueryModal: function(){ + var buttons = [], tableContent = []; + tableContent.push( + window.modalView.createTextEntry( + 'new-query-name', + 'Name', + '', + undefined, + undefined, + false, + /[<>&'"]/ + ) + ); + buttons.push( + window.modalView.createSuccessButton('Save', this.saveAQL.bind(this)) + ); + window.modalView.show('modalTable.ejs', 'Save Query', buttons, tableContent, undefined, + {'keyup #new-query-name' : this.listenKey.bind(this)}); + }, + + updateTable: function () { + this.tableDescription.rows = this.customQueries; + + _.each(this.tableDescription.rows, function(k,v) { + k.thirdRow = ''; + }); + + this.$(this.id).html(this.table.render({content: this.tableDescription})); + }, + + editCustomQuery: function(e) { + var queryName = $(e.target).parent().children().first().text(); + var inputEditor = ace.edit("aqlEditor"); + inputEditor.setValue(this.getCustomQueryValueByName(queryName)); + this.deselect(inputEditor); + $('#querySelect').val(queryName); + this.switchTab("query-switch"); + }, + initTabArray: function() { var self = this; $(".arango-tab").children().each( function(index) { @@ -92,42 +110,20 @@ return; } - //check for invalid query names, if present change the box-shadoq to red + //check for invalid query names, if present change the box-shadow to red // and disable the save functionality - - var dangerCss = { - "webkit-box-shadow" : "inset 0 1px 1px rgba( 0,0,0, 0.075), 0 0 8px rgba(234, 23, 23, 0.6)", - "moz-box-shadow" : "inset 0 1px 1px rgba( 0,0,0, 0.075), 0 0 8px rgba(234, 23, 23, 0.6)", - "box-shadow" : "inset 0 1px 1px rgba( 0,0,0, 0.075), 0 0 8px rgba(234, 23, 23, 0.6)", - "border-color" : "rgba(234, 23, 23, 0.8)" - }; - - var normalCss = { - "webkit-box-shadow" : "inset 0 1px 1px rgba( 0,0,0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6)", - "moz-box-shadow" : "inset 0 1px 1px rgba( 0,0,0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6)", - "box-shadow" : "inset 0 1px 1px rgba( 0,0,0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6)", - "border-color" : "rgba(82, 168, 236, 0.8)" - }; - - if ( saveName.match(/[<>&'"]/g)){ - $('#new-query-name').css(dangerCss); - $('#new-query-name').addClass('invalid'); - } else { - $('#new-query-name').css(normalCss); - $('#new-query-name').removeClass('invalid'); - } - + //console.log(saveName.match(/[<>&'"]/)); var boolTemp = false; this.customQueries.some(function(query){ if( query.name === saveName ){ - $('#save-query').removeClass('button-success'); - $('#save-query').addClass('button-warning'); - $('#save-query').text('Update'); + $('#modalButton1').removeClass('button-success'); + $('#modalButton1').addClass('button-warning'); + $('#modalButton1').text('Update'); boolTemp = true; } else { - $('#save-query').removeClass('button-warning'); - $('#save-query').addClass('button-success'); - $('#save-query').text('Save'); + $('#modalButton1').removeClass('button-warning'); + $('#modalButton1').addClass('button-success'); + $('#modalButton1').text('Save'); } if (boolTemp) { @@ -309,8 +305,8 @@ addAQL: function () { //render options + this.createCustomQueryModal(); $('#new-query-name').val($('#querySelect').val()); - $('#new-aql-query').modal('show'); setTimeout(function () { $('#new-query-name').focus(); }, 500); @@ -363,10 +359,11 @@ }, saveAQL: function (e) { + e.stopPropagation(); var inputEditor = ace.edit("aqlEditor"); var saveName = $('#new-query-name').val(); - if ($('#new-query-name').hasClass('invalid')) { + if ($('#new-query-name').hasClass('invalid-input')) { return; } @@ -389,8 +386,7 @@ if (quit === true) { //Heiko: Form-Validator - name already taken - $('#new-aql-query').modal('hide'); - $('#edit-aql-query').modal('hide'); + window.modalView.hide(); return; } @@ -399,8 +395,7 @@ value: content }); - $('#new-aql-query').modal('hide'); - $('#edit-aql-query').modal('hide'); + window.modalView.hide(); localStorage.setItem("customQueries", JSON.stringify(this.customQueries)); this.renderSelectboxes(); diff --git a/js/apps/system/aardvark/frontend/scss/_modals.scss b/js/apps/system/aardvark/frontend/scss/_modals.scss index 43b234bffb..09b24f069b 100644 --- a/js/apps/system/aardvark/frontend/scss/_modals.scss +++ b/js/apps/system/aardvark/frontend/scss/_modals.scss @@ -219,6 +219,13 @@ pre.gv-object-view { margin-bottom: 10px; } +.modal-body input[type='text'].invalid-input{ + webkit-box-shadow : inset 0 1px 1px rgba( 0,0,0, 0.075), 0 0 8px rgba(234, 23, 23, 0.6); + moz-box-shadow : inset 0 1px 1px rgba( 0,0,0, 0.075), 0 0 8px rgba(234, 23, 23, 0.6); + box-shadow : inset 0 1px 1px rgba( 0,0,0, 0.075), 0 0 8px rgba(234, 23, 23, 0.6); + border-color : rgba(234, 23, 23, 0.8) +} + .modal-delete-confirmation { display: none; diff --git a/js/apps/system/aardvark/frontend/scss/generated.css b/js/apps/system/aardvark/frontend/scss/generated.css index d6181d3b59..1687f0d2fa 100644 --- a/js/apps/system/aardvark/frontend/scss/generated.css +++ b/js/apps/system/aardvark/frontend/scss/generated.css @@ -21,31 +21,37 @@ textarea, font-style: normal; font-weight: 300; src: local("Open Sans Light"), local("OpenSans-Light"), url("../fonts/opensans/OpenSansLight.woff") format("woff"); } + @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; src: local("Open Sans"), local("OpenSans"), url("../fonts/opensans/OpenSans.woff") format("woff"); } + @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; src: local("Open Sans Bold"), local("OpenSans-Bold"), url("../fonts/opensans/OpenSansBold.woff") format("woff"); } + @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 300; src: local("Open Sans Light Italic"), local("OpenSansLight-Italic"), url("../fonts/opensans/OpenSansLightItalic.woff") format("woff"); } + @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 400; src: local("Open Sans Italic"), local("OpenSans-Italic"), url("../fonts/opensans/OpenSansItalic.woff") format("woff"); } + @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 700; src: local("Open Sans Bold Italic"), local("OpenSans-BoldItalic"), url("../fonts/opensans/OpenSansBoldItalic.woff") format("woff"); } + /*! * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) @@ -58,6 +64,7 @@ textarea, src: url("../fonts/fontawesome/fontawesome-webfont.eot?#iefix&v=4.0.3") format("embedded-opentype"), url("../fonts/fontawesome/fontawesome-webfont.woff?v=4.0.3") format("woff"), url("../fonts/fontawesome/fontawesome-webfont.ttf?v=4.0.3") format("truetype"), url("../fonts/fontawesome/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular") format("svg"); font-weight: normal; font-style: normal; } + .fa { display: inline-block; font-family: FontAwesome; @@ -133,30 +140,35 @@ textarea, 100% { -moz-transform: rotate(359deg); } } + @-webkit-keyframes spin { 0% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); } } + @-o-keyframes spin { 0% { -o-transform: rotate(0deg); } 100% { -o-transform: rotate(359deg); } } + @-ms-keyframes spin { 0% { -ms-transform: rotate(0deg); } 100% { -ms-transform: rotate(359deg); } } + @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(359deg); } } + .fa-rotate-90 { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=$rotation); -webkit-transform: rotate(90deg); @@ -1444,7 +1456,7 @@ nav.navbar, footer.footer { background-color: #f87c0f; } .button-inactive { - background-color: lightgray; } + background-color: lightgrey; } .button-inactive:hover, .button-inactive:focus { background-color: gray; } @@ -3997,6 +4009,12 @@ pre.gv-object-view { .modal-body input[type='checkbox'] { margin-bottom: 10px; } +.modal-body input[type='text'].invalid-input { + webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(234, 23, 23, 0.6); + moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(234, 23, 23, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(234, 23, 23, 0.6); + border-color: rgba(234, 23, 23, 0.8); } + .modal-delete-confirmation { display: none; } .modal-delete-confirmation button { @@ -4155,7 +4173,7 @@ pre.gv-object-view { width: 5%; } .user-menu-img { - background-color: lightgray; + background-color: lightgrey; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; diff --git a/js/apps/system/aardvark/test/specs/views/documentsViewSpec.js b/js/apps/system/aardvark/test/specs/views/documentsViewSpec.js index fa724253da..bba796eb90 100644 --- a/js/apps/system/aardvark/test/specs/views/documentsViewSpec.js +++ b/js/apps/system/aardvark/test/specs/views/documentsViewSpec.js @@ -1290,9 +1290,11 @@ spyOn(view, "drawTable"); view.collection = new window.arangoDocuments(); view.target = "#confirmDeleteBtn"; + spyOn(view, "renderPaginationElements"); view.reallyDelete(); + expect(view.renderPaginationElements).toHaveBeenCalled(); expect(window.$).toHaveBeenCalledWith("#confirmDeleteBtn"); expect(window.$).toHaveBeenCalledWith("#documentsTableID"); expect(window.$).toHaveBeenCalledWith("#docDeleteModal"); @@ -1375,8 +1377,11 @@ view.collection = new window.arangoDocuments(); view.target = "#confirmDeleteBtn"; spyOn(view, "drawTable"); + spyOn(view, "renderPaginationElements"); + view.reallyDelete(); + expect(view.renderPaginationElements).toHaveBeenCalled(); expect(window.$).toHaveBeenCalledWith("#confirmDeleteBtn"); diff --git a/js/common/modules/org/arangodb/general-graph.js b/js/common/modules/org/arangodb/general-graph.js index 6138c13541..79b80dc33b 100644 --- a/js/common/modules/org/arangodb/general-graph.js +++ b/js/common/modules/org/arangodb/general-graph.js @@ -53,7 +53,7 @@ var stringToArray = function (x) { if (typeof x === "string") { return [x]; } - return x; + return _.clone(x); }; //////////////////////////////////////////////////////////////////////////////// @@ -127,10 +127,6 @@ var findOrCreateCollectionsByEdgeDefinitions = function (edgeDefinitions, noCrea // --SECTION-- Fluent AQL Interface // ----------------------------------------------------------------------------- -// ----------------------------------------------------------------------------- -// --SECTION-- Fluent AQL Interface -// ----------------------------------------------------------------------------- - var AQLStatement = function(query, isEdgeQuery) { this.query = query; this.edgeQuery = isEdgeQuery || false; @@ -279,7 +275,7 @@ var _directedRelationDefinition = function ( relationName, fromVertexCollections, toVertexCollections) { if (arguments.length < 3) { - throw "method _undirectedRelationDefinition expects 3 arguments"; + throw "method _directedRelationDefinition expects 3 arguments"; } if (typeof relationName !== "string" || relationName === "") { @@ -430,6 +426,51 @@ var _graph = function(graphName) { return new Graph(graphName, g.edgeDefinitions, collections[0], collections[1]); }; +//////////////////////////////////////////////////////////////////////////////// +/// @brief drop a graph. +//////////////////////////////////////////////////////////////////////////////// + +var _drop = function(graphId, dropCollections) { + + var gdb = db._graphs; + + + if (gdb === null || gdb === undefined) { + throw "_graphs collection does not exist."; + } + + if (!gdb.exists(graphId)) { + throw "Graph " + graphId + " does not exist."; + } + + if (dropCollections !== false) { + var graph = gdb.document(graphId); + var edgeDefinitions = graph.edgeDefinitions; + require("internal").print(edgeDefinitions); + edgeDefinitions.forEach( + function(edgeDefinition) { + var from = edgeDefinition.from; + var to = edgeDefinition.to; + var edge = edgeDefinition.collection; + db._drop(edge); + from.forEach( + function(col) { + db._drop(col); + } + ); + to.forEach( + function(col) { + db._drop(col); + } + ); + } + ); + } + + gdb.remove(graphId); + return true; +}; + //////////////////////////////////////////////////////////////////////////////// /// @brief return all edge collections of the graph. //////////////////////////////////////////////////////////////////////////////// @@ -487,7 +528,7 @@ Graph.prototype._INEDGES = function(vertexId) { /// @brief outEdges(vertexId). //////////////////////////////////////////////////////////////////////////////// -Graph.prototype._outEdges = function(vertexId) { +Graph.prototype._OUTEDGES = function(vertexId) { var edgeCollections = this._edgeCollections(); var result = []; @@ -587,6 +628,7 @@ exports._directedRelationDefinition = _directedRelationDefinition; exports._graph = _graph; exports.edgeDefinitions = edgeDefinitions; exports._create = _create; +exports._drop = _drop; // ----------------------------------------------------------------------------- // --SECTION-- END-OF-FILE diff --git a/js/common/modules/org/arangodb/graph/traversal.js b/js/common/modules/org/arangodb/graph/traversal.js index 11b1dbf2b1..e9a5035d1a 100644 --- a/js/common/modules/org/arangodb/graph/traversal.js +++ b/js/common/modules/org/arangodb/graph/traversal.js @@ -29,6 +29,7 @@ //////////////////////////////////////////////////////////////////////////////// var graph = require("org/arangodb/graph-blueprint"); +var generalGraph = require("org/arangodb/general-graph"); var arangodb = require("org/arangodb"); var BinaryHeap = require("org/arangodb/heap").BinaryHeap; var ArangoError = arangodb.ArangoError; @@ -158,6 +159,72 @@ function collectionDatasourceFactory (edgeCollection) { }; } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief general graph datasource +/// +/// This is a factory function that creates a datasource that operates on the +/// specified general graph. The vertices and edges are delivered by the +/// the general-graph module. +//////////////////////////////////////////////////////////////////////////////// + +function generalGraphDatasourceFactory (graph) { + var g = graph; + if (typeof g === 'string') { + g = generalGraph._graph(g); + } + + return { + graph: g, + + getVertexId: function (vertex) { + return vertex._id; + }, + + getPeerVertex: function (edge, vertex) { + if (edge._from === vertex._id) { + return db._document(edge._to); + } + + if (edge._to === vertex._id) { + return db._document(edge._from); + } + + return null; + }, + + getInVertex: function (edge) { + return db._document(edge._to); + }, + + getOutVertex: function (edge) { + return db._document(edge._from); + }, + + getEdgeId: function (edge) { + return edge._id; + }, + + getLabel: function (edge) { + return edge.$label; + }, + + getAllEdges: function (vertex) { + return this.graph._EDGES(vertex._id); + }, + + getInEdges: function (vertex) { + return this.graph._INEDGES(vertex._id); + }, + + getOutEdges: function (vertex) { + return this.graph._OUTEDGES(vertex._id); + } + }; +} + + + //////////////////////////////////////////////////////////////////////////////// /// @brief default Graph datasource /// @@ -1486,6 +1553,7 @@ ArangoTraverser.EXCLUDE = 'exclude'; //////////////////////////////////////////////////////////////////////////////// exports.collectionDatasourceFactory = collectionDatasourceFactory; +exports.generalGraphDatasourceFactory = generalGraphDatasourceFactory; exports.graphDatasourceFactory = graphDatasourceFactory; exports.outboundExpander = outboundExpander; diff --git a/js/common/tests/shell-general-graph.js b/js/common/tests/shell-general-graph.js index a92426994e..0ff51f8335 100644 --- a/js/common/tests/shell-general-graph.js +++ b/js/common/tests/shell-general-graph.js @@ -478,14 +478,32 @@ function GeneralGraphAQLQueriesSuite() { }); }; + // The testee graph object + var g; + return { +//////////////////////////////////////////////////////////////////////////////// +/// @brief setUp: query creation for edges +//////////////////////////////////////////////////////////////////////////////// + + setUp: function() { + g = createInclExcl(); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test: query creation for edges +//////////////////////////////////////////////////////////////////////////////// + + tearDown: function() { + dropInclExcl(); + }, + //////////////////////////////////////////////////////////////////////////////// /// @brief test: query creation for edges //////////////////////////////////////////////////////////////////////////////// test_edges: function() { - var g = createInclExcl(); var query = g._edges("v1/1"); assertEqual(query.printQuery(), 'FOR edges_0 IN GRAPH_EDGES(' + '@graphName,@startVertex_0,"any")'); @@ -497,7 +515,6 @@ function GeneralGraphAQLQueriesSuite() { assertTrue(findIdInResult(result, e1), "Did not include e1"); assertTrue(findIdInResult(result, e2), "Did not include e2"); assertTrue(findIdInResult(result, e3), "Did not include e3"); - dropInclExcl(); }, //////////////////////////////////////////////////////////////////////////////// @@ -505,7 +522,6 @@ function GeneralGraphAQLQueriesSuite() { //////////////////////////////////////////////////////////////////////////////// test_outEdges: function() { - var g = createInclExcl(); var query = g._outEdges("v1/1"); assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES(" + '@graphName,@startVertex_0,"outbound")'); @@ -517,7 +533,6 @@ function GeneralGraphAQLQueriesSuite() { assertTrue(findIdInResult(result, e1), "Did not include e1"); assertTrue(findIdInResult(result, e3), "Did not include e3"); assertFalse(findIdInResult(result, e2), "e2 is not excluded"); - dropInclExcl(); }, //////////////////////////////////////////////////////////////////////////////// @@ -525,7 +540,6 @@ function GeneralGraphAQLQueriesSuite() { //////////////////////////////////////////////////////////////////////////////// test_inEdges: function() { - var g = createInclExcl(); var query = g._inEdges("v1/1"); assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES(" + '@graphName,@startVertex_0,"inbound")'); @@ -537,11 +551,9 @@ function GeneralGraphAQLQueriesSuite() { assertTrue(findIdInResult(result, e2), "Did not include e2"); assertFalse(findIdInResult(result, e1), "e1 is not excluded"); assertFalse(findIdInResult(result, e3), "e3 is not excluded"); - dropInclExcl(); }, test_restrictOnEdges: function() { - var g = createInclExcl(); var query = g._edges("v1/1").restrict("included"); assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES(" + '@graphName,@startVertex_0,"any",{},@restrictions_0)'); @@ -555,7 +567,6 @@ function GeneralGraphAQLQueriesSuite() { assertTrue(findIdInResult(result, e1), "Did not include e1"); assertTrue(findIdInResult(result, e2), "Did not include e2"); assertFalse(findIdInResult(result, e3), "e3 is not excluded"); - dropInclExcl(); }, //////////////////////////////////////////////////////////////////////////////// @@ -563,7 +574,6 @@ function GeneralGraphAQLQueriesSuite() { //////////////////////////////////////////////////////////////////////////////// test_restrictOnInEdges: function() { - var g = createInclExcl(); var query = g._inEdges("v1/1").restrict("included"); assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES(" + '@graphName,@startVertex_0,"inbound",{},@restrictions_0)'); @@ -576,7 +586,6 @@ function GeneralGraphAQLQueriesSuite() { assertTrue(findIdInResult(result, e2), "Did not include e2"); assertFalse(findIdInResult(result, e1), "e1 is not excluded"); assertFalse(findIdInResult(result, e3), "e3 is not excluded"); - dropInclExcl(); }, //////////////////////////////////////////////////////////////////////////////// @@ -584,7 +593,6 @@ function GeneralGraphAQLQueriesSuite() { //////////////////////////////////////////////////////////////////////////////// test_restrictOnOutEdges: function() { - var g = createInclExcl(); var query = g._outEdges("v1/1").restrict("included"); assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES(" + '@graphName,@startVertex_0,"outbound",{},@restrictions_0)'); @@ -597,7 +605,6 @@ function GeneralGraphAQLQueriesSuite() { assertTrue(findIdInResult(result, e1), "Did not include e1"); assertFalse(findIdInResult(result, e2), "e2 is not excluded"); assertFalse(findIdInResult(result, e3), "e3 is not excluded"); - dropInclExcl(); }, //////////////////////////////////////////////////////////////////////////////// @@ -605,7 +612,6 @@ function GeneralGraphAQLQueriesSuite() { //////////////////////////////////////////////////////////////////////////////// test_filterOnEdges: function() { - var g = createInclExcl(); var query = g._edges("v1/1").filter({val: true}); // var query = g._edges("v1/1").filter("e.val = true"); assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES(" @@ -619,8 +625,6 @@ function GeneralGraphAQLQueriesSuite() { assertTrue(findIdInResult(result, e1), "Did not include e1"); assertFalse(findIdInResult(result, e2), "e2 is not excluded"); assertFalse(findIdInResult(result, e3), "e3 is not excluded"); - dropInclExcl(); - }, //////////////////////////////////////////////////////////////////////////////// @@ -628,7 +632,6 @@ function GeneralGraphAQLQueriesSuite() { //////////////////////////////////////////////////////////////////////////////// test_filterOnInEdges: function() { - var g = createInclExcl(); var query = g._inEdges("v1/1").filter({val: true}); assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES(" + '@graphName,@startVertex_0,"inbound") ' @@ -641,7 +644,6 @@ function GeneralGraphAQLQueriesSuite() { assertFalse(findIdInResult(result, e1), "e1 is not excluded"); assertFalse(findIdInResult(result, e2), "e2 is not excluded"); assertFalse(findIdInResult(result, e3), "e3 is not excluded"); - dropInclExcl(); }, //////////////////////////////////////////////////////////////////////////////// @@ -649,7 +651,6 @@ function GeneralGraphAQLQueriesSuite() { //////////////////////////////////////////////////////////////////////////////// test_filterOnOutEdges: function() { - var g = createInclExcl(); var query = g._outEdges("v1/1").filter({val: true}); // var query = g._outEdges("v1/1").filter("e.val = true"); assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES(" @@ -663,7 +664,6 @@ function GeneralGraphAQLQueriesSuite() { assertTrue(findIdInResult(result, e1), "Did not include e1"); assertFalse(findIdInResult(result, e2), "e2 is not excluded"); assertFalse(findIdInResult(result, e3), "e3 is not excluded"); - dropInclExcl(); } //////////////////////////////////////////////////////////////////////////////// @@ -672,7 +672,6 @@ function GeneralGraphAQLQueriesSuite() { /* Broken string replacement test_letOnEdges: function() { - var g = createInclExcl(); var query = g._edges("v1/1").let("myVal = e.val"); assertEqual(query.printQuery(), "FOR edges_0 IN GRAPH_EDGES(" + "@graphName,@startVertex_0,any) LET myVal = edges_0.val"); @@ -688,7 +687,6 @@ function GeneralGraphAQLQueriesSuite() { assertFalse(findIdInResult(result, e2)); */ /* - dropInclExcl(); } */ @@ -698,141 +696,249 @@ function GeneralGraphAQLQueriesSuite() { function EdgesAndVerticesSuite() { - try { - arangodb.db._collection("_graphs").remove("_graphs/blubGraph") - } catch (err) { - } - var g = graph._create( - "blubGraph", - graph.edgeDefinitions( - graph._undirectedRelationDefinition("edgeCollection1", "vertexCollection1"), - graph._directedRelationDefinition("edgeCollection2", - ["vertexCollection1", "vertexCollection2"], ["vertexCollection3", "vertexCollection4"] - ) - ) - ); - + var g; var vertexIds = []; var vertexId1, vertexId2; var edgeId1, edgeId2; + fillCollections = function() { + var ids = {}; + var vertex = g.vertexCollection1.save({first_name: "Tam"}); + ids["vId11"] = vertex._id; + vertex = g.vertexCollection1.save({first_name: "Tem"}); + ids["vId12"] = vertex._id; + vertex = g.vertexCollection1.save({first_name: "Tim"}); + ids["vId13"] = vertex._id; + vertex = g.vertexCollection1.save({first_name: "Tom"}); + ids["vId14"] = vertex._id; + vertex = g.vertexCollection1.save({first_name: "Tum"}); + ids["vId15"] = vertex._id; + vertex = g.unitTestVertexCollection3.save({first_name: "Tam"}); + ids["vId31"] = vertex._id; + vertex = g.unitTestVertexCollection3.save({first_name: "Tem"}); + ids["vId32"] = vertex._id; + vertex = g.unitTestVertexCollection3.save({first_name: "Tim"}); + ids["vId33"] = vertex._id; + vertex = g.unitTestVertexCollection3.save({first_name: "Tom"}); + ids["vId34"] = vertex._id; + vertex = g.unitTestVertexCollection3.save({first_name: "Tum"}); + ids["vId35"] = vertex._id; + + var edge = g.unitTestEdgeCollection1.save(ids.vId11, ids.vId12, {}); + ids["eId11"] = edge._id; + edge = g.unitTestEdgeCollection1.save(ids.vId11, ids.vId13, {}); + ids["eId12"] = edge._id; + edge = g.unitTestEdgeCollection1.save(ids.vId11, ids.vId14, {}); + ids["eId13"] = edge._id; + edge = g.unitTestEdgeCollection1.save(ids.vId11, ids.vId15, {}); + ids["eId14"] = edge._id; + edge = g.unitTestEdgeCollection1.save(ids.vId12, ids.vId11, {}); + ids["eId15"] = edge._id; + edge = g.unitTestEdgeCollection1.save(ids.vId13, ids.vId11, {}); + ids["eId16"] = edge._id; + edge = g.unitTestEdgeCollection1.save(ids.vId14, ids.vId11, {}); + ids["eId17"] = edge._id; + edge = g.unitTestEdgeCollection1.save(ids.vId15, ids.vId11, {}); + ids["eId18"] = edge._id; + edge = g.unitTestEdgeCollection2.save(ids.vId11, ids.vId31, {}); + ids["eId21"] = edge._id; + edge = g.unitTestEdgeCollection2.save(ids.vId11, ids.vId32, {}); + ids["eId22"] = edge._id; + edge = g.unitTestEdgeCollection2.save(ids.vId11, ids.vId33, {}); + ids["eId23"] = edge._id; + edge = g.unitTestEdgeCollection2.save(ids.vId11, ids.vId34, {}); + ids["eId24"] = edge._id; + edge = g.unitTestEdgeCollection2.save(ids.vId11, ids.vId35, {}); + ids["eId25"] = edge._id; + return ids; + } + return { + setUp : function() { + try { + arangodb.db._collection("_graphs").remove("_graphs/unitTestGraph") + } catch (err) { + } + g = graph._create( + "unitTestGraph", + graph.edgeDefinitions( + graph._undirectedRelationDefinition("unitTestEdgeCollection1", "unitTestVertexCollection1"), + graph._directedRelationDefinition("unitTestEdgeCollection2", + ["unitTestVertexCollection1", "unitTestVertexCollection2"], ["unitTestVertexCollection3", "unitTestVertexCollection4"] + ) + ) + ); + }, + + tearDown : function() { + db.unitTestVertexCollection1.drop(); + db.unitTestVertexCollection2.drop(); + db.unitTestVertexCollection3.drop(); + db.unitTestVertexCollection4.drop(); + db.unitTestEdgeCollection1.drop(); + db.unitTestEdgeCollection2.drop(); + }, + test_edgeCollections : function () { var edgeCollections = g._edgeCollections(); - assertEqual(edgeCollections[0].name(), 'edgeCollection1'); - assertEqual(edgeCollections[1].name(), 'edgeCollection2'); + assertEqual(edgeCollections[0].name(), 'unitTestEdgeCollection1'); + assertEqual(edgeCollections[1].name(), 'unitTestEdgeCollection2'); }, test_vertexCollections : function () { var vertexCollections = g._vertexCollections(); - assertEqual(vertexCollections[0].name(), 'vertexCollection1'); - assertEqual(vertexCollections[1].name(), 'vertexCollection2'); - assertEqual(vertexCollections[2].name(), 'vertexCollection3'); - assertEqual(vertexCollections[3].name(), 'vertexCollection4'); + assertEqual(vertexCollections[0].name(), 'unitTestVertexCollection1'); + assertEqual(vertexCollections[1].name(), 'unitTestVertexCollection2'); + assertEqual(vertexCollections[2].name(), 'unitTestVertexCollection3'); + assertEqual(vertexCollections[3].name(), 'unitTestVertexCollection4'); }, test_vC_save : function () { - var vertex = g.vertexCollection1.save({first_name: "Tom"}); + var vertex = g.unitTestVertexCollection1.save({first_name: "Tom"}); assertFalse(vertex.error); vertexId1 = vertex._id; - var vertexObj = g.vertexCollection1.document(vertexId1); + var vertexObj = g.unitTestVertexCollection1.document(vertexId1); assertEqual(vertexObj.first_name, "Tom"); }, test_vC_replace : function () { - var vertex = g.vertexCollection1.replace(vertexId1, {first_name: "Tim"}); + var vertex = g.unitTestVertexCollection1.save({first_name: "Tom"}); + var vertexId = vertex._id; + vertex = g.unitTestVertexCollection1.replace(vertexId, {first_name: "Tim"}); assertFalse(vertex.error); - var vertexObj = g.vertexCollection1.document(vertexId1); + var vertexObj = g.unitTestVertexCollection1.document(vertexId); assertEqual(vertexObj.first_name, "Tim"); }, test_vC_update : function () { - var vertex = g.vertexCollection1.update(vertexId1, {age: 42}); + var vertex = g.unitTestVertexCollection1.save({first_name: "Tim"}); + var vertexId = vertex._id; + vertex = g.unitTestVertexCollection1.update(vertexId, {age: 42}); assertFalse(vertex.error); - var vertexObj = g.vertexCollection1.document(vertexId1); + var vertexObj = g.unitTestVertexCollection1.document(vertexId); assertEqual(vertexObj.first_name, "Tim"); assertEqual(vertexObj.age, 42); }, test_vC_remove : function () { - var vertex = g.vertexCollection1.remove(vertexId1); + var vertex = g.unitTestVertexCollection1.save({first_name: "Tim"}); + var vertexId = vertex._id; + var vertex = g.unitTestVertexCollection1.remove(vertexId); assertTrue(vertex); }, test_eC_save_undirected : function() { - var vertex1 = g.vertexCollection1.save({first_name: "Tom"}); - vertexId1 = vertex1._id; - var vertex2 = g.vertexCollection1.save({first_name: "Tim"}); - vertexId2 = vertex2._id; - var edge = g.edgeCollection1.save(vertexId1, vertexId2, {}); + var vertex1 = g.unitTestVertexCollection1.save({first_name: "Tom"}); + var vertexId1 = vertex1._id; + var vertex2 = g.unitTestVertexCollection1.save({first_name: "Tim"}); + var vertexId2 = vertex2._id; + var edge = g.unitTestEdgeCollection1.save(vertexId1, vertexId2, {}); assertFalse(edge.error); edgeId1 = edge._id; - g.vertexCollection1.remove(vertexId1); - g.vertexCollection1.remove(vertexId2); + g.unitTestVertexCollection1.remove(vertexId1); + g.unitTestVertexCollection1.remove(vertexId2); }, test_eC_save_directed : function() { - var vertex1 = g.vertexCollection2.save({first_name: "Tom"}); + var vertex1 = g.unitTestVertexCollection2.save({first_name: "Tom"}); vertexId1 = vertex1._id; - var vertex2 = g.vertexCollection4.save({first_name: "Tim"}); + var vertex2 = g.unitTestVertexCollection4.save({first_name: "Tim"}); vertexId2 = vertex2._id; - var edge = g.edgeCollection2.save(vertexId1, vertexId2, {}); + var edge = g.unitTestEdgeCollection2.save(vertexId1, vertexId2, {}); assertFalse(edge.error); edgeId2 = edge._id; - g.vertexCollection2.remove(vertexId1); - g.vertexCollection4.remove(vertexId2); + g.unitTestVertexCollection2.remove(vertexId1); + g.unitTestVertexCollection4.remove(vertexId2); }, test_eC_save_withError : function() { - var vertex1 = g.vertexCollection1.save({first_name: "Tom"}); + var vertex1 = g.unitTestVertexCollection1.save({first_name: "Tom"}); vertexId1 = vertex1._id; - var vertex2 = g.vertexCollection2.save({first_name: "Tim"}); + var vertex2 = g.unitTestVertexCollection2.save({first_name: "Tim"}); vertexId2 = vertex2._id; try { - var edge = g.edgeCollection1.save(vertexId1, vertexId2, {}); + var edge = g.unitTestEdgeCollection1.save(vertexId1, vertexId2, {}); } catch (e) { assertEqual(e, "Edge is not allowed between " + vertexId1 + " and " + vertexId2 + ".") } - g.vertexCollection1.remove(vertexId1); - g.vertexCollection2.remove(vertexId2); + g.unitTestVertexCollection1.remove(vertexId1); + g.unitTestVertexCollection2.remove(vertexId2); }, test_eC_replace : function() { - var edge = g.edgeCollection1.replace(edgeId1, {label: "knows"}); + var vertex1 = g.unitTestVertexCollection1.save({first_name: "Tom"}); + var vertexId1 = vertex1._id; + var vertex2 = g.unitTestVertexCollection1.save({first_name: "Tim"}); + var vertexId2 = vertex2._id; + var edge = g.unitTestEdgeCollection1.save(vertexId1, vertexId2, {}); + var edgeId1 = edge._id; + edge = g.unitTestEdgeCollection1.replace(edgeId1, {label: "knows"}); assertFalse(edge.error); - var edgeObj = g.edgeCollection1.document(edgeId1); + var edgeObj = g.unitTestEdgeCollection1.document(edgeId1); assertEqual(edgeObj.label, "knows"); assertEqual(edgeObj._id, edgeId1); }, test_eC_update : function () { - var edge = g.edgeCollection1.update(edgeId1, {blub: "blub"}); + var vertex1 = g.unitTestVertexCollection1.save({first_name: "Tom"}); + var vertexId1 = vertex1._id; + var vertex2 = g.unitTestVertexCollection1.save({first_name: "Tim"}); + var vertexId2 = vertex2._id; + var edge = g.unitTestEdgeCollection1.save(vertexId1, vertexId2, {}); + var edgeId1 = edge._id; + edge = g.unitTestEdgeCollection1.replace(edgeId1, {label: "knows"}); + edge = g.unitTestEdgeCollection1.update(edgeId1, {blub: "blub"}); assertFalse(edge.error); - var edgeObj = g.edgeCollection1.document(edgeId1); + var edgeObj = g.unitTestEdgeCollection1.document(edgeId1); assertEqual(edgeObj.label, "knows"); assertEqual(edgeObj.blub, "blub"); assertEqual(edgeObj._id, edgeId1); }, test_eC_remove : function () { - var edge = g.edgeCollection1.remove(edgeId1); - assertTrue(edge); - edge = g.edgeCollection2.remove(edgeId2); + var vertex1 = g.unitTestVertexCollection1.save({first_name: "Tom"}); + var vertexId1 = vertex1._id; + var vertex2 = g.unitTestVertexCollection1.save({first_name: "Tim"}); + var vertexId2 = vertex2._id; + var edge = g.unitTestEdgeCollection1.save(vertexId1, vertexId2, {}); + var edgeId1 = edge._id; + edge = g.unitTestEdgeCollection1.remove(edgeId1); assertTrue(edge); }, + test_edges : function() { + var ids = fillCollections(); + var result = g._edges(ids.vId11).toArray(); + assertEqual(result.length, 13) + }, + test_inEdges : function() { + var ids = fillCollections(); + var result = g._inEdges(ids.vId11).toArray(); + assertEqual(result.length, 4) + }, - dump : function() { - db.vertexCollection1.drop(); - db.vertexCollection2.drop(); - db.vertexCollection3.drop(); - db.vertexCollection4.drop(); - db.edgeCollection1.drop(); - db.edgeCollection2.drop(); + test_outEdges : function() { + var ids = fillCollections(); + var result = g._outEdges(ids.vId11).toArray(); + assertEqual(result.length, 9) + }, + + test_getInVertex : function() { + var ids = fillCollections(); + var result = g._getInVertex(ids.eId11); + assertEqual(result._id, ids.vId11); + }, + + test_getOutVertex : function() { + var ids = fillCollections(); + var result = g._getOutVertex(ids.eId11); + assertEqual(result._id, ids.vId12); + result = g._getOutVertex(ids.eId25); + assertEqual(result._id, ids.vId35); } }; diff --git a/js/common/tests/shell-graph-traversal.js b/js/common/tests/shell-graph-traversal.js index bf51659e56..83eda88577 100644 --- a/js/common/tests/shell-graph-traversal.js +++ b/js/common/tests/shell-graph-traversal.js @@ -33,6 +33,7 @@ var jsunity = require("jsunity"); var arangodb = require("org/arangodb"); var traversal = require("org/arangodb/graph/traversal"); var graph = require("org/arangodb/graph"); +var generalGraph = require("org/arangodb/general-graph"); var db = arangodb.db; var Traverser = traversal.Traverser; @@ -1856,6 +1857,370 @@ function CollectionTraversalSuite () { }; } + +// ----------------------------------------------------------------------------- +// --SECTION-- general graph traversal +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test: general-graph-based graph traversal +//////////////////////////////////////////////////////////////////////////////// + +function GeneralGraphTraversalSuite () { + // Definition of the edges: A -> BDEH <-> CFGI + var vnA = "UnitTestsVertices1"; + var enDir = "UnitTestsEdges1"; + var vnBDH = "UnitTestsVertices2"; + var enUndir = "UnitTestsEdges2"; + var vnCEFGI = "UnitTestsVertices3"; + + var gn = "UnitTestsGraph"; + + var g; + + var getResult = function () { + return { + visited: { + vertices: [ ], + paths: [ ] + } + }; + }; + + var getIds = function (data) { + var r = [ ]; + data.forEach(function (item) { + r.push(item._id); + }); + return r; + }; + var saveVertex = function(colName, key) { + g[colName].save({ _key: key, name: key }); + }; + var saveEdge = function(edgeCol, fromCol, toCol, nodePair) { + var l = nodePair[0]; + var r = nodePair[1]; + g[edgeCol].save(fromCol + "/" + l, toCol + "/" + r, {_key: l + r, what: l + "->" + r }); + }; + + var cleanUp = function() { + db._drop(vnA); + db._drop(vnBDH); + db._drop(vnCEFGI); + db._drop(enDir); + db._drop(enUndir); + if (db._graphs.exists(gn)) { + db._graphs.remove(gn); + } + }; + + return { + +//////////////////////////////////////////////////////////////////////////////// +/// @brief set up +//////////////////////////////////////////////////////////////////////////////// + + setUp : function () { + cleanUp(); + + var edgeDef = []; + edgeDef.push(generalGraph._directedRelationDefinition(enDir, vnA, vnBDH)); + edgeDef.push(generalGraph._undirectedRelationDefinition(enUndir, [vnBDH, vnCEFGI])); + g = generalGraph._create(gn, edgeDef); + + saveVertex(vnA, "A"); + [ "B", "D", "H" ].forEach(function (item) { + saveVertex(vnBDH, item); + }); + [ "C", "E", "F", "G", "I" ].forEach(function (item) { + saveVertex(vnCEFGI, item); + }); + + [ [ "A", "B" ], [ "A", "D" ] ].forEach(function (item) { + saveEdge(enDir, vnA, vnBDH, item); + }); + [ [ "B", "C" ], [ "D", "E" ], [ "D", "F" ], [ "B", "G" ], [ "B", "I" ] ].forEach(function (item) { + saveEdge(enUndir, vnBDH, vnCEFGI, item); + }); + [ [ "C", "D" ], [ "G", "H" ], [ "I", "H"] ].forEach(function (item) { + saveEdge(enUndir, vnCEFGI, vnBDH, item); + }); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief tear down +//////////////////////////////////////////////////////////////////////////////// + + tearDown : function () { + cleanUp(); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test outbound expander +//////////////////////////////////////////////////////////////////////////////// + + testOutboundExpander : function () { + var config = { + sort: function (l, r) { return l._key < r._key ? -1 : 1; }, + datasource: traversal.generalGraphDatasourceFactory(gn) + }; + + var expander = traversal.outboundExpander; + var connected; + + connected = [ ]; + expander(config, g[vnA].document("A")).forEach(function(item) { + connected.push(item.vertex._key); + }); + + assertEqual([ "B", "D" ], connected); + + connected = [ ]; + expander(config, g[vnBDH].document("D")).forEach(function(item) { + connected.push(item.vertex._key); + }); + + assertEqual([ "E", "F" ], connected); + + connected = [ ]; + expander(config, g[vnBDH].document("H")).forEach(function(item) { + connected.push(item.vertex._key); + }); + + assertEqual([ ], connected); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test inbound expander +//////////////////////////////////////////////////////////////////////////////// + + testInboundExpander : function () { + var config = { + sort: function (l, r) { return l._key < r._key ? -1 : 1; }, + datasource: traversal.generalGraphDatasourceFactory(gn) + }; + + var expander = traversal.inboundExpander; + var connected; + + connected = [ ]; + expander(config, g[vnBDH].document("D")).forEach(function(item) { + connected.push(item.vertex._key); + }); + + assertEqual([ "A", "C" ], connected); + + connected = [ ]; + expander(config, g[vnBDH].document("H")).forEach(function(item) { + connected.push(item.vertex._key); + }); + + assertEqual([ "G", "I" ], connected); + + connected = [ ]; + expander(config, g[vnA].document("A")).forEach(function(item) { + connected.push(item.vertex._key); + }); + + assertEqual([ ], connected); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test iteration +//////////////////////////////////////////////////////////////////////////////// + + testIterateFullOutbound : function () { + var config = { + datasource: traversal.generalGraphDatasourceFactory(gn), + strategy: Traverser.DEPTH_FIRST, + order: Traverser.PRE_ORDER, + itemOrder: Traverser.FORWARD, + filter: traversal.visitAllFilter, + expander: traversal.outboundExpander, + + sort: function (l, r) { return l._key < r._key ? -1 : 1; } + }; + + var traverser = new Traverser(config); + var result = getResult(); + traverser.traverse(result, g[vnA].document("A")); + + var expectedVisits = [ + vnA + "/A", + vnBDH + "/B", + vnCEFGI + "/C", + vnBDH + "/D", + vnCEFGI + "/E", + vnCEFGI + "/F", + vnCEFGI + "/G", + vnBDH + "/H", + vnCEFGI + "/I", + vnBDH + "/H", + vnBDH + "/D", + vnCEFGI + "/E", + vnCEFGI + "/F" + ]; + + assertEqual(expectedVisits, getIds(result.visited.vertices)); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test iteration +//////////////////////////////////////////////////////////////////////////////// + + testIterateInbound : function () { + var config = { + datasource: traversal.generalGraphDatasourceFactory(gn), + strategy: Traverser.DEPTH_FIRST, + order: Traverser.PRE_ORDER, + itemOrder: Traverser.FORWARD, + filter: traversal.visitAllFilter, + expander: traversal.inboundExpander, + + sort: function (l, r) { return l._key < r._key ? -1 : 1; } + }; + + var result = getResult(); + var traverser = new Traverser(config); + traverser.traverse(result, g[vnCEFGI].document("F")); + + var expectedVisits = [ + vnCEFGI + "/F", + vnBDH + "/D", + vnA + "/A", + vnCEFGI + "/C", + vnBDH + "/B", + vnA + "/A" + ]; + + assertEqual(expectedVisits, getIds(result.visited.vertices)); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test iteration +//////////////////////////////////////////////////////////////////////////////// + + testIterateUniqueGlobalVertices : function () { + var config = { + datasource: traversal.generalGraphDatasourceFactory(gn), + strategy: Traverser.DEPTH_FIRST, + order: Traverser.PRE_ORDER, + itemOrder: Traverser.FORWARD, + uniqueness: { + vertices: Traverser.UNIQUE_GLOBAL, + edges: Traverser.UNIQUE_NONE + }, + filter: traversal.visitAllFilter, + expander: traversal.outboundExpander, + + sort: function (l, r) { return l._key < r._key ? -1 : 1; } + }; + + var result = getResult(); + var traverser = new Traverser(config); + traverser.traverse(result, g[vnA].document("A")); + + var expectedVisits = [ + vnA + "/A", + vnBDH + "/B", + vnCEFGI + "/C", + vnBDH + "/D", + vnCEFGI + "/E", + vnCEFGI + "/F", + vnCEFGI + "/G", + vnBDH + "/H", + vnCEFGI + "/I" + ]; + + assertEqual(expectedVisits, getIds(result.visited.vertices)); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test iteration +//////////////////////////////////////////////////////////////////////////////// + + testIterateUniquePathVertices : function () { + var config = { + datasource: traversal.generalGraphDatasourceFactory(gn), + strategy: Traverser.DEPTH_FIRST, + order: Traverser.PRE_ORDER, + itemOrder: Traverser.FORWARD, + uniqueness: { + vertices: Traverser.UNIQUE_PATH, + edges: Traverser.UNIQUE_NONE + }, + filter: traversal.visitAllFilter, + expander: traversal.outboundExpander, + + sort: function (l, r) { return l._key < r._key ? -1 : 1; } + }; + + var result = getResult(); + var traverser = new Traverser(config); + traverser.traverse(result, g[vnA].document("A")); + + var expectedVisits = [ + vnA + "/A", + vnBDH + "/B", + vnCEFGI + "/C", + vnBDH + "/D", + vnCEFGI + "/E", + vnCEFGI + "/F", + vnCEFGI + "/G", + vnBDH + "/H", + vnCEFGI + "/I", + vnBDH + "/H", + vnBDH + "/D", + vnCEFGI + "/E", + vnCEFGI + "/F" + ]; + + assertEqual(expectedVisits, getIds(result.visited.vertices)); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test iteration +//////////////////////////////////////////////////////////////////////////////// + + testIterateUniqueEdges : function () { + var config = { + datasource: traversal.generalGraphDatasourceFactory(gn), + strategy: Traverser.DEPTH_FIRST, + order: Traverser.PRE_ORDER, + itemOrder: Traverser.FORWARD, + uniqueness: { + vertices: Traverser.UNIQUE_NONE, + edges: Traverser.UNIQUE_GLOBAL + }, + filter: traversal.visitAllFilter, + expander: traversal.outboundExpander, + + sort: function (l, r) { return l._key < r._key ? -1 : 1; } + }; + + var result = getResult(); + var traverser = new Traverser(config); + traverser.traverse(result, g[vnA].document("A")); + + var expectedVisits = [ + vnA + "/A", + vnBDH + "/B", + vnCEFGI + "/C", + vnBDH + "/D", + vnCEFGI + "/E", + vnCEFGI + "/F", + vnCEFGI + "/G", + vnBDH + "/H", + vnCEFGI + "/I", + vnBDH + "/H", + vnBDH + "/D" + ]; + + assertEqual(expectedVisits, getIds(result.visited.vertices)); + } + }; +} + // ----------------------------------------------------------------------------- // --SECTION-- main // ----------------------------------------------------------------------------- @@ -1867,6 +2232,7 @@ function CollectionTraversalSuite () { jsunity.run(GraphTraversalSuite); jsunity.run(MemoryTraversalSuite); jsunity.run(CollectionTraversalSuite); +jsunity.run(GeneralGraphTraversalSuite); return jsunity.done(); diff --git a/lib/Utilities/ShellImplFactory.cpp b/lib/Utilities/ShellImplFactory.cpp index cea37c77b1..ee9b764ef9 100644 --- a/lib/Utilities/ShellImplFactory.cpp +++ b/lib/Utilities/ShellImplFactory.cpp @@ -41,11 +41,10 @@ using namespace triagens; using namespace std; -ShellImplementation * ShellImplFactory::buildShell(string const & history, Completer * completer) { - +ShellImplementation * ShellImplFactory::buildShell (string const & history, Completer * completer) { #ifdef _WIN32 - //under windows the realine is not compilable + //under windows the readline is not compilable return new LinenoiseShell(history, completer); #elif defined TRI_HAVE_LINENOISE return new LinenoiseShell(history, completer);