mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:triAGENS/AvocadoDB
This commit is contained in:
commit
fb5034b0cf
|
@ -35,11 +35,553 @@
|
||||||
// --SECTION-- private functions
|
// --SECTION-- private functions
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief hash a variable
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static uint64_t HashFieldAccess (TRI_associative_pointer_t* array,
|
||||||
|
void const* element) {
|
||||||
|
TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) element;
|
||||||
|
|
||||||
|
return TRI_FnvHashString(fieldAccess->_fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief comparison function used to determine variable equality
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static bool EqualFieldAccess (TRI_associative_pointer_t* array,
|
||||||
|
void const* key,
|
||||||
|
void const* element) {
|
||||||
|
TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) element;
|
||||||
|
|
||||||
|
return TRI_EqualString(key, fieldAccess->_fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int TypeWeight (const TRI_json_t* const value) {
|
||||||
|
switch (value->_type) {
|
||||||
|
case TRI_JSON_BOOLEAN:
|
||||||
|
return 1;
|
||||||
|
case TRI_JSON_NUMBER:
|
||||||
|
return 2;
|
||||||
|
case TRI_JSON_STRING:
|
||||||
|
return 3;
|
||||||
|
case TRI_JSON_LIST:
|
||||||
|
return 4;
|
||||||
|
case TRI_JSON_ARRAY:
|
||||||
|
return 5;
|
||||||
|
case TRI_JSON_NULL:
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Compare (const TRI_json_t* const lhs, const TRI_json_t* const rhs) {
|
||||||
|
int lWeight = TypeWeight(lhs);
|
||||||
|
int rWeight = TypeWeight(rhs);
|
||||||
|
|
||||||
|
if (lWeight < rWeight) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (lWeight > rWeight) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// equal weight
|
||||||
|
switch (lhs->_type) {
|
||||||
|
case TRI_JSON_NULL:
|
||||||
|
return 0; // null == null;
|
||||||
|
case TRI_JSON_BOOLEAN:
|
||||||
|
if (lhs->_value._boolean == rhs->_value._boolean) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!lhs->_value._boolean && rhs->_value._boolean) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
case TRI_JSON_NUMBER:
|
||||||
|
if (lhs->_value._number == rhs->_value._number) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (lhs->_value._number < rhs->_value._number) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
case TRI_JSON_STRING:
|
||||||
|
return strcmp(lhs->_value._string.data, rhs->_value._string.data);
|
||||||
|
case TRI_JSON_LIST: {
|
||||||
|
size_t nl = lhs->_value._objects._length;
|
||||||
|
size_t nr = rhs->_value._objects._length;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < nl; ++i) {
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (i >= nr) {
|
||||||
|
// left list is longer
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = Compare(TRI_AtVector(&lhs->_value._objects, i), TRI_AtVector(&rhs->_value._objects, i));
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// right list is longer
|
||||||
|
if (nr > nl) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case TRI_JSON_ARRAY: {
|
||||||
|
size_t nl = lhs->_value._objects._length;
|
||||||
|
size_t nr = rhs->_value._objects._length;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < nl; i += 2) {
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (i > nr) {
|
||||||
|
// left list is longer
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare key
|
||||||
|
result = Compare(TRI_AtVector(&lhs->_value._objects, i), TRI_AtVector(&rhs->_value._objects, i));
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare value
|
||||||
|
result = Compare(TRI_AtVector(&lhs->_value._objects, i + 1), TRI_AtVector(&rhs->_value._objects, i + 1));
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// right list is longer
|
||||||
|
if (nr > nl) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsSameValue (const TRI_json_t* const lhs, const TRI_json_t* const rhs) {
|
||||||
|
if (!lhs || !rhs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs->_type != rhs->_type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (lhs->_type) {
|
||||||
|
case TRI_JSON_NULL:
|
||||||
|
return true;
|
||||||
|
case TRI_JSON_BOOLEAN:
|
||||||
|
return (lhs->_value._boolean == rhs->_value._boolean);
|
||||||
|
case TRI_JSON_NUMBER:
|
||||||
|
return (lhs->_value._number == rhs->_value._number); // TODO: handle epsilon
|
||||||
|
case TRI_JSON_STRING:
|
||||||
|
return TRI_EqualString(lhs->_value._string.data, rhs->_value._string.data);
|
||||||
|
case TRI_JSON_LIST:
|
||||||
|
case TRI_JSON_ARRAY: {
|
||||||
|
// lists and arrays can be treated the same here
|
||||||
|
size_t n = lhs->_value._objects._length;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (n != rhs->_value._objects._length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
if (!IsSameValue(TRI_AtVector(&lhs->_value._objects, i), TRI_AtVector(&rhs->_value._objects, i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsInList (const TRI_json_t* const lhs, const TRI_json_t* const rhs) {
|
||||||
|
size_t n;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!lhs || !rhs || !rhs->_type == TRI_JSON_LIST) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = rhs->_value._objects._length;
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
TRI_json_t* r = (TRI_json_t*) TRI_AtVector(&rhs->_value._objects, i);
|
||||||
|
|
||||||
|
if (IsSameValue(lhs, r)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* AccessName (const TRI_aql_access_e type) {
|
||||||
|
switch (type) {
|
||||||
|
case TRI_AQL_ACCESS_ALL:
|
||||||
|
return "all";
|
||||||
|
case TRI_AQL_ACCESS_IMPOSSIBLE:
|
||||||
|
return "impossible";
|
||||||
|
case TRI_AQL_ACCESS_EXACT:
|
||||||
|
return "exact";
|
||||||
|
case TRI_AQL_ACCESS_LIST:
|
||||||
|
return "list";
|
||||||
|
case TRI_AQL_ACCESS_SINGLE_RANGE:
|
||||||
|
return "single range";
|
||||||
|
case TRI_AQL_ACCESS_DOUBLE_RANGE:
|
||||||
|
return "double range";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static TRI_aql_field_access_t* MergeAccess (TRI_aql_context_t* const context,
|
||||||
|
TRI_aql_field_access_t* lhs,
|
||||||
|
TRI_aql_field_access_t* rhs) {
|
||||||
|
assert(lhs);
|
||||||
|
assert(rhs);
|
||||||
|
|
||||||
|
assert(lhs->_fieldName != NULL);
|
||||||
|
assert(rhs->_fieldName != NULL);
|
||||||
|
|
||||||
|
if (lhs->_type > rhs->_type) {
|
||||||
|
// swap operands so they are always sorted
|
||||||
|
TRI_aql_field_access_t* tmp = lhs;
|
||||||
|
lhs = rhs;
|
||||||
|
rhs = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs->_type == TRI_AQL_ACCESS_ALL) {
|
||||||
|
// TODO: free lhs
|
||||||
|
return rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs->_type == TRI_AQL_ACCESS_IMPOSSIBLE) {
|
||||||
|
// TODO: free rhs
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs->_type == TRI_AQL_ACCESS_EXACT) {
|
||||||
|
if (rhs->_type == TRI_AQL_ACCESS_EXACT) {
|
||||||
|
if (!IsSameValue(lhs->_value._exactValue, rhs->_value._exactValue)) {
|
||||||
|
// lhs and rhs values are non-identical
|
||||||
|
lhs->_type = TRI_AQL_ACCESS_IMPOSSIBLE;
|
||||||
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, lhs->_value._exactValue);
|
||||||
|
// TODO: free rhs
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lhs and rhs values are identical
|
||||||
|
// TODO: free rhs
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
else if (rhs->_type == TRI_AQL_ACCESS_LIST) {
|
||||||
|
if (!IsInList(lhs->_value._exactValue, rhs->_value._list)) {
|
||||||
|
// lhs value is not in rhs list
|
||||||
|
lhs->_type = TRI_AQL_ACCESS_IMPOSSIBLE;
|
||||||
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, lhs->_value._exactValue);
|
||||||
|
// TODO: free rhs
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lhs value is contained in rhs
|
||||||
|
// TODO: free rhs
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
else if (rhs->_type == TRI_AQL_ACCESS_SINGLE_RANGE) {
|
||||||
|
// check if value is in range
|
||||||
|
int result = Compare(lhs->_value._exactValue, rhs->_value._singleRange._value);
|
||||||
|
|
||||||
|
bool contained = ((rhs->_value._singleRange._type == TRI_AQL_RANGE_LOWER_EXCLUDED && result > 0) ||
|
||||||
|
(rhs->_value._singleRange._type == TRI_AQL_RANGE_LOWER_INCLUDED && result >= 0) ||
|
||||||
|
(rhs->_value._singleRange._type == TRI_AQL_RANGE_UPPER_EXCLUDED && result < 0) ||
|
||||||
|
(rhs->_value._singleRange._type == TRI_AQL_RANGE_UPPER_INCLUDED && result <= 0));
|
||||||
|
|
||||||
|
if (!contained) {
|
||||||
|
// lhs value is not contained in rhs range
|
||||||
|
lhs->_type = TRI_AQL_ACCESS_IMPOSSIBLE;
|
||||||
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, lhs->_value._exactValue);
|
||||||
|
// TODO: free rhs
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lhs value is contained in rhs range
|
||||||
|
// TODO: free lhs
|
||||||
|
return rhs;
|
||||||
|
}
|
||||||
|
else if (rhs->_type == TRI_AQL_ACCESS_DOUBLE_RANGE) {
|
||||||
|
// check if value is in range
|
||||||
|
int result;
|
||||||
|
bool contained;
|
||||||
|
|
||||||
|
result = Compare(lhs->_value._exactValue, rhs->_value._between._lower._value);
|
||||||
|
|
||||||
|
contained = ((rhs->_value._between._lower._type == TRI_AQL_RANGE_LOWER_EXCLUDED && result > 0) ||
|
||||||
|
(rhs->_value._between._lower._type == TRI_AQL_RANGE_LOWER_INCLUDED && result >= 0));
|
||||||
|
|
||||||
|
if (!contained) {
|
||||||
|
// lhs value is not contained in rhs range
|
||||||
|
lhs->_type = TRI_AQL_ACCESS_IMPOSSIBLE;
|
||||||
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, lhs->_value._exactValue);
|
||||||
|
// TODO: free rhs
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = Compare(lhs->_value._exactValue, rhs->_value._between._upper._value);
|
||||||
|
|
||||||
|
contained = ((rhs->_value._between._upper._type == TRI_AQL_RANGE_UPPER_EXCLUDED && result < 0) ||
|
||||||
|
(rhs->_value._between._upper._type == TRI_AQL_RANGE_UPPER_INCLUDED && result <= 0));
|
||||||
|
|
||||||
|
if (!contained) {
|
||||||
|
// lhs value is not contained in rhs range
|
||||||
|
lhs->_type = TRI_AQL_ACCESS_IMPOSSIBLE;
|
||||||
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, lhs->_value._exactValue);
|
||||||
|
// TODO: free rhs
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lhs value is contained in rhs range
|
||||||
|
// TODO: free lhs
|
||||||
|
return rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs->_type == TRI_AQL_ACCESS_LIST) {
|
||||||
|
if (rhs->_type == TRI_AQL_ACCESS_LIST) {
|
||||||
|
// make a list of both
|
||||||
|
}
|
||||||
|
else if (rhs->_type == TRI_AQL_ACCESS_SINGLE_RANGE) {
|
||||||
|
// check if value in range
|
||||||
|
}
|
||||||
|
else if (rhs->_type == TRI_AQL_ACCESS_DOUBLE_RANGE) {
|
||||||
|
// check if value in range
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs->_type == TRI_AQL_ACCESS_SINGLE_RANGE) {
|
||||||
|
if (rhs->_type == TRI_AQL_ACCESS_SINGLE_RANGE) {
|
||||||
|
// check if value in range
|
||||||
|
}
|
||||||
|
else if (rhs->_type == TRI_AQL_ACCESS_DOUBLE_RANGE) {
|
||||||
|
// check if value in range
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhs->_type == TRI_AQL_ACCESS_DOUBLE_RANGE) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static TRI_aql_field_access_t* CreateAccess (TRI_aql_context_t* const context,
|
||||||
|
const TRI_aql_field_name_t* const field,
|
||||||
|
const TRI_aql_node_type_e operator,
|
||||||
|
const TRI_aql_node_t* const node) {
|
||||||
|
TRI_aql_field_access_t* fieldAccess;
|
||||||
|
TRI_json_t* value;
|
||||||
|
|
||||||
|
value = TRI_NodeJsonAql(context, node);
|
||||||
|
if (!value) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldAccess = (TRI_aql_field_access_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_field_access_t), false);
|
||||||
|
if (fieldAccess == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldAccess->_fieldName = TRI_DuplicateString(field->_name._buffer);
|
||||||
|
if (fieldAccess->_fieldName == NULL) {
|
||||||
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, fieldAccess);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operator == AQL_NODE_OPERATOR_BINARY_EQ) {
|
||||||
|
fieldAccess->_type = TRI_AQL_ACCESS_EXACT;
|
||||||
|
fieldAccess->_value._exactValue = value;
|
||||||
|
}
|
||||||
|
else if (operator == AQL_NODE_OPERATOR_BINARY_LT) {
|
||||||
|
fieldAccess->_type = TRI_AQL_ACCESS_SINGLE_RANGE;
|
||||||
|
fieldAccess->_value._singleRange._type = TRI_AQL_RANGE_UPPER_EXCLUDED;
|
||||||
|
fieldAccess->_value._singleRange._value = value;
|
||||||
|
}
|
||||||
|
else if (operator == AQL_NODE_OPERATOR_BINARY_LE) {
|
||||||
|
fieldAccess->_type = TRI_AQL_ACCESS_SINGLE_RANGE;
|
||||||
|
fieldAccess->_value._singleRange._type = TRI_AQL_RANGE_UPPER_INCLUDED;
|
||||||
|
fieldAccess->_value._singleRange._value = value;
|
||||||
|
}
|
||||||
|
else if (operator == AQL_NODE_OPERATOR_BINARY_GT) {
|
||||||
|
fieldAccess->_type = TRI_AQL_ACCESS_SINGLE_RANGE;
|
||||||
|
fieldAccess->_value._singleRange._type = TRI_AQL_RANGE_LOWER_EXCLUDED;
|
||||||
|
fieldAccess->_value._singleRange._value = value;
|
||||||
|
}
|
||||||
|
else if (operator == AQL_NODE_OPERATOR_BINARY_GE) {
|
||||||
|
fieldAccess->_type = TRI_AQL_ACCESS_SINGLE_RANGE;
|
||||||
|
fieldAccess->_value._singleRange._type = TRI_AQL_RANGE_LOWER_INCLUDED;
|
||||||
|
fieldAccess->_value._singleRange._value = value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fieldAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void CreateFieldAccess (TRI_aql_context_t* const context,
|
||||||
|
const TRI_aql_field_name_t* const field,
|
||||||
|
const TRI_aql_node_type_e operator,
|
||||||
|
const TRI_aql_node_t* const node) {
|
||||||
|
TRI_aql_field_access_t* previous;
|
||||||
|
TRI_aql_field_access_t* fieldAccess;
|
||||||
|
|
||||||
|
if (!field || !field->_name._buffer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldAccess = CreateAccess(context, field, operator, node);
|
||||||
|
if (!fieldAccess) {
|
||||||
|
// TODO: mark failure
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous = (TRI_aql_field_access_t*) TRI_LookupByKeyAssociativePointer(&context->_ranges, field->_name._buffer);
|
||||||
|
if (previous) {
|
||||||
|
printf("ENTER MERGE\n");
|
||||||
|
TRI_aql_field_access_t* merged = MergeAccess(context, fieldAccess, previous);
|
||||||
|
printf("LEAVE MERGE\n");
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// free previous
|
||||||
|
// free fieldAccess
|
||||||
|
if (merged) {
|
||||||
|
TRI_InsertKeyAssociativePointer(&context->_ranges, fieldAccess->_fieldName, merged, true);
|
||||||
|
printf("MERGE1\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// previous access exists, must merge
|
||||||
|
// merge(previous, new)
|
||||||
|
// TRI_InsertKeyAssociativePointer(&context
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// no previous access exists, no need to merge
|
||||||
|
TRI_InsertKeyAssociativePointer(&context->_ranges, fieldAccess->_fieldName, fieldAccess, false);
|
||||||
|
printf("INSERT1\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @addtogroup Ahuacatl
|
/// @addtogroup Ahuacatl
|
||||||
/// @{
|
/// @{
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static TRI_aql_field_name_t* GetFieldName (TRI_aql_context_t* const context,
|
||||||
|
const TRI_aql_node_t* const node) {
|
||||||
|
if (node->_type == AQL_NODE_ATTRIBUTE_ACCESS) {
|
||||||
|
TRI_aql_field_name_t* field = GetFieldName(context, TRI_AQL_NODE_MEMBER(node, 0));
|
||||||
|
|
||||||
|
if (!field) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRI_AppendCharStringBuffer(&field->_name, '.');
|
||||||
|
TRI_AppendStringStringBuffer(&field->_name, TRI_AQL_NODE_STRING(node));
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
else if (node->_type == AQL_NODE_REFERENCE) {
|
||||||
|
TRI_aql_field_name_t* field;
|
||||||
|
|
||||||
|
field = (TRI_aql_field_name_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_field_name_t), false);
|
||||||
|
|
||||||
|
if (!field) {
|
||||||
|
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
field->_variable = TRI_AQL_NODE_STRING(node);
|
||||||
|
TRI_InitStringBuffer(&field->_name, TRI_UNKNOWN_MEM_ZONE);
|
||||||
|
TRI_AppendStringStringBuffer(&field->_name, TRI_AQL_NODE_STRING(node));
|
||||||
|
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief inspect a filter expression
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void InspectFilter (TRI_aql_context_t* const context,
|
||||||
|
TRI_aql_node_t* node) {
|
||||||
|
printf("ITERATION SOMETHING %s\n", TRI_NodeNameAql(node->_type));
|
||||||
|
if (node->_type == AQL_NODE_OPERATOR_UNARY_NOT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->_type == AQL_NODE_OPERATOR_BINARY_OR) {
|
||||||
|
TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
|
||||||
|
TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
|
||||||
|
|
||||||
|
InspectFilter(context, lhs);
|
||||||
|
InspectFilter(context, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->_type == AQL_NODE_OPERATOR_BINARY_AND) {
|
||||||
|
TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
|
||||||
|
TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
|
||||||
|
|
||||||
|
InspectFilter(context, lhs);
|
||||||
|
InspectFilter(context, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->_type == AQL_NODE_OPERATOR_BINARY_EQ ||
|
||||||
|
// node->_type == AQL_NODE_OPERATOR_BINARY_NE ||
|
||||||
|
node->_type == AQL_NODE_OPERATOR_BINARY_LT ||
|
||||||
|
node->_type == AQL_NODE_OPERATOR_BINARY_LE ||
|
||||||
|
node->_type == AQL_NODE_OPERATOR_BINARY_GT ||
|
||||||
|
node->_type == AQL_NODE_OPERATOR_BINARY_GE) {
|
||||||
|
TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
|
||||||
|
TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
|
||||||
|
|
||||||
|
if (lhs->_type == AQL_NODE_ATTRIBUTE_ACCESS) {
|
||||||
|
TRI_aql_field_name_t* field = GetFieldName(context, lhs);
|
||||||
|
|
||||||
|
if (field) {
|
||||||
|
CreateFieldAccess(context, field, node->_type, rhs);
|
||||||
|
TRI_DestroyStringBuffer(&field->_name);
|
||||||
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lhs->_type == AQL_NODE_ATTRIBUTE_ACCESS) {
|
||||||
|
TRI_aql_field_name_t* field = GetFieldName(context, rhs);
|
||||||
|
|
||||||
|
if (field) {
|
||||||
|
CreateFieldAccess(context, field, node->_type, lhs);
|
||||||
|
TRI_DestroyStringBuffer(&field->_name);
|
||||||
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief create javascript function code for a relational operation
|
/// @brief create javascript function code for a relational operation
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -265,7 +807,12 @@ static TRI_aql_node_t* OptimiseFilter (TRI_aql_context_t* const context,
|
||||||
TRI_aql_node_t* expression = TRI_AQL_NODE_MEMBER(node, 0);
|
TRI_aql_node_t* expression = TRI_AQL_NODE_MEMBER(node, 0);
|
||||||
bool result;
|
bool result;
|
||||||
|
|
||||||
if (!expression || !TRI_IsConstantValueNodeAql(expression)) {
|
if (!expression) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TRI_IsConstantValueNodeAql(expression)) {
|
||||||
|
//InspectFilter(context, expression);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,6 +1105,32 @@ static TRI_aql_node_t* OptimiseBinaryArithmeticOperation (TRI_aql_context_t* con
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief mark a for node
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static TRI_aql_node_t* MarkFor (TRI_aql_context_t* const context,
|
||||||
|
TRI_aql_node_t* node) {
|
||||||
|
TRI_aql_node_t* nameNode = TRI_AQL_NODE_MEMBER(node, 0);
|
||||||
|
TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 1);
|
||||||
|
|
||||||
|
if (!nameNode || !expressionNode) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expressionNode->_type == AQL_NODE_COLLECTION) {
|
||||||
|
char* varName = TRI_AQL_NODE_STRING(nameNode);
|
||||||
|
char* collectionName = TRI_AQL_NODE_STRING(expressionNode);
|
||||||
|
|
||||||
|
if (!varName || !collectionName) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief fold constants in a node
|
/// @brief fold constants in a node
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -598,6 +1171,8 @@ static TRI_aql_node_t* ModifyNode (void* data, TRI_aql_node_t* node) {
|
||||||
return OptimiseFilter(context, node);
|
return OptimiseFilter(context, node);
|
||||||
case AQL_NODE_FCALL:
|
case AQL_NODE_FCALL:
|
||||||
return OptimiseFcall(context, node);
|
return OptimiseFcall(context, node);
|
||||||
|
case AQL_NODE_FOR:
|
||||||
|
// return MarkFor(context, node);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -625,6 +1200,14 @@ static TRI_aql_node_t* ModifyNode (void* data, TRI_aql_node_t* node) {
|
||||||
TRI_aql_node_t* TRI_FoldConstantsAql (TRI_aql_context_t* const context,
|
TRI_aql_node_t* TRI_FoldConstantsAql (TRI_aql_context_t* const context,
|
||||||
TRI_aql_node_t* node) {
|
TRI_aql_node_t* node) {
|
||||||
TRI_aql_modify_tree_walker_t* walker;
|
TRI_aql_modify_tree_walker_t* walker;
|
||||||
|
|
||||||
|
// todo: must free
|
||||||
|
TRI_InitAssociativePointer(&context->_ranges,
|
||||||
|
TRI_UNKNOWN_MEM_ZONE,
|
||||||
|
&TRI_HashStringKeyAssociativePointer,
|
||||||
|
&HashFieldAccess,
|
||||||
|
&EqualFieldAccess,
|
||||||
|
NULL);
|
||||||
|
|
||||||
walker = TRI_CreateModifyTreeWalkerAql((void*) context, &ModifyNode);
|
walker = TRI_CreateModifyTreeWalkerAql((void*) context, &ModifyNode);
|
||||||
if (!walker) {
|
if (!walker) {
|
||||||
|
@ -635,7 +1218,33 @@ TRI_aql_node_t* TRI_FoldConstantsAql (TRI_aql_context_t* const context,
|
||||||
node = TRI_ModifyWalkTreeAql(walker, node);
|
node = TRI_ModifyWalkTreeAql(walker, node);
|
||||||
|
|
||||||
TRI_FreeModifyTreeWalkerAql(walker);
|
TRI_FreeModifyTreeWalkerAql(walker);
|
||||||
|
/*
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < context->_ranges._nrAlloc; ++i) {
|
||||||
|
TRI_aql_field_access_t* fieldAccess = context->_ranges._table[i];
|
||||||
|
|
||||||
|
if (!fieldAccess) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nFIELD ACCESS\n- FIELD: %s\n",fieldAccess->_fieldName);
|
||||||
|
printf("- TYPE: %s\n", AccessName(fieldAccess->_type));
|
||||||
|
if (fieldAccess->_type == TRI_AQL_ACCESS_EXACT) {
|
||||||
|
TRI_string_buffer_t b;
|
||||||
|
TRI_InitStringBuffer(&b, TRI_UNKNOWN_MEM_ZONE);
|
||||||
|
TRI_StringifyJson(&b, fieldAccess->_value._exactValue);
|
||||||
|
|
||||||
|
printf("- VALUE: %s\n", b._buffer);
|
||||||
|
}
|
||||||
|
else if (fieldAccess->_type == TRI_AQL_ACCESS_SINGLE_RANGE) {
|
||||||
|
TRI_string_buffer_t b;
|
||||||
|
TRI_InitStringBuffer(&b, TRI_UNKNOWN_MEM_ZONE);
|
||||||
|
TRI_StringifyJson(&b, fieldAccess->_value._singleRange._value);
|
||||||
|
|
||||||
|
printf("- VALUE: %s\n", b._buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include <BasicsC/common.h>
|
#include <BasicsC/common.h>
|
||||||
#include <BasicsC/strings.h>
|
#include <BasicsC/strings.h>
|
||||||
|
#include <BasicsC/string-buffer.h>
|
||||||
#include <BasicsC/hashes.h>
|
#include <BasicsC/hashes.h>
|
||||||
#include <BasicsC/logging.h>
|
#include <BasicsC/logging.h>
|
||||||
#include <BasicsC/vector.h>
|
#include <BasicsC/vector.h>
|
||||||
|
@ -51,6 +52,66 @@ extern "C" {
|
||||||
/// @{
|
/// @{
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief access type
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TRI_AQL_RANGE_LOWER_EXCLUDED,
|
||||||
|
TRI_AQL_RANGE_LOWER_INCLUDED,
|
||||||
|
TRI_AQL_RANGE_UPPER_EXCLUDED,
|
||||||
|
TRI_AQL_RANGE_UPPER_INCLUDED
|
||||||
|
}
|
||||||
|
TRI_aql_range_e;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TRI_AQL_ACCESS_ALL = 0,
|
||||||
|
TRI_AQL_ACCESS_IMPOSSIBLE,
|
||||||
|
TRI_AQL_ACCESS_EXACT,
|
||||||
|
TRI_AQL_ACCESS_LIST,
|
||||||
|
TRI_AQL_ACCESS_SINGLE_RANGE,
|
||||||
|
TRI_AQL_ACCESS_DOUBLE_RANGE,
|
||||||
|
}
|
||||||
|
TRI_aql_access_e;
|
||||||
|
|
||||||
|
typedef struct TRI_aql_range_s {
|
||||||
|
TRI_json_t* _value;
|
||||||
|
TRI_aql_range_e _type;
|
||||||
|
}
|
||||||
|
TRI_aql_range_t;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief attribute access container used during optimisation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef struct TRI_aql_field_access_s {
|
||||||
|
char* _fieldName;
|
||||||
|
TRI_aql_access_e _type;
|
||||||
|
union {
|
||||||
|
TRI_json_t* _exactValue;
|
||||||
|
TRI_json_t* _list;
|
||||||
|
TRI_aql_range_t _singleRange;
|
||||||
|
struct {
|
||||||
|
TRI_aql_range_t _lower;
|
||||||
|
TRI_aql_range_t _upper;
|
||||||
|
}
|
||||||
|
_between;
|
||||||
|
}
|
||||||
|
_value;
|
||||||
|
}
|
||||||
|
TRI_aql_field_access_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct TRI_aql_field_name_s {
|
||||||
|
const char* _variable;
|
||||||
|
TRI_string_buffer_t _name;
|
||||||
|
}
|
||||||
|
TRI_aql_field_name_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief fold constants recursively
|
/// @brief fold constants recursively
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -82,6 +82,7 @@ typedef struct TRI_aql_context_s {
|
||||||
TRI_associative_pointer_t _parameterValues;
|
TRI_associative_pointer_t _parameterValues;
|
||||||
TRI_associative_pointer_t _parameterNames;
|
TRI_associative_pointer_t _parameterNames;
|
||||||
TRI_associative_pointer_t _collectionNames;
|
TRI_associative_pointer_t _collectionNames;
|
||||||
|
TRI_associative_pointer_t _ranges;
|
||||||
size_t _variableIndex;
|
size_t _variableIndex;
|
||||||
void* _first;
|
void* _first;
|
||||||
char* _query;
|
char* _query;
|
||||||
|
|
|
@ -60,6 +60,59 @@ static bool AppendListValues (TRI_string_buffer_t* const buffer,
|
||||||
/// @{
|
/// @{
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief create a json struct from a value node
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TRI_json_t* TRI_NodeJsonAql (TRI_aql_context_t* const context,
|
||||||
|
const TRI_aql_node_t* const node) {
|
||||||
|
switch (node->_type) {
|
||||||
|
case AQL_NODE_VALUE: {
|
||||||
|
switch (node->_value._type) {
|
||||||
|
case AQL_TYPE_FAIL:
|
||||||
|
case AQL_TYPE_NULL:
|
||||||
|
return TRI_CreateNullJson(TRI_UNKNOWN_MEM_ZONE);
|
||||||
|
case AQL_TYPE_BOOL:
|
||||||
|
return TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, node->_value._value._bool);
|
||||||
|
case AQL_TYPE_INT:
|
||||||
|
return TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, (double) node->_value._value._int);
|
||||||
|
case AQL_TYPE_DOUBLE:
|
||||||
|
return TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, node->_value._value._double);
|
||||||
|
case AQL_TYPE_STRING:
|
||||||
|
return TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, node->_value._value._string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case AQL_NODE_LIST: {
|
||||||
|
TRI_json_t* result = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE);
|
||||||
|
size_t i, n;
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
n = node->_members._length;
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, TRI_NodeJsonAql(context, TRI_AQL_NODE_MEMBER(node, i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case AQL_NODE_ARRAY: {
|
||||||
|
TRI_json_t* result = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
|
||||||
|
size_t i, n;
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
n = node->_members._length;
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
TRI_aql_node_t* element = TRI_AQL_NODE_MEMBER(node, i);
|
||||||
|
TRI_InsertArrayJson(TRI_UNKNOWN_MEM_ZONE, result, TRI_AQL_NODE_STRING(element), TRI_NodeJsonAql(context, TRI_AQL_NODE_MEMBER(element, 0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief create a value node from a json struct
|
/// @brief create a value node from a json struct
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -48,6 +48,13 @@ extern "C" {
|
||||||
/// @{
|
/// @{
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief create a json struct from a value node
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TRI_json_t* TRI_NodeJsonAql (TRI_aql_context_t* const,
|
||||||
|
const TRI_aql_node_t* const);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief create a value node from a json struct
|
/// @brief create a value node from a json struct
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -209,6 +209,9 @@ pre ul li span{
|
||||||
.ui-tabs-nav {
|
.ui-tabs-nav {
|
||||||
font-size: 0.8em !important;
|
font-size: 0.8em !important;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
-webkit-box-shadow: inset 0 0 1px 1px #f6f6f6 !important;
|
||||||
|
-moz-box-shadow: inset 0 0 1px 1px #f6f6f6 !important;
|
||||||
|
box-shadow: inset 0 0 1px 1px #f6f6f6 !important;
|
||||||
//border-bottom: 0px !important;
|
//border-bottom: 0px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,7 @@ else {
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var collectionTable = $('#collectionsTableID').dataTable({
|
var collectionTable = $('#collectionsTableID').dataTable({
|
||||||
|
"aaSorting": [[ 2, "desc" ]],
|
||||||
"bPaginate": false,
|
"bPaginate": false,
|
||||||
"bFilter": false,
|
"bFilter": false,
|
||||||
"bLengthChange": false,
|
"bLengthChange": false,
|
||||||
|
@ -152,7 +153,7 @@ var collectionTable = $('#collectionsTableID').dataTable({
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var documentEditTable = $('#documentEditTableID').dataTable({
|
var documentEditTable = $('#documentEditTableID').dataTable({
|
||||||
"aaSorting": [],
|
"aaSorting": [[ 1, "desc" ]],
|
||||||
"bFilter": false,
|
"bFilter": false,
|
||||||
"bPaginate":false,
|
"bPaginate":false,
|
||||||
"bSortable": false,
|
"bSortable": false,
|
||||||
|
@ -2030,4 +2031,3 @@ function stateReplace (value) {
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue