1
0
Fork 0

added AQL date functions

This commit is contained in:
Jan Steemann 2014-05-07 18:17:46 +02:00
parent 4f4c5388d5
commit 7d28a03782
11 changed files with 1284 additions and 0 deletions

View File

@ -1,6 +1,8 @@
v2.1.0 (XXXX-XX-XX)
-------------------
* added AQL date functions
* added index memory statistics to `db.<collection>.figures()` function
The `figures` function will now return a sub-document `indexes`, which lists

View File

@ -1046,6 +1046,117 @@ supported:
- @FN{RAND()}: Returns a pseudo-random number between 0 and 1
@subsubsection AqlFunctionsDate Date functions
AQL offers functionality to work with dates. Dates are no datatypes of their own in
AQL (neither they are in JSON, which is often used as a format to ship data into and
out of ArangoDB). Instead, dates in AQL are internally represented by either numbers
(timestamps) or strings. The date functions in AQL provide mechanisms to convert from
a numeric timestamp to a string representation and vice versa.
There are two date functions in AQL to create dates for further use:
- @FN{DATE_TIMESTAMP(@FA{date})}: Creates a UTC timestamp value from @FA{date}.
- @FN{DATE_TIMESTAMP(@FA{year}, @FA{month}, @FA{day}, @FA{hour}, @FA{minute}, @FA{second}, @FA{millisecond})}:
Same as before, but allows specifying the individual date components separately.
All parameters after @FA{day} are optional.
- @FN{DATE_ISO8601(@FA{date})}: Returns an ISO8601 datetime string from @FA{date}.
The datetime string will always use UTC time, indicated by the `Z` at its end.
- @FN{DATE_ISO8601(@FA{year}, @FA{month}, @FA{day}, @FA{hour}, @FA{minute}, @FA{second}, @FA{millisecond})}:
same as before, but allows specifying the individual date components separately.
All parameters after @FA{day} are optional.
These two above date functions accept the following input values:
- numeric timestamps, indicating the number of milliseconds elapsed since the UNIX
epoch (i.e. January 1st 1970 00:00:00 UTC).
An example timestamp value is `1399472349522`, which translates to
`2014-05-07T14:19:09.522Z`.
- datetime strings in formats @LIT{YYYY-MM-DDTHH:MM:SS.MMM},
@LIT{YYYY-MM-DD HH:MM:SS.MMM}, or @LIT{YYYY-MM-DD}. Milliseconds are always optional.
A timezone difference may optionally be added at the end of the string, e.g.:
`2014-05-07T14:19:09+01:00` for a one hour offset. Alternatively, a `Z` can be
specified at the end of the string to indicate UTC / Zulu time.
An example value is `2014-05-07T14:19:09.522Z` meaning May 7th 2014, 14:19:09 and
522 milliseconds, Zulu time. Another example value without time component is
`2014-05-07Z`.
- individual date components as separate function arguments, in the following order:
- year
- month
- day
- hour
- minute
- second
- millisecond
All components following `day` are optional and can be omitted.
Please note that if no timezone offset is specified in a datestring, ArangoDB will
assume UTC time automatically. This is done to ensure portability of queries across
servers with different timezone settings, and because timestamps will always be
UTC-based.
The following calls to `DATE_TIMESTAMP` are equivalent and will all return
`1399472349522`:
DATE_TIMESTAMP("2014-05-07T14:19:09.522")
DATE_TIMESTAMP("2014-05-07T14:19:09.522Z")
DATE_TIMESTAMP("2014-05-07 14:19:09.522")
DATE_TIMESTAMP("2014-05-07 14:19:09.522Z")
DATE_TIMESTAMP(2014, 5, 7, 14, 19, 9, 522)
DATE_TIMESTAMP(1399472349522)
The same is true for calls to `DATE_ISO8601` that also accepts variable input
formats:
DATE_ISO8601("2014-05-07T14:19:09.522Z")
DATE_ISO8601("2014-05-07 14:19:09.522Z")
DATE_ISO8601(2014, 5, 7, 14, 19, 9, 522)
DATE_ISO8601(1399472349522)
The above functions are all equivalent and will return `"2014-05-07T14:19:09.522Z"`.
The following date functions can be used with dates created by `DATE_TIMESTAMP` and
`DATE_ISO8601`:
- @FN{DATE_DAYOFWEEK(@FA{date})}: Returns the weekday number of @FA{date}. The
return values have the following meanings:
- 0: Sunday
- 1: Monday
- 2: Tuesday
- 3: Wednesday
- 4: Thursday
- 5: Friday
- 6: Saturday
- @FN{DATE_YEAR(@FA{date})}: Returns the year part of @FA{date} as a number.
- @FN{DATE_MONTH(@FA{date})}: Returns the month part of @FA{date} as a number.
- @FN{DATE_DAY(@FA{date})}: Returns the day part of @FA{date} as a number.
- @FN{DATE_HOUR(@FA{date})}: Returns the hour part of @FA{date} as a number.
- @FN{DATE_MINUTE(@FA{date})}: Returns the minute part of @FA{date} as a number.
- @FN{DATE_SECOND(@FA{date})}: Returns the seconds part of @FA{date} as a number.
- @FN{DATE_MILLISECOND(@FA{date})}: Returns the milliseconds part of @FA{date} as a number.
The following other date functions are also available:
- @FN{DATE_NOW()}: Returns the current time as a timestamp.
Note that this function is evaluated on every invocation and may return different
values when invoked multiple times in the same query.
@subsubsection AqlFunctionsList List functions
AQL supports the following functions to operate on list values:

View File

