1
0
Fork 0

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

This commit is contained in:
Heiko Kernbach 2012-04-25 11:13:46 +02:00
commit c1c449f441
39 changed files with 11312 additions and 140 deletions

4
.gitignore vendored
View File

@ -28,6 +28,8 @@ build.h
build.info
commit.sh
config/config.h
config/config.guess
config/config.sub
config.h
config.log
config/revision.sh
@ -86,7 +88,7 @@ stamp-h*
.svn
*.swp
tags
Ahuacatl/grammar.output
Ahuacatl/ahuacatl-grammar.output
UnitTests/HttpInterface/logs
UnitTests/Jutland/CsvReaderTest.cpp
UnitTests/Jutland/Makefile.am

View File

@ -0,0 +1,232 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Ahuacatl, bind parameters
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-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
////////////////////////////////////////////////////////////////////////////////
#include "Ahuacatl/ahuacatl-bind-parameter.h"
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_bind_parameter_t* CreateParameter (const char* const name,
const TRI_json_t* const value) {
TRI_aql_bind_parameter_t* parameter;
assert(name);
assert(value);
parameter = (TRI_aql_bind_parameter_t*) TRI_Allocate(sizeof(TRI_aql_bind_parameter_t));
if (!parameter) {
return NULL;
}
parameter->_name = TRI_DuplicateString(name);
if (!parameter->_name) {
TRI_Free(parameter);
return NULL;
}
parameter->_value = TRI_CopyJson((TRI_json_t*) value);
if (!parameter->_value) {
TRI_Free(parameter->_name);
TRI_Free(parameter);
return NULL;
}
return parameter;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief hash bind parameter
////////////////////////////////////////////////////////////////////////////////
uint64_t TRI_HashBindParameterAql (TRI_associative_pointer_t* array,
void const* element) {
TRI_aql_bind_parameter_t* parameter = (TRI_aql_bind_parameter_t*) element;
return TRI_FnvHashString(parameter->_name);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief comparison function used to determine bind parameter equality
////////////////////////////////////////////////////////////////////////////////
bool TRI_EqualBindParameterAql (TRI_associative_pointer_t* array,
void const* key,
void const* element) {
TRI_aql_bind_parameter_t* parameter = (TRI_aql_bind_parameter_t*) element;
return TRI_EqualString(key, parameter->_name);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free bind parameters
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeBindParametersAql (TRI_aql_parse_context_t* const context) {
size_t i;
size_t n;
// iterate thru all parameters allocated
n = context->_parameterValues._nrAlloc;
for (i = 0; i < n; ++i) {
TRI_aql_bind_parameter_t* parameter;
parameter = (TRI_aql_bind_parameter_t*) context->_parameterValues._table[i];
if (!parameter) {
continue;
}
assert(parameter->_name);
assert(parameter->_value);
TRI_FreeString(parameter->_name);
TRI_FreeJson(parameter->_value);
TRI_Free(parameter);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add bind parameters
////////////////////////////////////////////////////////////////////////////////
bool TRI_AddParameterValuesAql (TRI_aql_parse_context_t* const context,
const TRI_json_t* const parameters) {
size_t i;
size_t n;
assert(context);
if (parameters == NULL) {
// no bind parameters
return true;
}
if (parameters->_type != TRI_JSON_ARRAY) {
// parameters must be a list
TRI_SetErrorAql(context, TRI_ERROR_QUERY_BIND_PARAMETERS_INVALID, NULL);
return false;
}
n = parameters->_value._objects._length;
if (n == 0) {
// empty list, this is ok
return true;
}
for (i = 0; i < n; i += 2) {
TRI_json_t* name = TRI_AtVector(&parameters->_value._objects, i);
TRI_json_t* value = TRI_AtVector(&parameters->_value._objects, i + 1);
TRI_aql_bind_parameter_t* parameter;
assert(name);
assert(name->_type == TRI_JSON_STRING);
assert(value);
parameter = CreateParameter(name->_value._string.data, value);
if (!parameter) {
TRI_SetErrorAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return false;
}
TRI_InsertKeyAssociativePointer(&context->_parameterValues, parameter->_name, parameter, false);
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief validate bind parameters passed
////////////////////////////////////////////////////////////////////////////////
bool TRI_ValidateBindParametersAql (TRI_aql_parse_context_t* const context) {
size_t i;
size_t n;
// iterate thru all parameter names used in the query
n = context->_parameterNames._nrAlloc;
for (i = 0; i < n; ++i) {
char* name = (char*) context->_parameterNames._table[i];
if (!name) {
continue;
}
if (!TRI_LookupByKeyAssociativePointer(&context->_parameterValues, name)) {
TRI_SetErrorAql(context, TRI_ERROR_QUERY_BIND_PARAMETER_MISSING, name);
return false;
}
}
// iterate thru all parameters that we have values for
n = context->_parameterValues._nrAlloc;
for (i = 0; i < n; ++i) {
TRI_aql_bind_parameter_t* parameter;
parameter = (TRI_aql_bind_parameter_t*) context->_parameterValues._table[i];
if (!parameter) {
continue;
}
assert(parameter->_name);
if (!TRI_LookupByKeyAssociativePointer(&context->_parameterNames, parameter->_name)) {
TRI_SetErrorAql(context, TRI_ERROR_QUERY_BIND_PARAMETER_UNDECLARED, parameter->_name);
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -0,0 +1,122 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Ahuacatl, bind parameters
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-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
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_DURHAM_AHUACATL_BIND_PARAMETER_H
#define TRIAGENS_DURHAM_AHUACATL_BIND_PARAMETER_H 1
#include <BasicsC/common.h>
#include <BasicsC/strings.h>
#include <BasicsC/hashes.h>
#include <BasicsC/vector.h>
#include <BasicsC/associative.h>
#include <BasicsC/json.h>
#include "Ahuacatl/ahuacatl-parser.h"
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// --SECTION-- public types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief bind parameter container
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_aql_bind_parameter_s {
char* _name;
TRI_json_t* _value;
}
TRI_aql_bind_parameter_t;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief hash bind parameter
////////////////////////////////////////////////////////////////////////////////
uint64_t TRI_HashBindParameterAql (TRI_associative_pointer_t*, void const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief comparison function used to determine bind parameter equality
////////////////////////////////////////////////////////////////////////////////
bool TRI_EqualBindParameterAql (TRI_associative_pointer_t*,
void const*,
void const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief free bind parameters
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeBindParametersAql (TRI_aql_parse_context_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @brief add bind parameters
////////////////////////////////////////////////////////////////////////////////
bool TRI_AddParameterValuesAql (TRI_aql_parse_context_t* const,
const TRI_json_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @brief validate bind parameters passed
////////////////////////////////////////////////////////////////////////////////
bool TRI_ValidateBindParametersAql (TRI_aql_parse_context_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -25,7 +25,7 @@
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "Ahuacatl/error.h"
#include "Ahuacatl/ahuacatl-error.h"
// -----------------------------------------------------------------------------
// --SECTION-- defines

View File

@ -127,13 +127,15 @@ TRI_associative_pointer_t* TRI_InitialiseFunctionsAql (void) {
REGISTER_FUNCTION("ISDOCUMENT", "IS_DOCUMENT", true, 1, 1);
// string concat
REGISTER_FUNCTION("CONCAT", "STRING_CONCAT", true, 2, 2);
REGISTER_FUNCTION("CONCAT", "STRING_CONCAT", true, 2, 256);
// numeric functions
// string functions
// misc functions
REGISTER_FUNCTION("MERGE", "MERGE", true, 2, 256);
REGISTER_FUNCTION("UNION", "UNION", true, 2, 256);
REGISTER_FUNCTION("LENGTH", "LENGTH", true, 1, 1);
if (!result) {

3085
Ahuacatl/ahuacatl-grammar.c Normal file

File diff suppressed because it is too large Load Diff

133
Ahuacatl/ahuacatl-grammar.h Normal file
View File

@ -0,0 +1,133 @@
/* A Bison parser, made by GNU Bison 2.4.1. */
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
T_END = 0,
T_FOR = 258,
T_LET = 259,
T_FILTER = 260,
T_RETURN = 261,
T_COLLECT = 262,
T_SORT = 263,
T_LIMIT = 264,
T_ASC = 265,
T_DESC = 266,
T_IN = 267,
T_INTO = 268,
T_NULL = 269,
T_TRUE = 270,
T_FALSE = 271,
T_STRING = 272,
T_QUOTED_STRING = 273,
T_NUMBER = 274,
T_PARAMETER = 275,
T_ASSIGN = 276,
T_NOT = 277,
T_AND = 278,
T_OR = 279,
T_EQ = 280,
T_NE = 281,
T_LT = 282,
T_GT = 283,
T_LE = 284,
T_GE = 285,
T_PLUS = 286,
T_MINUS = 287,
T_TIMES = 288,
T_DIV = 289,
T_MOD = 290,
T_QUESTION = 291,
T_COLON = 292,
T_COMMA = 293,
T_OPEN = 294,
T_CLOSE = 295,
T_DOC_OPEN = 296,
T_DOC_CLOSE = 297,
T_LIST_OPEN = 298,
T_LIST_CLOSE = 299,
UPLUS = 300,
UMINUS = 301,
FUNCCALL = 302,
REFERENCE = 303,
INDEXED = 304
};
#endif
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
/* Line 1676 of yacc.c */
#line 26 "Ahuacatl/ahuacatl-grammar.y"
TRI_aql_node_t* node;
char* strval;
bool boolval;
int64_t intval;
/* Line 1676 of yacc.c */
#line 111 "Ahuacatl/ahuacatl-grammar.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
typedef struct YYLTYPE
{
int first_line;
int first_column;
int last_line;
int last_column;
} YYLTYPE;
# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
#endif

View File

@ -17,8 +17,8 @@
#include <BasicsC/strings.h>
#include "Ahuacatl/ast-node.h"
#include "Ahuacatl/parser.h"
#include "Ahuacatl/error.h"
#include "Ahuacatl/ahuacatl-parser.h"
#include "Ahuacatl/ahuacatl-error.h"
%}
@ -33,7 +33,7 @@
%{
////////////////////////////////////////////////////////////////////////////////
/// @brief forward for lexer function defined in tokens.l
/// @brief forward for lexer function defined in ahuacatl-tokens.l
////////////////////////////////////////////////////////////////////////////////
int Ahuacatllex (YYSTYPE*, YYLTYPE*, void*);
@ -810,13 +810,7 @@ value_literal:
bind_parameter:
T_PARAMETER {
TRI_aql_node_t* node;
if (!$1) {
YYABORT;
}
node = TRI_CreateNodeParameterAql(context, $1);
TRI_aql_node_t* node = TRI_CreateNodeParameterAql(context, $1);
if (!node) {
YYABORT;
}

View File

@ -25,8 +25,9 @@
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "Ahuacatl/parser.h"
#include "Ahuacatl/ahuacatl-parser.h"
#include "Ahuacatl/ast-node.h"
#include "Ahuacatl/ahuacatl-bind-parameter.h"
// -----------------------------------------------------------------------------
// --SECTION-- private macros
@ -109,6 +110,20 @@ TRI_aql_parse_context_t* TRI_CreateParseContextAql (TRI_vocbase_t* vocbase,
context->_vocbase = vocbase;
// actual bind parameter values
TRI_InitAssociativePointer(&context->_parameterValues,
&TRI_HashStringKeyAssociativePointer,
&TRI_HashBindParameterAql,
&TRI_EqualBindParameterAql,
0);
// bind parameter names used in the query
TRI_InitAssociativePointer(&context->_parameterNames,
&TRI_HashStringKeyAssociativePointer,
&TRI_HashStringKeyAssociativePointer,
&TRI_EqualStringKeyAssociativePointer,
0);
TRI_InitVectorPointer(&context->_stack);
TRI_InitVectorPointer(&context->_nodes);
TRI_InitVectorPointer(&context->_strings);
@ -185,6 +200,13 @@ void TRI_FreeParseContextAql (TRI_aql_parse_context_t* const context) {
// free the stack
TRI_DestroyVectorPointer(&context->_stack);
// free parameter names hash
TRI_DestroyAssociativePointer(&context->_parameterNames);
// free parameter values
TRI_FreeBindParametersAql(context);
TRI_DestroyAssociativePointer(&context->_parameterValues);
// free query string
if (context->_query) {
TRI_Free(context->_query);
@ -202,6 +224,33 @@ void TRI_FreeParseContextAql (TRI_aql_parse_context_t* const context) {
TRI_Free(context);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add bind parameters to the context
////////////////////////////////////////////////////////////////////////////////
bool TRI_AddBindParametersAql (TRI_aql_parse_context_t* const context,
const TRI_json_t* const parameters) {
return TRI_AddParameterValuesAql(context, parameters);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief parse & validate the query string
////////////////////////////////////////////////////////////////////////////////
bool TRI_ParseQueryAql (TRI_aql_parse_context_t* const context) {
if (Ahuacatlparse(context)) {
// lexing/parsing failed
return false;
}
if (!TRI_ValidateBindParametersAql(context)) {
// invalid bind parameters
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a new variable scope
////////////////////////////////////////////////////////////////////////////////
@ -594,6 +643,27 @@ bool TRI_VariableExistsAql (TRI_aql_parse_context_t* const context,
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks if a variable name follows the required naming convention
////////////////////////////////////////////////////////////////////////////////
bool TRI_IsValidVariableNameAql (const char* const name) {
assert(name);
if (strlen(name) == 0) {
// name must be at least one char long
return false;
}
if (*name == '_') {
// name must not start with an underscore
return false;
}
// everything else is allowed
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -33,9 +33,11 @@
#include <BasicsC/hashes.h>
#include <BasicsC/vector.h>
#include <BasicsC/associative.h>
#include <BasicsC/json.h>
#include "VocBase/vocbase.h"
#include "Ahuacatl/error.h"
#include "VocBase/collection.h"
#include "Ahuacatl/ahuacatl-error.h"
#ifdef __cplusplus
extern "C" {
@ -94,6 +96,8 @@ typedef struct TRI_aql_parse_context_s {
TRI_vector_pointer_t _stack;
TRI_aql_error_t _error;
TRI_vocbase_t* _vocbase;
TRI_associative_pointer_t _parameterValues;
TRI_associative_pointer_t _parameterNames;
void* _first;
char* _query;
}
@ -117,7 +121,7 @@ TRI_aql_parse_context_t;
////////////////////////////////////////////////////////////////////////////////
TRI_aql_parse_context_t* TRI_CreateParseContextAql (TRI_vocbase_t*,
const char* const);
const char* const);
////////////////////////////////////////////////////////////////////////////////
/// @brief free a parse context
@ -125,6 +129,19 @@ TRI_aql_parse_context_t* TRI_CreateParseContextAql (TRI_vocbase_t*,
void TRI_FreeParseContextAql (TRI_aql_parse_context_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @brief add bind parameters to the context
////////////////////////////////////////////////////////////////////////////////
bool TRI_AddBindParametersAql (TRI_aql_parse_context_t* const,
const TRI_json_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @brief parse & validate the query string
////////////////////////////////////////////////////////////////////////////////
bool TRI_ParseQueryAql (TRI_aql_parse_context_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @brief create a new variable scope
////////////////////////////////////////////////////////////////////////////////
@ -241,6 +258,12 @@ char* TRI_RegisterStringAql (TRI_aql_parse_context_t* const,
bool TRI_VariableExistsAql (TRI_aql_parse_context_t* const, const char* const);
////////////////////////////////////////////////////////////////////////////////
/// @brief checks if a variable name follows the required naming convention
////////////////////////////////////////////////////////////////////////////////
bool TRI_IsValidVariableNameAql (const char* const);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

2703
Ahuacatl/ahuacatl-tokens.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,8 @@
#include <BasicsC/strings.h>
#include "Ahuacatl/ast-node.h"
#include "Ahuacatl/parser.h"
#include "Ahuacatl/grammar.h"
#include "Ahuacatl/ahuacatl-parser.h"
#include "Ahuacatl/ahuacatl-grammar.h"
#define YY_EXTRA_TYPE TRI_aql_parse_context_t*

View File

@ -1222,14 +1222,20 @@ char* TRI_GenerateCodeAql (const void* const data) {
if (!generator->_error) {
char* funcName = generator->_funcName;
TRI_AppendStringStringBuffer(&generator->_buffer, "return ");
TRI_AppendStringStringBuffer(&generator->_buffer, "try {\n");
TRI_AppendStringStringBuffer(&generator->_buffer, " return ");
TRI_AppendStringStringBuffer(&generator->_buffer, funcName);
TRI_AppendStringStringBuffer(&generator->_buffer, "( { } );\n");
TRI_AppendStringStringBuffer(&generator->_buffer, "}\n");
TRI_AppendStringStringBuffer(&generator->_buffer, "catch (e) {\n");
TRI_AppendStringStringBuffer(&generator->_buffer, "print(e);\n");
TRI_AppendStringStringBuffer(&generator->_buffer, "}\n");
TRI_AppendStringStringBuffer(&generator->_buffer, "})();\n");
code = TRI_DuplicateString(generator->_buffer._buffer);
LOG_TRACE("generated code:\n%s\n",code);
//printf("generated code:\n%s\n",code);
}
TRI_FreeCodegenAql(generator);

View File

@ -139,6 +139,11 @@ TRI_aql_node_t* TRI_CreateNodeForAql (TRI_aql_parse_context_t* const context,
if (!name || !expression) {
ABORT_OOM
}
if (!TRI_IsValidVariableNameAql(name)) {
TRI_SetErrorAql(context, TRI_ERROR_QUERY_VARIABLE_NAME_INVALID, name);
return NULL;
}
node = (TRI_aql_node_for_t*) TRI_Allocate(sizeof(TRI_aql_node_for_t));
@ -509,7 +514,10 @@ TRI_aql_node_t* TRI_CreateNodeParameterAql (TRI_aql_parse_context_t* const conte
if (!name) {
ABORT_OOM
}
// save name of bind parameter for later
TRI_InsertKeyAssociativePointer(&context->_parameterNames, name, (void*) name, true);
node = (TRI_aql_node_parameter_t*) TRI_Allocate(sizeof(TRI_aql_node_parameter_t));
if (!node) {
@ -1318,9 +1326,9 @@ TRI_aql_node_t* TRI_CreateNodeArrayAql (TRI_aql_parse_context_t* const context)
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_ARRAY);
TRI_InitAssociativePointer(&node->_values,
TRI_HashStringKeyAssociativePointer,
HashArrayElement,
EqualArrayElement,
&TRI_HashStringKeyAssociativePointer,
&HashArrayElement,
&EqualArrayElement,
0);
node->_base.free = &FreeNodeArray;

View File

@ -34,7 +34,7 @@
#include <BasicsC/vector.h>
#include <BasicsC/associative.h>
#include "Ahuacatl/parser.h"
#include "Ahuacatl/ahuacatl-parser.h"
#ifdef __cplusplus
extern "C" {

View File

@ -88,7 +88,7 @@
#include "Ahuacatl/ast-node.h"
#include "Ahuacatl/parser.h"
#include "Ahuacatl/error.h"
#include "Ahuacatl/ahuacatl-error.h"
@ -216,7 +216,7 @@ typedef struct YYLTYPE
////////////////////////////////////////////////////////////////////////////////
/// @brief forward for lexer function defined in tokens.l
/// @brief forward for lexer function defined in ahuacatl-tokens.l
////////////////////////////////////////////////////////////////////////////////
int Ahuacatllex (YYSTYPE*, YYLTYPE*, void*);
@ -569,8 +569,8 @@ static const yytype_uint16 yyrline[] =
574, 582, 593, 604, 606, 611, 614, 620, 623, 629,
629, 642, 644, 649, 654, 662, 662, 675, 677, 682,
684, 689, 697, 706, 713, 720, 730, 737, 744, 754,
757, 763, 771, 785, 793, 801, 812, 829, 836, 845,
851, 858
757, 763, 771, 785, 793, 801, 812, 823, 830, 839,
845, 852
};
#endif
@ -2792,13 +2792,7 @@ yyreduce:
/* Line 1455 of yacc.c */
#line 812 "Ahuacatl/grammar.y"
{
TRI_aql_node_t* node;
if (!(yyvsp[(1) - (1)].strval)) {
YYABORT;
}
node = TRI_CreateNodeParameterAql(context, (yyvsp[(1) - (1)].strval));
TRI_aql_node_t* node = TRI_CreateNodeParameterAql(context, (yyvsp[(1) - (1)].strval));
if (!node) {
YYABORT;
}
@ -2810,7 +2804,7 @@ yyreduce:
case 97:
/* Line 1455 of yacc.c */
#line 829 "Ahuacatl/grammar.y"
#line 823 "Ahuacatl/grammar.y"
{
if (!(yyvsp[(1) - (1)].strval)) {
YYABORT;
@ -2823,7 +2817,7 @@ yyreduce:
case 98:
/* Line 1455 of yacc.c */
#line 836 "Ahuacatl/grammar.y"
#line 830 "Ahuacatl/grammar.y"
{
if (!(yyvsp[(1) - (1)].strval)) {
YYABORT;
@ -2836,7 +2830,7 @@ yyreduce:
case 99:
/* Line 1455 of yacc.c */
#line 845 "Ahuacatl/grammar.y"
#line 839 "Ahuacatl/grammar.y"
{
(yyval.strval) = (yyvsp[(1) - (1)].strval);
;}
@ -2845,7 +2839,7 @@ yyreduce:
case 100:
/* Line 1455 of yacc.c */
#line 851 "Ahuacatl/grammar.y"
#line 845 "Ahuacatl/grammar.y"
{
if (!(yyvsp[(1) - (1)].strval)) {
YYABORT;
@ -2858,7 +2852,7 @@ yyreduce:
case 101:
/* Line 1455 of yacc.c */
#line 858 "Ahuacatl/grammar.y"
#line 852 "Ahuacatl/grammar.y"
{
if (!(yyvsp[(2) - (2)].strval)) {
YYABORT;
@ -2871,7 +2865,7 @@ yyreduce:
/* Line 1455 of yacc.c */
#line 2875 "Ahuacatl/grammar.c"
#line 2869 "Ahuacatl/grammar.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);

View File

@ -28,6 +28,7 @@
#include "associative.h"
#include "hashes.h"
#include "strings.h"
// -----------------------------------------------------------------------------
// --SECTION-- ASSOCIATIVE ARRAY
@ -638,6 +639,16 @@ uint64_t TRI_HashStringKeyAssociativePointer (TRI_associative_pointer_t* array,
return TRI_FnvHashString((char const*) key);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief General function to determine equality of two string values
////////////////////////////////////////////////////////////////////////////////
bool TRI_EqualStringKeyAssociativePointer (TRI_associative_pointer_t* array,
void const* key,
void const* element) {
return TRI_EqualString((char*) key, (char*) element);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief lookups an element given a key
////////////////////////////////////////////////////////////////////////////////

View File

@ -299,7 +299,13 @@ void TRI_FreeAssociativePointer (TRI_associative_pointer_t*);
/// @brief General hash function that can be used to hash a string key
////////////////////////////////////////////////////////////////////////////////
uint64_t TRI_HashStringKeyAssociativePointer (TRI_associative_pointer_t*, void const* key);
uint64_t TRI_HashStringKeyAssociativePointer (TRI_associative_pointer_t*, void const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief General function to determine equality of two string values
////////////////////////////////////////////////////////////////////////////////
bool TRI_EqualStringKeyAssociativePointer (TRI_associative_pointer_t*, void const*, void const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief lookups an element given a key

View File

@ -118,6 +118,8 @@ ERROR_QUERY_RUNTIME_ERROR,1520,"runtime error in query","Will be raised when a J
ERROR_QUERY_LIMIT_VALUE_OUT_OF_RANGE,1521,"limit value '%s' is out of range","Will be raised when a limit value in the query is outside the allowed range (e. g. when passing a negative skip value)."
ERROR_QUERY_VARIABLE_REDECLARED,1522,"variable '%s' is assigned multiple times","Will be raised when a variable gets re-assigned in a query."
ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED,1523,"document attribute '%s' is assigned multiple times","Will be raised when a document attribute is re-assigned."
ERROR_QUERY_VARIABLE_NAME_INVALID,1524,"variable name '%s' has an invalid format","Will be raised when an invalid variable name is used."
ERROR_QUERY_BIND_PARAMETERS_INVALID,1525,"invalid structure of bind parameters","Will be raised when the structure of bind parameters passed has an unexpected format."
################################################################################
## AvocadoDB cursor errors

View File

@ -84,6 +84,8 @@ void TRI_InitialiseErrorMessages (void) {
REG_ERROR(ERROR_QUERY_LIMIT_VALUE_OUT_OF_RANGE, "limit value '%s' is out of range");
REG_ERROR(ERROR_QUERY_VARIABLE_REDECLARED, "variable '%s' is assigned multiple times");
REG_ERROR(ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED, "document attribute '%s' is assigned multiple times");
REG_ERROR(ERROR_QUERY_VARIABLE_NAME_INVALID, "variable name '%s' has an invalid format");
REG_ERROR(ERROR_QUERY_BIND_PARAMETERS_INVALID, "invalid structure of bind parameters");
REG_ERROR(ERROR_CURSOR_NOT_FOUND, "cursor not found");
REG_ERROR(ERROR_SESSION_USERHANDLER_URL_INVALID, "expecting <prefix>/user/<username>");
REG_ERROR(ERROR_SESSION_USERHANDLER_CANNOT_CREATE_USER, "cannot create user");

View File

@ -184,6 +184,11 @@ extern "C" {
/// Will be raised when a variable gets re-assigned in a query.
/// - 1523: @CODE{document attribute '\%s' is assigned multiple times}
/// Will be raised when a document attribute is re-assigned.
/// - 1524: @CODE{variable name '\%s' has an invalid format}
/// Will be raised when an invalid variable name is used.
/// - 1525: @CODE{invalid structure of bind parameters}
/// Will be raised when the structure of bind parameters passed has an
/// unexpected format.
/// - 1600: @CODE{cursor not found}
/// Will be raised when a cursor is requested via its id but a cursor with
/// that id cannot be found.
@ -1027,6 +1032,27 @@ void TRI_InitialiseErrorMessages (void);
#define TRI_ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED (1523)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1524: ERROR_QUERY_VARIABLE_NAME_INVALID
///
/// variable name '%s' has an invalid format
///
/// Will be raised when an invalid variable name is used.
////////////////////////////////////////////////////////////////////////////////
#define TRI_ERROR_QUERY_VARIABLE_NAME_INVALID (1524)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1525: ERROR_QUERY_BIND_PARAMETERS_INVALID
///
/// invalid structure of bind parameters
///
/// Will be raised when the structure of bind parameters passed has an
/// unexpected format.
////////////////////////////////////////////////////////////////////////////////
#define TRI_ERROR_QUERY_BIND_PARAMETERS_INVALID (1525)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1600: ERROR_CURSOR_NOT_FOUND
///

View File

@ -146,14 +146,15 @@ avocado_SOURCES = \
HttpsServer/HttpsServerImpl.cpp \
PriorityQueue/pqueueindex.c \
PriorityQueue/priorityqueue.c \
Ahuacatl/ahuacatl-bind-parameter.c \
Ahuacatl/ahuacatl-error.c \
Ahuacatl/ahuacatl-functions.c \
Ahuacatl/ahuacatl-grammar.c \
Ahuacatl/ahuacatl-parser.c \
Ahuacatl/ahuacatl-tokens.c \
Ahuacatl/ast-codegen-js.c \
Ahuacatl/ast-dump.c \
Ahuacatl/ast-node.c \
Ahuacatl/error.c \
Ahuacatl/grammar.c \
Ahuacatl/parser.c \
Ahuacatl/tokens.c \
QL/ast-query.c \
QL/formatter.c \
QL/optimize.c \
@ -302,7 +303,7 @@ BUILT_SOURCES += $(FLEXXX_FILES)
BISON_FILES = \
QL/parser.c \
Ahuacatl/grammar.c
Ahuacatl/ahuacatl-grammar.c
BUILT_SOURCES += $(BISON_FILES)

View File

@ -277,11 +277,14 @@ am_avocado_OBJECTS = Admin/ApplicationAdminServer.$(OBJEXT) \
HttpsServer/HttpsServerImpl.$(OBJEXT) \
PriorityQueue/pqueueindex.$(OBJEXT) \
PriorityQueue/priorityqueue.$(OBJEXT) \
Ahuacatl/ahuacatl-bind-parameter.$(OBJEXT) \
Ahuacatl/ahuacatl-error.$(OBJEXT) \
Ahuacatl/ahuacatl-functions.$(OBJEXT) \
Ahuacatl/ahuacatl-grammar.$(OBJEXT) \
Ahuacatl/ahuacatl-parser.$(OBJEXT) \
Ahuacatl/ahuacatl-tokens.$(OBJEXT) \
Ahuacatl/ast-codegen-js.$(OBJEXT) Ahuacatl/ast-dump.$(OBJEXT) \
Ahuacatl/ast-node.$(OBJEXT) Ahuacatl/error.$(OBJEXT) \
Ahuacatl/grammar.$(OBJEXT) Ahuacatl/parser.$(OBJEXT) \
Ahuacatl/tokens.$(OBJEXT) QL/ast-query.$(OBJEXT) \
Ahuacatl/ast-node.$(OBJEXT) QL/ast-query.$(OBJEXT) \
QL/formatter.$(OBJEXT) QL/optimize.$(OBJEXT) \
QL/parser.$(OBJEXT) QL/tokens.$(OBJEXT) \
RestHandler/RestActionHandler.$(OBJEXT) \
@ -752,14 +755,15 @@ avocado_SOURCES = \
HttpsServer/HttpsServerImpl.cpp \
PriorityQueue/pqueueindex.c \
PriorityQueue/priorityqueue.c \
Ahuacatl/ahuacatl-bind-parameter.c \
Ahuacatl/ahuacatl-error.c \
Ahuacatl/ahuacatl-functions.c \
Ahuacatl/ahuacatl-grammar.c \
Ahuacatl/ahuacatl-parser.c \
Ahuacatl/ahuacatl-tokens.c \
Ahuacatl/ast-codegen-js.c \
Ahuacatl/ast-dump.c \
Ahuacatl/ast-node.c \
Ahuacatl/error.c \
Ahuacatl/grammar.c \
Ahuacatl/parser.c \
Ahuacatl/tokens.c \
QL/ast-query.c \
QL/formatter.c \
QL/optimize.c \
@ -892,7 +896,7 @@ FLEXXX_FILES = \
################################################################################
BISON_FILES = \
QL/parser.c \
Ahuacatl/grammar.c
Ahuacatl/ahuacatl-grammar.c
################################################################################
@ -1009,7 +1013,10 @@ UNITTESTS_SERVER = $(addprefix --unit-tests ,$(SHELL_SERVER))
################################################################################
################################################################################
SHELL_SERVER_AHUACATL = @srcdir@/js/server/tests/ahuacatl-queries-collection.js \
SHELL_SERVER_AHUACATL = @srcdir@/js/server/tests/ahuacatl-operators.js \
@srcdir@/js/server/tests/ahuacatl-escaping.js \
@srcdir@/js/server/tests/ahuacatl-functions.js \
@srcdir@/js/server/tests/ahuacatl-queries-collection.js \
@srcdir@/js/server/tests/ahuacatl-queries-noncollection.js
UNITTESTS_SERVER_AHUACATL = $(addprefix --unit-tests ,$(SHELL_SERVER_AHUACATL))
@ -1647,22 +1654,24 @@ Ahuacatl/$(am__dirstamp):
Ahuacatl/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) Ahuacatl/$(DEPDIR)
@: > Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/ahuacatl-bind-parameter.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/ahuacatl-error.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/ahuacatl-functions.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/ahuacatl-grammar.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/ahuacatl-parser.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/ahuacatl-tokens.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/ast-codegen-js.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/ast-dump.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/ast-node.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/error.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/grammar.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/parser.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
Ahuacatl/tokens.$(OBJEXT): Ahuacatl/$(am__dirstamp) \
Ahuacatl/$(DEPDIR)/$(am__dirstamp)
QL/$(am__dirstamp):
@$(MKDIR_P) QL
@: > QL/$(am__dirstamp)
@ -1901,14 +1910,15 @@ mostlyclean-compile:
-rm -f Admin/RestAdminLogHandler.$(OBJEXT)
-rm -f Admin/RestBaseHandler.$(OBJEXT)
-rm -f Admin/RestVersionHandler.$(OBJEXT)
-rm -f Ahuacatl/ahuacatl-bind-parameter.$(OBJEXT)
-rm -f Ahuacatl/ahuacatl-error.$(OBJEXT)
-rm -f Ahuacatl/ahuacatl-functions.$(OBJEXT)
-rm -f Ahuacatl/ahuacatl-grammar.$(OBJEXT)
-rm -f Ahuacatl/ahuacatl-parser.$(OBJEXT)
-rm -f Ahuacatl/ahuacatl-tokens.$(OBJEXT)
-rm -f Ahuacatl/ast-codegen-js.$(OBJEXT)
-rm -f Ahuacatl/ast-dump.$(OBJEXT)
-rm -f Ahuacatl/ast-node.$(OBJEXT)
-rm -f Ahuacatl/error.$(OBJEXT)
-rm -f Ahuacatl/grammar.$(OBJEXT)
-rm -f Ahuacatl/parser.$(OBJEXT)
-rm -f Ahuacatl/tokens.$(OBJEXT)
-rm -f ApplicationServer/ApplicationServer.$(OBJEXT)
-rm -f ApplicationServer/ApplicationServerImpl.$(OBJEXT)
-rm -f ApplicationServer/ApplicationServerSchedulerImpl.$(OBJEXT)
@ -2128,14 +2138,15 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@Admin/$(DEPDIR)/RestAdminLogHandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Admin/$(DEPDIR)/RestBaseHandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Admin/$(DEPDIR)/RestVersionHandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/ahuacatl-bind-parameter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/ahuacatl-error.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/ahuacatl-functions.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/ahuacatl-grammar.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/ahuacatl-parser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/ahuacatl-tokens.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/ast-codegen-js.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/ast-dump.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/ast-node.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/error.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/grammar.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/parser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@Ahuacatl/$(DEPDIR)/tokens.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ApplicationServer/$(DEPDIR)/ApplicationServer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ApplicationServer/$(DEPDIR)/ApplicationServerImpl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ApplicationServer/$(DEPDIR)/ApplicationServerSchedulerImpl.Po@am__quote@
@ -2977,7 +2988,7 @@ start-server:
unittests-shell-server:
@echo
@echo "================================================================================"
@echo "|| SHELL SERVER TESTS (BASCIS) ||"
@echo "|| SHELL SERVER TESTS (BASICS) ||"
@echo "================================================================================"
@echo

View File

@ -122,7 +122,7 @@ unittests-boost:
endif
################################################################################
## SHELL SERVER TESTS (BASCIS)
## SHELL SERVER TESTS (BASICS)
################################################################################
SHELL_SERVER = @srcdir@/js/common/tests/shell-document.js \
@ -136,7 +136,7 @@ UNITTESTS_SERVER = $(addprefix --unit-tests ,$(SHELL_SERVER))
unittests-shell-server:
@echo
@echo "================================================================================"
@echo "|| SHELL SERVER TESTS (BASCIS) ||"
@echo "|| SHELL SERVER TESTS (BASICS) ||"
@echo "================================================================================"
@echo
@ -153,7 +153,10 @@ unittests-shell-server:
## SHELL SERVER TESTS (AHUACATL)
################################################################################
SHELL_SERVER_AHUACATL = @srcdir@/js/server/tests/ahuacatl-queries-collection.js \
SHELL_SERVER_AHUACATL = @srcdir@/js/server/tests/ahuacatl-operators.js \
@srcdir@/js/server/tests/ahuacatl-escaping.js \
@srcdir@/js/server/tests/ahuacatl-functions.js \
@srcdir@/js/server/tests/ahuacatl-queries-collection.js \
@srcdir@/js/server/tests/ahuacatl-queries-noncollection.js

View File

@ -860,7 +860,7 @@ int AvocadoServer::executeShell (bool tests) {
char* input = console->prompt("avocado> ");
if (input == 0) {
printf("<ctrl-D>\nBye Bye! Auf Wiedersehen!\n");
printf("<ctrl-D>\nBye Bye! Auf Wiedersehen! さようなら\n");
break;
}

View File

@ -46,7 +46,7 @@
#include "SkipLists/sl-operator.h"
#include "Ahuacatl/ast-node.h"
#include "Ahuacatl/ast-codegen-js.h"
#include "Ahuacatl/parser.h"
#include "Ahuacatl/ahuacatl-parser.h"
using namespace std;
using namespace triagens::basics;
@ -2279,6 +2279,8 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
}
string queryString = TRI_ObjectToString(queryArg);
/* currently unused, causes compile warnings
// return number of total records in cursor?
bool doCount = false;
if (argv.Length() > 0) {
@ -2293,26 +2295,38 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
max = (uint32_t) maxValue;
}
}
*/
v8::Handle<v8::Value> result;
TRI_json_t* parameters = NULL;
TRI_aql_parse_context_t* context;
context = TRI_CreateParseContextAql(vocbase, queryString.c_str());
context = TRI_CreateParseContextAql(vocbase, queryString.c_str());
if (!context) {
return scope.Close(v8::ThrowException(v8::String::New("out of memory")));
}
if (argv.Length() > 1) {
parameters = ConvertHelper(argv[1]);
if (!TRI_AddBindParametersAql(context, parameters)) {
v8::Handle<v8::Object> errorObject = CreateErrorObjectAhuacatl(&context->_error);
TRI_FreeJson(parameters);
TRI_FreeParseContextAql(context);
return scope.Close(errorObject);
}
}
if (Ahuacatlparse(context)) {
if (parameters) {
TRI_FreeJson(parameters);
}
if (!TRI_ParseQueryAql(context)) {
v8::Handle<v8::Object> errorObject = CreateErrorObjectAhuacatl(&context->_error);
TRI_FreeParseContextAql(context);
return scope.Close(errorObject);
}
if (argv.Length() > 1) {
parameters = ConvertHelper(argv[1]);
}
if (context->_first) {
char* code = TRI_GenerateCodeAql((TRI_aql_node_t*) context->_first);
@ -2324,10 +2338,6 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
}
TRI_FreeParseContextAql(context);
if (parameters) {
TRI_FreeJson(parameters);
}
return scope.Close(result);
}

View File

@ -71,6 +71,7 @@ namespace triagens {
_separator = ',';
regcomp(&_doubleRegex, "^[-+]?([0-9]+\\.?[0-9]*|\\.[0-9]+)([eE][-+]?[0-8]+)?$", REG_ICASE | REG_EXTENDED);
regcomp(&_intRegex, "^[-+]?([0-9]+)$", REG_ICASE | REG_EXTENDED);
_hasError = false;
}
ImportHelper::~ImportHelper () {
@ -89,9 +90,17 @@ namespace triagens {
_outputBuffer.clear();
_lineBuffer.clear();
_errorMessage = "";
_hasError = false;
// read and convert
int fd = open(fileName.c_str(), O_RDONLY);
int fd;
if (fileName == "-") {
fd = STDIN_FILENO;
}
else {
fd = open(fileName.c_str(), O_RDONLY);
}
if (fd < 0) {
_errorMessage = TRI_LAST_ERROR_STR;
@ -111,7 +120,7 @@ namespace triagens {
char buffer[10240];
while (true) {
while (!_hasError) {
v8::HandleScope scope;
ssize_t n = read(fd, buffer, sizeof (buffer));
@ -134,9 +143,12 @@ namespace triagens {
TRI_DestroyCsvParser(&parser);
close(fd);
if (fileName != "-") {
close(fd);
}
return true;
_outputBuffer.clear();
return !_hasError;
}
bool ImportHelper::importJson (const string& collectionName, const string& fileName) {
@ -147,9 +159,17 @@ namespace triagens {
_numberError = 0;
_outputBuffer.clear();
_errorMessage = "";
_hasError = false;
// read and convert
int fd = open(fileName.c_str(), O_RDONLY);
int fd;
if (fileName == "-") {
fd = STDIN_FILENO;
}
else {
fd = open(fileName.c_str(), O_RDONLY);
}
if (fd < 0) {
_errorMessage = TRI_LAST_ERROR_STR;
@ -158,7 +178,7 @@ namespace triagens {
char buffer[10240];
while (true) {
while (!_hasError) {
ssize_t n = read(fd, buffer, sizeof(buffer));
if (n < 0) {
@ -192,9 +212,12 @@ namespace triagens {
_numberLines = _numberError + _numberOk;
close(fd);
if (fileName != "-") {
close(fd);
}
return true;
_outputBuffer.clear();
return !_hasError;
}
@ -333,6 +356,10 @@ namespace triagens {
}
void ImportHelper::sendCsvBuffer () {
if (_hasError) {
return;
}
map<string, string> headerFields;
SimpleHttpResult* result = _client->request(SimpleHttpClient::POST, "/_api/import?collection=" + StringUtils::urlEncode(_collectionName), _outputBuffer.c_str(), _outputBuffer.length(), headerFields);
@ -342,12 +369,14 @@ namespace triagens {
}
void ImportHelper::sendJsonBuffer (char const* str, size_t len) {
if (_hasError) {
return;
}
map<string, string> headerFields;
SimpleHttpResult* result = _client->request(SimpleHttpClient::POST, "/_api/import?type=documents&collection=" + StringUtils::urlEncode(_collectionName), str, len, headerFields);
handleResult(result);
_outputBuffer.clear();
}
void ImportHelper::handleResult (SimpleHttpResult* result) {
@ -361,7 +390,11 @@ namespace triagens {
VariantBoolean* vb = va->lookupBoolean("error");
if (vb && vb->getValue()) {
// is error
_hasError = true;
VariantString* vs = va->lookupString("errorMessage");
if (vs) {
_errorMessage = vs->getValue();
}
}
VariantInt64* vi = va->lookupInt64("created");

View File

@ -200,6 +200,7 @@ namespace triagens {
regex_t _doubleRegex;
regex_t _intRegex;
bool _hasError;
string _errorMessage;
};
}

View File

@ -33,6 +33,7 @@
#include "Basics/ProgramOptions.h"
#include "Basics/ProgramOptionsDescription.h"
#include "Basics/StringUtils.h"
#include "Basics/FileUtils.h"
#include "BasicsC/files.h"
#include "BasicsC/init.h"
#include "BasicsC/logging.h"
@ -40,7 +41,6 @@
#include "Logger/Logger.h"
#include "SimpleHttpClient/SimpleHttpClient.h"
#include "SimpleHttpClient/SimpleHttpResult.h"
#include "ImportHelper.h"
#include "V8ClientConnection.h"
@ -156,7 +156,7 @@ static void ParseProgramOptions (int argc, char* argv[]) {
("help,h", "help message")
("log.level,l", &level, "log level")
("server", &ServerAddress, "server address and port")
("file", &FileName, "file name")
("file", &FileName, "file name (\"-\" for STDIN)")
("collection", &CollectionName, "collection name")
("type", &TypeImport, "type of file (\"csv\" or \"json\")")
("quote", &QuoteChar, "quote character")
@ -271,6 +271,11 @@ int main (int argc, char* argv[]) {
cout << "file name is missing." << endl;
return EXIT_FAILURE;
}
if (FileName != "-" && !FileUtils::isRegularFile(FileName)) {
cout << "file '" << FileName << "' is not a regular file." << endl;
return EXIT_FAILURE;
}
bool ok;
if (TypeImport == "csv") {

View File

@ -78,6 +78,8 @@ ModuleCache["/internal"].exports.errors = {
"ERROR_QUERY_LIMIT_VALUE_OUT_OF_RANGE" : { "code" : 1521, "message" : "limit value '%s' is out of range" },
"ERROR_QUERY_VARIABLE_REDECLARED" : { "code" : 1522, "message" : "variable '%s' is assigned multiple times" },
"ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED" : { "code" : 1523, "message" : "document attribute '%s' is assigned multiple times" },
"ERROR_QUERY_VARIABLE_NAME_INVALID" : { "code" : 1524, "message" : "variable name '%s' has an invalid format" },
"ERROR_QUERY_BIND_PARAMETERS_INVALID" : { "code" : 1525, "message" : "invalid structure of bind parameters" },
"ERROR_CURSOR_NOT_FOUND" : { "code" : 1600, "message" : "cursor not found" },
"ERROR_SESSION_USERHANDLER_URL_INVALID" : { "code" : 1700, "message" : "expecting <prefix>/user/<username>" },
"ERROR_SESSION_USERHANDLER_CANNOT_CREATE_USER" : { "code" : 1701, "message" : "cannot create user" },

View File

@ -79,6 +79,8 @@ static string JS_common_bootstrap_errors =
" \"ERROR_QUERY_LIMIT_VALUE_OUT_OF_RANGE\" : { \"code\" : 1521, \"message\" : \"limit value '%s' is out of range\" }, \n"
" \"ERROR_QUERY_VARIABLE_REDECLARED\" : { \"code\" : 1522, \"message\" : \"variable '%s' is assigned multiple times\" }, \n"
" \"ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED\" : { \"code\" : 1523, \"message\" : \"document attribute '%s' is assigned multiple times\" }, \n"
" \"ERROR_QUERY_VARIABLE_NAME_INVALID\" : { \"code\" : 1524, \"message\" : \"variable name '%s' has an invalid format\" }, \n"
" \"ERROR_QUERY_BIND_PARAMETERS_INVALID\" : { \"code\" : 1525, \"message\" : \"invalid structure of bind parameters\" }, \n"
" \"ERROR_CURSOR_NOT_FOUND\" : { \"code\" : 1600, \"message\" : \"cursor not found\" }, \n"
" \"ERROR_SESSION_USERHANDLER_URL_INVALID\" : { \"code\" : 1700, \"message\" : \"expecting <prefix>/user/<username>\" }, \n"
" \"ERROR_SESSION_USERHANDLER_CANNOT_CREATE_USER\" : { \"code\" : 1701, \"message\" : \"cannot create user\" }, \n"

View File

@ -79,7 +79,7 @@ function AHUACATL_CLONE (obj) {
////////////////////////////////////////////////////////////////////////////////
function AHUACATL_FCALL(name, parameters) {
return name(parameters);
return name.apply(null, parameters);
}
////////////////////////////////////////////////////////////////////////////////
@ -350,6 +350,13 @@ function AHUACATL_RELATIONAL_EQUAL (lhs, rhs) {
}
// primitive type
if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {
lhs = null;
}
if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {
rhs = null;
}
return (lhs === rhs);
}
@ -397,6 +404,13 @@ function AHUACATL_RELATIONAL_UNEQUAL (lhs, rhs) {
}
// primitive type
if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {
lhs = null;
}
if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {
rhs = null;
}
return (lhs !== rhs);
}
@ -453,6 +467,13 @@ function AHUACATL_RELATIONAL_GREATER_REC (lhs, rhs) {
}
// primitive type
if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {
lhs = null;
}
if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {
rhs = null;
}
if (lhs === rhs) {
return null;
}
@ -528,6 +549,13 @@ function AHUACATL_RELATIONAL_GREATEREQUAL_REC (lhs, rhs) {
}
// primitive type
if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {
lhs = null;
}
if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {
rhs = null;
}
if (lhs === rhs) {
return null;
}
@ -604,6 +632,13 @@ function AHUACATL_RELATIONAL_LESS_REC (lhs, rhs) {
}
// primitive type
if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {
lhs = null;
}
if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {
rhs = null;
}
if (lhs === rhs) {
return null;
}
@ -677,11 +712,18 @@ function AHUACATL_RELATIONAL_LESSEQUAL_REC (lhs, rhs) {
return null;
}
// primitive type
if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {
lhs = null;
}
if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {
rhs = null;
}
if (lhs === rhs) {
return null;
}
// primitive type
return (lhs <= rhs);
}
@ -752,7 +794,11 @@ function AHUACATL_UNARY_PLUS (value) {
throw "expecting number for unary plus";
}
return AHUACATL_NUMERIC_VALUE(value);
var result = AHUACATL_NUMERIC_VALUE(value);
if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {
throw "number out of range";
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
@ -766,7 +812,11 @@ function AHUACATL_UNARY_MINUS (value) {
throw "expecting number for unary minus";
}
return AHUACATL_NUMERIC_VALUE(-value);
var result = AHUACATL_NUMERIC_VALUE(-value);
if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {
throw "number out of range";
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
@ -781,7 +831,11 @@ function AHUACATL_ARITHMETIC_PLUS (lhs, rhs) {
throw "expecting numbers for plus";
}
return AHUACATL_NUMERIC_VALUE(lhs + rhs);
var result = AHUACATL_NUMERIC_VALUE(lhs + rhs);
if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {
throw "number out of range";
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
@ -796,7 +850,11 @@ function AHUACATL_ARITHMETIC_MINUS (lhs, rhs) {
throw "expecting numbers for minus";
}
return AHUACATL_NUMERIC_VALUE(lhs - rhs);
var result = AHUACATL_NUMERIC_VALUE(lhs - rhs);
if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {
throw "number out of range";
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
@ -811,7 +869,11 @@ function AHUACATL_ARITHMETIC_TIMES (lhs, rhs) {
throw "expecting numbers for times";
}
return AHUACATL_NUMERIC_VALUE(lhs * rhs);
var result = AHUACATL_NUMERIC_VALUE(lhs * rhs);
if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {
throw "number out of range";
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
@ -830,7 +892,11 @@ function AHUACATL_ARITHMETIC_DIVIDE (lhs, rhs) {
throw "division by zero";
}
return AHUACATL_NUMERIC_VALUE(lhs / rhs);
var result = AHUACATL_NUMERIC_VALUE(lhs / rhs);
if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {
throw "number out of range";
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
@ -849,7 +915,11 @@ function AHUACATL_ARITHMETIC_MODULUS (lhs, rhs) {
throw "division by zero";
}
return AHUACATL_NUMERIC_VALUE(lhs % rhs);
var result = AHUACATL_NUMERIC_VALUE(lhs % rhs);
if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {
throw "number out of range";
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
@ -871,13 +941,24 @@ function AHUACATL_ARITHMETIC_MODULUS (lhs, rhs) {
/// both operands must be strings or this function will fail
////////////////////////////////////////////////////////////////////////////////
function AHUACATL_STRING_CONCAT (lhs, rhs) {
if (AHUACATL_TYPEWEIGHT(lhs) !== AHUACATL_TYPEWEIGHT_STRING ||
AHUACATL_TYPEWEIGHT(rhs) !== AHUACATL_TYPEWEIGHT_STRING) {
throw "expecting strings for string concatenation";
function AHUACATL_STRING_CONCAT () {
var result = '';
for (var i in arguments) {
var element = arguments[i];
if (AHUACATL_TYPEWEIGHT(element) === AHUACATL_TYPEWEIGHT_NULL) {
continue;
}
if (AHUACATL_TYPEWEIGHT(element) !== AHUACATL_TYPEWEIGHT_STRING) {
throw "expecting strings for string concatenation";
}
result += element;
}
return (lhs + rhs);
return result;
}
////////////////////////////////////////////////////////////////////////////////
@ -1135,14 +1216,66 @@ function AHUACATL_LIMIT (value, offset, count) {
/// @brief get the length of a list
////////////////////////////////////////////////////////////////////////////////
function AHUACATL_LENGTH (args) {
var value = args[0];
function AHUACATL_LENGTH () {
var value = arguments[0];
AHUACATL_LIST(value);
return value.length;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief merge all arguments
////////////////////////////////////////////////////////////////////////////////
function AHUACATL_MERGE () {
var result = { };
for (var i in arguments) {
var element = arguments[i];
if (AHUACATL_TYPEWEIGHT(element) !== AHUACATL_TYPEWEIGHT_DOCUMENT) {
throw "expecting documents for merge";
}
for (var k in element) {
if (!element.hasOwnProperty(k)) {
continue;
}
result[k] = element[k];
}
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create the union (all) of all arguments
////////////////////////////////////////////////////////////////////////////////
function AHUACATL_UNION () {
var result = [ ];
for (var i in arguments) {
var element = arguments[i];
if (AHUACATL_TYPEWEIGHT(element) !== AHUACATL_TYPEWEIGHT_LIST) {
throw "expecting lists for union";
}
for (var k in element) {
if (!element.hasOwnProperty(k)) {
continue;
}
result.push(element[k]);
}
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -80,7 +80,7 @@ static string JS_server_ahuacatl =
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"function AHUACATL_FCALL(name, parameters) {\n"
" return name(parameters);\n"
" return name.apply(null, parameters);\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
@ -351,6 +351,13 @@ static string JS_server_ahuacatl =
" }\n"
"\n"
" // primitive type\n"
" if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" lhs = null;\n"
" }\n"
" if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" rhs = null;\n"
" }\n"
"\n"
" return (lhs === rhs);\n"
"}\n"
"\n"
@ -398,6 +405,13 @@ static string JS_server_ahuacatl =
" }\n"
"\n"
" // primitive type\n"
" if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" lhs = null;\n"
" }\n"
" if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" rhs = null;\n"
" }\n"
"\n"
" return (lhs !== rhs);\n"
"}\n"
"\n"
@ -454,6 +468,13 @@ static string JS_server_ahuacatl =
" }\n"
"\n"
" // primitive type\n"
" if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" lhs = null;\n"
" }\n"
" if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" rhs = null;\n"
" }\n"
"\n"
" if (lhs === rhs) {\n"
" return null;\n"
" }\n"
@ -529,6 +550,13 @@ static string JS_server_ahuacatl =
" }\n"
"\n"
" // primitive type\n"
" if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" lhs = null;\n"
" }\n"
" if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" rhs = null;\n"
" }\n"
"\n"
" if (lhs === rhs) {\n"
" return null;\n"
" }\n"
@ -605,6 +633,13 @@ static string JS_server_ahuacatl =
" }\n"
"\n"
" // primitive type\n"
" if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" lhs = null;\n"
" }\n"
" if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" rhs = null;\n"
" }\n"
"\n"
" if (lhs === rhs) {\n"
" return null;\n"
" }\n"
@ -678,11 +713,18 @@ static string JS_server_ahuacatl =
" return null;\n"
" }\n"
" \n"
" // primitive type\n"
" if (AHUACATL_TYPEWEIGHT(lhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" lhs = null;\n"
" }\n"
" if (AHUACATL_TYPEWEIGHT(rhs) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" rhs = null;\n"
" }\n"
" \n"
" if (lhs === rhs) {\n"
" return null;\n"
" }\n"
"\n"
" // primitive type\n"
" return (lhs <= rhs);\n"
"}\n"
"\n"
@ -753,7 +795,11 @@ static string JS_server_ahuacatl =
" throw \"expecting number for unary plus\";\n"
" }\n"
"\n"
" return AHUACATL_NUMERIC_VALUE(value);\n"
" var result = AHUACATL_NUMERIC_VALUE(value);\n"
" if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {\n"
" throw \"number out of range\";\n"
" }\n"
" return result;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
@ -767,7 +813,11 @@ static string JS_server_ahuacatl =
" throw \"expecting number for unary minus\";\n"
" }\n"
"\n"
" return AHUACATL_NUMERIC_VALUE(-value);\n"
" var result = AHUACATL_NUMERIC_VALUE(-value);\n"
" if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {\n"
" throw \"number out of range\";\n"
" }\n"
" return result;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
@ -782,7 +832,11 @@ static string JS_server_ahuacatl =
" throw \"expecting numbers for plus\";\n"
" }\n"
"\n"
" return AHUACATL_NUMERIC_VALUE(lhs + rhs);\n"
" var result = AHUACATL_NUMERIC_VALUE(lhs + rhs);\n"
" if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {\n"
" throw \"number out of range\";\n"
" }\n"
" return result;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
@ -797,7 +851,11 @@ static string JS_server_ahuacatl =
" throw \"expecting numbers for minus\";\n"
" }\n"
"\n"
" return AHUACATL_NUMERIC_VALUE(lhs - rhs);\n"
" var result = AHUACATL_NUMERIC_VALUE(lhs - rhs);\n"
" if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {\n"
" throw \"number out of range\";\n"
" }\n"
" return result;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
@ -812,7 +870,11 @@ static string JS_server_ahuacatl =
" throw \"expecting numbers for times\";\n"
" }\n"
"\n"
" return AHUACATL_NUMERIC_VALUE(lhs * rhs);\n"
" var result = AHUACATL_NUMERIC_VALUE(lhs * rhs);\n"
" if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {\n"
" throw \"number out of range\";\n"
" }\n"
" return result;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
@ -831,7 +893,11 @@ static string JS_server_ahuacatl =
" throw \"division by zero\";\n"
" }\n"
"\n"
" return AHUACATL_NUMERIC_VALUE(lhs / rhs);\n"
" var result = AHUACATL_NUMERIC_VALUE(lhs / rhs);\n"
" if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {\n"
" throw \"number out of range\";\n"
" }\n"
" return result;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
@ -850,7 +916,11 @@ static string JS_server_ahuacatl =
" throw \"division by zero\";\n"
" }\n"
"\n"
" return AHUACATL_NUMERIC_VALUE(lhs % rhs);\n"
" var result = AHUACATL_NUMERIC_VALUE(lhs % rhs);\n"
" if (AHUACATL_TYPEWEIGHT(result) !== AHUACATL_TYPEWEIGHT_NUMBER) {\n"
" throw \"number out of range\";\n"
" }\n"
" return result;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
@ -872,13 +942,24 @@ static string JS_server_ahuacatl =
"/// both operands must be strings or this function will fail\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"function AHUACATL_STRING_CONCAT (lhs, rhs) {\n"
" if (AHUACATL_TYPEWEIGHT(lhs) !== AHUACATL_TYPEWEIGHT_STRING ||\n"
" AHUACATL_TYPEWEIGHT(rhs) !== AHUACATL_TYPEWEIGHT_STRING) {\n"
" throw \"expecting strings for string concatenation\";\n"
"function AHUACATL_STRING_CONCAT () {\n"
" var result = '';\n"
"\n"
" for (var i in arguments) {\n"
" var element = arguments[i];\n"
"\n"
" if (AHUACATL_TYPEWEIGHT(element) === AHUACATL_TYPEWEIGHT_NULL) {\n"
" continue;\n"
" }\n"
" \n"
" if (AHUACATL_TYPEWEIGHT(element) !== AHUACATL_TYPEWEIGHT_STRING) {\n"
" throw \"expecting strings for string concatenation\";\n"
" }\n"
"\n"
" result += element;\n"
" }\n"
"\n"
" return (lhs + rhs);\n"
" return result; \n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
@ -1136,8 +1217,8 @@ static string JS_server_ahuacatl =
"/// @brief get the length of a list\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"function AHUACATL_LENGTH (args) {\n"
" var value = args[0];\n"
"function AHUACATL_LENGTH () {\n"
" var value = arguments[0];\n"
"\n"
" AHUACATL_LIST(value);\n"
"\n"
@ -1145,6 +1226,58 @@ static string JS_server_ahuacatl =
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief merge all arguments\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"function AHUACATL_MERGE () {\n"
" var result = { };\n"
"\n"
" for (var i in arguments) {\n"
" var element = arguments[i];\n"
"\n"
" if (AHUACATL_TYPEWEIGHT(element) !== AHUACATL_TYPEWEIGHT_DOCUMENT) {\n"
" throw \"expecting documents for merge\";\n"
" }\n"
"\n"
" for (var k in element) {\n"
" if (!element.hasOwnProperty(k)) {\n"
" continue;\n"
" }\n"
"\n"
" result[k] = element[k];\n"
" }\n"
" }\n"
"\n"
" return result; \n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief create the union (all) of all arguments\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"function AHUACATL_UNION () {\n"
" var result = [ ];\n"
"\n"
" for (var i in arguments) {\n"
" var element = arguments[i];\n"
"\n"
" if (AHUACATL_TYPEWEIGHT(element) !== AHUACATL_TYPEWEIGHT_LIST) {\n"
" throw \"expecting lists for union\";\n"
" }\n"
"\n"
" for (var k in element) {\n"
" if (!element.hasOwnProperty(k)) {\n"
" continue;\n"
" }\n"
"\n"
" result.push(element[k]);\n"
" }\n"
" }\n"
"\n"
" return result; \n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @}\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"

View File

@ -0,0 +1,177 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for query language, escaping
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-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
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function ahuacatlEscapingTestSuite () {
////////////////////////////////////////////////////////////////////////////////
/// @brief execute a given query
////////////////////////////////////////////////////////////////////////////////
function executeQuery (query) {
var cursor = AHUACATL_RUN(query, undefined);
if (cursor instanceof AvocadoQueryError) {
print(query, cursor.message);
}
assertFalse(cursor instanceof AvocadoQueryError);
return cursor;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief execute a given query and return the results as an array
////////////////////////////////////////////////////////////////////////////////
function getQueryResults (query, isFlat) {
var result = executeQuery(query);
var results = [ ];
for (var i in result) {
if (!result.hasOwnProperty(i)) {
continue;
}
var row = result[i];
if (isFlat) {
results.push(row);
}
else {
var keys = [ ];
for (var k in row) {
if (row.hasOwnProperty(k) && k != '_id' && k != '_rev') {
keys.push(k);
}
}
keys.sort();
var resultRow = { };
for (var k in keys) {
if (keys.hasOwnProperty(k)) {
resultRow[keys[k]] = row[keys[k]];
}
}
results.push(resultRow);
}
}
return results;
}
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test simple name handling
////////////////////////////////////////////////////////////////////////////////
testSimpleName : function () {
var expected = [ 1, 2, 3 ];
var actual = getQueryResults("FOR `x` IN [ 1, 2, 3 ] RETURN `x`", true);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test reserved name handling
////////////////////////////////////////////////////////////////////////////////
testReservedNames1 : function () {
var expected = [ 1, 2, 3 ];
var names = [ "for", "let", "return", "sort", "collect", "limit", "filter", "asc", "desc", "in", "into" ];
for (var i in names) {
if (!names.hasOwnProperty(i)) {
continue;
}
var actual = getQueryResults("FOR `" + names[i] + "` IN [ 1, 2, 3 ] RETURN `" + names[i] + "`", true);
assertEqual(expected, actual);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test reserved names handling
////////////////////////////////////////////////////////////////////////////////
testReservedNames2 : function () {
var expected = [ { "let" : 1 }, { "collect" : 2 }, { "sort" : 3 } ];
var actual = getQueryResults("FOR `for` IN [ { \"let\" : 1 }, { \"collect\" : 2 }, { \"sort\" : 3 } ] RETURN `for`", false);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test punctuation names escaping
////////////////////////////////////////////////////////////////////////////////
testPunctuationName1 : function () {
var expected = [ 1, 2, 3 ];
var actual = getQueryResults("FOR `brown_fox` IN [ 1, 2, 3 ] RETURN `brown_fox`", true);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test punctuation names escaping
////////////////////////////////////////////////////////////////////////////////
testPunctuationName2 : function () {
var expected = [ 1, 2, 3 ];
var actual = getQueryResults("FOR `brown_fox__1234_` IN [ 1, 2, 3 ] RETURN `brown_fox__1234_`", true);
assertEqual(expected, actual);
},
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(ahuacatlEscapingTestSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:

View File

@ -0,0 +1,209 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for query language, functions
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-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
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function ahuacatlFunctionsTestSuite () {
////////////////////////////////////////////////////////////////////////////////
/// @brief execute a given query
////////////////////////////////////////////////////////////////////////////////
function executeQuery (query) {
var cursor = AHUACATL_RUN(query, undefined);
if (cursor instanceof AvocadoQueryError) {
print(query, cursor.message);
}
assertFalse(cursor instanceof AvocadoQueryError);
return cursor;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief execute a given query and return the results as an array
////////////////////////////////////////////////////////////////////////////////
function getQueryResults (query, isFlat) {
var result = executeQuery(query);
var results = [ ];
for (var i in result) {
if (!result.hasOwnProperty(i)) {
continue;
}
var row = result[i];
if (isFlat) {
results.push(row);
}
else {
var keys = [ ];
for (var k in row) {
if (row.hasOwnProperty(k) && k != '_id' && k != '_rev') {
keys.push(k);
}
}
keys.sort();
var resultRow = { };
for (var k in keys) {
if (keys.hasOwnProperty(k)) {
resultRow[keys[k]] = row[keys[k]];
}
}
results.push(resultRow);
}
}
return results;
}
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test length function
////////////////////////////////////////////////////////////////////////////////
testLength : function () {
var expected = [ 4, 4, 4 ];
var actual = getQueryResults("FOR year IN [ 2010, 2011, 2012 ] LET quarters = ((FOR q IN [ 1, 2, 3, 4 ] return q)) return LENGTH(quarters)", true);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test concat function
////////////////////////////////////////////////////////////////////////////////
testConcat : function () {
var expected = [ "theQuickBrownFoxJumps" ];
var actual = getQueryResults("FOR r IN [ 1 ] return CONCAT('the', 'Quick', null, 'Brown', null, 'Fox', 'Jumps')", true);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test merge function
////////////////////////////////////////////////////////////////////////////////
testMerge1 : function () {
var expected = [ { "quarter" : 1, "year" : 2010 }, { "quarter" : 2, "year" : 2010 }, { "quarter" : 3, "year" : 2010 }, { "quarter" : 4, "year" : 2010 }, { "quarter" : 1, "year" : 2011 }, { "quarter" : 2, "year" : 2011 }, { "quarter" : 3, "year" : 2011 }, { "quarter" : 4, "year" : 2011 }, { "quarter" : 1, "year" : 2012 }, { "quarter" : 2, "year" : 2012 }, { "quarter" : 3, "year" : 2012 }, { "quarter" : 4, "year" : 2012 } ];
var actual = getQueryResults("FOR year IN [ 2010, 2011, 2012 ] FOR quarter IN [ 1, 2, 3, 4 ] return MERGE({ \"year\" : year }, { \"quarter\" : quarter })", false);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test merge function
////////////////////////////////////////////////////////////////////////////////
testMerge2 : function () {
var expected = [ { "age" : 15, "isAbove18" : false, "name" : "John" }, { "age" : 19, "isAbove18" : true, "name" : "Corey" } ];
var actual = getQueryResults("FOR u IN [ { \"name\" : \"John\", \"age\" : 15 }, { \"name\" : \"Corey\", \"age\" : 19 } ] return MERGE(u, { \"isAbove18\" : u.age >= 18 })", false);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test merge function
////////////////////////////////////////////////////////////////////////////////
testMerge3 : function () {
var expected = [ { "age" : 15, "id" : 9, "name" : "John" }, { "age" : 19, "id" : 9, "name" : "Corey" } ];
var actual = getQueryResults("FOR u IN [ { \"id\" : 100, \"name\" : \"John\", \"age\" : 15 }, { \"id\" : 101, \"name\" : \"Corey\", \"age\" : 19 } ] return MERGE(u, { \"id\" : 9 })", false);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test merge function
////////////////////////////////////////////////////////////////////////////////
testMerge4 : function () {
var expected = [ { "age" : 15, "id" : 33, "name" : "foo" }, { "age" : 19, "id" : 33, "name" : "foo" } ];
var actual = getQueryResults("FOR u IN [ { \"id\" : 100, \"name\" : \"John\", \"age\" : 15 }, { \"id\" : 101, \"name\" : \"Corey\", \"age\" : 19 } ] return MERGE(u, { \"id\" : 9 }, { \"name\" : \"foo\", \"id\" : 33 })", false);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test union function
////////////////////////////////////////////////////////////////////////////////
testUnion1 : function () {
var expected = [ [ 1, 2, 3, 1, 2, 3 ], [ 1, 2, 3, 1, 2, 3 ] ];
var actual = getQueryResults("FOR u IN [ 1, 2 ] return UNION([ 1, 2, 3 ], [ 1, 2, 3 ])", true);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test union function
////////////////////////////////////////////////////////////////////////////////
testUnion2 : function () {
var expected = [ [ 1, 2, 3, 3, 2, 1 ], [ 1, 2, 3, 3, 2, 1 ] ];
var actual = getQueryResults("FOR u IN [ 1, 2 ] return UNION([ 1, 2, 3 ], [ 3, 2, 1 ])", true);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test union function
////////////////////////////////////////////////////////////////////////////////
testUnion3 : function () {
var expected = [ "Fred", "John", "John", "Amy" ];
var actual = getQueryResults("FOR u IN UNION([ \"Fred\", \"John\" ], [ \"John\", \"Amy\"]) return u", true);
assertEqual(expected, actual);
},
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(ahuacatlFunctionsTestSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:

File diff suppressed because it is too large Load Diff

View File

@ -507,18 +507,16 @@ function ahuacatlQueryCollectionTestSuite () {
testCollectSimple : function () {
var expected = [ { "gender" : "f", "numUsers" : 10 }, { "gender" : "m", "numUsers" : 10 } ];
var actual = getQueryResults("FOR u in " + users.name() + " COLLECT gender = u.gender INTO g SORT gender ASC RETURN { \"gender\" : gender, \"numUsers\" : LENGTH(g) }", false);
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test collect with filter
////////////////////////////////////////////////////////////////////////////////
testCollectFiltered : function () {
var expected = [ { "gender" : "m", "numUsers" : 8 }, { "gender" : "f", "numUsers" : 8 } ];
actual = getQueryResults("FOR u in " + users.name() + " FILTER u.active == true COLLECT gender = u.gender INTO g SORT gender DESC RETURN { \"gender\" : gender, \"numUsers\" : LENGTH(g) }", false);
assertEqual(expected, actual);
},
@ -529,7 +527,6 @@ function ahuacatlQueryCollectionTestSuite () {
testCollectMultipleCriteria : function () {
var expected = [ { "active" : false, "gender" : "m", "numUsers" : 2 }, { "active" : true, "gender" : "m", "numUsers" : 8 }, { "active" : false, "gender" : "f", "numUsers" : 2 }, { "active" : true, "gender" : "f", "numUsers" : 8 } ];
actual = getQueryResults("FOR u in " + users.name() + " COLLECT gender = u.gender, active = u.active INTO g SORT gender DESC, active ASC RETURN { \"gender\" : gender, \"active\" : active, \"numUsers\" : LENGTH(g) }", false);
assertEqual(expected, actual);
},

View File

@ -32,8 +32,6 @@ var jsunity = require("jsunity");
////////////////////////////////////////////////////////////////////////////////
function ahuacatlQueryNonCollectionTestSuite () {
var users = null;
var relations = null;
////////////////////////////////////////////////////////////////////////////////
/// @brief execute a given query