1
0
Fork 0

Merge branch 'devel' of https://github.com/triAGENS/AvocadoDB into devel

Conflicts:
	configure
This commit is contained in:
Jan Steemann 2012-05-08 12:38:41 +02:00
commit bf21b866aa
43 changed files with 894 additions and 301 deletions

View File

@ -240,6 +240,58 @@ void* TRI_AtVector (TRI_vector_t const* vector, size_t pos) {
return (void*) (vector->_buffer + pos * vector->_elementSize);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief inserts an element at a given position
////////////////////////////////////////////////////////////////////////////////
void TRI_InsertVector (TRI_vector_t* vector, void const* element, size_t position) {
char* newBuffer;
size_t newSize;
// ...........................................................................
// Check and see if we need to extend the vector
// ...........................................................................
if (vector->_length >= vector->_capacity || position >= vector->_length) {
newSize = (size_t) (1 + GROW_FACTOR * vector->_capacity);
if (position >= newSize) {
newSize = position + 1;
}
newBuffer = (char*) TRI_Allocate(vector->_memoryZone, newSize * vector->_elementSize, false);
if (newBuffer == NULL) {
TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
return;
}
vector->_capacity = newSize;
if (vector->_buffer != NULL) {
memcpy(newBuffer, vector->_buffer, vector->_length * vector->_elementSize);
TRI_Free(vector->_memoryZone, vector->_buffer);
}
vector->_buffer = newBuffer;
}
if (position < vector->_length) {
memmove(vector->_buffer + (vector->_elementSize * (position + 1)),
vector->_buffer + (vector->_elementSize * position),
vector->_elementSize * (vector->_length - position)
);
vector->_length += 1;
}
else {
vector->_length = position + 1;
}
memcpy(vector->_buffer + (vector->_elementSize * position), element, vector->_elementSize);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief sets an element at a given position
////////////////////////////////////////////////////////////////////////////////
@ -458,6 +510,11 @@ int TRI_PushBackVectorPointer (TRI_vector_pointer_t* vector, void* element) {
////////////////////////////////////////////////////////////////////////////////
int TRI_InsertVectorPointer (TRI_vector_pointer_t* vector, void* element, size_t n) {
// ...........................................................................
// Check and see if we need to extend the vector
// ...........................................................................
if (vector->_length >= vector->_capacity || n >= vector->_length) {
void* newBuffer;
size_t newSize = (size_t) (1 + GROW_FACTOR * vector->_capacity);
@ -728,6 +785,11 @@ int TRI_PushBackVectorString (TRI_vector_string_t* vector, char* element) {
////////////////////////////////////////////////////////////////////////////////
int TRI_InsertVectorString (TRI_vector_string_t* vector, char* element, size_t n) {
// ...........................................................................
// Check and see if we need to extend the vector
// ...........................................................................
if (n >= vector->_capacity || n >= vector->_length) {
char** newBuffer;
size_t newSize = (size_t) (1 + GROW_FACTOR * vector->_capacity);

View File

@ -146,6 +146,13 @@ void TRI_RemoveVector (TRI_vector_t*, size_t n);
void* TRI_AtVector (TRI_vector_t const*, size_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief inserts an element at a given position
////////////////////////////////////////////////////////////////////////////////
void TRI_InsertVector (TRI_vector_t* vector, void const* element, size_t position);
////////////////////////////////////////////////////////////////////////////////
/// @brief sets an element at a given position
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,18 @@
> curl --data @- -X PUT --dump - http://localhost:8529/_api/simple/by-example
{ "collection" : "3179705695", "example" : [ { "i" : 1 } ] }
HTTP/1.1 201 Created
content-type: application/json
{
"result": [
{ "a": { "k": 2, "j": 2 }, "i": 1, "_rev": 3181802847, "_id": "3179705695/3181802847" },
{ "a": { "j": 1 }, "i": 1, "_rev": 3181475167, "_id": "3179705695/3181475167" },
{ "a": { "k": 1, "j": 1 }, "i": 1, "_rev": 3181737311, "_id": "3179705695/3181737311" },
{ "i": 1, "_rev": 3181147487, "_id": "3179705695/3181147487" }
],
"count": 4,
"error": false,
"hasMore": false,
"code": 201
}

View File

@ -0,0 +1,15 @@
> curl --data @- -X PUT --dump - http://localhost:8529/_api/simple/by-example
{ "collection" : "3179705695", "example" : [ { "a" : { "j" : 1 } } ] }
HTTP/1.1 201 Created
content-type: application/json
{
"result": [
{ "a": { "j": 1 }, "i": 1, "_rev": 3181475167, "_id": "3179705695/3181475167" }
],
"count": 1,
"error": false,
"hasMore": false,
"code": 201
}

View File

@ -0,0 +1,16 @@
> curl --data @- -X PUT --dump - http://localhost:8529/_api/simple/by-example
{ "collection" : "3179705695", "example" : [ "a.j", 1 ] }
HTTP/1.1 201 Created
content-type: application/json
{
"result": [
{ "a": { "j": 1 }, "i": 1, "_rev": 3181475167, "_id": "3179705695/3181475167" },
{ "a": { "k": 1, "j": 1 }, "i": 1, "_rev": 3181737311, "_id": "3179705695/3181737311" }
],
"count": 2,
"error": false,
"hasMore": false,
"code": 201
}

View File

@ -0,0 +1,11 @@
> curl --data @- -X PUT --dump - http://localhost:8529/_api/simple/first-example
{ "collection" : "666351134", "example" : [ "a.j", 1, "a.k", 1 ] }
HTTP/1.1 200 OK
content-type: application/json
{
"error": false,
"code": 200,
"document": { "_rev": 668382750, "_id": "666351134/668382750", "a": { "k": 1, "j": 1, "l" : 10 }, "i": 1 }
}

View File

@ -0,0 +1,12 @@
> curl --data @- -X PUT --dump - http://localhost:8529/_api/simple/first-example
{ "collection" : "666351134", "example" : [ "a.j", 1, "a.k", 2 ] }
HTTP/1.1 404 Not Found
content-type: application/json
{
"errorMessage": "no match",
"error": true,
"code": 404,
"errorNum": 404
}

View File

@ -1,7 +1,10 @@
function aqlTestSuite () {
function testSizeOfTestCollection () {
return {
testSizeOfTestCollection : function () {
assertEqual(5, 5);
}
};
}
jsUnity.run(aqlTestSuite);
return jsunity.done();

View File

@ -0,0 +1,2 @@
avocado> db.users.count();
10001

View File

@ -0,0 +1,2 @@
avocado> db.users.firstExample("name", 1237);
{ "_id" : "100225/83049373", "_rev" : 83049373, "name" : 1237 }

View File

@ -11,6 +11,6 @@ fi
HEADER='<html><head><title>AvocadoDB Manual</title> <style media="screen" type="text/css" style="display:none">body{background-color:white;font:13px Helvetica,arial,freesans,clean,sans-serif;line-height:1.4;color:#333;}#access{font-size:16px;margin-left:12px;display:block;margin-left:10px;margin-right:10px;background-color:#F3F1EE!important;}#access a{border-right:1px solid #DBDEDF;color:#A49F96;display:block;line-height:38px;padding:0 10px;text-decoration:none;}#navigation ul{text-transform:uppercase;list-style:none;margin:0;}#navigation li{float:left;position:relative;}#container{width:920px;margin:0 auto;}a{color:#4183C4;text-decoration:none;}.contents h2{font-size:24px;border-bottom:1px solid #CCC;color:black;}.contents h1{font-size:33px;border-bottom:1px solid #CCC;color:black;}.clearfix:after{content:".";display:block;clear:both;font-size:0;height:0;visibility:hidden;}/**/ *:first-child+html .clearfix{min-height:0;}/**/ * html .clearfix{height:1%;}</style></head><body><div id="container"><img src="images/logo_avocadodb.jpg" width="397" height="67" alt="AvocadoDB"><div id="access" role="navigation"><div id="navigation"><ul id="menu-ahome" class="menu"><li><a href="Home.html">Table of contents</a></li> <li><a href="http://www.avocadodb.org">AvocadoDB homepage</a></li></ul></div><div class="clearfix"></div></div><div>'
FOOTER='</div></body></html>'
sed -e "s~<\\?php include \"include/header.php\" \\?> ~${HEADER}~" $INPUT \
| sed -e "s~<\\?php include \"include/footer.php\" \\?> ~${FOOTER}~" \
sed -e "s~<?php include \"include/header.php\" ?> ~${HEADER}~" $INPUT \
| sed -e "s~<?php include \"include/footer.php\" ?> ~${FOOTER}~" \
| sed -e "s~<div class=\"title\">\\([^<]*\\)</div>~<h1>\\1</h1>~" > $OUTPUT

View File

@ -410,6 +410,8 @@ WIKI = \
ShellIndex \
SimpleQueries \
UserManualServer \
UserManualServerBasics \
UserManualServerStartStop \
UserManualShell \
UserManualShellStartStop \
jsUnity

View File

@ -1011,6 +1011,8 @@ WIKI = \
ShellIndex \
SimpleQueries \
UserManualServer \
UserManualServerBasics \
UserManualServerStartStop \
UserManualShell \
UserManualShellStartStop \
jsUnity

View File

@ -11,6 +11,6 @@ MANUAL_DST="fceller@www.avocadodb.org:/srv/www/www.avocadodb.org/avoc/manuals"
publish:
(cd Doxygen/wiki && git checkout --force && git pull)
$(MAKE) wiki
(cd Doxygen/wiki && git commit -m "`date`" -a; git push)
(cd Doxygen/wiki && git add *.md; git commit -m "`date`" -a; git push)
@for w in $(WIKI); do scp Doxygen/html/$$w.html $(MANUAL_DST); done

View File

@ -52,7 +52,7 @@
/// @page HttpIndex HTTP Interface for Indexes
///
/// This is an introduction to AvocadoDB's Http interface for indexes in
/// general. There are special section for
/// general. There are special sections for
///
/// @copydoc IndexesTOC
///

View File

@ -41,6 +41,8 @@
///
/// <ol>
/// <li>@ref HttpSimpleAll "POST /_api/simple/all"</li>
/// <li>@ref HttpSimpleByExample "POST /_api/simple/by-example"</li>
/// <li>@ref HttpSimpleFirstExample "POST /_api/simple/first-example"</li>
/// <li>@ref HttpSimpleNear "POST /_api/simple/near"</li>
/// <li>@ref HttpSimpleWithin "POST /_api/simple/within"</li>
/// </ol>
@ -71,13 +73,20 @@
/// @copydetails JSA_PUT_api_simple_all
/// <hr>
///
/// @anchor HttpSimpleByExample
/// @copydetails JSA_PUT_api_simple_by_example
/// <hr>
///
/// @anchor HttpSimpleFirstExample
/// @copydetails JSA_PUT_api_simple_first_example
/// <hr>
///
/// @anchor HttpSimpleNear
/// @copydetails JSA_PUT_api_simple_near
/// <hr>
///
/// @anchor HttpSimpleWithin
/// @copydetails JSA_PUT_api_simple_within
/// <hr>
////////////////////////////////////////////////////////////////////////////////
// Local Variables:

View File

@ -74,9 +74,6 @@
///
/// @subsection HomePython Python
///
/// Help wanted:
/// http://www.avocadodb.org/2012/03/24/contributors-for-python-api-wanted-for-nosql-project
///
/// @subsection HomeREST REST
///
/// @subsection HomeRuby Ruby

View File

@ -29,10 +29,8 @@
/// @page InstallManual AvocadoDB Installation Manual
///
/// <ol>
/// <li>@ref Installing
/// <li>
/// <li>@ref Compiling
/// </li>
/// <li>@ref Installing</li>
/// <li>@ref Compiling</li>
/// </ol>
////////////////////////////////////////////////////////////////////////////////
@ -56,7 +54,7 @@
/// @page Installing Installing the AvocadoDB
///
/// <hr>
/// @copydoc CompilingTOC
/// @copydoc InstallingTOC
/// <hr>
///
/// @section MacOSX

View File

@ -0,0 +1,64 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief module "internal"
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @page jsUnity Using jsUnity and node-jscoverage
///
/// The AvocadoDB contains a wrapper for
/// <a href="http://jsunity.com/">jsUnity</a>, a lightyweight universal
/// JavAScript unit testing framework.
///
/// @section jsUnityRunningTest Running jsUnity Tests
/////////////////////////////////////////////////////
///
/// Assume that you have a test file containing
///
/// @verbinclude jsunity1
///
/// Then you can run the test suite using @FN{jsunity.runTest}
///
/// @verbinclude jsunity2
///
/// @section jsUnityRunningCoverage Running jsUnity Tests with Coverage
///////////////////////////////////////////////////////////////////////
///
/// You can use the coverage tool
/// <a href="https://github.com/visionmedia/node-jscoverage">@LIT{node-jscoverage}</a>.
///
/// Assume that your file live in a directory called @LIT{lib}. Use
///
/// @CODE{node-jscoverage lib lib-cov}
///
/// to create a copy of the JavaScript files with coverage information. Start
/// the AvocadoDB with these files and use @FN{jsunity.runCoverage} instead of
/// @FN{jsunity.runTest}.
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @\\}\\)"
// End:

View File

@ -60,20 +60,16 @@
/// <li>@ref HttpSystem
/// @copydetails HttpSystemTOC
/// </li>
/// <li>@ref OTWPSimpleQueries
/// <ol>
/// <li>@ref OTWPSimpleQueriesByExample "PUT /_api/simple/by-example"</li>
/// </li>
/// </ol>
/// </li>
/// <li>@ref Key-Value
/// <li>@ref Key-Value (Under Construction)
/// <ol>
/// <li>@ref Key-ValuePost "POST /_api/key/@FA{collection-name}/@FA{key}"</li>
/// <li>@ref Key-ValuePut "PUT /_api/key/@FA{collection-name}/@FA{key}"</li>
/// <li>@ref Key-ValueGet "GET /_api/key/@FA{collection-name}/@FA{key}"</li>
/// <li>@ref Key-ValueDelete "DELETE /_api/key/@FA{collection-name}/@FA{key}"</li>
/// <li>@ref Key-ValueSearch "GET /_api/keys/@FA{collection-name}/@FA{prefix}"</li>
/// </ol>
/// </li>
/// <li>@ref Key-ValuePost "POST /_api/key/collection-name/key"</li>
/// <li>@ref Key-ValuePut "PUT /_api/key/collection-name/key"</li>
/// <li>@ref Key-ValueGet "GET /_api/key/collection-name/key"</li>
/// <li>@ref Key-ValueDelete "DELETE /_api/key/collection-name/key"</li>
/// <li>@ref Key-ValueSearch "GET /_api/keys/collection-name/prefix"</li>
/// </ol>
/// </li>
/// </ol>
@ -85,14 +81,6 @@
/// <hr>
/// @copydoc OTWPTOC
/// <hr>
///
/// @section OTWPSimpleQueries Simple Queries
/////////////////////////////////////////////
///
/// @anchor OTWPSimpleQueriesByExample
/// @copydetails JSA_PUT_api_simple_by_example
/// <hr>
///
////////////////////////////////////////////////////////////////////////////////
// Local Variables:

View File

@ -31,36 +31,39 @@
/// <ol>
/// <li>@ref SimpleQueriesQueries
/// <ol>
/// <li>@ref SimpleQueryDocument "db.@FA{collection}.document(@FA{document-reference})"</li>
/// <li>@ref SimpleQueryAll "db.@FA{collection}.all()"</li>
/// <li>@ref SimpleQueryByExample "db.@FA{collection}.byExample()"</li>
/// <li>@ref SimpleQueryCount "@FA{query}.count()"</li>
/// <li>@ref SimpleQueryDocument "collection.document(document-reference)"</li>
/// <li>@ref SimpleQueryAll "collection.all()"</li>
/// <li>@ref SimpleQueryByExample "collection.byExample(example)"</li>
/// <li>@ref SimpleQueryFirstExample "collection.firstExample(example)"</li>
/// <li>@ref SimpleQueryCollectionCount "collection.count()"</li>
/// <li>@ref SimpleQueryToArray "collection.toArray()"</li>
/// </ol>
/// </li>
/// <li>@ref SimpleQueriesGeoQueries
/// <ol>
/// <li>@ref SimpleQueryNear "db.@FA{collection}.near()"</li>
/// <li>@ref SimpleQueryWithin "db.@FA{collection}.within()"</li>
/// <li>@ref SimpleQueryGeo "db.@FA{collection}.geo()"</li>
/// <li>@ref SimpleQueryNear "collection.near(latitude, longitude)"</li>
/// <li>@ref SimpleQueryWithin "collection.within(latitude, longitude)"</li>
/// <li>@ref SimpleQueryGeo "collection.geo(location)"</li>
/// </ol>
/// </li>
/// <li>@ref SimpleQueriesEdgesQueries
/// <ol>
/// <li>@ref SimpleQueryEdges "edges.@FA{collection}.edges()"</li>
/// <li>@ref SimpleQueryInEdges "edges.@FA{collection}.inEdges()"</li>
/// <li>@ref SimpleQueryOutEdges "edges.@FA{collection}.outEdges()"</li>
/// <li>@ref SimpleQueryEdges "edges-collection.edges(vertex)"</li>
/// <li>@ref SimpleQueryInEdges "edges-collection.inEdges(vertex)"</li>
/// <li>@ref SimpleQueryOutEdges "edges-collection.outEdges(vertex)"</li>
/// </ol>
/// </li>
/// <li>@ref SimpleQueriesPagination
/// <ol>
/// <li>@ref SimpleQueryLimit "@FA{query}.limit(@FA{limit})"</li>
/// <li>@ref SimpleQuerySkip "@FA{query}.skip(@FA{skip})"</li>
/// <li>@ref SimpleQueryLimit "query.limit(limit)"</li>
/// <li>@ref SimpleQuerySkip "query.skip(skip)"</li>
/// </ol>
/// </li>
/// <li>@ref SimpleQueriesSequentialAccess
/// <ol>
/// <li>@ref SimpleQueryHasNext "@FA{query}.hasNext()"</li>
/// <li>@ref SimpleQueryNext "@FA{query}.next()"</li>
/// <li>@ref SimpleQueryHasNext "query.hasNext()"</li>
/// <li>@ref SimpleQueryNext "query.next()"</li>
/// <li>@ref SimpleQueryCount "query.count()"</li>
/// </ol>
/// </li>
/// </ol>
@ -72,17 +75,20 @@
/// Simple queries can be used if the query condition is straight forward
/// simple, i. e., a document reference, all documents, a query-by-example, or a
/// simple geo query. In a simple query you can specify exactly one collection
/// and one condition. The result can then be sorted and result can be split
/// into pages.
/// and one condition.
///
/// <hr>
/// @copydoc SimpleQueriesTOC
/// <hr>
///
/// If a query returns a cursor, then you can use @FN{hasNext} and @FN{next} to
/// iterate over the result set or @FN{toArray} to convert it to an array.
///
/// @section SimpleQueriesQueries Queries
/////////////////////////////////////////
///
/// @anchor SimpleQueryDocument
/// @copydetails JS_DocumentVocbaseCol
/// <hr>
///
/// @anchor SimpleQueryAll
@ -93,8 +99,16 @@
/// @copydetails JSF_AvocadoCollection_prototype_byExample
/// <hr>
///
/// @anchor SimpleQueryCount
/// @copydetails JSF_SimpleQuery_prototype_count
/// @anchor SimpleQueryFirstExample
/// @copydetails JSF_AvocadoCollection_prototype_firstExample
/// <hr>
///
/// @anchor SimpleQueryCollectionCount
/// @copydetails JS_CountVocbaseCol
/// <hr>
///
/// @anchor SimpleQueryToArray
/// @copydetails JSF_AvocadoCollection_prototype_toArray
///
/// @section SimpleQueriesGeoQueries Geo Queries
////////////////////////////////////////////////
@ -148,7 +162,7 @@
/// If, for example, you display the result of a user search, then you are in
/// general not interested in the completed result set, but only the first 10 or
/// so documents. Or maybe the next 10 documents for the second page. In this
/// case, you can the @FN{skip} and @FN{limit} operators. These operators works
/// case, you can the @FN{skip} and @FN{limit} operators. These operators work
/// like LIMIT in MySQL.
///
/// @FN{skip} used together with @FN{limit} can be used to implement pagination.
@ -174,6 +188,10 @@
///
/// @anchor SimpleQueryNext
/// @copydetails JSF_SimpleQuery_prototype_next
/// <hr>
///
/// @anchor SimpleQueryCount
/// @copydetails JSF_SimpleQuery_prototype_count
////////////////////////////////////////////////////////////////////////////////
// Local Variables:

View File

@ -33,12 +33,6 @@
/// <ol>
/// <li>@ref UserManualServerStartStop
/// </li>
/// <li>AvocadoScript
/// <ol>
/// <li>@ref SimpleQueries
/// </li>
/// </ol>
/// </li>
/// <li>Avocado Query Language
/// <ol>
/// <li>@ref AQLBasics
@ -49,47 +43,18 @@
/// </li>
/// </ol>
/// </li>
/// <li>@ref AvocadoScript
/// <ol>
/// <li>GeoCoordinates
/// </li>
/// </ol>
/// </li>
/// <li>Vertices, Edges, and Graphs
/// <ol>
/// <li>@ref Graphs
/// </li>
/// <li>@ref JSModuleGraph
/// </li>
/// </ol>
/// </li>
/// <li>@ref AvocadoErrors
/// </li>
/// </ol>
/// </li>
/// <li>Client Communication
/// <ol>
/// <li>@ref HttpInterface
/// <ol>
/// <li>@ref RestDocument
/// </li>
/// </ol>
/// </li>
/// </ol>
/// </li>
/// <li>@ref DBAdmin
/// <ol>
/// <li>@ref DBAdminDurability
/// </li>
/// <li>@ref DBAdminIndex
/// <ol>
/// <li>@ref DBAdminIndexGeo
/// </ol>
/// </li>
/// </ol>
/// </li>
/// <li>Advanced Topics
/// <ol>
/// <li>@ref DBAdmin
/// <ol>
/// <li>@ref DBAdminDurability
/// </li>
/// </ol>
/// </li>
/// <li>Actions
/// <ol>
/// <li>@ref Actions
@ -98,12 +63,6 @@
/// </li>
/// </ol>
/// </li>
/// <li>@ref HttpInterface
/// <ol>
/// <li>@ref RestSystem
/// </li>
/// </ol>
/// </li>
/// <li>@ref jsUnity
/// </li>
/// </ol>
@ -128,20 +87,21 @@
/// @page UserManualServerStartStopTOC
///
/// <ol>
/// <li>@ref UserManualServerStartStopHttp "Starting the HTTP Server"</li>
/// <li>@ref UserManualServerStartStopDebug "Starting the Debug Shell"</li>
/// <li>@ref UserManualServerStartStopOptions "Frequently Used Options"</li>
/// <li>@ref UserManualServerStartStopHttp</li>
/// <li>@ref UserManualServerStartStopDebug</li>
/// <li>@ref UserManualServerStartStopOptions</li>
/// </ol>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @page UserManualServerStartStop Starting the AvocadoDB
///
/// The AvocadoDB has two mode of operation: as server, where it will answer to
/// HTTP requests, see @ref HttpInterface, and a debug shell, where you can
/// access the database directly. Using the debug shell allows you to issue all
/// commands normally available in actions and transactions, see @ref
/// AvocadoScript.
/// The AvocadoDB has two modes of operation: as server, where it will answer to
/// client requests and an emergency console, where you can access the database
/// directly. The latter should - as the name suggests - only be used in case of
/// an emergency, for example, a corrupted collection. Using the emergency
/// console allows you to issue all commands normally available in actions and
/// transactions.
///
/// You should never start more than one server for the same database,
/// independent from the mode of operation.
@ -151,6 +111,7 @@
/// <hr>
///
/// @section UserManualServerStartStopHttp Starting the HTTP Server
///////////////////////////////////////////////////////////////////
///
/// The following command starts the AvocadoDB in server mode. You will be able
/// to access the server using HTTP request on port 8529. See below for a list
@ -158,14 +119,16 @@
///
/// @verbinclude option-database-directory
///
/// @section UserManualServerStartStopDebug Starting the Debug Shell
/// @section UserManualServerStartStopDebug Starting the Emergency Console
//////////////////////////////////////////////////////////////////////////
///
/// The following command starts a debug shell. See below for a list of
/// The following command starts a emergency console. See below for a list of
/// frequently used options, see @ref CommandLine "here" for a complete list.
///
/// @verbinclude start1
///
/// @section UserManualServerStartStopOptions Frequently Used Options
/////////////////////////////////////////////////////////////////////
///
/// The following command-line options are frequently used. For a full
/// list of options see @ref CommandLine "here".
@ -198,11 +161,6 @@
/// <ol>
/// <li>@ref DBAdminDurability
/// </li>
/// <li>@ref DBAdminIndex
/// <ol>
/// <li>@ref DBAdminIndexGeo
/// </ol>
/// </li>
/// </ol>
////////////////////////////////////////////////////////////////////////////////
@ -214,8 +172,10 @@
/// <hr>
///
/// @section DBAdminDurability Durability
/////////////////////////////////////////
///
/// @subsection DBAdminDurability1 Mostly Memory/Durability
///////////////////////////////////////////////////////////
///
/// Database documents are stored in the memory-memory-mapped files are used to
/// store them. The operating system has the advantageous option to decide
@ -224,6 +184,7 @@
/// documents securely at once (durability).
///
/// @subsection DBAdminDurability2 AppendOnly/MVCC
//////////////////////////////////////////////////
///
/// Instead of overwriting existing documents, a completely new version of the
/// document is generated. The two benefits are:
@ -237,18 +198,9 @@
/// processes.
///
/// @subsection DBAdminDurability3 Configuration
////////////////////////////////////////////////
///
/// @copydetails JS_PropertiesVocbaseCol
///
/// @section DBAdminIndex Index Management
///
/// @subsection DBAdminIndexHash Hash Indexes
///
/// copydetails JS_EnsureHashIndexVocbaseCol
///
/// @subsection DBAdminIndexGeo Geo Indexes
///
/// copydetails JS_EnsureGeoIndexVocbaseCol
////////////////////////////////////////////////////////////////////////////////
// Local Variables:

View File

@ -74,6 +74,8 @@ typedef struct array_shaper_s {
TRI_associative_pointer_t _shapeDictionary;
TRI_vector_pointer_t _shapes;
// todo: add attribute weight structure
}
array_shaper_t;
@ -402,6 +404,12 @@ static char const* LookupAttributeIdArrayShaper (TRI_shaper_t* shaper, TRI_shape
return NULL;
}
static int64_t LookupAttributeWeight (TRI_shaper_t* shaper, TRI_shape_aid_t aid) {
// todo: add support for an attribute weight
assert(0);
return -1;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
@ -559,6 +567,7 @@ TRI_shaper_t* TRI_CreateArrayShaper (TRI_memory_zone_t* zone) {
shaper->base.lookupAttributeId = LookupAttributeIdArrayShaper;
shaper->base.findShape = FindShapeShape;
shaper->base.lookupShapeId = LookupShapeId;
shaper->base.lookupAttributeWeight = LookupAttributeWeight;
// handle basics
ok = TRI_InsertBasicTypesShaper(&shaper->base);

View File

@ -60,7 +60,7 @@ typedef struct TRI_shaper_s {
char const* (*lookupAttributeId) (struct TRI_shaper_s*, TRI_shape_aid_t);
TRI_shape_t const* (*findShape) (struct TRI_shaper_s*, TRI_shape_t*);
TRI_shape_t const* (*lookupShapeId) (struct TRI_shaper_s*, TRI_shape_sid_t);
int64_t (*lookupAttributeWeight) (struct TRI_shaper_s*, TRI_shape_aid_t);
TRI_shape_path_t const* (*lookupAttributePathByPid) (struct TRI_shaper_s*, TRI_shape_pid_t);
TRI_shape_pid_t (*findAttributePathByName) (struct TRI_shaper_s*, char const*);

View File

@ -470,6 +470,21 @@ static int CompareShapedJsonShapedJson (const TRI_shaped_json_t* left, const TRI
result = CompareShapeTypes (left, right, leftShaper, rightShaper);
// ............................................................................
// In the above function CompareShaeTypes we use strcmp which may return
// an integer greater than 1 or less than -1. From this function we only
// need to know whether we have equality (0), less than (-1) or greater than (1)
// ............................................................................
if (result < 0) {
result = -1;
}
else if (result > 0) {
result = 1;
}
return result;
} // end of function CompareShapedJsonShapedJson
@ -718,7 +733,16 @@ static int IndexStaticMultiCompareElementElement (TRI_skiplist_multi_t* multiSki
for (j = 0; j < hLeftElement->numFields; j++) {
compareResult = CompareShapedJsonShapedJson((j + hLeftElement->fields), (j + hRightElement->fields), leftShaper, rightShaper);
if (compareResult != 0) {
// ......................................................................
// The function CompareShaedJsonShapedJson can only return 0, -1, or 1
// that is, TRI_SKIPLIST_COMPARE_STRICTLY_EQUAL (0)
// TRI_SKIPLIST_COMPARE_STRICTLY_LESS (-1)
// TRI_SKIPLIST_COMPARE_STRICTLY_GREATER (1)
// ......................................................................
return compareResult;
}
}

View File

@ -25,9 +25,10 @@
/// @author Copyright 2006-2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "skiplist.h"
#include <BasicsC/logging.h>
#include <BasicsC/random.h>
#include "skiplist.h"
#include "compare.h"
#define SKIPLIST_ABSOLUTE_MAX_HEIGHT 100
@ -340,11 +341,11 @@ void TRI_InitSkipList (TRI_skiplist_t* skiplist, size_t elementSize,
}
// ..........................................................................
// Assign the comparision call back functions
// Assign the STATIC comparision call back functions
// ..........................................................................
skiplist->compareElementElement = compareElementElement;
skiplist->compareKeyElement = compareKeyElement;
skiplist->compareElementElement = IndexStaticCompareElementElement; // compareElementElement;
skiplist->compareKeyElement = IndexStaticCompareKeyElement; // compareKeyElement;
// ..........................................................................
// Assign the maximum height of the skip list. This maximum height must be
@ -352,7 +353,7 @@ void TRI_InitSkipList (TRI_skiplist_t* skiplist, size_t elementSize,
// ..........................................................................
skiplist->_base._maxHeight = maximumHeight;
if (maximumHeight > SKIPLIST_ABSOLUTE_MAX_HEIGHT) {
printf("%s:%d:Invalid maximum height for skiplist\n",__FILE__,__LINE__);
LOG_ERROR("Invalid maximum height for skiplist", TRI_ERROR_INTERNAL);
assert(false);
}
@ -1290,7 +1291,7 @@ void* TRI_RightLookupByKeySkipList (TRI_skiplist_t* skiplist, void* key) {
// Use the callback to determine if the element is less or greater than
// the next node element.
// .......................................................................
compareResult = IndexStaticCompareKeyElement(skiplist,key,&(prevNode->_element), 1);
compareResult = IndexStaticCompareKeyElement(skiplist, key, &(prevNode->_element), 1);
// .......................................................................
@ -1311,7 +1312,7 @@ void* TRI_RightLookupByKeySkipList (TRI_skiplist_t* skiplist, void* key) {
}
// .......................................................................
// The element is greater than the next node element. Keep going on this
// The key is greater than the next node element. Keep going on this
// level.
// .......................................................................
if (compareResult < 0) {
@ -1399,9 +1400,9 @@ void TRI_InitSkipListMulti (TRI_skiplist_multi_t* skiplist,
// Assign the comparision call back functions
// ..........................................................................
skiplist->compareElementElement = compareElementElement;
skiplist->compareKeyElement = compareKeyElement;
skiplist->equalElementElement = equalElementElement;
skiplist->compareElementElement = IndexStaticMultiCompareElementElement; //compareElementElement;
skiplist->compareKeyElement = IndexStaticMultiCompareKeyElement; // compareKeyElement;
skiplist->equalElementElement = IndexStaticMultiEqualElementElement; //equalElementElement;
// ..........................................................................
// Assign the maximum height of the skip list. This maximum height must be
@ -1409,7 +1410,7 @@ void TRI_InitSkipListMulti (TRI_skiplist_multi_t* skiplist,
// ..........................................................................
skiplist->_base._maxHeight = maximumHeight;
if (maximumHeight > SKIPLIST_ABSOLUTE_MAX_HEIGHT) {
printf("%s:%d:Invalid maximum height for skiplist\n",__FILE__,__LINE__);
LOG_ERROR("Invalid maximum height for skiplist", TRI_ERROR_INTERNAL);
assert(false);
}
@ -2114,7 +2115,7 @@ int TRI_RemoveElementSkipListMulti (TRI_skiplist_multi_t* skiplist, void* elemen
}
// .....................................................................
// The element could be located and we are at the lowest level
// The element could be located (by matching the key) and we are at the lowest level
// .....................................................................
if (compareResult == TRI_SKIPLIST_COMPARE_SLIGHTLY_LESS) {
goto END;
@ -2163,7 +2164,7 @@ int TRI_RemoveElementSkipListMulti (TRI_skiplist_multi_t* skiplist, void* elemen
// ..........................................................................
if (old != NULL) {
memcpy(old, &(currentNode->_element), skiplist->_base._elementSize);
IndexStaticCopyElementElement(&(skiplist->_base), old, &(currentNode->_element));
}

View File

@ -1150,6 +1150,8 @@ static bool multiSkiplistIndex_findHelperIntervalValid(SkiplistIndex* skiplistIn
compareResult = skiplistIndex->skiplist.nonUniqueSkiplist->compareKeyElement(
skiplistIndex->skiplist.nonUniqueSkiplist,
&(lNode->_element), &(rNode->_element), 0);
return (compareResult == -1);
}
@ -1292,6 +1294,7 @@ TRI_skiplist_iterator_t* MultiSkiplistIndex_find(SkiplistIndex* skiplistIndex, T
if (results == NULL) {
return NULL;
}
results->_index = skiplistIndex;
TRI_InitVector(&(results->_intervals), TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_skiplist_iterator_interval_t));
results->_currentInterval = 0;

View File

@ -109,10 +109,6 @@ describe AvocadoDB do
AvocadoDB.drop_collection(@cn)
@cid = AvocadoDB.create_collection(@cn, false)
cmd = api + "?collection=#{@cid}"
body = "{ \"type\" : \"geo\", \"fields\" : [ \"a\" ] }"
#doc = AvocadoDB.post(cmd, :body => body)
(0..10).each{|i|
lat = 10 * (i - 5)
@ -189,10 +185,6 @@ describe AvocadoDB do
AvocadoDB.drop_collection(@cn)
@cid = AvocadoDB.create_collection(@cn, false)
cmd = api + "?collection=#{@cid}"
body = "{ \"type\" : \"geo\", \"fields\" : [ \"a\" ] }"
#doc = AvocadoDB.post(cmd, :body => body)
(0..10).each{|i|
lat = 10 * (i - 5)
@ -259,5 +251,116 @@ describe AvocadoDB do
end
end
################################################################################
## by-example query
################################################################################
context "by-example query:" do
before do
@cn = "UnitTestsCollectionByExample"
AvocadoDB.drop_collection(@cn)
@cid = AvocadoDB.create_collection(@cn, false)
end
after do
AvocadoDB.drop_collection(@cn)
end
it "finds the examples" do
body = "{ \"i\" : 1 }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(202)
d1 = doc.parsed_response['_id']
body = "{ \"i\" : 1, \"a\" : { \"j\" : 1 } }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(202)
d2 = doc.parsed_response['_id']
body = "{ \"i\" : 1, \"a\" : { \"j\" : 1, \"k\" : 1 } }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(202)
d3 = doc.parsed_response['_id']
body = "{ \"i\" : 1, \"a\" : { \"j\" : 2, \"k\" : 2 } }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(202)
d4 = doc.parsed_response['_id']
body = "{ \"i\" : 2 }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(202)
d5 = doc.parsed_response['_id']
body = "{ \"i\" : 2, \"a\" : 2 }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(202)
d6 = doc.parsed_response['_id']
body = "{ \"i\" : 2, \"a\" : { \"j\" : 2, \"k\" : 2 } }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(202)
d7 = doc.parsed_response['_id']
cmd = api + "/by-example"
body = "{ \"collection\" : \"#{@cid}\", \"example\" : [ { \"i\" : 1 } ] }"
doc = AvocadoDB.log_put("#{prefix}-by-example1", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(201)
doc.parsed_response['hasMore'].should eq(false)
doc.parsed_response['result'].length.should eq(4)
doc.parsed_response['count'].should eq(4)
doc.parsed_response['result'].map{|i| i['_id']}.should =~ [d1,d2,d3,d4]
cmd = api + "/by-example"
body = "{ \"collection\" : \"#{@cid}\", \"example\" : [ { \"a\" : { \"j\" : 1 } } ] }"
doc = AvocadoDB.log_put("#{prefix}-by-example2", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(201)
doc.parsed_response['hasMore'].should eq(false)
doc.parsed_response['result'].length.should eq(1)
doc.parsed_response['count'].should eq(1)
doc.parsed_response['result'].map{|i| i['_id']}.should =~ [d2]
cmd = api + "/by-example"
body = "{ \"collection\" : \"#{@cid}\", \"example\" : [ \"a.j\", 1 ] }"
doc = AvocadoDB.log_put("#{prefix}-by-example3", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(201)
doc.parsed_response['hasMore'].should eq(false)
doc.parsed_response['result'].length.should eq(2)
doc.parsed_response['count'].should eq(2)
doc.parsed_response['result'].map{|i| i['_id']}.should =~ [d2,d3]
cmd = api + "/first-example"
body = "{ \"collection\" : \"#{@cid}\", \"example\" : [ \"a.j\", 1, \"a.k\", 1 ] }"
doc = AvocadoDB.log_put("#{prefix}-first-example", cmd, :body => body)
doc.code.should eq(200)
doc.headers['content-type'].should eq("application/json")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(200)
doc.parsed_response['document']['_id'].should eq(d3)
cmd = api + "/first-example"
body = "{ \"collection\" : \"#{@cid}\", \"example\" : [ \"a.j\", 1, \"a.k\", 2 ] }"
doc = AvocadoDB.log_put("#{prefix}-first-example-not-found", cmd, :body => body)
doc.code.should eq(404)
doc.headers['content-type'].should eq("application/json")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(404)
end
end
end
end

View File

@ -480,6 +480,14 @@ BOOST_AUTO_TEST_CASE (tst_insert) {
void* r = 0;
// ...........................................................................
// this test needs to be altered slightly e.g.
// TRI_InsertVectorPointer(&v1, &a, 100);
// TRI_InsertVectorPointer(&v1, &a, 20);
// TRI_InsertVectorPointer(&v1, &a, 200);
// ...........................................................................
TRI_InsertVectorPointer(&v1, &a, 0);
BOOST_CHECK_EQUAL((size_t) 1, v1._length);
BOOST_CHECK_EQUAL(&a, TRI_AtVectorPointer(&v1, 0));

View File

@ -1851,7 +1851,7 @@ static v8::Handle<v8::Value> JS_ByExampleQuery (v8::Arguments const& argv) {
ReleaseCollection(collection);
return scope.Close(v8::ThrowException(
CreateErrorObject(TRI_ERROR_BAD_PARAMETER,
"usage: document(<path1>, <value1>, ...)")));
"usage: byExample(<path1>, <value1>, ...)")));
}
size_t n = argv.Length() / 2;
@ -4112,6 +4112,14 @@ static v8::Handle<v8::Value> JS_ExecuteAql (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief counts the number of documents in a result set
///
/// @FUN{@FA{collection}.count()}
///
/// Returns the number of living documents in the collection.
///
/// @EXAMPLES
///
/// @verbinclude shell-collection-count
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_CountVocbaseCol (v8::Arguments const& argv) {

View File

@ -1 +1 @@
0.4.0
0.4.2

20
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.68 for triAGENS AvocadoDB 0.4.0.
# Generated by GNU Autoconf 2.68 for triAGENS AvocadoDB 0.4.2.
#
# Report bugs to <info@triagens.de>.
#
@ -560,8 +560,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='triAGENS AvocadoDB'
PACKAGE_TARNAME='avocado'
PACKAGE_VERSION='0.4.0'
PACKAGE_STRING='triAGENS AvocadoDB 0.4.0'
PACKAGE_VERSION='0.4.2'
PACKAGE_STRING='triAGENS AvocadoDB 0.4.2'
PACKAGE_BUGREPORT='info@triagens.de'
PACKAGE_URL='http://www.avocadodb.org'
@ -1398,7 +1398,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures triAGENS AvocadoDB 0.4.0 to adapt to many kinds of systems.
\`configure' configures triAGENS AvocadoDB 0.4.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1469,7 +1469,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of triAGENS AvocadoDB 0.4.0:";;
short | recursive ) echo "Configuration of triAGENS AvocadoDB 0.4.2:";;
esac
cat <<\_ACEOF
@ -1622,7 +1622,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
triAGENS AvocadoDB configure 0.4.0
triAGENS AvocadoDB configure 0.4.2
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@ -2087,7 +2087,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by triAGENS AvocadoDB $as_me 0.4.0, which was
It was created by triAGENS AvocadoDB $as_me 0.4.2, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@ -3214,7 +3214,7 @@ fi
# Define the identity of the package.
PACKAGE='avocado'
VERSION='0.4.0'
VERSION='0.4.2'
cat >>confdefs.h <<_ACEOF
@ -10112,7 +10112,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by triAGENS AvocadoDB $as_me 0.4.0, which was
This file was extended by triAGENS AvocadoDB $as_me 0.4.2, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -10179,7 +10179,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
triAGENS AvocadoDB config.status 0.4.0
triAGENS AvocadoDB config.status 0.4.2
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"

View File

@ -6,7 +6,7 @@ dnl ============================================================================
dnl PREAMBLE triAGENS GmbH Build Environment
dnl ============================================================================
AC_INIT([triAGENS AvocadoDB], [0.4.0], [info@triagens.de], [avocado], [http://www.avocadodb.org])
AC_INIT([triAGENS AvocadoDB], [0.4.2], [info@triagens.de], [avocado], [http://www.avocadodb.org])
dnl ----------------------------------------------------------------------------
dnl auxillary directory for install-sh and missing

View File

@ -209,6 +209,9 @@ pre ul li span{
.ui-tabs-nav {
font-size: 0.8em !important;
height: 35px;
-webkit-box-shadow: inset 0 0 1px 1px #f6f6f6 !important;
-moz-box-shadow: inset 0 0 1px 1px #f6f6f6 !important;
box-shadow: inset 0 0 1px 1px #f6f6f6 !important;
//border-bottom: 0px !important;
}

View File

@ -136,6 +136,7 @@ else {
///////////////////////////////////////////////////////////////////////////////
var collectionTable = $('#collectionsTableID').dataTable({
"aaSorting": [[ 2, "desc" ]],
"bPaginate": false,
"bFilter": false,
"bLengthChange": false,
@ -152,7 +153,7 @@ var collectionTable = $('#collectionsTableID').dataTable({
///////////////////////////////////////////////////////////////////////////////
var documentEditTable = $('#documentEditTableID').dataTable({
"aaSorting": [],
"aaSorting": [[ 1, "desc" ]],
"bFilter": false,
"bPaginate":false,
"bSortable": false,
@ -2030,4 +2031,3 @@ function stateReplace (value) {
return output;
}

View File

@ -351,25 +351,29 @@ actions.defineHttp({
///
/// The call expects a JSON hash array as body with the following attributes:
///
/// @FA{collection}
/// - @LIT{collection}: The identifier or name of the collection to query.
///
/// The identifier or name of the collection to query.
/// - @LIT{example}: The example.
///
/// @FA{example}
/// - @LIT{skip}: The documents to skip in the query. (optional)
///
/// The example.
/// - @LIT{limit}: The maximal amount of documents to return. (optional)
///
/// @FA{skip} (optional)
///
/// The documents to skip in the query.
///
/// @FA{limit} (optional)
///
/// The maximal amount of documents to return.
/// Returns a cursor containing the result, see @ref HttpCursor for details.
///
/// @EXAMPLES
///
/// @verbinclude api_simple7
/// Matching an attribute:
///
/// @verbinclude api-simple-by-example1
///
/// Matching an attribute which is a sub-document:
///
/// @verbinclude api-simple-by-example2
///
/// Matching an attribute within a sub-document:
///
/// @verbinclude api-simple-by-example3
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -383,16 +387,18 @@ actions.defineHttp({
return;
}
if (req.requestType != actions.PUT) {
actions.unsupported(req, res);
}
else {
var limit = body.limit;
var skip = body.skip;
var name = body.collection;
var example = body.example;
if (req.requestType != actions.PUT) {
actions.unsupported(req, res);
}
else {
collection = internal.db._collection(name);
var name = body.collection;
var id = parseInt(name) || name;
var collection = internal.db._collection(id);
if (collection == null) {
actions.collectionNotFound(req, res, name);
@ -401,7 +407,8 @@ actions.defineHttp({
actions.badParameter(req, res, "example");
}
else {
var result = collection.byExample(example);
try {
var result = collection.byExample.apply(collection, example);
if (skip != null) {
result = result.skip(skip);
@ -411,7 +418,84 @@ actions.defineHttp({
result = result.limit(limit);
}
actions.resultOk(req, res, actions.HTTP_OK, result.toArray());
actions.resultCursor(req, res, CREATE_CURSOR(result.toArray(), true));
}
catch (err) {
actions.resultException(req, res, err);
}
}
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSA_PUT_api_simple_first_example
/// @brief returns one document of a collection matching a given example
///
/// @REST{PUT /_api/simple/first-example}
///
/// This will return the first document matching a given example.
///
/// The call expects a JSON hash array as body with the following attributes:
///
/// - @LIT{collection}: The identifier or name of the collection to query.
///
/// - @LIT{example}: The example.
///
/// - @LIT{skip}: The documents to skip in the query. (optional)
///
/// - @LIT{limit}: The maximal amount of documents to return. (optional)
///
/// Returns a result containing the document or @LIT{HTTP 404} if no
/// document matched the example.
///
/// @EXAMPLES
///
/// If a matching document was found:
///
/// @verbinclude api-simple-first-example
///
/// If no document was found:
///
/// @verbinclude api-simple-first-example-not-found
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url : API + "first-example",
context : "api",
callback : function (req, res) {
var body = actions.getJsonBody(req, res);
if (body === undefined) {
return;
}
if (req.requestType != actions.PUT) {
actions.unsupported(req, res);
}
else {
var example = body.example;
var name = body.collection;
var id = parseInt(name) || name;
var collection = internal.db._collection(id);
if (collection == null) {
actions.collectionNotFound(req, res, name);
}
else if (typeof example !== "object") {
actions.badParameter(req, res, "example");
}
else {
var result = collection.byExample.apply(collection, example).limit(1);
if (result.hasNext()) {
actions.resultOk(req, res, actions.HTTP_OK, { document : result.next() });
}
else {
actions.resultNotFound(req, res, "no match");
}
}
}
}

View File

@ -98,29 +98,28 @@ SQ.SimpleQueryByExample.prototype.execute = function () {
var documents;
if (this._execution == null) {
if (this._skip == null || this._skip <= 0) {
this._skip = 0;
var data = {
collection : this._collection._id,
example : this._example
}
var parameters = [ ];
// the actual example is passed in the first argument
for (var i in this._example[0]) {
if (this._example[0].hasOwnProperty(i)) {
// attribute name
parameters.push(i);
// attribute value
parameters.push(this._example[0][i]);
}
if (this._limit != null) {
data.limit = this._limit;
}
var documents = this._collection.BY_EXAMPLE.apply(this._collection, parameters);
if (this._skip != null) {
data.skip = this._skip;
}
this._execution = new SQ.GeneralArrayCursor(documents, this._skip, this._limit);
this._countQuery = documents.length;
this._countTotal = documents.length;
var requestResult = this._collection._database._connection.PUT("/_api/simple/by-example", JSON.stringify(data));
TRI_CheckRequestResult(requestResult);
this._execution = new AvocadoQueryCursor(this._collection._database, requestResult);
if (requestResult.hasOwnProperty("count")) {
this._countQuery = requestResult.count;
}
}
}
@ -128,6 +127,52 @@ SQ.SimpleQueryByExample.prototype.execute = function () {
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SimpleQuery
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a query-by-example for a collection
////////////////////////////////////////////////////////////////////////////////
AvocadoCollection.prototype.firstExample = function () {
// create a REAL array, otherwise JSON.stringify will fail
var example = [];
for (var i = 0; i < arguments.length; ++i) {
example.push(arguments[i]);
}
var data = {
collection : this._id,
example : example
}
var requestResult = this._database._connection.PUT("/_api/simple/first-example", JSON.stringify(data));
if (requestResult != null
&& requestResult.error == true
&& requestResult.errorNum == internal.errors.ERROR_HTTP_NOT_FOUND.code) {
return null;
}
TRI_CheckRequestResult(requestResult);
return requestResult.document;
}
AvocadoEdgesCollection.prototype.firstExample = AvocadoCollection.prototype.firstExample;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- SIMPLE QUERY NEAR
// -----------------------------------------------------------------------------

View File

@ -36,37 +36,6 @@ var DURATION = 0;
internal.loadFile("jsunity/jsunity");
jsUnity.log = console;
////////////////////////////////////////////////////////////////////////////////
/// @page jsUnity Using jsUnity and node-jscoverage
///
/// The AvocadoDB contains a wrapper for
/// <a href="http://jsunity.com/">jsUnity</a>, a lightyweight universal
/// JavAScript unit testing framework.
///
/// @section jsUnityRunningTest Running jsUnity Tests
///
/// Assume that you have a test file containing
///
/// @verbinclude jsunity1
///
/// Then you can run the test suite using @FN{jsunity.runTest}
///
/// @verbinclude jsunity2
///
/// @section jsUnityRunningCoverage Running jsUnity Tests with Coverage
///
/// You can use the coverage tool
/// <a href="https://github.com/visionmedia/node-jscoverage">@LIT{node-jscoverage}</a>.
///
/// Assume that your file live in a directory called @LIT{lib}. Use
///
/// @CODE{node-jscoverage lib lib-cov}
///
/// to create a copy of the JavaScript files with coverage information. Start
/// the AvocadoDB with these files and use @FN{jsunity.runCoverage} instead of
/// @FN{jsunity.runTest}.
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------

View File

@ -47,9 +47,9 @@ var AvocadoEdgesCollection = internal.AvocadoEdgesCollection;
///
/// @FUN{all()}
///
/// Selects all documents of a collection. You can use @FN{toArray}, @FN{next},
/// or @FN{hasNext} to access the result. The result can be limited using the
/// @FN{skip} and @FN{limit} operator.
/// Selects all documents of a collection and returns a cursor. You can use
/// @FN{toArray}, @FN{next}, or @FN{hasNext} to access the result. The result
/// can be limited using the @FN{skip} and @FN{limit} operator.
///
/// @EXAMPLES
///
@ -257,14 +257,20 @@ AvocadoEdgesCollection.prototype.geo = AvocadoCollection.geo;
///
/// @FUN{@FA{collection}.byExample(@FA{path1}, @FA{value1}, ...)}
///
/// Selects all documents of a collection that match the specified
/// example. The example must be specified as paths and values. Allowed
/// Selects all documents of a collection that match the specified example and
/// returns a cursor. The example must be specified as paths and values. Allowed
/// attribute types for searching are numbers, strings, and boolean values.
///
/// You can use @FN{toArray}, @FN{next}, or @FN{hasNext} to access
/// the result. The result can be limited using the @FN{skip} and @FN{limit}
/// operator.
///
/// @FUN{@FA{collection}.byExample(@FA{example})}
///
/// As alternative you can supply an example as single argument. Note that an
/// attribute name of the form @LIT{a.b} is interpreted as attribute path, not
/// as attribute.
///
/// @EXAMPLES
///
/// Use @FN{toArray} to get all documents at once:
@ -277,40 +283,19 @@ AvocadoEdgesCollection.prototype.geo = AvocadoCollection.geo;
////////////////////////////////////////////////////////////////////////////////
AvocadoCollection.prototype.byExample = function () {
return new SimpleQueryByExample(this, arguments);
// create a REAL array, otherwise JSON.stringify will fail
var example = [];
for (var i = 0; i < arguments.length; ++i) {
example.push(arguments[i]);
}
return new SimpleQueryByExample(this, example);
}
AvocadoEdgesCollection.prototype.byExample = AvocadoCollection.prototype.byExample;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a query-by-example for a collection
///
/// @FUN{@FA{collection}.firstExample(@FA{path1}, @FA{value1}, ...)}
///
/// Returns the first documents of a collection that match the specified example
/// or @LIT{null}. The example must be specified as paths and
/// values. Allowed attribute types for searching are numbers, strings, and
/// boolean values.
///
/// @EXAMPLES
////////////////////////////////////////////////////////////////////////////////
AvocadoCollection.prototype.firstExample = function () {
var cursor = new SimpleQueryByExample(this, arguments);
var result = null;
if (cursor.hasNext()) {
result = cursor.next();
}
cursor.dispose();
return result;
}
AvocadoEdgesCollection.prototype.firstExample = AvocadoCollection.prototype.firstExample;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -41,7 +41,7 @@ var SQB = require("simple-query-basics");
require("simple-query");
// -----------------------------------------------------------------------------
// --SECTION-- basic skips and limits
// --SECTION-- basic skips and limits for array
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
@ -176,14 +176,14 @@ function SimpleQueryArraySkipLimitSuite () {
}
// -----------------------------------------------------------------------------
// --SECTION-- basic skips and limits
// --SECTION-- basic skips and limits for all
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: skip and limit with a collection
////////////////////////////////////////////////////////////////////////////////
function SimpleQuerySkipLimitSuite () {
function SimpleQueryAllSkipLimitSuite () {
var cn = "UnitTestsCollectionSkipLimit";
var collection = null;
var numbers = null;
@ -218,7 +218,7 @@ function SimpleQuerySkipLimitSuite () {
/// @brief test: skip
////////////////////////////////////////////////////////////////////////////////
testSkip : function () {
testAllSkip : function () {
var n = collection.all().skip(0).toArray().map(num);
assertEqual(n, numbers);
@ -256,7 +256,7 @@ function SimpleQuerySkipLimitSuite () {
/// @brief test: limit
////////////////////////////////////////////////////////////////////////////////
testLimit : function () {
testAllLimit : function () {
var n = collection.all().limit(10).toArray().map(num);
assertEqual(n, numbers);
@ -290,7 +290,7 @@ function SimpleQuerySkipLimitSuite () {
/// @brief test: skip and limit
////////////////////////////////////////////////////////////////////////////////
testSkipLimit : function () {
testAllSkipLimit : function () {
var n = collection.all().skip(0).limit(10).toArray().map(num);
assertEqual(n, numbers);
@ -318,6 +318,112 @@ function SimpleQuerySkipLimitSuite () {
};
}
// -----------------------------------------------------------------------------
// --SECTION-- basic tests for byExample
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: skip and limit with a collection
////////////////////////////////////////////////////////////////////////////////
function SimpleQueryByExampleSuite () {
var cn = "UnitTestsCollectionByExample";
var collection = null;
var id = function(d) { return d._id; };
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
internal.db._drop(cn);
collection = internal.db._create(cn, { waitForSync : false });
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
collection.drop();
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test: byExample
////////////////////////////////////////////////////////////////////////////////
testByExampleObject : function () {
var d1 = collection.save({ i : 1 });
var d2 = collection.save({ i : 1, a : { j : 1 } });
var d3 = collection.save({ i : 1, a : { j : 1, k : 1 } });
var d4 = collection.save({ i : 1, a : { j : 2, k : 2 } });
var d5 = collection.save({ i : 2 });
var d6 = collection.save({ i : 2, a : 2 });
var d7 = collection.save({ i : 2, a : { j : 2, k : 2 } });
var s;
s = collection.byExample({ i : 1 }).toArray().map(id).sort();
assertEqual([d1._id, d2._id, d3._id, d4._id].sort(), s);
s = collection.byExample({ i : 2 }).toArray().map(id).sort();
assertEqual([d5._id, d6._id, d7._id].sort(), s);
s = collection.byExample({ a : { j : 1 } }).toArray().map(id).sort();
assertEqual([d2._id], s);
s = collection.byExample({ "a.j" : 1 }).toArray().map(id).sort();
assertEqual([d2._id, d3._id].sort(), s);
s = collection.byExample({ i : 2, "a.k" : 2 }).toArray().map(id).sort();
assertEqual([d7._id], s);
s = collection.firstExample({ "i" : 2, "a.k" : 2 });
assertEqual(d7._id, s._id);
s = collection.firstExample({ "i" : 2, "a.k" : 27 });
assertEqual(null, s);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test: byExample
////////////////////////////////////////////////////////////////////////////////
testByExampleList : function () {
var d1 = collection.save({ i : 1 });
var d2 = collection.save({ i : 1, a : { j : 1 } });
var d3 = collection.save({ i : 1, a : { j : 1, k : 1 } });
var d4 = collection.save({ i : 1, a : { j : 2, k : 2 } });
var d5 = collection.save({ i : 2 });
var d6 = collection.save({ i : 2, a : 2 });
var d7 = collection.save({ i : 2, a : { j : 2, k : 2 } });
var s;
s = collection.byExample("i", 1).toArray().map(id).sort();
assertEqual([d1._id, d2._id, d3._id, d4._id].sort(), s);
s = collection.byExample("i", 2).toArray().map(id).sort();
assertEqual([d5._id, d6._id, d7._id].sort(), s);
s = collection.byExample("a", { j : 1 }).toArray().map(id).sort();
assertEqual([d2._id], s);
s = collection.byExample("a.j", 1).toArray().map(id).sort();
assertEqual([d2._id, d3._id].sort(), s);
s = collection.byExample("i", 2, "a.k", 2).toArray().map(id).sort();
assertEqual([d7._id], s);
s = collection.firstExample("i", 2, "a.k", 2);
assertEqual(d7._id, s._id);
s = collection.firstExample("i", 2, "a.k", 27);
assertEqual(null, s);
}
};
}
// -----------------------------------------------------------------------------
// --SECTION-- main
// -----------------------------------------------------------------------------
@ -327,7 +433,8 @@ function SimpleQuerySkipLimitSuite () {
////////////////////////////////////////////////////////////////////////////////
jsunity.run(SimpleQueryArraySkipLimitSuite);
jsunity.run(SimpleQuerySkipLimitSuite);
jsunity.run(SimpleQueryAllSkipLimitSuite);
jsunity.run(SimpleQueryByExampleSuite);
return jsunity.done();

View File

@ -419,6 +419,11 @@ static string JS_server_server =
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief converts collection into an array\n"
"///\n"
"/// @FUN{@FA{collection}.toArray()}\n"
"///\n"
"/// Converts the collection into an array of documents. Never use this call\n"
"/// in a production environment.\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"AvocadoCollection.prototype.toArray = function() {\n"

View File

@ -90,9 +90,10 @@ SQ.SimpleQueryByExample.prototype.execute = function () {
this._skip = 0;
}
var parameters = [ ];
var parameters = [];
// the actual example is passed in the first argument
if (this._example.length == 1) {
for (var i in this._example[0]) {
if (this._example[0].hasOwnProperty(i)) {
@ -103,6 +104,12 @@ SQ.SimpleQueryByExample.prototype.execute = function () {
parameters.push(this._example[0][i]);
}
}
}
// the arguments are passed
else {
parameters = this._example;
}
var documents = this._collection.BY_EXAMPLE.apply(this._collection, parameters);
@ -116,6 +123,55 @@ SQ.SimpleQueryByExample.prototype.execute = function () {
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SimpleQuery
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a query-by-example for a collection
///
/// @FUN{@FA{collection}.firstExample(@FA{path1}, @FA{value1}, ...)}
///
/// Returns the first documents of a collection that match the specified example
/// or @LIT{null}. The example must be specified as paths and
/// values. Allowed attribute types for searching are numbers, strings, and
/// boolean values.
///
/// @FUN{@FA{collection}.firstExample(@FA{example})}
///
/// As alternative you can supply an example as single argument. Note that an
/// attribute name of the form @LIT{a.b} is interpreted as attribute path, not
/// as attribute.
///
/// @EXAMPLES
///
/// @verbinclude shell-simple-query-first-example
////////////////////////////////////////////////////////////////////////////////
AvocadoCollection.prototype.firstExample = function () {
var cursor = new SQ.SimpleQueryByExample(this, arguments);
var result = null;
if (cursor.hasNext()) {
result = cursor.next();
}
cursor.dispose();
return result;
}
AvocadoEdgesCollection.prototype.firstExample = AvocadoCollection.prototype.firstExample;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- SIMPLE QUERY NEAR
// -----------------------------------------------------------------------------

View File

@ -418,6 +418,11 @@ AvocadoEdgesCollection.STATUS_DELETED = 5;
////////////////////////////////////////////////////////////////////////////////
/// @brief converts collection into an array
///
/// @FUN{@FA{collection}.toArray()}
///
/// Converts the collection into an array of documents. Never use this call
/// in a production environment.
////////////////////////////////////////////////////////////////////////////////
AvocadoCollection.prototype.toArray = function() {