@ -20,6 +20,7 @@ TOC {#AqlTOC}
- @ref AqlFunctionsChecking
- @ref AqlFunctionsString
- @ref AqlFunctionsNumeric
- @ref AqlFunctionsDate
- @ref AqlFunctionsList
- @ref AqlFunctionsDocument
- @ref AqlFunctionsGeo

View File

@ -708,6 +708,19 @@ TRI_associative_pointer_t* TRI_CreateFunctionsAql (void) {
REGISTER_FUNCTION("TRAVERSAL_TREE", "GRAPH_TRAVERSAL_TREE", false, false, "h,h,s,s,s|a", NULL);
REGISTER_FUNCTION("EDGES", "GRAPH_EDGES", false, false, "h,s,s|l", NULL);
REGISTER_FUNCTION("NEIGHBORS", "GRAPH_NEIGHBORS", false, false, "h,h,s,s|l", NULL);
// date functions
REGISTER_FUNCTION("DATE_NOW", "DATE_NOW", false, false, "", NULL); // NOW is non-deterministic
REGISTER_FUNCTION("DATE_TIMESTAMP", "DATE_TIMESTAMP", true, false, "ns|ns,ns,ns,ns,ns,ns", NULL);
REGISTER_FUNCTION("DATE_ISO8601", "DATE_ISO8601", true, false, "ns|ns,ns,ns,ns,ns,ns", NULL);
REGISTER_FUNCTION("DATE_DAYOFWEEK", "DATE_DAYOFWEEK", true, false, "ns", NULL);
REGISTER_FUNCTION("DATE_YEAR", "DATE_YEAR", true, false, "ns", NULL);
REGISTER_FUNCTION("DATE_MONTH", "DATE_MONTH", true, false, "ns", NULL);
REGISTER_FUNCTION("DATE_DAY", "DATE_DAY", true, false, "ns", NULL);
REGISTER_FUNCTION("DATE_HOUR", "DATE_HOUR", true, false, "ns", NULL);
REGISTER_FUNCTION("DATE_MINUTE", "DATE_MINUTE", true, false, "ns", NULL);
REGISTER_FUNCTION("DATE_SECOND", "DATE_SECOND", true, false, "ns", NULL);
REGISTER_FUNCTION("DATE_MILLISECOND", "DATE_MILLISECOND", true, false, "ns", NULL);
// misc functions
REGISTER_FUNCTION("FAIL", "FAIL", false, false, "|s", NULL); // FAIL is non-deterministic, otherwise query optimisation will fail!

View File

@ -162,6 +162,7 @@
"ERROR_QUERY_FAIL_CALLED" : { "code" : 1569, "message" : "FAIL(%s) called" },
"ERROR_QUERY_GEO_INDEX_MISSING" : { "code" : 1570, "message" : "no suitable geo index found for geo restriction on '%s'" },
"ERROR_QUERY_FULLTEXT_INDEX_MISSING" : { "code" : 1571, "message" : "no suitable fulltext index found for fulltext query on '%s'" },
"ERROR_QUERY_INVALID_DATE_VALUE" : { "code" : 1572, "message" : "invalid date value" },
"ERROR_QUERY_FUNCTION_INVALID_NAME" : { "code" : 1580, "message" : "invalid user function name" },
"ERROR_QUERY_FUNCTION_INVALID_CODE" : { "code" : 1581, "message" : "invalid user function code" },
"ERROR_QUERY_FUNCTION_NOT_FOUND" : { "code" : 1582, "message" : "user function '%s()' not found" },

View File

@ -162,6 +162,7 @@
"ERROR_QUERY_FAIL_CALLED" : { "code" : 1569, "message" : "FAIL(%s) called" },
"ERROR_QUERY_GEO_INDEX_MISSING" : { "code" : 1570, "message" : "no suitable geo index found for geo restriction on '%s'" },
"ERROR_QUERY_FULLTEXT_INDEX_MISSING" : { "code" : 1571, "message" : "no suitable fulltext index found for fulltext query on '%s'" },
"ERROR_QUERY_INVALID_DATE_VALUE" : { "code" : 1572, "message" : "invalid date value" },
"ERROR_QUERY_FUNCTION_INVALID_NAME" : { "code" : 1580, "message" : "invalid user function name" },
"ERROR_QUERY_FUNCTION_INVALID_CODE" : { "code" : 1581, "message" : "invalid user function code" },
"ERROR_QUERY_FUNCTION_NOT_FOUND" : { "code" : 1582, "message" : "user function '%s()' not found" },

View File

@ -3724,6 +3724,238 @@ function FAIL (message) {
THROW(INTERNAL.errors.ERROR_QUERY_FAIL_CALLED, "");
}
// -----------------------------------------------------------------------------
// --SECTION-- date functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief helper function for date creation
////////////////////////////////////////////////////////////////////////////////
function MAKE_DATE (args, func) {
"use strict";
var weight;
var i, n = args.length;
if (n === 1) {
// called with one argument only
weight = TYPEWEIGHT(args[0]);
if (weight !== TYPEWEIGHT_NUMBER) {
if (weight !== TYPEWEIGHT_STRING) {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, func);
}
// argument is a string
// append zulu time specifier if no other present
if (! args[0].match(/([zZ]|[+\-]\d+(:\d+)?)$/) ||
(args[0].match(/-\d+(:\d+)?$/) && ! args[0].match(/[tT ]/))) {
args[0] += 'Z';
}
}
return new Date(args[0]);
}
// called with more than one argument
if (n < 3) {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, func);
}
for (i = 0; i < n; ++i) {
weight = TYPEWEIGHT(args[i]);
if (weight === TYPEWEIGHT_NULL) {
args[i] = 0;
}
else {
if (weight === TYPEWEIGHT_STRING) {
args[i] = parseInt(args[i], 10);
}
else if (weight !== TYPEWEIGHT_NUMBER) {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, func);
}
if (args[i] < 0) {
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_DATE_VALUE, func);
}
if (i === 1) {
// an exception for handling months: months are 0-based in JavaScript,
// but 1-based in AQL
args[i]--;
}
}
}
return new Date(Date.UTC.apply(null, args));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the number of milliseconds since the Unix epoch
///
/// this function is evaluated on every call
////////////////////////////////////////////////////////////////////////////////
function DATE_NOW () {
"use strict";
return Date.now();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the timestamp of the date passed (in milliseconds)
////////////////////////////////////////////////////////////////////////////////
function DATE_TIMESTAMP () {
"use strict";
try {
return MAKE_DATE(arguments, "DATE_TIMESTAMP").getTime();
}
catch (err) {
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_DATE_VALUE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the ISO string representation of the date passed
////////////////////////////////////////////////////////////////////////////////
function DATE_ISO8601 () {
"use strict";
try {
return MAKE_DATE(arguments, "DATE_ISO8601").toISOString();
}
catch (err) {
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_DATE_VALUE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the weekday of the date passed (0 = Sunday, 1 = Monday etc.)
////////////////////////////////////////////////////////////////////////////////
function DATE_DAYOFWEEK (value) {
"use strict";
try {
return MAKE_DATE([ value ], "DATE_DAYOFWEEK").getUTCDay();
}
catch (err) {
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_DATE_VALUE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the year of the date passed
////////////////////////////////////////////////////////////////////////////////
function DATE_YEAR (value) {
"use strict";
try {
return MAKE_DATE([ value ], "DATE_YEAR").getUTCFullYear();
}
catch (err) {
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_DATE_VALUE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the month of the date passed
////////////////////////////////////////////////////////////////////////////////
function DATE_MONTH (value) {
"use strict";
try {
return MAKE_DATE([ value ], "DATE_MONTH").getUTCMonth() + 1;
}
catch (err) {
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_DATE_VALUE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the day of the date passed
////////////////////////////////////////////////////////////////////////////////
function DATE_DAY (value) {
"use strict";
try {
return MAKE_DATE([ value ], "DATE_DAY").getUTCDate();
}
catch (err) {
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_DATE_VALUE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the hours of the date passed
////////////////////////////////////////////////////////////////////////////////
function DATE_HOUR (value) {
"use strict";
try {
return MAKE_DATE([ value ], "DATE_HOUR").getUTCHours();
}
catch (err) {
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_DATE_VALUE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the minutes of the date passed
////////////////////////////////////////////////////////////////////////////////
function DATE_MINUTE (value) {
"use strict";
try {
return MAKE_DATE([ value ], "DATE_MINUTE").getUTCMinutes();
}
catch (err) {
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_DATE_VALUE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the seconds of the date passed
////////////////////////////////////////////////////////////////////////////////
function DATE_SECOND (value) {
"use strict";
try {
return MAKE_DATE([ value ], "DATE_SECOND").getUTCSeconds();
}
catch (err) {
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_DATE_VALUE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the milliseconds of the date passed
////////////////////////////////////////////////////////////////////////////////
function DATE_MILLISECOND (value) {
"use strict";
try {
return MAKE_DATE([ value ], "DATE_MILLISECOND").getUTCMilliseconds();
}
catch (err) {
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_DATE_VALUE);
}
}
// -----------------------------------------------------------------------------
// --SECTION-- graph functions
// -----------------------------------------------------------------------------
@ -4414,6 +4646,17 @@ exports.SLEEP = SLEEP;
exports.CURRENT_DATABASE = CURRENT_DATABASE;
exports.CURRENT_USER = CURRENT_USER;
exports.FAIL = FAIL;
exports.DATE_NOW = DATE_NOW;
exports.DATE_TIMESTAMP = DATE_TIMESTAMP;
exports.DATE_ISO8601 = DATE_ISO8601;
exports.DATE_DAYOFWEEK = DATE_DAYOFWEEK;
exports.DATE_YEAR = DATE_YEAR;
exports.DATE_MONTH = DATE_MONTH;
exports.DATE_DAY = DATE_DAY;
exports.DATE_HOUR = DATE_HOUR;
exports.DATE_MINUTE = DATE_MINUTE;
exports.DATE_SECOND = DATE_SECOND;
exports.DATE_MILLISECOND = DATE_MILLISECOND;
exports.reload = reloadUserFunctions;

View File

@ -3788,6 +3788,904 @@ function ahuacatlFunctionsTestSuite () {
assertTrue(diff >= 1.5 && diff <= 2.5);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_now function
////////////////////////////////////////////////////////////////////////////////
testDateNowInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_NOW(1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_NOW(1, 1)");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_now function
////////////////////////////////////////////////////////////////////////////////
testDateNow : function () {
var time = require("internal").time() * 1000;
var actual = getQueryResults("RETURN DATE_NOW()")[0];
// allow for some small tolerance
assertTrue(Math.abs(time - actual) <= 1500);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_dayofweek function
////////////////////////////////////////////////////////////////////////////////
testDateDayOfWeekInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_DAYOFWEEK()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_DAYOFWEEK(1, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_DAYOFWEEK(null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_DAYOFWEEK(false)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_DAYOFWEEK([])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_DAYOFWEEK({})");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_dayofweek function
////////////////////////////////////////////////////////////////////////////////
testDateDayOfWeek : function () {
var values = [
[ "2000-04-29", 6 ],
[ "2000-04-29Z", 6 ],
[ "2012-02-12 13:24:12", 0 ],
[ "2012-02-12 13:24:12Z", 0 ],
[ "2012-02-12 23:59:59.991", 0 ],
[ "2012-02-12 23:59:59.991Z", 0 ],
[ "2012-02-12", 0 ],
[ "2012-02-12Z", 0 ],
[ "2012-02-12T13:24:12Z", 0 ],
[ "2012-02-12Z", 0 ],
[ "2012-2-12Z", 0 ],
[ "1910-01-02T03:04:05Z", 0 ],
[ "1910-01-02 03:04:05Z", 0 ],
[ "1910-01-02", 0 ],
[ "1910-01-02Z", 0 ],
[ "1970-01-01T01:05:27", 4 ],
[ "1970-01-01T01:05:27Z", 4 ],
[ "1970-01-01 01:05:27Z", 4 ],
[ "1970-1-1Z", 4 ],
[ "1221-02-28T23:59:59Z", 0 ],
[ "1221-02-28 23:59:59Z", 0 ],
[ "1221-02-28Z", 0 ],
[ "1221-2-28Z", 0 ],
[ "1000-12-24T04:12:00Z", 3 ],
[ "1000-12-24Z", 3 ],
[ "1000-12-24 04:12:00Z", 3 ],
[ "6789-12-31T23:59:58.99Z", 0 ],
[ "6789-12-31Z", 0 ],
[ "9999-12-31T23:59:59.999Z", 5 ],
[ "9999-12-31Z", 5 ],
[ "9999-12-31z", 5 ],
[ "9999-12-31", 5 ],
[ "2012Z", 0 ],
[ "2012z", 0 ],
[ "2012", 0 ],
[ "2012-1Z", 0 ],
[ "2012-1z", 0 ],
[ "2012-1-1z", 0 ],
[ "2012-01-01Z", 0 ],
[ "2012-01-01Z", 0 ],
[ " 2012-01-01Z", 0 ],
[ " 2012-01-01z", 0 ],
[ 1399395674000, 2 ],
[ 60123, 4 ],
[ 1, 4 ],
[ 0, 4 ]
];
values.forEach(function (value) {
var actual = getQueryResults("RETURN DATE_DAYOFWEEK(@value)", { value: value[0] });
assertEqual([ value[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_year function
////////////////////////////////////////////////////////////////////////////////
testDateDayOfWeekInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_YEAR()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_YEAR(1, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_YEAR(null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_YEAR(false)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_YEAR([])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_YEAR({})");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_year function
////////////////////////////////////////////////////////////////////////////////
testDateYear : function () {
var values = [
[ "2000-04-29Z", 2000 ],
[ "2012-02-12 13:24:12Z", 2012 ],
[ "2012-02-12 23:59:59.991Z", 2012 ],
[ "2012-02-12Z", 2012 ],
[ "2012-02-12T13:24:12Z", 2012 ],
[ "2012-02-12Z", 2012 ],
[ "2012-2-12Z", 2012 ],
[ "1910-01-02T03:04:05Z", 1910 ],
[ "1910-01-02 03:04:05Z", 1910 ],
[ "1910-01-02Z", 1910 ],
[ "1970-01-01T01:05:27Z", 1970 ],
[ "1970-01-01 01:05:27Z", 1970 ],
[ "1970-1-1Z", 1970 ],
[ "1221-02-28T23:59:59Z", 1221 ],
[ "1221-02-28 23:59:59Z", 1221 ],
[ "1221-02-28Z", 1221 ],
[ "1221-2-28Z", 1221 ],
[ "1000-12-24T04:12:00Z", 1000 ],
[ "1000-12-24Z", 1000 ],
[ "1000-12-24 04:12:00Z", 1000 ],
[ "6789-12-31T23:59:58.99Z", 6789 ],
[ "6789-12-31Z", 6789 ],
[ "9999-12-31T23:59:59.999Z", 9999 ],
[ "9999-12-31Z", 9999 ],
[ "9999-12-31z", 9999 ],
[ "9999-12-31", 9999 ],
[ "2012Z", 2012 ],
[ "2012z", 2012 ],
[ "2012", 2012 ],
[ "2012-1Z", 2012 ],
[ "2012-1z", 2012 ],
[ "2012-1-1z", 2012 ],
[ "2012-01-01Z", 2012 ],
[ "2012-01-01Z", 2012 ],
[ " 2012-01-01Z", 2012 ],
[ " 2012-01-01z", 2012 ],
[ 1399395674000, 2014 ],
[ 60123, 1970 ],
[ 1, 1970 ],
[ 0, 1970 ]
];
values.forEach(function (value) {
var actual = getQueryResults("RETURN DATE_YEAR(@value)", { value: value[0] });
assertEqual([ value[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_month function
////////////////////////////////////////////////////////////////////////////////
testDateMonthInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_MONTH()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_MONTH(1, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MONTH(null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MONTH(false)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MONTH([])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MONTH({})");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_month function
////////////////////////////////////////////////////////////////////////////////
testDateMonth : function () {
var values = [
[ "2000-04-29Z", 4 ],
[ "2012-02-12 13:24:12Z", 2 ],
[ "2012-02-12 23:59:59.991Z", 2 ],
[ "2012-02-12Z", 2 ],
[ "2012-02-12T13:24:12Z", 2 ],
[ "2012-02-12Z", 2 ],
[ "2012-2-12Z", 2 ],
[ "1910-01-02T03:04:05Z", 1 ],
[ "1910-01-02 03:04:05Z", 1 ],
[ "1910-01-02Z", 1 ],
[ "1970-01-01T01:05:27Z", 1 ],
[ "1970-01-01 01:05:27Z", 1 ],
[ "1970-1-1Z", 1 ],
[ "1221-02-28T23:59:59Z", 2 ],
[ "1221-02-28 23:59:59Z", 2 ],
[ "1221-02-28Z", 2 ],
[ "1221-2-28Z", 2 ],
[ "1000-12-24T04:12:00Z", 12 ],
[ "1000-12-24Z", 12 ],
[ "1000-12-24 04:12:00Z", 12 ],
[ "6789-12-31T23:59:58.99Z", 12 ],
[ "6789-12-31Z", 12 ],
[ "9999-12-31T23:59:59.999Z", 12 ],
[ "9999-12-31Z", 12 ],
[ "9999-12-31z", 12 ],
[ "9999-12-31", 12 ],
[ "2012Z", 1 ],
[ "2012z", 1 ],
[ "2012", 1 ],
[ "2012-2Z", 2 ],
[ "2012-1Z", 1 ],
[ "2012-1z", 1 ],
[ "2012-1-1z", 1 ],
[ "2012-01-01Z", 1 ],
[ "2012-01-01Z", 1 ],
[ " 2012-01-01Z", 1 ],
[ " 2012-01-01z", 1 ],
[ 1399395674000, 5 ],
[ 60123, 1 ],
[ 1, 1 ],
[ 0, 1 ]
];
values.forEach(function (value) {
var actual = getQueryResults("RETURN DATE_MONTH(@value)", { value: value[0] });
assertEqual([ value[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_day function
////////////////////////////////////////////////////////////////////////////////
testDateDayInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_DAY()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_DAY(1, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_DAY(null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_DAY(false)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_DAY([])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_DAY({})");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_day function
////////////////////////////////////////////////////////////////////////////////
testDateDay : function () {
var values = [
[ "2000-04-29Z", 29 ],
[ "2012-02-12 13:24:12Z", 12 ],
[ "2012-02-12 23:59:59.991Z", 12 ],
[ "2012-02-12Z", 12 ],
[ "2012-02-12T13:24:12Z", 12 ],
[ "2012-02-12Z", 12 ],
[ "2012-2-12Z", 12 ],
[ "1910-01-02T03:04:05Z", 2 ],
[ "1910-01-02 03:04:05Z", 2 ],
[ "1910-01-02Z", 2 ],
[ "1970-01-01T01:05:27Z", 1 ],
[ "1970-01-01 01:05:27Z", 1 ],
[ "1970-1-1Z", 1 ],
[ "1221-02-28T23:59:59Z", 28 ],
[ "1221-02-28 23:59:59Z", 28 ],
[ "1221-02-28Z", 28 ],
[ "1221-2-28Z", 28 ],
[ "1000-12-24T04:12:00Z", 24 ],
[ "1000-12-24Z", 24 ],
[ "1000-12-24 04:12:00Z", 24 ],
[ "6789-12-31T23:59:58.99Z", 31 ],
[ "6789-12-31Z", 31 ],
[ "9999-12-31T23:59:59.999Z", 31 ],
[ "9999-12-31Z", 31 ],
[ "9999-12-31z", 31 ],
[ "9999-12-31", 31 ],
[ "2012Z", 1 ],
[ "2012z", 1 ],
[ "2012", 1 ],
[ "2012-2Z", 1 ],
[ "2012-1Z", 1 ],
[ "2012-1z", 1 ],
[ "2012-1-1z", 1 ],
[ "2012-01-01Z", 1 ],
[ "2012-01-01Z", 1 ],
[ "2012-01-02Z", 2 ],
[ "2012-01-2Z", 2 ],
[ " 2012-01-01Z", 1 ],
[ " 2012-01-01z", 1 ],
[ 1399395674000, 6 ],
[ 60123, 1 ],
[ 1, 1 ],
[ 0, 1 ]
];
values.forEach(function (value) {
var actual = getQueryResults("RETURN DATE_DAY(@value)", { value: value[0] });
assertEqual([ value[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_hour function
////////////////////////////////////////////////////////////////////////////////
testDateHourInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_HOUR()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_HOUR(1, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_HOUR(null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_HOUR(false)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_HOUR([])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_HOUR({})");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_hour function
////////////////////////////////////////////////////////////////////////////////
testDateHour : function () {
var values = [
[ "2000-04-29", 0 ],
[ "2000-04-29Z", 0 ],
[ "2012-02-12 13:24:12", 13 ],
[ "2012-02-12 13:24:12Z", 13 ],
[ "2012-02-12 23:59:59.991Z", 23 ],
[ "2012-02-12", 0 ],
[ "2012-02-12Z", 0 ],
[ "2012-02-12T13:24:12", 13 ],
[ "2012-02-12T13:24:12Z", 13 ],
[ "2012-02-12", 0 ],
[ "2012-02-12Z", 0 ],
[ "2012-2-12Z", 0 ],
[ "1910-01-02T03:04:05", 3 ],
[ "1910-01-02T03:04:05Z", 3 ],
[ "1910-01-02 03:04:05Z", 3 ],
[ "1910-01-02Z", 0 ],
[ "1970-01-01T01:05:27Z", 1 ],
[ "1970-01-01 01:05:27Z", 1 ],
[ "1970-01-01T12:05:27Z", 12 ],
[ "1970-01-01 12:05:27Z", 12 ],
[ "1970-1-1Z", 0 ],
[ "1221-02-28T23:59:59Z", 23 ],
[ "1221-02-28 23:59:59Z", 23 ],
[ "1221-02-28Z", 0 ],
[ "1221-2-28Z", 0 ],
[ "1000-12-24T04:12:00Z", 4 ],
[ "1000-12-24Z", 0 ],
[ "1000-12-24 04:12:00Z", 4 ],
[ "6789-12-31T23:59:58.99Z", 23 ],
[ "6789-12-31Z", 0 ],
[ "9999-12-31T23:59:59.999Z", 23 ],
[ "9999-12-31Z", 0 ],
[ "9999-12-31z", 0 ],
[ "9999-12-31", 0 ],
[ "2012Z", 0 ],
[ "2012z", 0 ],
[ "2012", 0 ],
[ "2012-2Z", 0 ],
[ "2012-1Z", 0 ],
[ "2012-1z", 0 ],
[ "2012-1-1z", 0 ],
[ "2012-01-01Z", 0 ],
[ "2012-01-01Z", 0 ],
[ "2012-01-02Z", 0 ],
[ "2012-01-2Z", 0 ],
[ " 2012-01-01Z", 0 ],
[ " 2012-01-01z", 0 ],
[ 1399395674000, 17 ],
[ 3600000, 1 ],
[ 7200000, 2 ],
[ 8200000, 2 ],
[ 60123, 0 ],
[ 1, 0 ],
[ 0, 0 ]
];
values.forEach(function (value) {
var actual = getQueryResults("RETURN DATE_HOUR(@value)", { value: value[0] });
assertEqual([ value[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_minute function
////////////////////////////////////////////////////////////////////////////////
testDateMinuteInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_MINUTE()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_MINUTE(1, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MINUTE(null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MINUTE(false)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MINUTE([])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MINUTE({})");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_minute function
////////////////////////////////////////////////////////////////////////////////
testDateMinute : function () {
var values = [
[ "2000-04-29Z", 0 ],
[ "2012-02-12 13:24:12Z", 24 ],
[ "2012-02-12 23:59:59.991Z", 59 ],
[ "2012-02-12Z", 0 ],
[ "2012-02-12T13:24:12Z", 24 ],
[ "2012-02-12Z", 0 ],
[ "2012-2-12Z", 0 ],
[ "1910-01-02T03:04:05Z", 4 ],
[ "1910-01-02 03:04:05Z", 4 ],
[ "1910-01-02Z", 0 ],
[ "1970-01-01T01:05:27Z", 5 ],
[ "1970-01-01 01:05:27Z", 5 ],
[ "1970-01-01T12:05:27Z", 5 ],
[ "1970-01-01 12:05:27Z", 5 ],
[ "1970-1-1Z", 0 ],
[ "1221-02-28T23:59:59Z", 59 ],
[ "1221-02-28 23:59:59Z", 59 ],
[ "1221-02-28Z", 0 ],
[ "1221-2-28Z", 0 ],
[ "1000-12-24T04:12:00Z", 12 ],
[ "1000-12-24Z", 0 ],
[ "1000-12-24 04:12:00Z", 12 ],
[ "6789-12-31T23:59:58.99Z", 59 ],
[ "6789-12-31Z", 0 ],
[ "9999-12-31T23:59:59.999Z", 59 ],
[ "9999-12-31Z", 0 ],
[ "9999-12-31z", 0 ],
[ "9999-12-31", 0 ],
[ "2012Z", 0 ],
[ "2012z", 0 ],
[ "2012", 0 ],
[ "2012-2Z", 0 ],
[ "2012-1Z", 0 ],
[ "2012-1z", 0 ],
[ "2012-1-1z", 0 ],
[ "2012-01-01Z", 0 ],
[ "2012-01-01Z", 0 ],
[ "2012-01-02Z", 0 ],
[ "2012-01-2Z", 0 ],
[ " 2012-01-01Z", 0 ],
[ " 2012-01-01z", 0 ],
[ 1399395674000, 1 ],
[ 3600000, 0 ],
[ 7200000, 0 ],
[ 8200000, 16 ],
[ 60123, 1 ],
[ 1, 0 ],
[ 0, 0 ]
];
values.forEach(function (value) {
var actual = getQueryResults("RETURN DATE_MINUTE(@value)", { value: value[0] });
assertEqual([ value[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_second function
////////////////////////////////////////////////////////////////////////////////
testDateSecondInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_SECOND()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_SECOND(1, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_SECOND(null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_SECOND(false)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_SECOND([])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_SECOND({})");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_second function
////////////////////////////////////////////////////////////////////////////////
testDateSecond : function () {
var values = [
[ "2000-04-29Z", 0 ],
[ "2012-02-12 13:24:12Z", 12 ],
[ "2012-02-12 23:59:59.991Z", 59 ],
[ "2012-02-12Z", 0 ],
[ "2012-02-12T13:24:12Z", 12 ],
[ "2012-02-12Z", 0 ],
[ "2012-2-12Z", 0 ],
[ "1910-01-02T03:04:05Z", 5 ],
[ "1910-01-02 03:04:05Z", 5 ],
[ "1910-01-02Z", 0 ],
[ "1970-01-01T01:05:27Z", 27 ],
[ "1970-01-01 01:05:27Z", 27 ],
[ "1970-01-01T12:05:27Z", 27 ],
[ "1970-01-01 12:05:27Z", 27 ],
[ "1970-1-1Z", 0 ],
[ "1221-02-28T23:59:59Z", 59 ],
[ "1221-02-28 23:59:59Z", 59 ],
[ "1221-02-28Z", 0 ],
[ "1221-2-28Z", 0 ],
[ "1000-12-24T04:12:00Z", 0 ],
[ "1000-12-24Z", 0 ],
[ "1000-12-24 04:12:00Z", 0 ],
[ "6789-12-31T23:59:58.99Z", 58 ],
[ "6789-12-31Z", 0 ],
[ "9999-12-31T23:59:59.999Z", 59 ],
[ "9999-12-31Z", 0 ],
[ "9999-12-31z", 0 ],
[ "9999-12-31", 0 ],
[ "2012Z", 0 ],
[ "2012z", 0 ],
[ "2012", 0 ],
[ "2012-2Z", 0 ],
[ "2012-1Z", 0 ],
[ "2012-1z", 0 ],
[ "2012-1-1z", 0 ],
[ "2012-01-01Z", 0 ],
[ "2012-01-01Z", 0 ],
[ "2012-01-02Z", 0 ],
[ "2012-01-2Z", 0 ],
[ " 2012-01-01Z", 0 ],
[ " 2012-01-01z", 0 ],
[ 1399395674000, 14 ],
[ 3600000, 0 ],
[ 7200000, 0 ],
[ 8200000, 40 ],
[ 61123, 1 ],
[ 60123, 0 ],
[ 2001, 2 ],
[ 2000, 2 ],
[ 1000, 1 ],
[ 1, 0 ],
[ 0, 0 ]
];
values.forEach(function (value) {
var actual = getQueryResults("RETURN DATE_SECOND(@value)", { value: value[0] });
assertEqual([ value[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_millisecond function
////////////////////////////////////////////////////////////////////////////////
testDateMillisecondInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_MILLISECOND()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_MILLISECOND(1, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MILLISECOND(null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MILLISECOND(false)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MILLISECOND([])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_MILLISECOND({})");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_millisecond function
////////////////////////////////////////////////////////////////////////////////
testDateMillisecond : function () {
var values = [
[ "2000-04-29Z", 0 ],
[ "2012-02-12 13:24:12Z", 0 ],
[ "2012-02-12 23:59:59.991Z", 991 ],
[ "2012-02-12Z", 0 ],
[ "2012-02-12T13:24:12Z", 0 ],
[ "2012-02-12Z", 0 ],
[ "2012-2-12Z", 0 ],
[ "1910-01-02T03:04:05Z", 0 ],
[ "1910-01-02 03:04:05Z", 0 ],
[ "1910-01-02Z", 0 ],
[ "1970-01-01T01:05:27Z", 0 ],
[ "1970-01-01 01:05:27Z", 0 ],
[ "1970-01-01T12:05:27Z", 0 ],
[ "1970-01-01 12:05:27Z", 0 ],
[ "1970-1-1Z", 0 ],
[ "1221-02-28T23:59:59Z", 0 ],
[ "1221-02-28 23:59:59Z", 0 ],
[ "1221-02-28Z", 0 ],
[ "1221-2-28Z", 0 ],
[ "1000-12-24T04:12:00Z", 0 ],
[ "1000-12-24Z", 0 ],
[ "1000-12-24 04:12:00Z", 0 ],
[ "6789-12-31T23:59:58.99Z", 990 ],
[ "6789-12-31Z", 0 ],
[ "9999-12-31T23:59:59.999Z", 999 ],
[ "9999-12-31Z", 0 ],
[ "9999-12-31z", 0 ],
[ "9999-12-31", 0 ],
[ "2012Z", 0 ],
[ "2012z", 0 ],
[ "2012", 0 ],
[ "2012-2Z", 0 ],
[ "2012-1Z", 0 ],
[ "2012-1z", 0 ],
[ "2012-1-1z", 0 ],
[ "2012-01-01Z", 0 ],
[ "2012-01-01Z", 0 ],
[ "2012-01-02Z", 0 ],
[ "2012-01-2Z", 0 ],
[ " 2012-01-01Z", 0 ],
[ " 2012-01-01z", 0 ],
[ 1399395674000, 0 ],
[ 1399395674123, 123 ],
[ 3600000, 0 ],
[ 7200000, 0 ],
[ 8200000, 0 ],
[ 8200040, 40 ],
[ 61123, 123 ],
[ 60123, 123 ],
[ 2001, 1 ],
[ 2000, 0 ],
[ 1000, 0 ],
[ 753, 753 ],
[ 53, 53 ],
[ 1, 1 ],
[ 0, 0 ]
];
values.forEach(function (value) {
var actual = getQueryResults("RETURN DATE_MILLISECOND(@value)", { value: value[0] });
assertEqual([ value[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_timestamp function
////////////////////////////////////////////////////////////////////////////////
testDateTimestampInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_TIMESTAMP()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_TIMESTAMP(1, 1, 1, 1, 1, 1, 1, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_TIMESTAMP(null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_TIMESTAMP(1, null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_TIMESTAMP(false)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_TIMESTAMP([])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_TIMESTAMP({})");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_timestamp function
////////////////////////////////////////////////////////////////////////////////
testDateTimestamp : function () {
var values = [
[ "2000-04-29", 956966400000 ],
[ "2000-04-29Z", 956966400000 ],
[ "2012-02-12 13:24:12", 1329053052000 ],
[ "2012-02-12 13:24:12Z", 1329053052000 ],
[ "2012-02-12 23:59:59.991", 1329091199991 ],
[ "2012-02-12 23:59:59.991Z", 1329091199991 ],
[ "2012-02-12", 1329004800000 ],
[ "2012-02-12Z", 1329004800000 ],
[ "2012-02-12T13:24:12", 1329053052000 ],
[ "2012-02-12T13:24:12Z", 1329053052000 ],
[ "2012-02-12Z", 1329004800000 ],
[ "2012-2-12Z", 1329004800000 ],
[ "1910-01-02T03:04:05", -1893358555000 ],
[ "1910-01-02T03:04:05Z", -1893358555000 ],
[ "1910-01-02 03:04:05Z", -1893358555000 ],
[ "1910-01-02", -1893369600000 ],
[ "1910-01-02Z", -1893369600000 ],
[ "1970-01-01T01:05:27Z", 3927000 ],
[ "1970-01-01 01:05:27Z", 3927000 ],
[ "1970-01-01T12:05:27Z", 43527000 ],
[ "1970-01-01 12:05:27Z", 43527000 ],
[ "1970-1-1Z", 0 ],
[ "1221-02-28T23:59:59Z", -23631004801000 ],
[ "1221-02-28 23:59:59Z", -23631004801000 ],
[ "1221-02-28Z", -23631091200000 ],
[ "1221-2-28Z", -23631091200000 ],
[ "1000-12-24T04:12:00Z", -30579364080000 ],
[ "1000-12-24Z", -30579379200000 ],
[ "1000-12-24 04:12:00Z", -30579364080000 ],
[ "6789-12-31T23:59:58.99Z", 152104521598990 ],
[ "6789-12-31Z", 152104435200000 ],
[ "9999-12-31T23:59:59.999Z", 253402300799999 ],
[ "9999-12-31Z", 253402214400000 ],
[ "9999-12-31z", 253402214400000 ],
[ "9999-12-31", 253402214400000 ],
[ "2012Z", 1325376000000 ],
[ "2012z", 1325376000000 ],
[ "2012", 1325376000000 ],
[ "2012-2Z", 1328054400000 ],
[ "2012-1Z", 1325376000000 ],
[ "2012-1z", 1325376000000 ],
[ "2012-1-1z", 1325376000000 ],
[ "2012-01-01Z", 1325376000000 ],
[ "2012-01-01Z", 1325376000000 ],
[ "2012-01-02Z", 1325462400000 ],
[ "2012-01-2Z", 1325462400000 ],
[ " 2012-01-01Z", 1325376000000 ],
[ " 2012-01-01z", 1325376000000 ],
[ 1399395674000, 1399395674000 ],
[ 3600000, 3600000 ],
[ 7200000, 7200000 ],
[ 8200000, 8200000 ],
[ 61123, 61123 ],
[ 60123, 60123 ],
[ 2001, 2001 ],
[ 2000, 2000 ],
[ 1000, 1000 ],
[ 121, 121 ],
[ 1, 1 ],
[ 0, 0 ]
];
values.forEach(function (value) {
var actual = getQueryResults("RETURN DATE_TIMESTAMP(@value)", { value: value[0] });
assertEqual([ value[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_iso8601 function
////////////////////////////////////////////////////////////////////////////////
testDateIso8601Invalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_ISO8601()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DATE_ISO8601(1, 1, 1, 1, 1, 1, 1, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_ISO8601(1, null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_ISO8601(null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_ISO8601(false)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_ISO8601([])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DATE_ISO8601({})");
var values = [
"foobar",
"2012fjh",
" 2012tjjgg",
"",
" ",
"abc2012-01-01",
"2000-00-00",
"2001-02-11 24:00:00",
"2001-02-11 24:01:01",
"2001-02-11 25:01:01",
"2001-02-11 23:60:00",
"2001-02-11 23:01:60",
"2001-02-11 23:01:99",
"2001-00-11",
"2001-0-11",
"2001-13-11",
"2001-13-32",
"2001-01-0",
"2001-01-00",
"2001-01-32",
"2001-1-32"
];
values.forEach(function(value) {
assertQueryError(errors.ERROR_QUERY_INVALID_DATE_VALUE.code, "RETURN DATE_ISO8601(@value)", { value: value });
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_iso8601 function
////////////////////////////////////////////////////////////////////////////////
testDateIso8601 : function () {
var values = [
[ "2000-04-29", "2000-04-29T00:00:00.000Z" ],
[ "2000-04-29Z", "2000-04-29T00:00:00.000Z" ],
[ "2012-02-12 13:24:12", "2012-02-12T13:24:12.000Z" ],
[ "2012-02-12 13:24:12Z", "2012-02-12T13:24:12.000Z" ],
[ "2012-02-12 23:59:59.991", "2012-02-12T23:59:59.991Z" ],
[ "2012-02-12 23:59:59.991Z", "2012-02-12T23:59:59.991Z" ],
[ "2012-02-12", "2012-02-12T00:00:00.000Z" ],
[ "2012-02-12Z", "2012-02-12T00:00:00.000Z" ],
[ "2012-02-12T13:24:12", "2012-02-12T13:24:12.000Z" ],
[ "2012-02-12T13:24:12Z", "2012-02-12T13:24:12.000Z" ],
[ "2012-02-12Z", "2012-02-12T00:00:00.000Z" ],
[ "2012-2-12Z", "2012-02-12T00:00:00.000Z" ],
[ "1910-01-02T03:04:05", "1910-01-02T03:04:05.000Z" ],
[ "1910-01-02T03:04:05Z", "1910-01-02T03:04:05.000Z" ],
[ "1910-01-02 03:04:05", "1910-01-02T03:04:05.000Z" ],
[ "1910-01-02 03:04:05Z", "1910-01-02T03:04:05.000Z" ],
[ "1910-01-02", "1910-01-02T00:00:00.000Z" ],
[ "1910-01-02Z", "1910-01-02T00:00:00.000Z" ],
[ "1970-01-01T01:05:27+01:00", "1970-01-01T00:05:27.000Z" ],
[ "1970-01-01T01:05:27-01:00", "1970-01-01T02:05:27.000Z" ],
[ "1970-01-01T01:05:27", "1970-01-01T01:05:27.000Z" ],
[ "1970-01-01T01:05:27Z", "1970-01-01T01:05:27.000Z" ],
[ "1970-01-01 01:05:27Z", "1970-01-01T01:05:27.000Z" ],
[ "1970-01-01T12:05:27Z", "1970-01-01T12:05:27.000Z" ],
[ "1970-01-01 12:05:27Z", "1970-01-01T12:05:27.000Z" ],
[ "1970-1-1Z", "1970-01-01T00:00:00.000Z" ],
[ "1221-02-28T23:59:59", "1221-02-28T23:59:59.000Z" ],
[ "1221-02-28T23:59:59Z", "1221-02-28T23:59:59.000Z" ],
[ "1221-02-28 23:59:59Z", "1221-02-28T23:59:59.000Z" ],
[ "1221-02-28", "1221-02-28T00:00:00.000Z" ],
[ "1221-02-28Z", "1221-02-28T00:00:00.000Z" ],
[ "1221-2-28Z", "1221-02-28T00:00:00.000Z" ],
[ "1000-12-24T04:12:00Z", "1000-12-24T04:12:00.000Z" ],
[ "1000-12-24Z", "1000-12-24T00:00:00.000Z" ],
[ "1000-12-24 04:12:00Z", "1000-12-24T04:12:00.000Z" ],
[ "6789-12-31T23:59:58.99Z", "6789-12-31T23:59:58.990Z" ],
[ "6789-12-31Z", "6789-12-31T00:00:00.000Z" ],
[ "9999-12-31T23:59:59.999Z", "9999-12-31T23:59:59.999Z" ],
[ "9999-12-31Z", "9999-12-31T00:00:00.000Z" ],
[ "9999-12-31z", "9999-12-31T00:00:00.000Z" ],
[ "9999-12-31", "9999-12-31T00:00:00.000Z" ],
[ "2012Z", "2012-01-01T00:00:00.000Z" ],
[ "2012z", "2012-01-01T00:00:00.000Z" ],
[ "2012", "2012-01-01T00:00:00.000Z" ],
[ "2012-2Z", "2012-02-01T00:00:00.000Z" ],
[ "2012-1Z", "2012-01-01T00:00:00.000Z" ],
[ "2012-1z", "2012-01-01T00:00:00.000Z" ],
[ "2012-1-1z", "2012-01-01T00:00:00.000Z" ],
[ "2012-01-01", "2012-01-01T00:00:00.000Z" ],
[ "2012-01-01Z", "2012-01-01T00:00:00.000Z" ],
[ "2012-01-01Z", "2012-01-01T00:00:00.000Z" ],
[ "2012-01-02Z", "2012-01-02T00:00:00.000Z" ],
[ "2012-01-2Z", "2012-01-02T00:00:00.000Z" ],
[ " 2012-01-01Z", "2012-01-01T00:00:00.000Z" ],
[ " 2012-01-01z", "2012-01-01T00:00:00.000Z" ],
[ 1399395674000, "2014-05-06T17:01:14.000Z" ],
[ 3600000, "1970-01-01T01:00:00.000Z" ],
[ 7200000, "1970-01-01T02:00:00.000Z" ],
[ 8200000, "1970-01-01T02:16:40.000Z" ],
[ 61123, "1970-01-01T00:01:01.123Z" ],
[ 60123, "1970-01-01T00:01:00.123Z" ],
[ 2001, "1970-01-01T00:00:02.001Z" ],
[ 2000, "1970-01-01T00:00:02.000Z" ],
[ 1000, "1970-01-01T00:00:01.000Z" ],
[ 121, "1970-01-01T00:00:00.121Z" ],
[ 1, "1970-01-01T00:00:00.001Z" ],
[ 0, "1970-01-01T00:00:00.000Z" ]
];
values.forEach(function (value) {
var actual = getQueryResults("RETURN DATE_ISO8601(@value)", { value: value[0] });
assertEqual([ value[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date_iso8601 function
////////////////////////////////////////////////////////////////////////////////
testDateIso8601Alternative : function () {
var values = [
[ [ 1000, 1, 1, 0, 0, 0, 0 ], "1000-01-01T00:00:00.000Z" ],
[ [ 9999, 12, 31, 23, 59, 59, 999 ], "9999-12-31T23:59:59.999Z" ],
[ [ 2012, 1, 1, 13, 12, 14, 95 ], "2012-01-01T13:12:14.095Z" ],
[ [ 1234, 12, 31, 23, 59, 59, 477 ], "1234-12-31T23:59:59.477Z" ],
[ [ 2014, 5, 7, 12, 6 ], "2014-05-07T12:06:00.000Z" ],
[ [ 2014, 5, 7, 12 ], "2014-05-07T12:00:00.000Z" ],
[ [ 2014, 5, 7 ], "2014-05-07T00:00:00.000Z" ],
[ [ 2014, 5, 7 ], "2014-05-07T00:00:00.000Z" ],
[ [ 1000, 1, 1 ], "1000-01-01T00:00:00.000Z" ],
[ [ "1000", "01", "01", "00", "00", "00", "00" ], "1000-01-01T00:00:00.000Z" ],
[ [ "1000", "1", "1", "0", "0", "0", "0" ], "1000-01-01T00:00:00.000Z" ],
[ [ "9999", "12", "31", "23", "59", "59", "999" ], "9999-12-31T23:59:59.999Z" ],
[ [ "2012", "1", "1", "13", "12", "14", "95" ], "2012-01-01T13:12:14.095Z" ],
[ [ "1234", "12", "31", "23", "59", "59", "477" ], "1234-12-31T23:59:59.477Z" ],
[ [ "2014", "05", "07", "12", "06" ], "2014-05-07T12:06:00.000Z" ],
[ [ "2014", "5", "7", "12", "6" ], "2014-05-07T12:06:00.000Z" ],
[ [ "2014", "5", "7", "12" ], "2014-05-07T12:00:00.000Z" ],
[ [ "2014", "5", "7" ], "2014-05-07T00:00:00.000Z" ],
[ [ "2014", "5", "7" ], "2014-05-07T00:00:00.000Z" ],
[ [ "1000", "01", "01" ], "1000-01-01T00:00:00.000Z" ],
[ [ "1000", "1", "1" ], "1000-01-01T00:00:00.000Z" ],
];
values.forEach(function (value) {
var query = "RETURN DATE_ISO8601(" +
value[0].map(function(v) {
return JSON.stringify(v)
}).join(", ") + ")";
var actual = getQueryResults(query);
assertEqual([ value[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date transformations
////////////////////////////////////////////////////////////////////////////////
testDateTransformations1 : function () {
var dt = "2014-05-07T15:23:21.446";
var actual;
actual = getQueryResults("RETURN DATE_TIMESTAMP(DATE_YEAR(@value), DATE_MONTH(@value), DATE_DAY(@value), DATE_HOUR(@value), DATE_MINUTE(@value), DATE_SECOND(@value), DATE_MILLISECOND(@value))", { value: dt });
assertEqual([ new Date(dt).getTime() ], actual);
actual = getQueryResults("RETURN DATE_TIMESTAMP(DATE_YEAR(@value), DATE_MONTH(@value), DATE_DAY(@value), DATE_HOUR(@value), DATE_MINUTE(@value), DATE_SECOND(@value), DATE_MILLISECOND(@value))", { value: dt + "Z" });
assertEqual([ new Date(dt).getTime() ], actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test date transformations
////////////////////////////////////////////////////////////////////////////////
testDateTransformations2 : function () {
var dt = "2014-05-07T15:23:21.446";
var actual;
actual = getQueryResults("RETURN DATE_ISO8601(DATE_TIMESTAMP(DATE_YEAR(@value), DATE_MONTH(@value), DATE_DAY(@value), DATE_HOUR(@value), DATE_MINUTE(@value), DATE_SECOND(@value), DATE_MILLISECOND(@value)))", { value: dt });
assertEqual([ dt + "Z" ], actual);
actual = getQueryResults("RETURN DATE_ISO8601(DATE_TIMESTAMP(DATE_YEAR(@value), DATE_MONTH(@value), DATE_DAY(@value), DATE_HOUR(@value), DATE_MINUTE(@value), DATE_SECOND(@value), DATE_MILLISECOND(@value)))", { value: dt + "Z" });
assertEqual([ dt + "Z" ], actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test non-existing functions
////////////////////////////////////////////////////////////////////////////////

View File

@ -202,6 +202,7 @@ ERROR_QUERY_LIST_EXPECTED,1563,"list expected","Will be raised when a non-list o
ERROR_QUERY_FAIL_CALLED,1569,"FAIL(%s) called","Will be raised when the function FAIL() is called from inside a query."
ERROR_QUERY_GEO_INDEX_MISSING,1570,"no suitable geo index found for geo restriction on '%s'","Will be raised when a geo restriction was specified but no suitable geo index is found to resolve it."
ERROR_QUERY_FULLTEXT_INDEX_MISSING,1571,"no suitable fulltext index found for fulltext query on '%s'","Will be raised when a fulltext query is performed on a collection without a suitable fulltext index."
ERROR_QUERY_INVALID_DATE_VALUE,1572,"invalid date value","Will be raised when a value cannot be converted to a date."
################################################################################
## AQL user functions

View File

@ -158,6 +158,7 @@ void TRI_InitialiseErrorMessages (void) {
REG_ERROR(ERROR_QUERY_FAIL_CALLED, "FAIL(%s) called");
REG_ERROR(ERROR_QUERY_GEO_INDEX_MISSING, "no suitable geo index found for geo restriction on '%s'");
REG_ERROR(ERROR_QUERY_FULLTEXT_INDEX_MISSING, "no suitable fulltext index found for fulltext query on '%s'");
REG_ERROR(ERROR_QUERY_INVALID_DATE_VALUE, "invalid date value");
REG_ERROR(ERROR_QUERY_FUNCTION_INVALID_NAME, "invalid user function name");
REG_ERROR(ERROR_QUERY_FUNCTION_INVALID_CODE, "invalid user function code");
REG_ERROR(ERROR_QUERY_FUNCTION_NOT_FOUND, "user function '%s()' not found");

View File

@ -376,6 +376,8 @@ extern "C" {
/// - 1571: @LIT{no suitable fulltext index found for fulltext query on '\%s'}
/// Will be raised when a fulltext query is performed on a collection without
/// a suitable fulltext index.
/// - 1572: @LIT{invalid date value}
/// Will be raised when a value cannot be converted to a date.
/// - 1580: @LIT{invalid user function name}
/// Will be raised when a user function with an invalid name is registered.
/// - 1581: @LIT{invalid user function code}
@ -2040,6 +2042,16 @@ void TRI_InitialiseErrorMessages (void);
#define TRI_ERROR_QUERY_FULLTEXT_INDEX_MISSING (1571)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1572: ERROR_QUERY_INVALID_DATE_VALUE
///
/// invalid date value
///
/// Will be raised when a value cannot be converted to a date.
////////////////////////////////////////////////////////////////////////////////
#define TRI_ERROR_QUERY_INVALID_DATE_VALUE (1572)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1580: ERROR_QUERY_FUNCTION_INVALID_NAME
///