1
0
Fork 0

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

This commit is contained in:
Heiko Kernbach 2012-05-24 16:36:37 +02:00
commit ece2f2bdcc
16 changed files with 387 additions and 137 deletions

View File

@ -354,23 +354,22 @@ TRI_associative_pointer_t* TRI_InitialiseFunctionsAql (void) {
// a = array
// type check functions
REGISTER_FUNCTION("ISNULL", "IS_NULL", true, false, ".");
REGISTER_FUNCTION("ISBOOL", "IS_BOOL", true, false, ".");
REGISTER_FUNCTION("ISNUMBER", "IS_NUMBER", true, false, ".");
REGISTER_FUNCTION("ISSTRING", "IS_STRING", true, false, ".");
REGISTER_FUNCTION("ISLIST", "IS_LIST", true, false, ".");
REGISTER_FUNCTION("ISDOCUMENT", "IS_DOCUMENT", true, false, ".");
REGISTER_FUNCTION("IS_NULL", "IS_NULL", true, false, ".");
REGISTER_FUNCTION("IS_BOOL", "IS_BOOL", true, false, ".");
REGISTER_FUNCTION("IS_NUMBER", "IS_NUMBER", true, false, ".");
REGISTER_FUNCTION("IS_STRING", "IS_STRING", true, false, ".");
REGISTER_FUNCTION("IS_LIST", "IS_LIST", true, false, ".");
REGISTER_FUNCTION("IS_DOCUMENT", "IS_DOCUMENT", true, false, ".");
// cast functions
REGISTER_FUNCTION("TONUMBER", "CAST_NUMBER", true, false, ".");
REGISTER_FUNCTION("TOSTRING", "CAST_STRING", true, false, ".");
REGISTER_FUNCTION("TOBOOL", "CAST_BOOL", true, false, ".");
REGISTER_FUNCTION("TONULL", "CAST_NULL", true, false, ".");
REGISTER_FUNCTION("TO_NUMBER", "CAST_NUMBER", true, false, ".");
REGISTER_FUNCTION("TO_STRING", "CAST_STRING", true, false, ".");
REGISTER_FUNCTION("TO_BOOL", "CAST_BOOL", true, false, ".");
// string functions
REGISTER_FUNCTION("CONCAT", "STRING_CONCAT", true, false, "sz,sz|+");
REGISTER_FUNCTION("CONCATSEPARATOR", "STRING_CONCAT_SEPARATOR", true, false, "s,sz,sz|+");
REGISTER_FUNCTION("CHARLENGTH", "STRING_LENGTH", true, false, "s");
REGISTER_FUNCTION("CONCAT_SEPARATOR", "STRING_CONCAT_SEPARATOR", true, false, "s,sz,sz|+");
REGISTER_FUNCTION("CHAR_LENGTH", "STRING_LENGTH", true, false, "s");
REGISTER_FUNCTION("LOWER", "STRING_LOWER", true, false, "s");
REGISTER_FUNCTION("UPPER", "STRING_UPPER", true, false, "s");
REGISTER_FUNCTION("SUBSTRING", "STRING_SUBSTRING", true, false, "s,n|n");
@ -408,6 +407,7 @@ TRI_associative_pointer_t* TRI_InitialiseFunctionsAql (void) {
REGISTER_FUNCTION("FAIL", "FAIL", false, false, "|s"); // FAIL is non-deterministic, otherwise query optimisation will fail!
REGISTER_FUNCTION("PASSTHRU", "PASSTHRU", false, false, "."); // simple non-deterministic wrapper to avoid optimisations at parse time
REGISTER_FUNCTION("COLLECTIONS", "COLLECTIONS", false, false, "");
REGISTER_FUNCTION("NOT_NULL", "NOT_NULL", true, false, ".,.");
if (!result) {
TRI_FreeFunctionsAql(functions);

View File

@ -122,6 +122,10 @@ static void PatchForLoops (TRI_aql_context_t* const context) {
continue;
}
if (!scope->_ranges) {
continue;
}
// we found a for loop, inspect it
prefix = TRI_Concatenate2String(scope->_variableName, ".");
@ -130,7 +134,7 @@ static void PatchForLoops (TRI_aql_context_t* const context) {
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return;
}
// iterate over all possible field accesses we found in this scope
len = scope->_ranges->_length;
for (j = 0; j < len; ++j) {

View File

@ -0,0 +1,42 @@
/* return 5 documents from a users collection, unaltered */
FOR u IN users
LIMIT 0, 5
RETURN u
[ { "_id" : "9259836/10505020", "_rev" : 10505020, "active" : true, "id" : 100, "age" : 37, "name" : "John", "gender" : "m" },
{ "_id" : "9259836/11553596", "_rev" : 11553596, "active" : true, "id" : 107, "age" : 30, "gender" : "m", "name" : "Anthony" },
{ "_id" : "9259836/11094844", "_rev" : 11094844, "active" : true, "id" : 101, "age" : 36, "name" : "Fred", "gender" : "m" },
{ "_id" : "9259836/11619132", "_rev" : 11619132, "active" : true, "id" : 108, "age" : 29, "name" : "Jim", "gender" : "m" },
{ "_id" : "9259836/11160380", "_rev" : 11160380, "active" : false, "id" : 102, "age" : 35, "name" : "Jacob", "gender" : "m" } ]
/* return a projection from a users collection */
FOR u IN users
LIMIT 0, 5
RETURN { "user" : { "isActive": u.active ? "yes" : "no", "name" : u.name } }
[ { "user" : { "isActive" : "yes", "name" : "John" } },
{ "user" : { "isActive" : "yes", "name" : "Anthony" } },
{ "user" : { "isActive" : "yes", "name" : "Fred" } },
{ "user" : { "isActive" : "yes", "name" : "Jim" } },
{ "user" : { "isActive" : "no", "name" : "Jacob" } } ]
/* return a filtered projection from a users collection */
FOR u IN users
FILTER u.active == true && u.age >= 30
SORT u.age DESC
RETURN { "age" : u.age, "name" : u.name }
[ { "age" : 37, "name" : "John" },
{ "age" : 37, "name" : "Sophia" },
{ "age" : 36, "name" : "Fred" },
{ "age" : 36, "name" : "Emma" },
{ "age" : 34, "name" : "Madison" },
{ "age" : 33, "name" : "Michael" },
{ "age" : 33, "name" : "Chloe" },
{ "age" : 32, "name" : "Alexander" },
{ "age" : 31, "name" : "Daniel" },
{ "age" : 31, "name" : "Abigail" },
{ "age" : 30, "name" : "Anthony" },
{ "age" : 30, "name" : "Isabella" } ]

View File

@ -0,0 +1,45 @@
/* group users by age */
FOR u IN users
FILTER u.active == true
COLLECT age = u.age INTO group
SORT age DESC
RETURN { "age" : age, "users" : group }
[ { "age" : 37, "users" : ["Sophia", "John"] },
{ "age" : 36, "users" : ["Emma", "Fred"] },
{ "age" : 34, "users" : ["Madison"] },
{ "age" : 33, "users" : ["Chloe", "Michael"] },
{ "age" : 32, "users" : ["Alexander"] },
{ "age" : 31, "users" : ["Abigail", "Daniel"] },
{ "age" : 30, "users" : ["Isabella", "Anthony"] },
{ "age" : 29, "users" : ["Mary", "Jim"] },
{ "age" : 28, "users" : ["Mariah", "Diego"] } ]
/* group users by agegroup and gender */
FOR u IN users
FILTER u.active == true
COLLECT ageGroup = FLOOR(u.age/5) * 5, gender = u.gender INTO group
SORT ageGroup DESC
RETURN { "ageGroup" : ageGroup, "gender" : gender, "numUsers" : LENGTH(group) }
[ { "ageGroup" : 35, "gender" : "f", "numUsers" : 2 },
{ "ageGroup" : 35, "gender" : "m", "numUsers" : 2 },
{ "ageGroup" : 30, "gender" : "f", "numUsers" : 4 },
{ "ageGroup" : 30, "gender" : "m", "numUsers" : 4 },
{ "ageGroup" : 25, "gender" : "f", "numUsers" : 2 },
{ "ageGroup" : 25, "gender" : "m", "numUsers" : 2 } ]
/* get the 3 agegroups with most users */
FOR u IN users
FILTER u.active == true
COLLECT ageGroup = FLOOR(u.age/5) * 5 INTO group
FILTER LENGTH(group) > 2 /* group must contain at least 3 users */
SORT LENGTH(group) DESC
LIMIT 0, 3
RETURN { "ageGroup" : ageGroup, "numUsers" : LENGTH(group), "users" : group[*].u.name }
[ { "ageGroup" : 30, "numUsers" : 8, "users" : ["Alexander", "Isabella", "Michael", "Abigail", "Anthony", "Daniel", "Madison", "Chloe"] },
{ "ageGroup" : 25, "numUsers" : 4, "users" : ["Mariah", "Mary", "Jim", "Diego"] },
{ "ageGroup" : 35, "numUsers" : 4, "users" : ["Emma", "Sophia", "Fred", "John"] } ]

View File

@ -0,0 +1,49 @@
/* getting the names of friends (also users) for users. this is achieved by "joining" a relations table */
FOR u IN users
FILTER u.active == true
LET friends = (FOR f IN userRelations
FILTER f.from == u.id
FOR u2 IN users
FILTER f.to == u2.id
RETURN u2.name
)
RETURN { "user" : u.name, "friends" : friends }
[ { "user" : "John", "friends" : ["Diego", "Mary", "Abigail"] },
{ "user" : "Anthony", "friends" : ["Madison"] },
{ "user" : "Fred", "friends" : ["Mariah"] },
{ "user" : "Jim", "friends" : ["Mariah"] },
{ "user" : "Diego", "friends" : ["Mary"] },
{ "user" : "Sophia", "friends" : ["Madison", "John"] },
{ "user" : "Michael", "friends" : ["John", "Jim"] },
{ "user" : "Emma", "friends" : ["Jacob", "Madison"] },
{ "user" : "Alexander", "friends" : ["Michael", "John"] },
{ "user" : "Daniel", "friends" : ["Eva"] },
{ "user" : "Madison", "friends" : ["Anthony", "Daniel"] },
{ "user" : "Chloe", "friends" : ["Alexander"] },
{ "user" : "Abigail", "friends" : ["Daniel", "John", "Jacob", "Jim"] },
{ "user" : "Isabella", "friends" : ["Madison", "Diego"] },
{ "user" : "Mary", "friends" : ["Isabella", "Diego", "Michael"] },
{ "user" : "Mariah", "friends" : ["Madison", "Ethan", "Eva"] } ]
/* getting users favorite song names from a joined "songs" collection */
FOR u IN users
LET likes = (
FOR s IN songs
FILTER s._id IN u.likes
RETURN CONCAT(s.artist, " - ", s.song)
)
SORT RAND()
LIMIT 0, 8
RETURN { "user" : u.name, "likes" : likes }
[ { "user" : "Eva", "likes" : ["Chocolate - Ritmo De La Noche", "4 The Cause - Stand By Me", "Tony Carey - Room with a view"] },
{ "user" : "Mary", "likes" : ["Hall and Oates - Maneater", "Elton John - Candle In The Wind", "A-Ha - Crying In The Rain", "Laid Back - Sunshine Reggae", "Cock Robin - The promise you made"] },
{ "user" : "Alexander", "likes" : ["Moby - Feel so real", "Rednex - Old pop in an oak", "2 Unlimited - No Limit"] },
{ "user" : "Michael", "likes" : ["The Kelly Family - David's Song"] },
{ "user" : "Ethan", "likes" : ["Technotronic - Megamix", "Gipsy Kings - Baila me", "Goombay Dance Band - Seven Tears", "Sandra - Hiroshima"] }, { "user" : "Isabella", "likes" : ["Milli Vanilli - Girl, I'm Gonna Miss You", "Technotronic - Get Up", "Right Said Fred - Don't Talk Just Kiss", "Peter Schilling - Major Tom (Völlig losgelöst)"] },
{ "user" : "Abigail", "likes" : ["Tina Turner - Typical male", "Liquido - Narcotic"] },
{ "user" : "Jim", "likes" : ["Berlin - Take my breath away", "Ashford & Simpson - Solid", "Fine Young Cannibals - She drives me cracy", "Cut'N'Move - Give it up", "Cyndi Lauper - Time after time"] },
{ "user" : "Jacob", "likes" : ["Kylie Minogue - The Loco-motion", "Eruption - Runaway"] } ]

View File

@ -0,0 +1,23 @@
/* a query that returns a string value. the result string is contained in a list because the result of every valid query is a list */
RETURN "this will be returned"
["this will be returned"]
/* a query that creates the cross products of two lists, and runs a projection on it */
FOR year in [ 2011, 2012, 2013 ]
FOR quarter IN [ 1, 2, 3, 4 ]
RETURN { "y" : "year", "q" : quarter, "nice" : CONCAT(TOSTRING(quarter), "/", TOSTRING(year)) }
[ { "y" : "year", "q" : 1, "nice" : "1/2011" },
{ "y" : "year", "q" : 2, "nice" : "2/2011" },
{ "y" : "year", "q" : 3, "nice" : "3/2011" },
{ "y" : "year", "q" : 4, "nice" : "4/2011" },
{ "y" : "year", "q" : 1, "nice" : "1/2012" },
{ "y" : "year", "q" : 2, "nice" : "2/2012" },
{ "y" : "year", "q" : 3, "nice" : "3/2012" },
{ "y" : "year", "q" : 4, "nice" : "4/2012" },
{ "y" : "year", "q" : 1, "nice" : "1/2013" },
{ "y" : "year", "q" : 2, "nice" : "2/2013" },
{ "y" : "year", "q" : 3, "nice" : "3/2013" },
{ "y" : "year", "q" : 4, "nice" : "4/2013" } ]

View File

@ -407,4 +407,5 @@ WIKI = \
UserManual \
UserManualBasics \
Aql \
AqlExamples \
jsUnity

View File

@ -0,0 +1,56 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief ArangoDB query language (AQL), examples
///
/// @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 Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @page AqlExamples ArangoDB Query Language (AQL) Examples
///
/// This page contains some examples for how to write queries in AQL. For better
/// understandability, the query results are also included.
///
/// @section AqlExamplesSimple Simple queries
///
/// @verbinclude aqlexample-simple
///
/// @section AqlExamplesCollection Collection-based queries
///
/// @verbinclude aqlexample-collection
///
/// @section AqlExamplesJoins Joins
///
/// @verbinclude aqlexample-join
///
/// @section AqlExamplesGrouping Grouping
///
/// @verbinclude aqlexample-grouping
///
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: c++
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @\\}\\)"
// End:

View File

@ -106,6 +106,8 @@
/// to issue read-requests on your database, but modifying data via AQL is
/// currently not supported.
///
/// For some example queries, please refer to the page @ref AqlExamples.
///
/// @section AqlQueryResults Query results
///
/// @subsection AqlQueryResultsSet Result sets
@ -695,25 +697,23 @@
/// This helps avoiding unexpected results. All type casts have to be performed
/// by invoking a type cast function. AQL offers several type cast functions for this
/// task. Each of the these functions takes an operand of any data type and returns a
/// result value of type corresponding to the function name (e.g. @LIT{TONUMBER()} will
/// result value of type corresponding to the function name (e.g. @LIT{TO_NUMBER()} will
/// return a number value):
///
/// - @FN{TONULL(@FA{value})}: converts the @FA{value} into a @LIT{null} value. This
/// function will always return @LIT{null}.
/// - @FN{TOBOOL(@FA{value})}: takes an input @FA{value} of any type and converts it
/// - @FN{TO_BOOL(@FA{value})}: takes an input @FA{value} of any type and converts it
/// into the appropriate boolean value as follows:
/// - @LIT{null} is converted to false.
/// - Numbers are converted to true if they are unequal to 0, and to false otherwise.
/// - Strings are converted to true if they are non-empty, and to false otherwise.
/// - Lists are converted to true if they are non-empty, and to false otherwise.
/// - Documents are converted to true if they are non-empty, and to false otherwise.
/// - @FN{TONUMBER(@FA{value})}: takes an input @FA{value} of any type and converts it
/// - @FN{TO_NUMBER(@FA{value})}: takes an input @FA{value} of any type and converts it
/// into a numeric value as follows:
/// - @LIT{null}, false, lists, and documents are converted to the value @LIT{0}.
/// - true is converted to @LIT{1}.
/// - Strings are converted to their numeric equivalent if the full string content is
/// is a valid number, and to @LIT{0} otherwise.
/// - @FN{TOSTRING(@FA{value})}: takes an input @FA{value} of any type and converts it
/// - @FN{TO_STRING(@FA{value})}: takes an input @FA{value} of any type and converts it
/// into a string value as follows:
/// - @LIT{null} is converted to the string @LIT{"null"}
/// - false is converted to the string @LIT{"false"}, true to the string @LIT{"true"}
@ -728,12 +728,12 @@
///
/// The following type check functions are available:
///
/// - @FN{ISNULL(@FA{value})}: checks whether @FA{value} is a @LIT{null} value
/// - @FN{ISBOOL(@FA{value})}: checks whether @FA{value} is a boolean value
/// - @FN{ISNUMBER(@FA{value})}: checks whether @FA{value} is a numeric value
/// - @FN{ISSTRING(@FA{value})}: checks whether @FA{value} is a string value
/// - @FN{ISLIST(@FA{value})}: checks whether @FA{value} is a list value
/// - @FN{ISDOCUMENT(@FA{value})}: checks whether @FA{value} is a document value
/// - @FN{IS_NULL(@FA{value})}: checks whether @FA{value} is a @LIT{null} value
/// - @FN{IS_BOOL(@FA{value})}: checks whether @FA{value} is a boolean value
/// - @FN{IS_NUMBER(@FA{value})}: checks whether @FA{value} is a numeric value
/// - @FN{IS_STRING(@FA{value})}: checks whether @FA{value} is a string value
/// - @FN{IS_LIST(@FA{value})}: checks whether @FA{value} is a list value
/// - @FN{IS_DOCUMENT(@FA{value})}: checks whether @FA{value} is a document value
///
/// @subsubsection AqlFunctionsString String functions
///
@ -741,10 +741,10 @@
///
/// - @FN{CONCAT(@FA{value1}\, @FA{value2}\, ... @FA{valuen})}: concatenate the strings
/// passed as in @FA{value1} to @FA{valuen}. @LIT{null} values are ignored.
/// - @FN{CONCATSEPARATOR(@FA{separator}\, @FA{value1}\, @FA{value2}\, ... @FA{valuen})}:
/// - @FN{CONCAT_SEPARATOR(@FA{separator}\, @FA{value1}\, @FA{value2}\, ... @FA{valuen})}:
/// concatenate the strings passed as arguments @FA{value1} to @FA{valuen} using the
/// @FA{separator} string. @LIT{null} values are ignored.
/// - @FN{CHARLENGTH(@FA{value})}: return the number of characters in @FA{value}
/// - @FN{CHAR_LENGTH(@FA{value})}: return the number of characters in @FA{value}
/// - @FN{LOWER(@FA{value})}: lower-case @FA{value}
/// - @FN{UPPER(@FA{value})}: upper-case @FA{value}
/// - @FN{SUBSTRING(@FA{value}\, @FA{offset}\, @FA{length})}: return a substring of @FA{value},
@ -756,33 +756,33 @@
/// AQL offers some numeric functions for calculations. The following functions are
/// supported:
///
/// - @LIT{FLOOR(@FA{value})}: returns the integer closest but not greater to @FA{value}
/// - @LIT{CEIL(@FA{value})}: returns the integer closest but not less than @FA{value}
/// - @LIT{ROUND(@FA{value})}: returns the integer closest to @FA{value}
/// - @LIT{ABS(@FA{value})}: returns the absolute part of @FA{value}
/// - @LIT{RAND()}: returns a random number between 0 and 1
/// - @FN{FLOOR(@FA{value})}: returns the integer closest but not greater to @FA{value}
/// - @FN{CEIL(@FA{value})}: returns the integer closest but not less than @FA{value}
/// - @FN{ROUND(@FA{value})}: returns the integer closest to @FA{value}
/// - @FN{ABS(@FA{value})}: returns the absolute part of @FA{value}
/// - @FN{RAND()}: returns a pseudo-random number between 0 and 1
///
/// @subsubsection AqlFunctionsList List functions
///
/// AQL supports the following functions to operate on list values:
///
/// - @LIT{LENGTH(@FA{list})}: returns the length (number of elements) of @FA{list}
/// - @LIT{MIN(@FA{list})}: returns the smallest element of @FA{list}. @LIT{null} values
/// - @FN{LENGTH(@FA{list})}: returns the length (number of elements) of @FA{list}
/// - @FN{MIN(@FA{list})}: returns the smallest element of @FA{list}. @LIT{null} values
/// are ignored. If the list is empty or only @LIT{null} are contained in the list, the
/// function will return @LIT{null}.
/// - @LIT{MAX(@FA{list})}: returns the greatest element of @FA{list}. @LIT{null} values
/// - @FN{MAX(@FA{list})}: returns the greatest element of @FA{list}. @LIT{null} values
/// are ignored. If the list is empty or only @LIT{null} are contained in the list, the
/// function will return @LIT{null}.
/// - @LIT{SUM(@FA{list})}: returns the sum of values of the elements in @FA{list}. This
/// - @FN{SUM(@FA{list})}: returns the sum of values of the elements in @FA{list}. This
/// requires the elements in @FA{list} to be numbers. @LIT{null} values are ignored.
/// If the list is empty or only @LIT{null} are contained in the list, the function
/// will return @LIT{null}.
/// - @LIT{REVERSE(@FA{list})}: returns the elements in @FA{list} in reversed order.
/// - @LIT{FIRST(@FA{list})}: returns the first element in @FA{list} or @LIT{null} if the
/// - @FN{REVERSE(@FA{list})}: returns the elements in @FA{list} in reversed order.
/// - @FN{FIRST(@FA{list})}: returns the first element in @FA{list} or @LIT{null} if the
/// list is empty.
/// - @LIT{LAST(@FA{list})}: returns the last element in @FA{list} or @LIT{null} if the
/// - @FN{LAST(@FA{list})}: returns the last element in @FA{list} or @LIT{null} if the
/// list is empty.
/// - @LIT{UNIQUE(@FA{list})}: returns all unique elements in @FA{list}. To determine
/// - @FN{UNIQUE(@FA{list})}: returns all unique elements in @FA{list}. To determine
/// uniqueness, the function will use the comparison order defined in @ref AqlTypeOrder.
/// Calling this function might return the unique elements in any order.
///
@ -793,18 +793,18 @@
///
/// AQL supports the following functions to operate on document values:
///
/// - @LIT{MERGE(@FA{document1}\, @FA{document2}\, ... @FA{documentn})}: merges the documents
/// - @FN{MERGE(@FA{document1}\, @FA{document2}\, ... @FA{documentn})}: merges the documents
/// in @FA{document1} to @FA{documentn} into a single document. If document attribute
/// keys are ambigious, the merged result will contain the values of the documents
/// contained later in the argument list.
/// - @LIT{HAS(@FA{document}\, @FA{attributename})}: returns true if @FA{document} has an
/// - @FN{HAS(@FA{document}\, @FA{attributename})}: returns true if @FA{document} has an
/// attribute named @FA{attributename}, and false otherwise.
///
/// @subsubsection AqlFunctionsGeo Geo functions
///
/// AQL offers the following functions to filter data based on geo indexes:
///
/// - @LIT{NEAR(@FA{collection}\, @FA{latitude}\, @FA{longitude}\, @FA{limit}\, @FA{distancename})}:
/// - @FN{NEAR(@FA{collection}\, @FA{latitude}\, @FA{longitude}\, @FA{limit}\, @FA{distancename})}:
/// returns at most @FA{limit} documents from collection @FA{collection} that are near
/// @FA{latitude} and @FA{longitude}. The result contains at @FA{limit} documents, returned in
/// any order. If more than @FA{limit} documents qualify, it is undefined which of the qualifying
@ -813,7 +813,7 @@
/// To make use of that, an attribute name for the distance result has to be specified in
/// the @FA{distancename} argument. The result documents will contain the distance value in
/// an attribute of that name.
/// - @LIT{WITHIN(@FA{collection}\, @FA{latitude}\, @FA{longitude}\, @FA{radius}\, @FA{distancename})}:
/// - @FN{WITHIN(@FA{collection}\, @FA{latitude}\, @FA{longitude}\, @FA{radius}\, @FA{distancename})}:
/// returns all documents from collection @FA{collection} that are within a radius of
/// @FA{radius} around that specified coordinate (@FA{latitude} and @FA{longitude}). The order
/// in which the result documents are returned is undefined. Optionally, the distance between the
@ -829,7 +829,7 @@
///
/// AQL has the following functions to traverse graphs:
///
/// - @LIT{PATHS(@FA{vertexcollection}\, @FA{edgecollection}\, @FA{direction}\, @FA{followcycles})}:
/// - @FN{PATHS(@FA{vertexcollection}\, @FA{edgecollection}\, @FA{direction}\, @FA{followcycles})}:
/// returns a list of paths through the graph defined by the nodes in the collection
/// @FA{vertexcollection} and edges in the collection @FA{edgecollection}. For each vertex
/// in @FA{vertexcollection}, it will determine the paths through the graph depending on the
@ -852,12 +852,19 @@
///
/// @verbinclude aqlpaths
///
/// @subsubsection AqlFunctionsControl Control flow functions
///
/// AQL offers the following functions to let the user control the flow of operations:
///
/// - @FN{NOT_NULL(@FA{condition}\, @FA{alternative})}: returns @FA{condition} if it is not
/// @LIT{null}, and @FA{alternative} otherwise.
///
/// @subsubsection AqlFunctionsMisc Miscellaneous functions
///
/// Finally, AQL supports the following functions that do not belong to any of the other
/// function categories:
///
/// - @LIT{COLLECTIONS()}: returns a list of collections. Each collection is returned as a document
/// - @FN{COLLECTIONS()}: returns a list of collections. Each collection is returned as a document
/// with attributes @LIT{name} and @LIT{_id}.
///
/// @section AqlOperations High-level operations

View File

@ -58,7 +58,7 @@
///
/// @EMBEDTOC{ImpManualBasicsTOC}
///
/// The most convenient method to import a lot of data into AvocadoDB is to use
/// The most convenient method to import a lot of data into ArangoDB is to use
/// the @LIT{arangoimp} command-line tool. It allows you to import data records
/// from a file into an existing database collection.
///
@ -114,7 +114,7 @@
/// @LIT{arangoimp --file "data.csv" --type csv --collection "users"}
///
/// Note that the quote and separator characters can be adjusted via the
/// @CA{--quote} and @CA{--separator} arguments when invoking avocimp.
/// @CA{--quote} and @CA{--separator} arguments when invoking arangoimp.
////////////////////////////////////////////////////////////////////////////////
// Local Variables:

View File

@ -1033,7 +1033,7 @@ static v8::Handle<v8::Value> ExecuteQueryCursorAhuacatl (TRI_vocbase_t* const vo
}
if (allowDirectReturn || !result->IsArray()) {
// rethrow
// return the value we got as it is. this is a performance optimisation
return scope.Close(result);
}

View File

@ -202,7 +202,7 @@ static void ParseProgramOptions (int argc, char* argv[]) {
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup avocimp
/// @addtogroup arangoimp
/// @{
////////////////////////////////////////////////////////////////////////////////

View File

@ -1001,13 +1001,10 @@ function AHUACATL_RELATIONAL_IN (lhs, rhs) {
if (rightWeight !== AHUACATL_TYPEWEIGHT_LIST) {
AHUACATL_THROW(internal.errors.ERROR_QUERY_LIST_EXPECTED);
}
var r = AHUACATL_KEYS(rhs, false);
var numRight = r.length;
var numRight = rhs.length;
for (var i = 0; i < numRight; ++i) {
var key = r[i];
if (AHUACATL_RELATIONAL_EQUAL(lhs, rhs[key])) {
if (AHUACATL_RELATIONAL_EQUAL(lhs, rhs[i])) {
return true;
}
}
@ -1309,16 +1306,6 @@ function AHUACATL_STRING_SUBSTRING (value, offset, count) {
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief cast to null
///
/// the operand can have any type, always returns null
////////////////////////////////////////////////////////////////////////////////
function AHUACATL_CAST_NULL (value) {
return null;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief cast to a bool
///
@ -2052,6 +2039,20 @@ function AHUACATL_GRAPH_SUBNODES (searchAttributes, vertexId, visited, edges, ve
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief return value if it's not null, otherwise return alternative
///
/// the operands can have any type
////////////////////////////////////////////////////////////////////////////////
function AHUACATL_NOT_NULL (value, alternative) {
if (AHUACATL_TYPEWEIGHT(value) === AHUACATL_TYPEWEIGHT_NULL) {
return alternative;
}
return value;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief check whether a document has an attribute
////////////////////////////////////////////////////////////////////////////////

View File

@ -1002,13 +1002,10 @@ static string JS_server_ahuacatl =
" if (rightWeight !== AHUACATL_TYPEWEIGHT_LIST) {\n"
" AHUACATL_THROW(internal.errors.ERROR_QUERY_LIST_EXPECTED);\n"
" }\n"
" \n"
" var r = AHUACATL_KEYS(rhs, false);\n"
" var numRight = r.length;\n"
"\n"
" var numRight = rhs.length;\n"
" for (var i = 0; i < numRight; ++i) {\n"
" var key = r[i];\n"
" if (AHUACATL_RELATIONAL_EQUAL(lhs, rhs[key])) {\n"
" if (AHUACATL_RELATIONAL_EQUAL(lhs, rhs[i])) {\n"
" return true;\n"
" }\n"
" }\n"
@ -1311,16 +1308,6 @@ static string JS_server_ahuacatl =
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief cast to null\n"
"///\n"
"/// the operand can have any type, always returns null\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"function AHUACATL_CAST_NULL (value) {\n"
" return null;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief cast to a bool\n"
"///\n"
"/// the operand can have any type, always returns a bool\n"
@ -2054,6 +2041,20 @@ static string JS_server_ahuacatl =
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief return value if it's not null, otherwise return alternative\n"
"///\n"
"/// the operands can have any type\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"function AHUACATL_NOT_NULL (value, alternative) {\n"
" if (AHUACATL_TYPEWEIGHT(value) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" return alternative;\n"
" }\n"
"\n"
" return value;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief check whether a document has an attribute\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"

View File

@ -411,7 +411,7 @@ function ahuacatlFunctionsTestSuite () {
testConcatSeparator1 : function () {
var expected = [ "the,Quick,Brown,Fox,Jumps" ];
var actual = getQueryResults("FOR r IN [ 1 ] return CONCATSEPARATOR(',', 'the', 'Quick', null, 'Brown', null, 'Fox', 'Jumps')", true);
var actual = getQueryResults("FOR r IN [ 1 ] return CONCAT_SEPARATOR(',', 'the', 'Quick', null, 'Brown', null, 'Fox', 'Jumps')", true);
assertEqual(expected, actual);
},
@ -421,7 +421,7 @@ function ahuacatlFunctionsTestSuite () {
testConcatSeparator2 : function () {
var expected = [ "the*/*/Quick*/*/Brown*/*/*/*/Fox*/*/Jumps" ];
var actual = getQueryResults("FOR r IN [ 1 ] return CONCATSEPARATOR('*/*/', 'the', 'Quick', null, 'Brown', '', 'Fox', 'Jumps')", true);
var actual = getQueryResults("FOR r IN [ 1 ] return CONCAT_SEPARATOR('*/*/', 'the', 'Quick', null, 'Brown', '', 'Fox', 'Jumps')", true);
assertEqual(expected, actual);
},
@ -430,22 +430,22 @@ function ahuacatlFunctionsTestSuite () {
////////////////////////////////////////////////////////////////////////////////
testConcatSeparatorInvalid : function () {
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR()"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(\"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(\"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(null, \"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(true, \"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(4, \"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR([ ], \"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR({ }, \"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(\"yes\", true, \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(\"yes\", 4, \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(\"yes\", [ ], \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(\"yes\", { }, \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(\"yes\", \"yes\", true)"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(\"yes\", \"yes\", 4)"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(\"yes\", \"yes\", [ ])"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCATSEPARATOR(\"yes\", \"yes\", { })"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR()"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(\"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(\"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(null, \"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(true, \"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(4, \"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR([ ], \"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR({ }, \"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(\"yes\", true, \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(\"yes\", 4, \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(\"yes\", [ ], \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(\"yes\", { }, \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(\"yes\", \"yes\", true)"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(\"yes\", \"yes\", 4)"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(\"yes\", \"yes\", [ ])"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CONCAT_SEPARATOR(\"yes\", \"yes\", { })"); } ));
},
////////////////////////////////////////////////////////////////////////////////
@ -454,7 +454,7 @@ function ahuacatlFunctionsTestSuite () {
testCharLength1 : function () {
var expected = [ 13 ];
var actual = getQueryResults("FOR r IN [ 1 ] return CHARLENGTH('the quick fox')", true);
var actual = getQueryResults("FOR r IN [ 1 ] return CHAR_LENGTH('the quick fox')", true);
assertEqual(expected, actual);
},
@ -464,7 +464,7 @@ function ahuacatlFunctionsTestSuite () {
testCharLength2 : function () {
var expected = [ 7 ];
var actual = getQueryResults("FOR r IN [ 1 ] return CHARLENGTH('äöüÄÖÜß')", true);
var actual = getQueryResults("FOR r IN [ 1 ] return CHAR_LENGTH('äöüÄÖÜß')", true);
assertEqual(expected, actual);
},
@ -474,7 +474,7 @@ function ahuacatlFunctionsTestSuite () {
testCharLength3 : function () {
var expected = [ 10 ];
var actual = getQueryResults("FOR r IN [ 1 ] return CHARLENGTH('アボカド名称について')", true);
var actual = getQueryResults("FOR r IN [ 1 ] return CHAR_LENGTH('アボカド名称について')", true);
assertEqual(expected, actual);
},
@ -483,13 +483,13 @@ function ahuacatlFunctionsTestSuite () {
////////////////////////////////////////////////////////////////////////////////
testCharLengthInvalid : function () {
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHARLENGTH()"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHARLENGTH(\"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHARLENGTH(null)"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHARLENGTH(true)"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHARLENGTH(3)"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHARLENGTH([ ])"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHARLENGTH({ })"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHAR_LENGTH()"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHAR_LENGTH(\"yes\", \"yes\")"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHAR_LENGTH(null)"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHAR_LENGTH(true)"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHAR_LENGTH(3)"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHAR_LENGTH([ ])"); } ));
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN CHAR_LENGTH({ })"); } ));
},
////////////////////////////////////////////////////////////////////////////////
@ -990,6 +990,56 @@ function ahuacatlFunctionsTestSuite () {
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { AHUACATL_RUN("RETURN HAS({ }, { })"); } ));
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test not_null
////////////////////////////////////////////////////////////////////////////////
testNotNull1 : function () {
var expected = [ 6 ];
var actual = getQueryResults("RETURN NOT_NULL(null, 2 + 4)", true);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test not_null
////////////////////////////////////////////////////////////////////////////////
testNotNull2 : function () {
var expected = [ 6 ];
var actual = getQueryResults("RETURN NOT_NULL(2 + 4, 2 + 5)", true);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test not_null
////////////////////////////////////////////////////////////////////////////////
testNotNull3 : function () {
var expected = [ null ];
var actual = getQueryResults("RETURN NOT_NULL(null, null)", true);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test not_null
////////////////////////////////////////////////////////////////////////////////
testNotNull4 : function () {
var expected = [ 2 ];
var actual = getQueryResults("RETURN NOT_NULL(2, null)", true);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test not_null
////////////////////////////////////////////////////////////////////////////////
testNotNull5 : function () {
var expected = [ false ];
var actual = getQueryResults("RETURN NOT_NULL(false, true)", true);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test non-existing functions
////////////////////////////////////////////////////////////////////////////////

View File

@ -349,35 +349,6 @@ function ahuacatlOperatorsTestSuite () {
assertFalse(AHUACATL_IS_DOCUMENT([ false ]));
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test AHUACATL_CAST_NULL function
////////////////////////////////////////////////////////////////////////////////
testCastNull : function () {
assertEqual(null, AHUACATL_CAST_NULL(undefined));
assertEqual(null, AHUACATL_CAST_NULL(null));
assertEqual(null, AHUACATL_CAST_NULL(1));
assertEqual(null, AHUACATL_CAST_NULL(2));
assertEqual(null, AHUACATL_CAST_NULL(-1));
assertEqual(null, AHUACATL_CAST_NULL(0));
assertEqual(null, AHUACATL_CAST_NULL(NaN));
assertEqual(null, AHUACATL_CAST_NULL(true));
assertEqual(null, AHUACATL_CAST_NULL(false));
assertEqual(null, AHUACATL_CAST_NULL(''));
assertEqual(null, AHUACATL_CAST_NULL(' '));
assertEqual(null, AHUACATL_CAST_NULL(' '));
assertEqual(null, AHUACATL_CAST_NULL('1'));
assertEqual(null, AHUACATL_CAST_NULL('0'));
assertEqual(null, AHUACATL_CAST_NULL('-1'));
assertEqual(null, AHUACATL_CAST_NULL([ ]));
assertEqual(null, AHUACATL_CAST_NULL([ 0 ] ));
assertEqual(null, AHUACATL_CAST_NULL([ 0, 1 ] ));
assertEqual(null, AHUACATL_CAST_NULL([ 1, 2 ] ));
assertEqual(null, AHUACATL_CAST_NULL({ } ));
assertEqual(null, AHUACATL_CAST_NULL({ 'a' : true }));
assertEqual(null, AHUACATL_CAST_NULL({ 'a' : true, 'b' : 0 }));
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test AHUACATL_CAST_BOOL function
////////////////////////////////////////////////////////////////////////////////