mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' into HLC
This commit is contained in:
commit
36a9b7852e
|
@ -169,7 +169,7 @@ if (CMAKE_COMPILER_IS_GNUCC)
|
|||
message(STATUS "Compiler type GNU: ${CMAKE_CXX_COMPILER}")
|
||||
endif ()
|
||||
# -DSNAPPY -DZLIB
|
||||
if (SOLARIS)
|
||||
if (SOLARIS OR DARWIN)
|
||||
set(ROCKSDB_MALLOC_USABLE_SIZE "")
|
||||
else()
|
||||
set(ROCKSDB_MALLOC_USABLE_SIZE "-DROCKSDB_MALLOC_USABLE_SIZE")
|
||||
|
|
10
CHANGELOG
10
CHANGELOG
|
@ -1,8 +1,6 @@
|
|||
devel
|
||||
-----
|
||||
|
||||
* fixed issue #1930
|
||||
|
||||
* added option `--skip-lines` for arangoimp
|
||||
this allows skipping the first few lines from the import file in case the
|
||||
CSV or TSV import are used
|
||||
|
@ -29,7 +27,13 @@ devel
|
|||
v3.0.2 (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* don't expose local file paths in error messages.
|
||||
* fixed assertion failure in case multiple remove operations were used in the same query
|
||||
|
||||
* fixed upsert behavior in case upsert was used in a loop with the same document example
|
||||
|
||||
* fixed issue #1930
|
||||
|
||||
* don't expose local file paths in Foxx error messages.
|
||||
|
||||
* fixed issue #1929
|
||||
|
||||
|
|
|
@ -713,6 +713,10 @@ if (USE_OPENSSL_NO_SSL2)
|
|||
add_definitions(-DOPENSSL_NO_SSL2)
|
||||
endif ()
|
||||
|
||||
if(WIN32)
|
||||
option(BUNDLE_OPENSSL "Bundle OpenSSL library" ON)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
## V8
|
||||
################################################################################
|
||||
|
|
20
GNUmakefile
20
GNUmakefile
|
@ -155,11 +155,6 @@ pack-macosx-cmake:
|
|||
|
||||
test -d bin || mkdir bin
|
||||
|
||||
rm -f ./.file-list-js
|
||||
cd Build && ${MAKE}
|
||||
|
||||
./Installation/file-copy-js.sh . Build
|
||||
|
||||
cd Build && ${MAKE} install DESTDIR=${PACK_DESTDIR}
|
||||
|
||||
################################################################################
|
||||
|
@ -186,11 +181,6 @@ pack-arm-cmake:
|
|||
|
||||
${MAKE} ${BUILT_SOURCES}
|
||||
|
||||
rm -f ./.file-list-js
|
||||
cd Build && ${MAKE}
|
||||
|
||||
./Installation/file-copy-js.sh . Build
|
||||
|
||||
cd Build && cpack -G DEB
|
||||
|
||||
|
||||
|
@ -207,11 +197,8 @@ pack-deb-cmake:
|
|||
|
||||
${MAKE} ${BUILT_SOURCES}
|
||||
|
||||
rm -f ./.file-list-js
|
||||
cd Build && ${MAKE}
|
||||
|
||||
./Installation/file-copy-js.sh . Build
|
||||
|
||||
cd Build && cpack -G DEB
|
||||
|
||||
################################################################################
|
||||
|
@ -255,7 +242,6 @@ pack-winXX-MOREOPTS:
|
|||
${MAKE} packXX BITS="$(BITS)" TARGET="$(TARGET)" BUILD_TARGET=Debug
|
||||
|
||||
winXX-cmake:
|
||||
rm -f ./.file-list-js
|
||||
cd ../b && cmake \
|
||||
-G "$(TARGET)" \
|
||||
-D "CMAKE_BUILD_TYPE=RelWithDebInfo" \
|
||||
|
@ -269,9 +255,5 @@ winXX-build:
|
|||
cd ../b && cmake --build . --config $(BUILD_TARGET)
|
||||
|
||||
packXX:
|
||||
if test ! -d ../b/js; then ./Installation/file-copy-js.sh . ../b; fi
|
||||
cd ../b; rm -f ArangoDB-*.exe ArangoDB*.nsi
|
||||
cd ../b && cpack -G NSIS -C $(BUILD_TARGET)
|
||||
cd ../b && cpack -G NSIS64 -C $(BUILD_TARGET)
|
||||
cd ../b && cpack -G ZIP -C $(BUILD_TARGET)
|
||||
|
||||
./Installation/Windows/installer-generator.sh $(BITS) ..\\b
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
NSIS_PATH="/cygdrive/c/Program Files (x86)/NSIS"
|
||||
#shell parameter:
|
||||
#1 the bits (64 or 32)
|
||||
#2 the parent directory which contains the Build64 or Build32 directory
|
||||
BUILD=$2
|
||||
bits=$1
|
||||
|
||||
# Yo windows we like year backslash paths.
|
||||
WD=`pwd`
|
||||
SRCPATH=`cygpath -w ${WD}|sed "s;\\\\\;\\\\\\\\\\\\\;g"`
|
||||
|
||||
INSTALLERNAME=`grep CPACK_PACKAGE_FILE_NAME ${BUILD}/CPackConfig.cmake | grep -o '".*"' | awk -F\" '{print $2}'`
|
||||
|
||||
if [ ! -f ${BUILD}/$INSTALLERNAME-internal.exe ]; then
|
||||
cp ${BUILD}/$INSTALLERNAME.exe ${BUILD}/$INSTALLERNAME-internal.exe
|
||||
fi
|
||||
cat Installation/Windows/Templates/arango-packer-template.nsi | \
|
||||
sed -e "s;@BITS@;$bits;g" \
|
||||
-e "s;@INSTALLERNAME@;${INSTALLERNAME};" \
|
||||
-e "s;@SRCDIR@;${SRCPATH};g" > ${BUILD}/$INSTALLERNAME.nsi
|
||||
|
||||
"$NSIS_PATH"/makensis.exe ${BUILD}\\$INSTALLERNAME.nsi
|
||||
|
|
@ -77,7 +77,6 @@ build-stamp:
|
|||
# not used
|
||||
rm -rf js/node/node_modules/js-yaml/demo
|
||||
|
||||
rm -f .file-list-js
|
||||
make -j12 all
|
||||
|
||||
# --- end custom part for compiling
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SRCDIR=$1
|
||||
DSTDIR=$2
|
||||
|
||||
${SRCDIR}/Installation/file-list-js.sh ${SRCDIR} | while read a; do
|
||||
if test -f "$DSTDIR/$a"; then
|
||||
echo "$DSTDIR/$a: already exists, giving up"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FROM="${SRCDIR}/$a"
|
||||
TO="${DSTDIR}/$a"
|
||||
DIR=`dirname "${TO}"`
|
||||
|
||||
chmod a+r "${FROM}"
|
||||
test -d "${DIR}" || mkdir -p "${DIR}"
|
||||
cp -n "${FROM}" "${TO}"
|
||||
done
|
|
@ -1,35 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SRCDIR=$1
|
||||
|
||||
if test ! -f "$SRCDIR/.file-list-js"; then
|
||||
(
|
||||
cd ${SRCDIR}
|
||||
|
||||
find \
|
||||
js/actions \
|
||||
js/apps/system/_admin \
|
||||
js/apps/system/_api \
|
||||
js/apps/system/_system \
|
||||
js/client \
|
||||
js/common \
|
||||
js/node \
|
||||
js/server \
|
||||
\
|
||||
-type f -print
|
||||
) \
|
||||
| egrep -v "^js/common/tests/" \
|
||||
| egrep -v "^js/common/test-data/" \
|
||||
| egrep -v "^js/client/tests/" \
|
||||
| egrep -v "^js/client/test-data/" \
|
||||
| egrep -v "^js/server/tests/" \
|
||||
| egrep -v "^js/server/test-data/" \
|
||||
| egrep -v "^js/apps/system/_admin/.*/node_modules/" \
|
||||
| egrep -v "^js/apps/system/.*/test/" \
|
||||
| egrep -v "^js/apps/system/.*/test_data/" \
|
||||
| egrep -v "^js/apps/system/.*/coverage/" \
|
||||
| egrep -v "fileset.*tests.*fixtures.*an.*odd.*filename" > "$SRCDIR/.file-list-js"
|
||||
fi
|
||||
|
||||
cat "$SRCDIR/.file-list-js"
|
|
@ -398,7 +398,9 @@ void Executor::generateCodeExpression(AstNode const* node) {
|
|||
// thrown by the function
|
||||
_buffer->appendText(TRI_CHAR_LENGTH_PAIR(" = function(params) { try { return _AQL.fixValue(state.f"));
|
||||
_buffer->appendInteger(it.second);
|
||||
_buffer->appendText(TRI_CHAR_LENGTH_PAIR(".apply(null, params)); } catch (err) { _AQL.throwFromFunction(\""));
|
||||
_buffer->appendText(TRI_CHAR_LENGTH_PAIR(".apply({ name: \""));
|
||||
_buffer->appendText(it.first);
|
||||
_buffer->appendText(TRI_CHAR_LENGTH_PAIR("\" }, params)); } catch (err) { _AQL.throwFromFunction(\""));
|
||||
_buffer->appendText(it.first);
|
||||
_buffer->appendText(TRI_CHAR_LENGTH_PAIR("\", require(\"internal\").errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR, _AQL.AQL_TO_STRING(err.stack || String(err))); } }; "));
|
||||
}
|
||||
|
|
|
@ -72,6 +72,16 @@ ModificationBlock::~ModificationBlock() {}
|
|||
|
||||
/// @brief get some - this accumulates all input and calls the work() method
|
||||
AqlItemBlock* ModificationBlock::getSome(size_t atLeast, size_t atMost) {
|
||||
// for UPSERT operations, we read and write data in the same collection
|
||||
// we cannot use any batching here because if the search document is not
|
||||
// found, the UPSERTs INSERT operation may create it. after that, the
|
||||
// search document is present and we cannot use an already queried result
|
||||
// from the initial search batch
|
||||
if (getPlanNode()->getType() == ExecutionNode::NodeType::UPSERT) {
|
||||
atLeast = 1;
|
||||
atMost = 1;
|
||||
}
|
||||
|
||||
std::vector<AqlItemBlock*> blocks;
|
||||
std::unique_ptr<AqlItemBlock> replyBlocks;
|
||||
|
||||
|
|
|
@ -1545,7 +1545,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(
|
|||
// subqueries that modify data must not be optimized away
|
||||
continue;
|
||||
}
|
||||
// will remove calculation when we get here
|
||||
// will remove subquery when we get here
|
||||
}
|
||||
|
||||
auto outvars = n->getVariablesSetHere();
|
||||
|
|
|
@ -31,10 +31,6 @@
|
|||
#include "Random/RandomGenerator.h"
|
||||
|
||||
#include <ctime>
|
||||
//XXX #warning MOP why? use ConditionVariable
|
||||
#include <condition_variable>
|
||||
//XXX #warning MOP why? use Mutex
|
||||
#include <mutex>
|
||||
|
||||
#include <velocypack/Slice.h>
|
||||
#include <velocypack/velocypack-aliases.h>
|
||||
|
|
|
@ -156,18 +156,18 @@ void LogfileManager::collectOptions(std::shared_ptr<ProgramOptions> options) {
|
|||
options->addOption("--wal.directory", "logfile directory",
|
||||
new StringParameter(&_directory));
|
||||
|
||||
options->addHiddenOption(
|
||||
options->addOption(
|
||||
"--wal.historic-logfiles",
|
||||
"maximum number of historic logfiles to keep after collection",
|
||||
new UInt32Parameter(&_historicLogfiles));
|
||||
|
||||
options->addHiddenOption(
|
||||
options->addOption(
|
||||
"--wal.ignore-logfile-errors",
|
||||
"ignore logfile errors. this will read recoverable data from corrupted "
|
||||
"logfiles but ignore any unrecoverable data",
|
||||
new BooleanParameter(&_ignoreLogfileErrors));
|
||||
|
||||
options->addHiddenOption(
|
||||
options->addOption(
|
||||
"--wal.ignore-recovery-errors",
|
||||
"continue recovery even if re-applying operations fails",
|
||||
new BooleanParameter(&_ignoreRecoveryErrors));
|
||||
|
|
|
@ -469,13 +469,13 @@ ConsoleFeature::Prompt ConsoleFeature::buildPrompt(ClientFeature* client) {
|
|||
|
||||
if (c == 'E') {
|
||||
// replace protocol
|
||||
if (ep.find("tcp://") == 0) {
|
||||
if (ep.compare(0, strlen("tcp://"), "tcp://") == 0) {
|
||||
ep = ep.substr(strlen("tcp://"));
|
||||
} else if (ep.find("http+tcp://") == 0) {
|
||||
} else if (ep.compare(0, strlen("http+tcp://"), "http+tcp://") == 0) {
|
||||
ep = ep.substr(strlen("http+tcp://"));
|
||||
} else if (ep.find("ssl://") == 0) {
|
||||
} else if (ep.compare(0, strlen("ssl://"), "ssl://") == 0) {
|
||||
ep = ep.substr(strlen("ssl://"));
|
||||
} else if (ep.find("unix://") == 0) {
|
||||
} else if (ep.compare(0, strlen("unix://"), "unix://") == 0) {
|
||||
ep = ep.substr(strlen("unix://"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,9 @@ if (MSVC)
|
|||
INSTALL(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT} DESTINATION bin COMPONENT Libraries)
|
||||
endif()
|
||||
|
||||
STRING(REGEX REPLACE "\\\\" "\\\\\\\\" ETCDIR_ESCAPED "${CMAKE_INSTALL_FULL_SYSCONFDIR}")
|
||||
file(TO_NATIVE_PATH "${CMAKE_INSTALL_FULL_SYSCONFDIR}" ETCDIR_NATIVE)
|
||||
STRING(REGEX REPLACE "\\\\" "\\\\\\\\" ETCDIR_ESCAPED "${ETCDIR_NATIVE}")
|
||||
|
||||
add_definitions("-D_SYSCONFDIR_=\"${ETCDIR_ESCAPED}\"")
|
||||
|
||||
# database directory
|
||||
|
@ -406,3 +408,15 @@ install(
|
|||
install(
|
||||
DIRECTORY ${PROJECT_BINARY_DIR}/var/lib/arangodb3-apps
|
||||
DESTINATION ${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib)
|
||||
|
||||
if (BUNDLE_OPENSSL)
|
||||
if (NOT LIB_EAY_RELEASE_DLL OR NOT SSL_EAY_RELEASE_DLL)
|
||||
message(FATAL_ERROR, "BUNDLE_OPENSSL set but couldn't locate SSL DLLs. Please set LIB_EAY_RELEASE_DLL and SSL_EAY_RELEASE_DLL")
|
||||
endif()
|
||||
install (FILES "${LIB_EAY_RELEASE_DLL}"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bin"
|
||||
COMPONENT Libraries)
|
||||
install (FILES "${SSL_EAY_RELEASE_DLL}"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/bin"
|
||||
COMPONENT Libraries)
|
||||
endif()
|
||||
|
|
|
@ -64,13 +64,16 @@
|
|||
"frontend/js/lib/sigma.layout.noverlap.js",
|
||||
"frontend/js/lib/sigma.plugins.fullScreen.js",
|
||||
"frontend/js/lib/sigma.layout.fruchtermanReingold.js",
|
||||
"frontend/js/lib/sigma.exporters.svg.js",
|
||||
"frontend/js/lib/worker.js",
|
||||
"frontend/js/lib/supervisor.js",
|
||||
// END SIGMA LIBRARIES
|
||||
// START NEW
|
||||
"frontend/js/lib/wheelnav.slicePath.js",
|
||||
"frontend/js/lib/wheelnav.min.js",
|
||||
"frontend/js/lib/raphael.min.js",
|
||||
"frontend/js/lib/raphael.icons.min.js",
|
||||
// END NEW LIBRARIES
|
||||
"frontend/js/lib/jsoneditor-min.js",
|
||||
"frontend/js/lib/strftime-min.js",
|
||||
"frontend/js/lib/d3.fisheye.min.js",
|
||||
|
|
|
@ -1,28 +1,31 @@
|
|||
/* global AQL_EXECUTE */
|
||||
|
||||
'use strict';
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2013 triAGENS GmbH, Cologne, Germany
|
||||
/// Copyright 2016 ArangoDB 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 Michael Hackstein
|
||||
/// @author Alan Plum
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2010-2013 triAGENS GmbH, Cologne, Germany
|
||||
// Copyright 2016 ArangoDB 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 Michael Hackstein
|
||||
// @author Heiko Kernbach
|
||||
// @author Alan Plum
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const joi = require('joi');
|
||||
const dd = require('dedent');
|
||||
|
@ -42,7 +45,7 @@ API_DOCS.basePath = `/_db/${encodeURIComponent(db._name())}`;
|
|||
const router = createRouter();
|
||||
module.exports = router;
|
||||
|
||||
router.get('/config.js', function(req, res) {
|
||||
router.get('/config.js', function (req, res) {
|
||||
const scriptName = req.get('x-script-name');
|
||||
const basePath = req.trustProxy && scriptName || '';
|
||||
res.send(
|
||||
|
@ -56,7 +59,7 @@ router.get('/config.js', function(req, res) {
|
|||
})
|
||||
.response(['text/javascript']);
|
||||
|
||||
router.get('/whoAmI', function(req, res) {
|
||||
router.get('/whoAmI', function (req, res) {
|
||||
res.json({user: req.arangoUser || null});
|
||||
})
|
||||
.summary('Return the current user')
|
||||
|
@ -65,7 +68,6 @@ router.get('/whoAmI', function(req, res) {
|
|||
Returns "false" if authentication is disabled.
|
||||
`);
|
||||
|
||||
|
||||
const authRouter = createRouter();
|
||||
router.use(authRouter);
|
||||
|
||||
|
@ -78,9 +80,8 @@ authRouter.use((req, res, next) => {
|
|||
next();
|
||||
});
|
||||
|
||||
|
||||
router.get('/api/*', module.context.apiDocumentation({
|
||||
swaggerJson(req, res) {
|
||||
swaggerJson (req, res) {
|
||||
res.json(API_DOCS);
|
||||
}
|
||||
}))
|
||||
|
@ -89,8 +90,7 @@ router.get('/api/*', module.context.apiDocumentation({
|
|||
Mounts the system API documentation.
|
||||
`);
|
||||
|
||||
|
||||
authRouter.get('shouldCheckVersion', function(req, res) {
|
||||
authRouter.get('shouldCheckVersion', function (req, res) {
|
||||
const versions = notifications.versions();
|
||||
res.json(Boolean(versions && versions.enableVersionNotification));
|
||||
})
|
||||
|
@ -99,8 +99,7 @@ authRouter.get('shouldCheckVersion', function(req, res) {
|
|||
Check if version check is allowed.
|
||||
`);
|
||||
|
||||
|
||||
authRouter.post('disableVersionCheck', function(req, res) {
|
||||
authRouter.post('disableVersionCheck', function (req, res) {
|
||||
notifications.setVersions({enableVersionNotification: false});
|
||||
res.json('ok');
|
||||
})
|
||||
|
@ -109,8 +108,7 @@ authRouter.post('disableVersionCheck', function(req, res) {
|
|||
Disable the version check in web interface
|
||||
`);
|
||||
|
||||
|
||||
authRouter.post('/query/explain', function(req, res) {
|
||||
authRouter.post('/query/explain', function (req, res) {
|
||||
const bindVars = req.body.bindVars;
|
||||
const query = req.body.query;
|
||||
const id = req.body.id;
|
||||
|
@ -145,8 +143,7 @@ authRouter.post('/query/explain', function(req, res) {
|
|||
Explains a query in a more user-friendly way than the query_api/explain
|
||||
`);
|
||||
|
||||
|
||||
authRouter.post('/query/upload/:user', function(req, res) {
|
||||
authRouter.post('/query/upload/:user', function (req, res) {
|
||||
let user = req.pathParams.user;
|
||||
|
||||
try {
|
||||
|
@ -187,8 +184,7 @@ authRouter.post('/query/upload/:user', function(req, res) {
|
|||
This function uploads all given user queries.
|
||||
`);
|
||||
|
||||
|
||||
authRouter.get('/query/download/:user', function(req, res) {
|
||||
authRouter.get('/query/download/:user', function (req, res) {
|
||||
let user = req.pathParams.user;
|
||||
|
||||
try {
|
||||
|
@ -210,14 +206,12 @@ authRouter.get('/query/download/:user', function(req, res) {
|
|||
Download and export all queries from the given username.
|
||||
`);
|
||||
|
||||
|
||||
authRouter.get('/query/result/download/:query', function(req, res) {
|
||||
authRouter.get('/query/result/download/:query', function (req, res) {
|
||||
let query;
|
||||
try {
|
||||
query = internal.base64Decode(req.pathParams.query);
|
||||
query = JSON.parse(query);
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
res.throw('bad request', e.message, {cause: e});
|
||||
}
|
||||
|
||||
|
@ -232,8 +226,7 @@ authRouter.get('/query/result/download/:query', function(req, res) {
|
|||
This function downloads the result of a user query.
|
||||
`);
|
||||
|
||||
|
||||
authRouter.post('/graph-examples/create/:name', function(req, res) {
|
||||
authRouter.post('/graph-examples/create/:name', function (req, res) {
|
||||
const name = req.pathParams.name;
|
||||
|
||||
if (['knows_graph', 'social', 'routeplanner'].indexOf(name) === -1) {
|
||||
|
@ -249,8 +242,7 @@ authRouter.post('/graph-examples/create/:name', function(req, res) {
|
|||
Create one of the given example graphs.
|
||||
`);
|
||||
|
||||
|
||||
authRouter.post('/job', function(req, res) {
|
||||
authRouter.post('/job', function (req, res) {
|
||||
db._frontend.save(Object.assign(req.body, {model: 'job'}));
|
||||
res.json(true);
|
||||
})
|
||||
|
@ -265,8 +257,7 @@ authRouter.post('/job', function(req, res) {
|
|||
Create a new job id entry in a specific system database with a given id.
|
||||
`);
|
||||
|
||||
|
||||
authRouter.delete('/job', function(req, res) {
|
||||
authRouter.delete('/job', function (req, res) {
|
||||
db._frontend.removeByExample({model: 'job'}, false);
|
||||
res.json(true);
|
||||
})
|
||||
|
@ -275,8 +266,7 @@ authRouter.delete('/job', function(req, res) {
|
|||
Delete all jobs in a specific system database with a given id.
|
||||
`);
|
||||
|
||||
|
||||
authRouter.delete('/job/:id', function(req, res) {
|
||||
authRouter.delete('/job/:id', function (req, res) {
|
||||
db._frontend.removeByExample({id: req.pathParams.id}, false);
|
||||
res.json(true);
|
||||
})
|
||||
|
@ -285,8 +275,7 @@ authRouter.delete('/job/:id', function(req, res) {
|
|||
Delete an existing job id entry in a specific system database with a given id.
|
||||
`);
|
||||
|
||||
|
||||
authRouter.get('/job', function(req, res) {
|
||||
authRouter.get('/job', function (req, res) {
|
||||
const result = db._frontend.all().toArray();
|
||||
res.json(result);
|
||||
})
|
||||
|
@ -295,28 +284,30 @@ authRouter.get('/job', function(req, res) {
|
|||
This function returns the job ids of all currently running jobs.
|
||||
`);
|
||||
|
||||
|
||||
authRouter.get('/graph/:name', function(req, res) {
|
||||
var _ = require("lodash");
|
||||
authRouter.get('/graph/:name', function (req, res) {
|
||||
var _ = require('lodash');
|
||||
var name = req.pathParams.name;
|
||||
var gm = require("@arangodb/general-graph");
|
||||
//var traversal = require("@arangodb/graph/traversal");
|
||||
var gm = require('@arangodb/general-graph');
|
||||
// var traversal = require("@arangodb/graph/traversal");
|
||||
|
||||
var graph = gm._graph(name);
|
||||
var vertexName = graph._vertexCollections()[0].name();
|
||||
var startVertex = db[vertexName].any();
|
||||
|
||||
var aqlQuery =
|
||||
'FOR v, e, p IN 1..3 ANY "' + startVertex._id + '" GRAPH "' + name + '"' +
|
||||
var aqlQuery =
|
||||
'FOR v, e, p IN 1..3 ANY "' + startVertex._id + '" GRAPH "' + name + '"' +
|
||||
'RETURN p'
|
||||
;
|
||||
|
||||
var cursor = AQL_EXECUTE(aqlQuery);
|
||||
|
||||
var nodesObj = {}, nodesArr = [], edgesObj = {}, edgesArr = [];
|
||||
var nodesObj = {};
|
||||
var nodesArr = [];
|
||||
var edgesObj = {};
|
||||
var edgesArr = [];
|
||||
|
||||
_.each(cursor.json, function(obj) {
|
||||
_.each(obj.edges, function(edge) {
|
||||
_.each(cursor.json, function (obj) {
|
||||
_.each(obj.edges, function (edge) {
|
||||
if (edge._to && edge._from) {
|
||||
edgesObj[edge._from + edge._to] = {
|
||||
id: edge._id,
|
||||
|
@ -327,11 +318,10 @@ authRouter.get('/graph/:name', function(req, res) {
|
|||
}
|
||||
});
|
||||
var label;
|
||||
_.each(obj.vertices, function(node) {
|
||||
_.each(obj.vertices, function (node) {
|
||||
if (node.label) {
|
||||
label = node.label;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
label = node._id;
|
||||
}
|
||||
|
||||
|
@ -346,11 +336,11 @@ authRouter.get('/graph/:name', function(req, res) {
|
|||
});
|
||||
});
|
||||
|
||||
//array format for sigma.js
|
||||
_.each(edgesObj, function(node) {
|
||||
// array format for sigma.js
|
||||
_.each(edgesObj, function (node) {
|
||||
edgesArr.push(node);
|
||||
});
|
||||
_.each(nodesObj, function(node) {
|
||||
_.each(nodesObj, function (node) {
|
||||
nodesArr.push(node);
|
||||
});
|
||||
|
||||
|
@ -358,7 +348,6 @@ authRouter.get('/graph/:name', function(req, res) {
|
|||
nodes: nodesArr,
|
||||
edges: edgesArr
|
||||
});
|
||||
|
||||
})
|
||||
.summary('Return vertices and edges of a graph.')
|
||||
.description(dd`
|
||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1041,8 +1041,10 @@ if (list.length > 0) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pure-g pure-table pure-table-body"> <% _.each(specific, function(val, key) { %> <div class="<%= genClass %> left"><%=key%></div>
|
||||
<div class="<%= genClass %> left"><%=val%></div> <% }); %> </div>
|
||||
<div class="pure-g pure-table pure-table-body"> <% _.each(specific, function(val, key) { %> <div class="<%= genClass %> left"><%=val.name%></div>
|
||||
<div class="<%= genClass %> left"> <% var VALUE; %> <% if (val.value) { %> <% VALUE = val.value %> <% } else { %> <% VALUE = val.default %> <% } %> <% if (val.type === 'string') { %> <input type="text" value="<%=VALUE%>" placeholder=""></input> <% } %> <% if (val.type === 'color') { %> <input type='color' name='color' value="<%=VALUE%>"/> <% } %> <% if (val.type === 'select') { %> <div class="<%= genClass %> left">
|
||||
<select> <% _.each(val, function(option, optKey) { %> <% if (option.name) { %> <option> <%=option.name%> </option> <% } %> <% }); %> </select>
|
||||
</div> <% } %> </div> <% }); %> </div>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -1063,22 +1065,37 @@ if (list.length > 0) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pure-g pure-table pure-table-body"> <% _.each(general, function(val, key) { %> <div class="<%= genClass %> left"><%=key%></div>
|
||||
<div class="<%= genClass %> left"><%=val%></div> <% }); %> </div>
|
||||
<div class="pure-g pure-table pure-table-body"> <% _.each(general, function(val, key) { %> <div class="<%= genClass %> left"><%=key%></div> <% if (val.type === 'select') { %> <div class="<%= genClass %> left">
|
||||
<select> <% _.each(val, function(option, optKey) { %> <% if (option.name) { %> <option> <%=option.name%> </option> <% } %> <% }); %> </select>
|
||||
</div> <% } %> <% if (val.type === 'numeric') { %> <input type="text" id="<%=val %>" value="<%=val.value %>" placeholder=""></input> <% } %> <% }); %> </div>
|
||||
|
||||
</div>
|
||||
|
||||
<button id="saveGraphSettings" style="margin-top: 20px;" class="button-success pull-right">Save</button>
|
||||
<button id="saveGraphSettings" style="margin-top: 20px;" class="button-success pull-right">Restore defaults</button>
|
||||
</div></script><script id="graphViewer2.ejs" type="text/template"><div class="graphContent" id="graphContainer">
|
||||
|
||||
<div class="headerBar">
|
||||
<div class="headerButtonBar" style="margin: 0;">
|
||||
<ul class="headerButtonList">
|
||||
<li class="enabled">
|
||||
<a id="addDocument" class="headerButton">
|
||||
<span title="Add new document">
|
||||
<i class="fa fa-file fa-stack-1x"></i>
|
||||
<i class="fa fa-plus fa-stack-1x fa-top"></i>
|
||||
<a id="graph-fullscreen-btn" class="headerButton">
|
||||
<span title="Switch to fullscreen mode">
|
||||
<i class="fa fa-television"></i>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="enabled">
|
||||
<a id="downloadPNG" class="headerButton">
|
||||
<span title="Download visible graph as png image">
|
||||
<i class="fa fa-camera fa-stack-1x"></i>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="enabled">
|
||||
<a id="selectNodes" class="headerButton">
|
||||
<span title="Download visible graph as png image">
|
||||
<i class="fa fa-pencil fa-stack-1x"></i>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -1086,7 +1103,7 @@ if (list.length > 0) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="graph-fullscreen-btn"><i class="fa fa-television"></i></div>
|
||||
<!--<div id="graph-fullscreen-btn"><i class="fa fa-desktop"></i></div>-->
|
||||
<div id="graph-container" oncontextmenu="return false;"></div>
|
||||
</div></script><script id="graphViewGroupByEntry.ejs" type="text/template"><div class="control-group">
|
||||
<label for="<%=type %>_<%=id%>" class="control-label">Attribute <%=id%></label>
|
||||
|
@ -2706,4 +2723,4 @@ var cutByResolution = function (str) {
|
|||
</div>
|
||||
|
||||
<div id="workMonitorContent" class="innerContent">
|
||||
</div></script></head><body><nav class="navbar" style="display: none"><div class="primary"><div class="navlogo"><a class="logo big" href="#"><img class="arangodbLogo" src="img/arangodb_logo_big.png"></a><a class="logo small" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a><a class="version"><span>VERSION: </span><span id="currentVersion"></span></a></div><div class="statmenu" id="statisticBar"></div><div class="navmenu" id="navigationBar"></div></div></nav><div id="modalPlaceholder"></div><div class="bodyWrapper" style="display: none"><div class="centralRow"><div id="navbar2" class="navbarWrapper secondary"><div class="subnavmenu" id="subNavigationBar"></div></div><div class="resizecontainer contentWrapper"><div id="loadingScreen" class="loadingScreen" style="display: none"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw margin-bottom"></i> <span class="sr-only">Loading...</span></div><div id="content" class="centralContent"></div><footer class="footer"><div id="footerBar"></div></footer></div></div></div><div id="progressPlaceholder" style="display:none"></div><div id="spotlightPlaceholder" style="display:none"></div><div id="offlinePlaceholder" style="display:none"><div class="offline-div"><div class="pure-u"><div class="pure-u-1-4"></div><div class="pure-u-1-2 offline-window"><div class="offline-header"><h3>You have been disconnected from the server</h3></div><div class="offline-body"><p>The connection to the server has been lost. The server may be under heavy load.</p><p>Trying to reconnect in <span id="offlineSeconds">10</span> seconds.</p><p class="animation_state"><span><button class="button-success">Reconnect now</button></span></p></div></div><div class="pure-u-1-4"></div></div></div></div><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="libs.js?version=1467885481708"></script><script src="app.js?version=1467885481708"></script></body></html>
|
||||
</div></script></head><body><nav class="navbar" style="display: none"><div class="primary"><div class="navlogo"><a class="logo big" href="#"><img class="arangodbLogo" src="img/arangodb_logo_big.png"></a><a class="logo small" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a><a class="version"><span>VERSION: </span><span id="currentVersion"></span></a></div><div class="statmenu" id="statisticBar"></div><div class="navmenu" id="navigationBar"></div></div></nav><div id="modalPlaceholder"></div><div class="bodyWrapper" style="display: none"><div class="centralRow"><div id="navbar2" class="navbarWrapper secondary"><div class="subnavmenu" id="subNavigationBar"></div></div><div class="resizecontainer contentWrapper"><div id="loadingScreen" class="loadingScreen" style="display: none"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw margin-bottom"></i> <span class="sr-only">Loading...</span></div><div id="content" class="centralContent"></div><footer class="footer"><div id="footerBar"></div></footer></div></div></div><div id="progressPlaceholder" style="display:none"></div><div id="spotlightPlaceholder" style="display:none"></div><div id="offlinePlaceholder" style="display:none"><div class="offline-div"><div class="pure-u"><div class="pure-u-1-4"></div><div class="pure-u-1-2 offline-window"><div class="offline-header"><h3>You have been disconnected from the server</h3></div><div class="offline-body"><p>The connection to the server has been lost. The server may be under heavy load.</p><p>Trying to reconnect in <span id="offlineSeconds">10</span> seconds.</p><p class="animation_state"><span><button class="button-success">Reconnect now</button></span></p></div></div><div class="pure-u-1-4"></div></div></div></div><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="libs.js?version=1467901818158"></script><script src="app.js?version=1467901818158"></script></body></html>
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
@ -2,7 +2,7 @@
|
|||
/* jshint strict: false, unused: false */
|
||||
/* global Backbone, window, arangoDocumentModel, $, arangoHelper */
|
||||
|
||||
window.arangoDocument = Backbone.Collection.extend({
|
||||
window.ArangoDocument = Backbone.Collection.extend({
|
||||
url: '/_api/document/',
|
||||
model: arangoDocumentModel,
|
||||
collectionInfo: {},
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
;(function(undefined) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Sigma SVG Exporter
|
||||
* ===================
|
||||
*
|
||||
* This plugin is designed to export a graph to a svg file that can be
|
||||
* downloaded or just used elsewhere.
|
||||
*
|
||||
* Author: Guillaume Plique (Yomguithereal)
|
||||
* Version: 0.0.1
|
||||
*/
|
||||
|
||||
// Terminating if sigma were not to be found
|
||||
if (typeof sigma === 'undefined')
|
||||
throw 'sigma.renderers.snapshot: sigma not in scope.';
|
||||
|
||||
|
||||
/**
|
||||
* Polyfills
|
||||
*/
|
||||
var URL = this.URL || this.webkitURL || this;
|
||||
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
function createBlob(data) {
|
||||
return new Blob(
|
||||
[data],
|
||||
{type: 'image/svg+xml;charset=utf-8'}
|
||||
);
|
||||
}
|
||||
|
||||
function download(string, filename) {
|
||||
if (typeof safari !== 'undefined') {
|
||||
var msg = "File download does not work in Safari. Please use a modern web browser such as Firefox, Chrome, or Internet Explorer 11.";
|
||||
alert(msg);
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
// Blob
|
||||
var blob = createBlob(string),
|
||||
objectUrl = window.URL.createObjectURL(blob);
|
||||
|
||||
if (navigator.msSaveBlob) { // IE11+ : (has Blob, but not a[download])
|
||||
navigator.msSaveBlob(blob, filename);
|
||||
} else if (navigator.msSaveOrOpenBlob) { // IE10+ : (has Blob, but not a[download])
|
||||
navigator.msSaveOrOpenBlob(blob, filename);
|
||||
} else {
|
||||
// A-download
|
||||
var anchor = document.createElement('a');
|
||||
anchor.setAttribute('href', objectUrl);
|
||||
anchor.setAttribute('download', filename);
|
||||
|
||||
// Firefox requires the link to be added to the DOM before it can be clicked.
|
||||
document.body.appendChild(anchor);
|
||||
anchor.click();
|
||||
document.body.removeChild(anchor);
|
||||
}
|
||||
|
||||
setTimeout(function() { // Firefox needs a timeout
|
||||
window.URL.revokeObjectURL(objectUrl);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defaults
|
||||
*/
|
||||
var DEFAULTS = {
|
||||
size: '1000',
|
||||
width: '1000',
|
||||
height: '1000',
|
||||
margin: 0.05,
|
||||
classes: true,
|
||||
labels: true,
|
||||
data: false,
|
||||
download: false,
|
||||
filename: 'graph.svg'
|
||||
};
|
||||
|
||||
var XMLNS = 'http://www.w3.org/2000/svg';
|
||||
|
||||
|
||||
/**
|
||||
* Subprocesses
|
||||
*/
|
||||
function optimize(svg, prefix, params) {
|
||||
var nodeColorIndex = {},
|
||||
edgeColorIndex = {},
|
||||
count = 0,
|
||||
color,
|
||||
style,
|
||||
styleText = '',
|
||||
f,
|
||||
i,
|
||||
l;
|
||||
|
||||
// Creating style tag if needed
|
||||
if (params.classes) {
|
||||
style = document.createElementNS(XMLNS, 'style');
|
||||
svg.insertBefore(style, svg.firstChild);
|
||||
}
|
||||
|
||||
// Iterating over nodes
|
||||
var nodes = svg.querySelectorAll('[id="' + prefix + '-group-nodes"] > [class="' + prefix + '-node"]');
|
||||
|
||||
for (i = 0, l = nodes.length, f = true; i < l; i++) {
|
||||
color = nodes[i].getAttribute('fill');
|
||||
|
||||
if (!params.data)
|
||||
nodes[i].removeAttribute('data-node-id');
|
||||
|
||||
if (params.classes) {
|
||||
|
||||
if (!(color in nodeColorIndex)) {
|
||||
nodeColorIndex[color] = (f ? prefix + '-node' : 'c-' + (count++));
|
||||
styleText += '.' + nodeColorIndex[color] + '{fill: ' + color + '}';
|
||||
}
|
||||
|
||||
if (nodeColorIndex[color] !== prefix + '-node')
|
||||
nodes[i].setAttribute('class', nodes[i].getAttribute('class') + ' ' + nodeColorIndex[color]);
|
||||
nodes[i].removeAttribute('fill');
|
||||
}
|
||||
|
||||
f = false;
|
||||
}
|
||||
|
||||
// Iterating over edges
|
||||
var edges = svg.querySelectorAll('[id="' + prefix + '-group-edges"] > [class="' + prefix + '-edge"]');
|
||||
|
||||
for (i = 0, l = edges.length, f = true; i < l; i++) {
|
||||
color = edges[i].getAttribute('stroke');
|
||||
|
||||
if (!params.data)
|
||||
edges[i].removeAttribute('data-edge-id');
|
||||
|
||||
if (params.classes) {
|
||||
|
||||
if (!(color in edgeColorIndex)) {
|
||||
edgeColorIndex[color] = (f ? prefix + '-edge' : 'c-' + (count++));
|
||||
styleText += '.' + edgeColorIndex[color] + '{stroke: ' + color + '}';
|
||||
}
|
||||
|
||||
if (edgeColorIndex[color] !== prefix + '-edge')
|
||||
edges[i].setAttribute('class', edges[i].getAttribute('class') + ' ' + edgeColorIndex[color]);
|
||||
edges[i].removeAttribute('stroke');
|
||||
}
|
||||
|
||||
f = false;
|
||||
}
|
||||
|
||||
if (params.classes)
|
||||
style.appendChild(document.createTextNode(styleText));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extending prototype
|
||||
*/
|
||||
sigma.prototype.toSVG = function(params) {
|
||||
params = params || {};
|
||||
|
||||
var prefix = this.settings('classPrefix'),
|
||||
w = params.size || params.width || DEFAULTS.size,
|
||||
h = params.size || params.height || DEFAULTS.size,
|
||||
margin = params.margin || DEFAULTS.margin;
|
||||
|
||||
// Creating a dummy container
|
||||
var container = document.createElement('div');
|
||||
container.setAttribute('width', w);
|
||||
container.setAttribute('height', h);
|
||||
container.setAttribute('style', 'position:absolute; top: 0px; left:0px; width: ' + w + 'px; height: ' + h + 'px;');
|
||||
|
||||
// Add margin to deal with curved edges
|
||||
var sideMargin = this.settings('sideMargin');
|
||||
this.settings('sideMargin', margin);
|
||||
|
||||
// Fit graph to viewport
|
||||
var autoRescale = this.settings('autoRescale');
|
||||
this.settings('autoRescale', true);
|
||||
|
||||
// Creating a camera
|
||||
var camera = this.addCamera();
|
||||
|
||||
// Creating a svg renderer
|
||||
var renderer = this.addRenderer({
|
||||
camera: camera,
|
||||
container: container,
|
||||
type: 'svg',
|
||||
forceLabels: !!params.labels
|
||||
});
|
||||
|
||||
// Refreshing
|
||||
renderer.resize(w, h);
|
||||
this.refresh();
|
||||
|
||||
// Dropping camera and renderers before something nasty happens
|
||||
this.killRenderer(renderer);
|
||||
this.killCamera(camera);
|
||||
|
||||
// reset setting
|
||||
this.settings('sideMargin', sideMargin);
|
||||
this.settings('autoRescale', autoRescale);
|
||||
|
||||
// Retrieving svg
|
||||
var svg = container.querySelector('svg');
|
||||
svg.removeAttribute('style');
|
||||
svg.setAttribute('width', w + 'px');
|
||||
svg.setAttribute('height', h + 'px');
|
||||
svg.setAttribute('x', '0px');
|
||||
svg.setAttribute('y', '0px');
|
||||
// svg.setAttribute('viewBox', '0 0 1000 1000');
|
||||
|
||||
// Dropping labels
|
||||
if (!params.labels) {
|
||||
var labelGroup = svg.querySelector('[id="' + prefix + '-group-labels"]');
|
||||
svg.removeChild(labelGroup);
|
||||
}
|
||||
|
||||
// Dropping hovers
|
||||
var hoverGroup = svg.querySelector('[id="' + prefix + '-group-hovers"]');
|
||||
svg.removeChild(hoverGroup);
|
||||
|
||||
// Optims?
|
||||
params.classes = (params.classes !== false);
|
||||
if (!params.data || params.classes)
|
||||
optimize(svg, prefix, params);
|
||||
|
||||
// Retrieving svg string
|
||||
var svgString = svg.outerHTML;
|
||||
|
||||
// Paranoid cleanup
|
||||
container = null;
|
||||
|
||||
// Output string
|
||||
var output = '<?xml version="1.0" encoding="utf-8"?>\n';
|
||||
output += '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n';
|
||||
output += svgString;
|
||||
|
||||
if (params.download)
|
||||
download(output, params.filename || DEFAULTS.filename);
|
||||
|
||||
return output;
|
||||
};
|
||||
}).call(this);
|
|
@ -857,6 +857,9 @@
|
|||
if (this.queryView) {
|
||||
this.queryView.resize();
|
||||
}
|
||||
if (this.graphViewer2) {
|
||||
this.graphViewer2.resize();
|
||||
}
|
||||
if (this.documentsView) {
|
||||
this.documentsView.resize();
|
||||
}
|
||||
|
|
|
@ -30,8 +30,38 @@
|
|||
|
||||
<div class="pure-g pure-table pure-table-body">
|
||||
<% _.each(specific, function(val, key) { %>
|
||||
<div class="<%= genClass %> left"><%=key%></div>
|
||||
<div class="<%= genClass %> left"><%=val%></div>
|
||||
<div class="<%= genClass %> left"><%=val.name%></div>
|
||||
<div class="<%= genClass %> left">
|
||||
|
||||
|
||||
<% var VALUE; %>
|
||||
<% if (val.value) { %>
|
||||
<% VALUE = val.value %>
|
||||
<% } else { %>
|
||||
<% VALUE = val.default %>
|
||||
<% } %>
|
||||
|
||||
<% if (val.type === 'string') { %>
|
||||
<input type="text" value="<%=VALUE%>" placeholder=""></input>
|
||||
<% } %>
|
||||
|
||||
<% if (val.type === 'color') { %>
|
||||
<input type='color' name='color' value="<%=VALUE%>"/>
|
||||
<% } %>
|
||||
|
||||
<% if (val.type === 'select') { %>
|
||||
<div class="<%= genClass %> left">
|
||||
<select>
|
||||
<% _.each(val, function(option, optKey) { %>
|
||||
<% if (option.name) { %>
|
||||
<option> <%=option.name%> </option>
|
||||
<% } %>
|
||||
<% }); %>
|
||||
</select>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
|
||||
|
@ -55,15 +85,33 @@
|
|||
</div>
|
||||
|
||||
<div class="pure-g pure-table pure-table-body">
|
||||
|
||||
<% _.each(general, function(val, key) { %>
|
||||
<div class="<%= genClass %> left"><%=key%></div>
|
||||
<div class="<%= genClass %> left"><%=val%></div>
|
||||
|
||||
<% if (val.type === 'select') { %>
|
||||
<div class="<%= genClass %> left">
|
||||
<select>
|
||||
<% _.each(val, function(option, optKey) { %>
|
||||
<% if (option.name) { %>
|
||||
<option> <%=option.name%> </option>
|
||||
<% } %>
|
||||
<% }); %>
|
||||
</select>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<% if (val.type === 'numeric') { %>
|
||||
<input type="text" id="<%=val %>" value="<%=val.value %>" placeholder=""></input>
|
||||
<% } %>
|
||||
|
||||
<% }); %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<button id="saveGraphSettings" style="margin-top: 20px;" class="button-success pull-right">Save</button>
|
||||
<button id="saveGraphSettings" style="margin-top: 20px;" class="button-success pull-right">Restore defaults</button>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
|
|
|
@ -5,10 +5,23 @@
|
|||
<div class="headerButtonBar" style="margin: 0;">
|
||||
<ul class="headerButtonList">
|
||||
<li class="enabled">
|
||||
<a id="addDocument" class="headerButton">
|
||||
<span title="Add new document">
|
||||
<i class="fa fa-file fa-stack-1x"></i>
|
||||
<i class="fa fa-plus fa-stack-1x fa-top"></i>
|
||||
<a id="graph-fullscreen-btn" class="headerButton">
|
||||
<span title="Switch to fullscreen mode">
|
||||
<i class="fa fa-television"></i>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="enabled">
|
||||
<a id="downloadPNG" class="headerButton">
|
||||
<span title="Download visible graph as png image">
|
||||
<i class="fa fa-camera fa-stack-1x"></i>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="enabled">
|
||||
<a id="selectNodes" class="headerButton">
|
||||
<span title="Download visible graph as png image">
|
||||
<i class="fa fa-pencil fa-stack-1x"></i>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -16,7 +29,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="graph-fullscreen-btn"><i class="fa fa-television"></i></div>
|
||||
<!--<div id="graph-fullscreen-btn"><i class="fa fa-desktop"></i></div>-->
|
||||
<div id="graph-container" oncontextmenu="return false;"></div>
|
||||
</div>
|
||||
</script>
|
||||
|
|
|
@ -8,14 +8,81 @@
|
|||
el: '#content',
|
||||
|
||||
general: {
|
||||
'layout': undefined,
|
||||
'depth': undefined
|
||||
'Layout': {
|
||||
type: 'select',
|
||||
noverlap: {
|
||||
name: 'No overlap (fast)'
|
||||
},
|
||||
force: {
|
||||
name: 'Force (slow)'
|
||||
},
|
||||
fruchtermann: {
|
||||
name: 'Fruchtermann (very slow)'
|
||||
}
|
||||
},
|
||||
'Renderer': {
|
||||
type: 'select',
|
||||
canvas: {
|
||||
name: 'Canvas (editable)'
|
||||
},
|
||||
webgl: {
|
||||
name: 'WebGL (only display)'
|
||||
}
|
||||
},
|
||||
'depth': {
|
||||
type: 'numeric',
|
||||
value: 2
|
||||
}
|
||||
},
|
||||
|
||||
specific: {
|
||||
'node_label': undefined,
|
||||
'node_color': undefined,
|
||||
'node_size': undefined
|
||||
'nodeLabel': {
|
||||
type: 'string',
|
||||
name: 'Node label',
|
||||
desc: 'Default node color. RGB or HEX value.',
|
||||
default: '_key'
|
||||
},
|
||||
'nodeColor': {
|
||||
type: 'color',
|
||||
name: 'Node color',
|
||||
desc: 'Default node color. RGB or HEX value.',
|
||||
default: '#2ecc71'
|
||||
},
|
||||
'nodeSize': {
|
||||
type: 'string',
|
||||
name: 'Node size',
|
||||
desc: 'Default node size. Numeric value > 0.',
|
||||
value: undefined
|
||||
},
|
||||
'edgeLabel': {
|
||||
type: 'string',
|
||||
name: 'Edge label',
|
||||
desc: 'Default edge label.',
|
||||
value: undefined
|
||||
},
|
||||
'edgeColor': {
|
||||
type: 'color',
|
||||
name: 'Edge color',
|
||||
desc: 'Default edge color. RGB or HEX value.',
|
||||
default: '#cccccc'
|
||||
},
|
||||
'edgeSize': {
|
||||
type: 'string',
|
||||
name: 'Edge thickness',
|
||||
desc: 'Default edge thickness. Numeric value > 0.',
|
||||
value: undefined
|
||||
},
|
||||
'edgeType': {
|
||||
type: 'select',
|
||||
name: 'Edge type',
|
||||
desc: 'The type of the edge',
|
||||
canvas: {
|
||||
name: 'Straight'
|
||||
},
|
||||
webgl: {
|
||||
name: 'Curved'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
template: templateEngine.createTemplate('graphSettingsView.ejs'),
|
||||
|
@ -24,6 +91,14 @@
|
|||
this.name = options.name;
|
||||
},
|
||||
|
||||
loadGraphSettings: function () {
|
||||
|
||||
},
|
||||
|
||||
saveGraphSettings: function () {
|
||||
|
||||
},
|
||||
|
||||
events: {
|
||||
},
|
||||
|
||||
|
@ -33,6 +108,9 @@
|
|||
specific: this.specific
|
||||
}));
|
||||
arangoHelper.buildGraphSubNav(this.name, 'Settings');
|
||||
|
||||
// load graph settings from local storage
|
||||
// apply those values to view then
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
this.initSigma();
|
||||
},
|
||||
|
||||
events: {
|
||||
'click #downloadPNG': 'downloadSVG'
|
||||
},
|
||||
|
||||
initSigma: function () {
|
||||
// init sigma
|
||||
try {
|
||||
|
@ -30,19 +34,40 @@
|
|||
} catch (ignore) {}
|
||||
},
|
||||
|
||||
downloadSVG: function () {
|
||||
var self = this;
|
||||
|
||||
this.currentGraph.toSVG({
|
||||
download: true,
|
||||
filename: self.name + '.svg',
|
||||
size: 1000
|
||||
});
|
||||
},
|
||||
|
||||
resize: function () {
|
||||
// adjust container widht + height
|
||||
$('#graph-container').width($('.centralContent').width());
|
||||
$('#graph-container').height($('.centralRow').height() - 150);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.html(this.template.render({}));
|
||||
arangoHelper.buildGraphSubNav(this.name, 'Content');
|
||||
|
||||
// adjust container widht + height
|
||||
$('#graph-container').width($('.centralContent').width());
|
||||
$('#graph-container').height($('.centralRow').height() - 150);
|
||||
|
||||
this.resize();
|
||||
this.fetchGraph();
|
||||
},
|
||||
|
||||
fetchGraph: function () {
|
||||
var self = this;
|
||||
$('#content').append(
|
||||
'<div id="calculatingGraph" style="position: absolute; left: 25px; top: 130px;">' +
|
||||
'<i class="fa fa-circle-o-notch fa-spin" style="margin-right: 10px;"></i>' +
|
||||
'Calculating layout. Please wait ... </div>'
|
||||
);
|
||||
|
||||
// TODO LOAD GRAPH SETTINGS
|
||||
// var settings = this.loadGraphSettings();
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
|
@ -50,6 +75,9 @@
|
|||
contentType: 'application/json',
|
||||
success: function (data) {
|
||||
self.renderGraph(data);
|
||||
},
|
||||
error: function () {
|
||||
$('#calculatingGraph').html('Failed to fetch graph information.');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -117,6 +145,12 @@
|
|||
generateMenu(e, nodeId);
|
||||
},
|
||||
|
||||
loadGraphSettings: function () {
|
||||
var settings;
|
||||
|
||||
return settings;
|
||||
},
|
||||
|
||||
editNode: function (id) {
|
||||
var callback = function () {};
|
||||
|
||||
|
@ -132,35 +166,50 @@
|
|||
|
||||
this.Sigma = sigma;
|
||||
|
||||
var algorithm = 'force';
|
||||
var renderer = 'webgl';
|
||||
|
||||
var settings = {
|
||||
doubleClickEnabled: false,
|
||||
minEdgeSize: 0.5,
|
||||
maxEdgeSize: 4,
|
||||
enableEdgeHovering: true,
|
||||
// edgeHoverColor: 'edge',
|
||||
// defaultEdgeHoverColor: '#000',
|
||||
// defaultEdgeType: 'curve',
|
||||
edgeHoverSizeRatio: 1,
|
||||
edgeHoverExtremities: true
|
||||
};
|
||||
|
||||
// adjust display settings for big graphs
|
||||
if (graph.nodes.length > 500) {
|
||||
// show node label if size is 20
|
||||
settings.labelThreshold = 20;
|
||||
}
|
||||
|
||||
// adjust display settings for webgl renderer
|
||||
if (renderer === 'webgl') {
|
||||
settings.enableEdgeHovering = false;
|
||||
}
|
||||
|
||||
// create sigma graph
|
||||
var s = new this.Sigma({
|
||||
graph: graph,
|
||||
container: 'graph-container',
|
||||
renderer: {
|
||||
container: document.getElementById('graph-container'),
|
||||
type: 'canvas'
|
||||
type: renderer
|
||||
},
|
||||
settings: {
|
||||
doubleClickEnabled: false,
|
||||
minEdgeSize: 0.5,
|
||||
maxEdgeSize: 4,
|
||||
enableEdgeHovering: true,
|
||||
// edgeHoverColor: 'edge',
|
||||
// defaultEdgeHoverColor: '#000',
|
||||
// defaultEdgeType: 'curve',
|
||||
edgeHoverSizeRatio: 1,
|
||||
edgeHoverExtremities: true
|
||||
}
|
||||
settings: settings
|
||||
});
|
||||
this.currentGraph = s;
|
||||
|
||||
sigma.plugins.fullScreen({
|
||||
container: 'graph-container',
|
||||
btnId: 'graph-fullscreen-btn'
|
||||
});
|
||||
|
||||
var renderer = 'fruchtermann';
|
||||
|
||||
if (renderer === 'noverlap') {
|
||||
if (algorithm === 'noverlap') {
|
||||
var noverlapListener = s.configNoverlap({
|
||||
nodeMargin: 0.1,
|
||||
scaleNodes: 1.05,
|
||||
|
@ -175,7 +224,7 @@
|
|||
if (e.type === 'interpolate') {
|
||||
}
|
||||
});
|
||||
} else if (renderer === 'fruchtermann') {
|
||||
} else if (algorithm === 'fruchtermann') {
|
||||
var frListener = sigma.layouts.fruchtermanReingold.configure(s, {
|
||||
iterations: 500,
|
||||
easing: 'quadraticInOut',
|
||||
|
@ -192,70 +241,60 @@
|
|||
e.originalColor = e.color;
|
||||
});
|
||||
|
||||
if (document.addEventListener) {
|
||||
document.addEventListener('contextmenu', function (e) {
|
||||
// my custom functionality on right click
|
||||
e.preventDefault();
|
||||
}, false);
|
||||
} else {
|
||||
document.attachEvent('oncontextmenu', function () {
|
||||
// my custom functionality on right click
|
||||
window.event.returnValue = false;
|
||||
if (renderer !== 'webgl') {
|
||||
s.bind('rightClickNode', function (e) {
|
||||
var nodeId = e.data.node.id;
|
||||
self.createNodeContextMenu(nodeId, e);
|
||||
});
|
||||
|
||||
s.bind('doubleClickNode', function (e) {
|
||||
var nodeId = e.data.node.id;
|
||||
var toKeep = s.graph.neighbors(nodeId);
|
||||
toKeep[nodeId] = e.data.node;
|
||||
|
||||
s.graph.nodes().forEach(function (n) {
|
||||
if (toKeep[n.id]) {
|
||||
n.color = n.originalColor;
|
||||
} else {
|
||||
n.color = '#eee';
|
||||
}
|
||||
});
|
||||
|
||||
s.graph.edges().forEach(function (e) {
|
||||
if (toKeep[e.source] && toKeep[e.target]) {
|
||||
e.color = 'rgb(64, 74, 83)';
|
||||
} else {
|
||||
e.color = '#eee';
|
||||
}
|
||||
});
|
||||
|
||||
s.refresh();
|
||||
});
|
||||
|
||||
s.bind('doubleClickStage', function () {
|
||||
s.graph.nodes().forEach(function (n) {
|
||||
n.color = n.originalColor;
|
||||
});
|
||||
|
||||
s.graph.edges().forEach(function (e) {
|
||||
e.color = e.originalColor;
|
||||
});
|
||||
|
||||
s.refresh();
|
||||
});
|
||||
|
||||
s.bind('clickStage', function () {
|
||||
self.clearOldContextMenu();
|
||||
});
|
||||
}
|
||||
|
||||
s.bind('rightClickNode', function (e) {
|
||||
var nodeId = e.data.node.id;
|
||||
self.createNodeContextMenu(nodeId, e);
|
||||
});
|
||||
|
||||
s.bind('doubleClickNode', function (e) {
|
||||
var nodeId = e.data.node.id;
|
||||
var toKeep = s.graph.neighbors(nodeId);
|
||||
toKeep[nodeId] = e.data.node;
|
||||
|
||||
s.graph.nodes().forEach(function (n) {
|
||||
if (toKeep[n.id]) {
|
||||
n.color = n.originalColor;
|
||||
} else {
|
||||
n.color = '#eee';
|
||||
}
|
||||
});
|
||||
|
||||
s.graph.edges().forEach(function (e) {
|
||||
if (toKeep[e.source] && toKeep[e.target]) {
|
||||
e.color = 'rgb(64, 74, 83)';
|
||||
} else {
|
||||
e.color = '#eee';
|
||||
}
|
||||
});
|
||||
|
||||
s.refresh();
|
||||
});
|
||||
|
||||
s.bind('doubleClickStage', function () {
|
||||
s.graph.nodes().forEach(function (n) {
|
||||
n.color = n.originalColor;
|
||||
});
|
||||
|
||||
s.graph.edges().forEach(function (e) {
|
||||
e.color = e.originalColor;
|
||||
});
|
||||
|
||||
s.refresh();
|
||||
});
|
||||
|
||||
s.bind('clickStage', function () {
|
||||
self.clearOldContextMenu();
|
||||
});
|
||||
|
||||
var dragListener;
|
||||
// Initialize the dragNodes plugin:
|
||||
if (renderer === 'noverlap') {
|
||||
if (algorithm === 'noverlap') {
|
||||
s.startNoverlap();
|
||||
// allow draggin nodes
|
||||
dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
|
||||
} else if (renderer === 'force') {
|
||||
} else if (algorithm === 'force') {
|
||||
s.startForceAtlas2({worker: true, barnesHutOptimize: false});
|
||||
|
||||
window.setTimeout(function () {
|
||||
|
@ -263,7 +302,7 @@
|
|||
dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
|
||||
console.log('stopped force');
|
||||
}, 3000);
|
||||
} else if (renderer === 'fruchtermann') {
|
||||
} else if (algorithm === 'fruchtermann') {
|
||||
// Start the Fruchterman-Reingold algorithm:
|
||||
sigma.layouts.fruchtermanReingold.start(s);
|
||||
dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
|
||||
|
@ -271,6 +310,8 @@
|
|||
dragListener = sigma.plugins.dragNodes(s, s.renderers[0]);
|
||||
}
|
||||
console.log(dragListener);
|
||||
|
||||
$('#calculatingGraph').remove();
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -840,7 +840,7 @@ function FCALL_USER (name, parameters) {
|
|||
}
|
||||
|
||||
try {
|
||||
return FIX_VALUE(UserFunctions[prefix][name].func.apply(null, parameters));
|
||||
return FIX_VALUE(UserFunctions[prefix][name].func.apply({ name: name }, parameters));
|
||||
} catch (err) {
|
||||
WARN(name, INTERNAL.errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR, AQL_TO_STRING(err.stack || String(err)));
|
||||
return null;
|
||||
|
@ -888,7 +888,7 @@ function FCALL_DYNAMIC (func, applyDirect, values, name, args) {
|
|||
|
||||
if (applyDirect) {
|
||||
try {
|
||||
return FIX_VALUE(toCall.apply(null, args));
|
||||
return FIX_VALUE(toCall.apply({ name: name }, args));
|
||||
} catch (err) {
|
||||
WARN(name, INTERNAL.errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR, AQL_TO_STRING(err));
|
||||
return null;
|
||||
|
@ -902,7 +902,7 @@ function FCALL_DYNAMIC (func, applyDirect, values, name, args) {
|
|||
for (i in values) {
|
||||
if (values.hasOwnProperty(i)) {
|
||||
args[0] = values[i];
|
||||
result[i] = FIX_VALUE(toCall.apply(null, args));
|
||||
result[i] = FIX_VALUE(toCall.apply({ name: name }, args));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -910,7 +910,7 @@ function FCALL_DYNAMIC (func, applyDirect, values, name, args) {
|
|||
result = [];
|
||||
for (i = 0; i < values.length; ++i) {
|
||||
args[0] = values[i];
|
||||
result[i] = FIX_VALUE(toCall.apply(null, args));
|
||||
result[i] = FIX_VALUE(toCall.apply({ name: name }, args));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -320,6 +320,23 @@ function ahuacatlCallUserDefinedTestSuite () {
|
|||
testThrows : function () {
|
||||
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR.code, "RETURN CALL('UNITTESTS::FUNC::THROWING')");
|
||||
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR.code, "RETURN APPLY('UNITTESTS::FUNC::THROWING', [ ])");
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test function name passed from the outside
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFunctionName : function () {
|
||||
aqlfunctions.register("UnitTests::func::call", function () { return this.name; });
|
||||
|
||||
var actual = getQueryResults("RETURN UnitTests::func::call()");
|
||||
assertEqual("UNITTESTS::FUNC::CALL", actual[0]);
|
||||
|
||||
actual = getQueryResults("RETURN CALL('UNITTESTS::FUNC::CALL', [])");
|
||||
assertEqual("UNITTESTS::FUNC::CALL", actual[0]);
|
||||
|
||||
actual = getQueryResults("RETURN CALL('unittests::func::call', [])");
|
||||
assertEqual("UNITTESTS::FUNC::CALL", actual[0]);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -744,6 +744,78 @@ function ahuacatlModifySuite () {
|
|||
queries.forEach(function(query) {
|
||||
assertQueryError(errors.ERROR_QUERY_ACCESS_AFTER_MODIFICATION.code, query, { "@cn": cn1 }, query);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test upsert on same document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testUpsertDocumentInitiallyPresent : function () {
|
||||
AQL_EXECUTE("FOR i IN 0..1999 INSERT { _key: CONCAT('test', i), value1: i } IN @@cn1", { "@cn1" : cn1 });
|
||||
|
||||
var expected = { writesExecuted: 1, writesIgnored: 0 };
|
||||
var actual = AQL_EXECUTE("UPSERT { value1: 0 } INSERT { value1: 0, value2: 0 } UPDATE { value2: 1 } IN " + cn1, {});
|
||||
|
||||
assertEqual(2001, c1.count());
|
||||
assertEqual(expected, sanitizeStats(actual.stats));
|
||||
assertEqual([ ], actual.json);
|
||||
|
||||
assertEqual(0, c1.document("test0").value1);
|
||||
assertEqual(1, c1.document("test0").value2);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test upsert on same document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testUpsertDocumentInitiallyNotPresent : function () {
|
||||
AQL_EXECUTE("FOR i IN 0..1999 INSERT { _key: CONCAT('test', i), value1: i } IN @@cn1", { "@cn1" : cn1 });
|
||||
|
||||
var expected = { writesExecuted: 1, writesIgnored: 0 };
|
||||
var actual = AQL_EXECUTE("UPSERT { value1: 999999 } INSERT { _key: 'test999999', value1: 999999, value2: 0 } UPDATE { value2: 1 } IN " + cn1, {});
|
||||
|
||||
assertEqual(2002, c1.count());
|
||||
assertEqual(expected, sanitizeStats(actual.stats));
|
||||
assertEqual([ ], actual.json);
|
||||
|
||||
assertEqual(999999, c1.document("test999999").value1);
|
||||
assertEqual(0, c1.document("test999999").value2);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test upsert on same document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testUpsertDocumentRepeatedInitiallyPresent : function () {
|
||||
AQL_EXECUTE("FOR i IN 0..1999 INSERT { _key: CONCAT('test', i), value1: i } IN @@cn1", { "@cn1" : cn1 });
|
||||
|
||||
var expected = { writesExecuted: 2000, writesIgnored: 0 };
|
||||
var actual = AQL_EXECUTE("FOR i IN 1..2000 UPSERT { value1: 0 } INSERT { value1: 0, value2: 0 } UPDATE { value2: 1 } IN " + cn1, {});
|
||||
|
||||
assertEqual(2001, c1.count());
|
||||
assertEqual(expected, sanitizeStats(actual.stats));
|
||||
assertEqual([ ], actual.json);
|
||||
|
||||
assertEqual(0, c1.document("test0").value1);
|
||||
assertEqual(1, c1.document("test0").value2);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test upsert on same document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testUpsertDocumentRepeatedInitiallyNotPresent : function () {
|
||||
AQL_EXECUTE("FOR i IN 0..1999 INSERT { _key: CONCAT('test', i), value1: i } IN @@cn1", { "@cn1" : cn1 });
|
||||
|
||||
var expected = { writesExecuted: 2000, writesIgnored: 0 };
|
||||
var actual = AQL_EXECUTE("FOR i IN 1..2000 UPSERT { value1: 999999 } INSERT { _key: 'test999999', value1: 999999, value2: 0 } UPDATE { value2: 1 } IN " + cn1, {});
|
||||
|
||||
assertEqual(2002, c1.count());
|
||||
assertEqual(expected, sanitizeStats(actual.stats));
|
||||
assertEqual([ ], actual.json);
|
||||
|
||||
assertEqual(999999, c1.document("test999999").value1);
|
||||
assertEqual(1, c1.document("test999999").value2);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -546,7 +546,7 @@ void SimpleHttpClient::setRequest(
|
|||
for (; i != _pathToBasicAuth.end(); ++i) {
|
||||
std::string& f = i->first;
|
||||
|
||||
if (l->find(f) == 0) {
|
||||
if (l->compare(0, f.size(), f) == 0) {
|
||||
// f is prefix of l
|
||||
if (f.length() > foundPrefix.length()) {
|
||||
foundPrefix = f;
|
||||
|
|
|
@ -78,36 +78,34 @@ static v8::Handle<v8::Value> ObjectVPackObject(v8::Isolate* isolate,
|
|||
} else {
|
||||
// optimized code path for translated system attributes
|
||||
VPackSlice v = VPackSlice(k.begin() + 1);
|
||||
v8::Local<v8::Value> sub;
|
||||
if (v.isString()) {
|
||||
char const* p = v.getString(l);
|
||||
sub = TRI_V8_ASCII_PAIR_STRING(p, l);
|
||||
} else {
|
||||
sub = TRI_VPackToV8(isolate, v, options, &slice);
|
||||
}
|
||||
|
||||
uint8_t which = static_cast<uint8_t>(k.getUInt()) + VelocyPackHelper::AttributeBase;
|
||||
switch (which) {
|
||||
case VelocyPackHelper::KeyAttribute: {
|
||||
char const* p = v.getString(l);
|
||||
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_KeyKey), TRI_V8_ASCII_PAIR_STRING(p, l));
|
||||
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_KeyKey), sub);
|
||||
break;
|
||||
}
|
||||
case VelocyPackHelper::RevAttribute: {
|
||||
char const* p = v.getString(l);
|
||||
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_RevKey), TRI_V8_ASCII_PAIR_STRING(p, l));
|
||||
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_RevKey), sub);
|
||||
break;
|
||||
}
|
||||
case VelocyPackHelper::IdAttribute: {
|
||||
if (v.isString()) {
|
||||
char const* p = v.getString(l);
|
||||
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_IdKey), TRI_V8_ASCII_PAIR_STRING(p, l));
|
||||
} else {
|
||||
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_IdKey), TRI_VPackToV8(isolate, v, options, &slice));
|
||||
}
|
||||
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_IdKey), sub);
|
||||
break;
|
||||
}
|
||||
case VelocyPackHelper::FromAttribute: {
|
||||
char const* p = v.getString(l);
|
||||
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_FromKey), TRI_V8_ASCII_PAIR_STRING(p, l));
|
||||
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_FromKey), sub);
|
||||
break;
|
||||
}
|
||||
case VelocyPackHelper::ToAttribute: {
|
||||
char const* p = v.getString(l);
|
||||
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_ToKey), TRI_V8_ASCII_PAIR_STRING(p, l));
|
||||
object->ForceSet(v8::Local<v8::String>::New(isolate, v8g->_ToKey), sub);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue