Exemple #1
0
static TRI_aql_node_t* OptimiseUnaryArithmeticOperation (TRI_aql_context_t* const context,
                                                         TRI_aql_node_t* node) {
  TRI_aql_node_t* operand = TRI_AQL_NODE_MEMBER(node, 0);
  
  assert(node->_type == TRI_AQL_NODE_OPERATOR_UNARY_PLUS ||
         node->_type == TRI_AQL_NODE_OPERATOR_UNARY_MINUS);

  if (!operand || !TRI_IsConstantValueNodeAql(operand)) {
    return node;
  }

  if (!TRI_IsNumericValueNodeAql(operand)) {
    TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE, NULL);
    return node;
  }
  

  if (node->_type == TRI_AQL_NODE_OPERATOR_UNARY_PLUS) {
    // + number => number
    node = operand;
  }
  else if (node->_type == TRI_AQL_NODE_OPERATOR_UNARY_MINUS) {
    // - number => eval!
    node = TRI_CreateNodeValueDoubleAql(context, - TRI_GetNumericNodeValueAql(operand));
    if (node == NULL) {
      TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
    }
  }

  return node;
}
TRI_aql_node_t* TRI_JsonNodeAql (TRI_aql_context_t* const context,
                                 const TRI_json_t* const json) {
  TRI_aql_node_t* node = NULL;
  char* value;

  switch (json->_type) {
    case TRI_JSON_UNUSED:
      break;

    case TRI_JSON_NULL:
      node = TRI_CreateNodeValueNullAql(context);
      break;

    case TRI_JSON_BOOLEAN:
      node = TRI_CreateNodeValueBoolAql(context, json->_value._boolean);
      break;

    case TRI_JSON_NUMBER:
      node = TRI_CreateNodeValueDoubleAql(context, json->_value._number);
      break;

    case TRI_JSON_STRING:
      value = TRI_RegisterStringAql(context, json->_value._string.data, strlen(json->_value._string.data), true);
      node = TRI_CreateNodeValueStringAql(context, value);
      break;

    case TRI_JSON_LIST: {
      size_t i;
      size_t n;

      node = TRI_CreateNodeListAql(context);
      n = json->_value._objects._length;

      for (i = 0; i < n; ++i) {
        TRI_json_t* subJson;
        TRI_aql_node_t* member;

        subJson = (TRI_json_t*) TRI_AtVector(&json->_value._objects, i);
        assert(subJson);

        member = TRI_JsonNodeAql(context, subJson);
        if (member) {
          TRI_PushBackVectorPointer(&node->_members, (void*) member);
        }
        else {
          TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
          return NULL;
        }
      }
      break;
    }
    case TRI_JSON_ARRAY: {
      size_t i;
      size_t n;

      node = TRI_CreateNodeArrayAql(context);
      n = json->_value._objects._length;

      for (i = 0; i < n; i += 2) {
        TRI_json_t* nameJson;
        TRI_json_t* valueJson;
        TRI_aql_node_t* member;
        TRI_aql_node_t* valueNode;
        char* name;

        // json_t containing the array element name
        nameJson = (TRI_json_t*) TRI_AtVector(&json->_value._objects, i);
        assert(nameJson);
        assert(nameJson->_value._string.data);
        name = TRI_RegisterStringAql(context, nameJson->_value._string.data, strlen(nameJson->_value._string.data), false);
        if (! name) {
          TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
          return NULL;
        }

        // json_t containing the array element value
        valueJson = (TRI_json_t*) TRI_AtVector(&json->_value._objects, i + 1);
        assert(valueJson);

        valueNode = TRI_JsonNodeAql(context, valueJson);
        if (! valueNode) {
          TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
          return NULL;
        }

        member = TRI_CreateNodeArrayElementAql(context, name, valueNode);
        if (member) {
          TRI_PushBackVectorPointer(&node->_members, (void*) member);
        }
        else {
          TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
          return NULL;
        }
      }
      break;
    }
  }

  if (! node) {
    TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
  }

  return node;
}
Exemple #3
0
static TRI_aql_node_t* OptimiseBinaryArithmeticOperation (TRI_aql_context_t* const context,
                                                          TRI_aql_node_t* node) {
  TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
  TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
  bool isEligibleLhs;
  bool isEligibleRhs;
  double value;
  
  if (!lhs || !rhs) {
    return node;
  } 

  isEligibleLhs = TRI_IsConstantValueNodeAql(lhs);
  isEligibleRhs = TRI_IsConstantValueNodeAql(rhs);

  if (isEligibleLhs && !TRI_IsNumericValueNodeAql(lhs)) {
    // node is not a numeric value => error
    TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE, NULL);
    return node;
  }

  
  if (isEligibleRhs && !TRI_IsNumericValueNodeAql(rhs)) {
    // node is not a numeric value => error
    TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE, NULL);
    return node;
  }
  

  if (!isEligibleLhs || !isEligibleRhs) {
    return node;
  }
  
  assert(node->_type == TRI_AQL_NODE_OPERATOR_BINARY_PLUS ||
         node->_type == TRI_AQL_NODE_OPERATOR_BINARY_MINUS ||
         node->_type == TRI_AQL_NODE_OPERATOR_BINARY_TIMES ||
         node->_type == TRI_AQL_NODE_OPERATOR_BINARY_DIV ||
         node->_type == TRI_AQL_NODE_OPERATOR_BINARY_MOD);

  if (node->_type == TRI_AQL_NODE_OPERATOR_BINARY_PLUS) {
    value = TRI_GetNumericNodeValueAql(lhs) + TRI_GetNumericNodeValueAql(rhs);
  }
  else if (node->_type == TRI_AQL_NODE_OPERATOR_BINARY_MINUS) {
    value = TRI_GetNumericNodeValueAql(lhs) - TRI_GetNumericNodeValueAql(rhs);
  }
  else if (node->_type == TRI_AQL_NODE_OPERATOR_BINARY_TIMES) {
    value = TRI_GetNumericNodeValueAql(lhs) * TRI_GetNumericNodeValueAql(rhs);
  }
  else if (node->_type == TRI_AQL_NODE_OPERATOR_BINARY_DIV) {
    if (TRI_GetNumericNodeValueAql(rhs) == 0.0) {
      // division by zero
      TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_DIVISION_BY_ZERO, NULL);
      return node;
    }
    value = TRI_GetNumericNodeValueAql(lhs) / TRI_GetNumericNodeValueAql(rhs);
  }
  else if (node->_type == TRI_AQL_NODE_OPERATOR_BINARY_MOD) {
    if (TRI_GetNumericNodeValueAql(rhs) == 0.0) {
      // division by zero
      TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_DIVISION_BY_ZERO, NULL);
      return node;
    }
    value = fmod(TRI_GetNumericNodeValueAql(lhs), TRI_GetNumericNodeValueAql(rhs));
  }
  else {
    value = 0.0;
  }
  
  node = TRI_CreateNodeValueDoubleAql(context, value);

  if (!node) {
    TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
    return NULL;
  }
  
  LOG_TRACE("optimised away binary arithmetic operation");

  return node;
}