Ejemplo n.º 1
0
void PartitionByPlanNode::loadFromJSONObject(PlannerDomValue obj)
{
    // Start with the base class.
    AggregatePlanNode::loadFromJSONObject(obj);
    // Read the sort expressions and directions.
    PlannerDomValue sortByColumnArray = obj.valueForKey("SORT_COLUMNS");
    for (int idx = 0; idx < sortByColumnArray.arrayLen(); idx += 1) {
        PlannerDomValue sortColumnValue = sortByColumnArray.valueAtIndex(idx);
        if (sortColumnValue.hasNonNullKey("SORT_EXPRESSION")) {
            PlannerDomValue exprDom = sortColumnValue.valueForKey("SORT_EXPRESSION");
            m_sortExpressions.push_back(AbstractExpression::buildExpressionTree(exprDom));
        } else {
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                                       "PartitionByPlanNode::loadFromJSONObject:"
                                                       " Missing sort expression.");
        }
        if (sortColumnValue.hasNonNullKey("SORT_DIRECTION")) {
            std::string dirStr = sortColumnValue.valueForKey("SORT_DIRECTION").asStr();
            m_sortDirections.push_back(stringToSortDirection(dirStr));
        } else {
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                                       "PartitionByPlanNode::loadFromJSONObject:"
                                                       " Missing sort direction.");
        }
    }
}
Ejemplo n.º 2
0
/** convert the enumerated value type into a concrete c type for the
 *  operator expression templated ctors */
static AbstractExpression *
operatorFactory(ExpressionType et,
                AbstractExpression *lc, AbstractExpression *rc)
{
    AbstractExpression *ret = NULL;

   switch(et) {
     case (EXPRESSION_TYPE_OPERATOR_PLUS):
       ret = new OperatorExpression<OpPlus>(et, lc, rc);
       break;

     case (EXPRESSION_TYPE_OPERATOR_MINUS):
       ret = new OperatorExpression<OpMinus>(et, lc, rc);
       break;

     case (EXPRESSION_TYPE_OPERATOR_MULTIPLY):
       ret = new OperatorExpression<OpMultiply>(et, lc, rc);
       break;

     case (EXPRESSION_TYPE_OPERATOR_DIVIDE):
       ret = new OperatorExpression<OpDivide>(et, lc, rc);
       break;

     case (EXPRESSION_TYPE_OPERATOR_NOT):
       ret = new OperatorNotExpression(lc);
       break;

     case (EXPRESSION_TYPE_OPERATOR_IS_NULL):
         ret = new OperatorIsNullExpression(lc);
         break;

     case (EXPRESSION_TYPE_OPERATOR_EXISTS):
         ret = new OperatorExistsExpression(lc);
         break;

     case (EXPRESSION_TYPE_OPERATOR_MOD):
       throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                     "Mod operator is not yet supported.");

     case (EXPRESSION_TYPE_OPERATOR_CONCAT):
       throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                     "Concat operator not yet supported.");

     default:
       throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                     "operator ctor helper out of sync");
   }
   return ret;
}
Ejemplo n.º 3
0
void AbstractPlanNode::loadSortListFromJSONObject(PlannerDomValue obj,
                                                      std::vector<AbstractExpression*> *sortExprs,
                                                      std::vector<SortDirectionType>   *sortDirs) {
    PlannerDomValue sortColumnsArray = obj.valueForKey("SORT_COLUMNS");

    for (int i = 0; i < sortColumnsArray.arrayLen(); i++) {
        PlannerDomValue sortColumn = sortColumnsArray.valueAtIndex(i);
        bool hasDirection = (sortDirs == NULL), hasExpression = (sortExprs == NULL);

        if (sortDirs && sortColumn.hasNonNullKey("SORT_DIRECTION")) {
            hasDirection = true;
            std::string sortDirectionStr = sortColumn.valueForKey("SORT_DIRECTION").asStr();
            sortDirs->push_back(stringToSortDirection(sortDirectionStr));
        }
        if (sortExprs && sortColumn.hasNonNullKey("SORT_EXPRESSION")) {
            hasExpression = true;
            PlannerDomValue exprDom = sortColumn.valueForKey("SORT_EXPRESSION");
            sortExprs->push_back(AbstractExpression::buildExpressionTree(exprDom));
        }

        if (!(hasExpression && hasDirection)) {
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                          "OrderByPlanNode::loadFromJSONObject:"
                                          " Does not have expression and direction.");
        }
    }
}
Ejemplo n.º 4
0
static AbstractExpression*
getGeneral(ExpressionType c,
           AbstractExpression *l,
           AbstractExpression *r)
{
    assert (l);
    assert (r);
    switch (c) {
    case (EXPRESSION_TYPE_COMPARE_EQUAL):
        return new ComparisonExpression<CmpEq>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_NOTEQUAL):
        return new ComparisonExpression<CmpNe>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LESSTHAN):
        return new ComparisonExpression<CmpLt>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_GREATERTHAN):
        return new ComparisonExpression<CmpGt>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LESSTHANOREQUALTO):
        return new ComparisonExpression<CmpLte>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_GREATERTHANOREQUALTO):
        return new ComparisonExpression<CmpGte>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LIKE):
        return new ComparisonExpression<CmpLike>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_IN):
        return new ComparisonExpression<CmpIn>(c, l, r);
    default:
        char message[256];
        snprintf(message, 256, "Invalid ExpressionType '%s' called"
                " for ComparisonExpression",
                expressionToString(c).c_str());
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, message);
    }
}
Ejemplo n.º 5
0
/**
 * Create an instance of a window aggregator for the specified aggregate type.
 * The object is allocated from the provided memory pool.
 */
inline WindowAggregate* getWindowedAggInstance(Pool& memoryPool,
                                               ExpressionType agg_type)
{
    WindowAggregate *answer = NULL;

    switch (agg_type) {
    case EXPRESSION_TYPE_AGGREGATE_WINDOWED_RANK:
        answer = new (memoryPool) WindowedRankAgg();
        break;
    case EXPRESSION_TYPE_AGGREGATE_WINDOWED_DENSE_RANK:
        answer = new (memoryPool) WindowedDenseRankAgg();
        break;
    case EXPRESSION_TYPE_AGGREGATE_WINDOWED_COUNT:
        answer = new (memoryPool) WindowedCountAgg();
        break;
    case EXPRESSION_TYPE_AGGREGATE_WINDOWED_MAX:
        answer = new (memoryPool) WindowedMaxAgg(memoryPool);
        break;
    case EXPRESSION_TYPE_AGGREGATE_WINDOWED_MIN:
        answer = new (memoryPool) WindowedMinAgg(memoryPool);
        break;
    case EXPRESSION_TYPE_AGGREGATE_WINDOWED_SUM:
        answer = new (memoryPool) WindowedSumAgg();
        break;
    default:
        {
            char message[128];
            snprintf(message, sizeof(message), "Unknown aggregate type %d", agg_type);
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, message);
        }
    }
    return answer;
}
Ejemplo n.º 6
0
static AbstractExpression*
getMoreSpecialized(ExpressionType c, L* l, R* r)
{
    assert (l);
    assert (r);
    switch (c) {
    case (EXPRESSION_TYPE_COMPARE_EQUAL):
        return new InlinedComparisonExpression<CmpEq, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_NOTEQUAL):
        return new InlinedComparisonExpression<CmpNe, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LESSTHAN):
        return new InlinedComparisonExpression<CmpLt, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_GREATERTHAN):
        return new InlinedComparisonExpression<CmpGt, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LESSTHANOREQUALTO):
        return new InlinedComparisonExpression<CmpLte, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_GREATERTHANOREQUALTO):
        return new InlinedComparisonExpression<CmpGte, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_LIKE):
        return new InlinedComparisonExpression<CmpLike, L, R>(c, l, r);
    case (EXPRESSION_TYPE_COMPARE_IN):
        return new InlinedComparisonExpression<CmpIn, L, R>(c, l, r);
    default:
        char message[256];
        snprintf(message, 256, "Invalid ExpressionType '%s' called for"
                " ComparisonExpression",expressionToString(c).c_str());
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, message);
    }
}
Ejemplo n.º 7
0
/** Parse JSON parameters to create a subquery expression */
static AbstractExpression*
subqueryFactory(ExpressionType subqueryType, PlannerDomValue obj, const std::vector<AbstractExpression*>* args) {
    int subqueryId = obj.valueForKey("SUBQUERY_ID").asInt();
    std::vector<int> paramIdxs;
    if (obj.hasNonNullKey("PARAM_IDX")) {
        PlannerDomValue params = obj.valueForKey("PARAM_IDX");
        int paramSize = params.arrayLen();
        paramIdxs.reserve(paramSize);
        if (args == NULL || args->size() != paramSize) {
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "subqueryFactory: parameter indexes/tve count mismatch");
        }
        for (int i = 0; i < paramSize; ++i) {
            int paramIdx = params.valueAtIndex(i).asInt();
            paramIdxs.push_back(paramIdx);
        }
    }
    std::vector<int> otherParamIdxs;
    if (obj.hasNonNullKey("OTHER_PARAM_IDX")) {
        PlannerDomValue otherParams = obj.valueForKey("OTHER_PARAM_IDX");
        int otherParamSize = otherParams.arrayLen();
        otherParamIdxs.reserve(otherParamSize);
        otherParamIdxs.reserve(otherParamSize);
        for (int i = 0; i < otherParamSize; ++i) {
            int paramIdx = otherParams.valueAtIndex(i).asInt();
            otherParamIdxs.push_back(paramIdx);
        }
    }
    return new SubqueryExpression(subqueryType, subqueryId, paramIdxs, otherParamIdxs, args);
}
Ejemplo n.º 8
0
/*
 * Create an instance of an aggregator for the specified aggregate type and "distinct" flag.
 * The object is allocated from the provided memory pool.
 */
inline Agg* getAggInstance(Pool& memoryPool, ExpressionType agg_type, bool isDistinct)
{
    switch (agg_type) {
    case EXPRESSION_TYPE_AGGREGATE_COUNT_STAR:
        return new (memoryPool) CountStarAgg();
    case EXPRESSION_TYPE_AGGREGATE_MIN:
        return new (memoryPool) MinAgg();
    case EXPRESSION_TYPE_AGGREGATE_MAX  :
        return new (memoryPool) MaxAgg();
    case EXPRESSION_TYPE_AGGREGATE_COUNT:
        if (isDistinct) {
            return new (memoryPool) CountAgg<Distinct>();
        }
        return new (memoryPool) CountAgg<NotDistinct>();
    case EXPRESSION_TYPE_AGGREGATE_SUM:
        if (isDistinct) {
            return new (memoryPool) SumAgg<Distinct>();
        }
        return new (memoryPool) SumAgg<NotDistinct>();
    case EXPRESSION_TYPE_AGGREGATE_AVG:
        if (isDistinct) {
            return new (memoryPool) AvgAgg<Distinct>();
        }
        return new (memoryPool) AvgAgg<NotDistinct>();
    default:
    {
        char message[128];
        snprintf(message, sizeof(message), "Unknown aggregate type %d", agg_type);
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, message);
    }
    }
}
Ejemplo n.º 9
0
boost::shared_ptr<ExecutorVector> ExecutorVector::fromJsonPlan(VoltDBEngine* engine,
                                                      const std::string& jsonPlan,
                                                      int64_t fragId) {
    PlanNodeFragment *pnf = NULL;
    try {
        pnf = PlanNodeFragment::createFromCatalog(jsonPlan);
    }
    catch (SerializableEEException &seee) {
        throw;
    }
    catch (...) {
        char msg[1024 * 100];
        snprintf(msg, 1024 * 100, "Unable to initialize PlanNodeFragment for PlanFragment '%jd' with plan:\n%s",
                 (intmax_t)fragId, jsonPlan.c_str());
        VOLT_ERROR("%s", msg);
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, msg);
    }
    VOLT_TRACE("\n%s\n", pnf->debug().c_str());
    assert(pnf->getRootNode());

    if (!pnf->getRootNode()) {
        char msg[1024];
        snprintf(msg, 1024, "Deserialized PlanNodeFragment for PlanFragment '%jd' does not have a root PlanNode",
                 (intmax_t)fragId);
        VOLT_ERROR("%s", msg);
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, msg);
    }

    int64_t tempTableLogLimit = engine->tempTableLogLimit();
    int64_t tempTableMemoryLimit = engine->tempTableMemoryLimit();

    // ENG-1333 HACK.  If the plan node fragment has a delete node,
    // then turn off the governors
    if (pnf->hasDelete()) {
        tempTableLogLimit = DEFAULT_TEMP_TABLE_MEMORY;
        tempTableMemoryLimit = -1;
    }

    // Note: the executor vector takes ownership of the plan node
    // fragment here.
    boost::shared_ptr<ExecutorVector> ev(new ExecutorVector(fragId,
                                                            tempTableLogLimit,
                                                            tempTableMemoryLimit,
                                                            pnf));
    ev->init(engine);
    return ev;
}
Ejemplo n.º 10
0
void MaterializedViewMetadata::processTupleDelete(TableTuple &oldTuple) {
    // don't change the view if this tuple doesn't match the predicate
    if (m_filterPredicate && (m_filterPredicate->eval(&oldTuple, NULL).isFalse()))
        return;

    // this will assert if the tuple isn't there as param expected is true
    findExistingTuple(oldTuple, true);

    // clear the tuple that will be built to insert or overwrite
    memset(m_updatedTupleBackingStore, 0, m_target->schema()->tupleLength() + 1);

    //printf("  Existing tuple: %s.\n", m_existingTuple.debugNoHeader().c_str());
    //fflush(stdout);

    // set up the first column, which is a count
    NValue count = m_existingTuple.getNValue(m_groupByColumnCount).op_decrement();

    //printf("  Count is: %d.\n", (int)(m_existingTuple.getSlimValue(m_groupByColumnCount).getBigInt()));
    //fflush(stdout);

    // check if we should remove the tuple
    if (count.isZero()) {
        m_target->deleteTuple(m_existingTuple, true);
        return;
    }
    // assume from here that we're just updating the existing row

    int colindex = 0;
    // set up the first n columns, based on group-by columns
    for (colindex = 0; colindex < m_groupByColumnCount; colindex++) {
        m_updatedTuple.setNValue(colindex, oldTuple.getNValue(m_groupByColumns[colindex]));
    }

    m_updatedTuple.setNValue(colindex, count);
    colindex++;

    // set values for the other columns
    for (int i = colindex; i < m_outputColumnCount; i++) {
        NValue oldValue = oldTuple.getNValue(m_outputColumnSrcTableIndexes[i]);
        NValue existingValue = m_existingTuple.getNValue(i);

        if (m_outputColumnAggTypes[i] == EXPRESSION_TYPE_AGGREGATE_SUM) {
            m_updatedTuple.setNValue(i, existingValue.op_subtract(oldValue));
        }
        else if (m_outputColumnAggTypes[i] == EXPRESSION_TYPE_AGGREGATE_COUNT) {
            m_updatedTuple.setNValue(i, existingValue.op_decrement());
        }
        else {
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                          "Error in materialized view table"
                                          " update.");
        }
    }

    // update the row
    // shouldn't need to update indexes as this shouldn't ever change the key
    m_target->updateTuple(m_updatedTuple, m_existingTuple, false);
}
Ejemplo n.º 11
0
void MaterializedViewMetadata::processTupleInsert(TableTuple &newTuple) {
    // don't change the view if this tuple doesn't match the predicate
    if (m_filterPredicate
        && (m_filterPredicate->eval(&newTuple, NULL).isFalse()))
        return;

    bool exists = findExistingTuple(newTuple);
    if (!exists) {
        // create a blank tuple
        m_existingTuple.move(m_emptyTupleBackingStore);
    }

    // clear the tuple that will be built to insert or overwrite
    memset(m_updatedTupleBackingStore, 0, m_target->schema()->tupleLength() + 1);

    int colindex = 0;
    // set up the first n columns, based on group-by columns
    for (colindex = 0; colindex < m_groupByColumnCount; colindex++) {
        m_updatedTuple.setNValue(colindex,
                                 newTuple.getNValue(m_groupByColumns[colindex]));
    }

    // set up the next column, which is a count
    m_updatedTuple.setNValue(colindex,
                             m_existingTuple.getNValue(colindex).op_increment());
    colindex++;

    // set values for the other columns
    for (int i = colindex; i < m_outputColumnCount; i++) {
        NValue newValue = newTuple.getNValue(m_outputColumnSrcTableIndexes[i]);
        NValue existingValue = m_existingTuple.getNValue(i);

        if (m_outputColumnAggTypes[i] == EXPRESSION_TYPE_AGGREGATE_SUM) {
            m_updatedTuple.setNValue(i, newValue.op_add(existingValue));
        }
        else if (m_outputColumnAggTypes[i] == EXPRESSION_TYPE_AGGREGATE_COUNT) {
            m_updatedTuple.setNValue(i, existingValue.op_increment());
        }
        else {
            char message[128];
            sprintf(message, "Error in materialized view table update for"
                    " col %d. Expression type %d", i, m_outputColumnAggTypes[i]);
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                          message);
        }
    }

    // update or insert the row
    if (exists) {
        // shouldn't need to update indexes as this shouldn't ever change the
        // key
        m_target->updateTuple(m_updatedTuple, m_existingTuple, false);
    }
    else {
        m_target->insertTuple(m_updatedTuple);
    }
}
Ejemplo n.º 12
0
void InsertPlanNode::loadFromJSONObject(json_spirit::Object &obj) {
    AbstractOperationPlanNode::loadFromJSONObject(obj);
    json_spirit::Value multiPartitionValue = json_spirit::find_value(obj, "MULTI_PARTITION");
    if (multiPartitionValue == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "InsertPlanNode::loadFromJSONObject:"
                                      " Can't find MULTI_PARTITION value");
    }
    m_multiPartition = multiPartitionValue.get_bool();
}
Ejemplo n.º 13
0
void AbstractOperationPlanNode::loadFromJSONObject(json_spirit::Object &obj, const catalog::Database *catalog_db) {
    json_spirit::Value targetTableNameValue = json_spirit::find_value( obj, "TARGET_TABLE_NAME");
    if (targetTableNameValue == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "AbstractOperationPlanNode::"
                                      "loadFromJSONObject: "
                                      "Couldn't find TARGET_TABLE_NAME value");
    }
    target_table_name = targetTableNameValue.get_str();
}
Ejemplo n.º 14
0
static AbstractExpression* caseWhenFactory(ValueType vt,
                                       AbstractExpression *lc, AbstractExpression *rc)
{

    OperatorAlternativeExpression* alternative = dynamic_cast<OperatorAlternativeExpression*> (rc);
    if (!rc) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "operator case when has incorrect expression");
    }
    return new OperatorCaseWhenExpression(vt, lc, alternative);
}
Ejemplo n.º 15
0
/** convert the enumerated value type into a concrete c type for
 * tuple value expression templated ctors */
static AbstractExpression*
tupleValueFactory(json_spirit::Object &obj, ExpressionType et,
                  AbstractExpression *lc, AbstractExpression *rc)
{
    // read the tuple value expression specific data
    json_spirit::Value valueIdxValue =
      json_spirit::find_value( obj, "COLUMN_IDX");

    json_spirit::Value tableName =
      json_spirit::find_value(obj, "TABLE_NAME");

    json_spirit::Value columnName =
      json_spirit::find_value(obj, "COLUMN_NAME");

    // verify input
    if (valueIdxValue == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "tupleValueFactory: Could not find"
                                      " COLUMN_IDX value");
    }
    if (valueIdxValue.get_int() < 0) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "tupleValueFactory: invalid column_idx.");
    }

    if (tableName == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "tupleValueFactory: no table name in TVE");
    }

    if (columnName == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "tupleValueFactory: no column name in"
                                      " TVE");
    }


    return new TupleValueExpression(valueIdxValue.get_int(),
                                    tableName.get_str(),
                                    columnName.get_str());
}
Ejemplo n.º 16
0
/** convert the enumerated value type into a concrete c type for
 * parameter value expression templated ctors */
static AbstractExpression*
parameterValueFactory(json_spirit::Object &obj,
                      ExpressionType et,
                      AbstractExpression *lc, AbstractExpression *rc)
{
    // read before ctor - can then instantiate fully init'd obj.
    json_spirit::Value paramIdxValue = json_spirit::find_value( obj, "PARAM_IDX");
    if (paramIdxValue == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "parameterValueFactory: Could not find"
                                      " PARAM_IDX value");
    }
    int param_idx = paramIdxValue.get_int();
    assert (param_idx >= 0);
    return new ParameterValueExpression(param_idx);
}
Ejemplo n.º 17
0
/** convert the enumerated value type into a concrete c type for
 * tuple value expression templated ctors */
static AbstractExpression*
tupleValueFactory(PlannerDomValue obj, ExpressionType et,
                  AbstractExpression *lc, AbstractExpression *rc)
{
    // read the tuple value expression specific data
    int columnIndex = obj.valueForKey("COLUMN_IDX").asInt();
    std::string tableName = obj.valueForKey("TABLE_NAME").asStr();

    // verify input
    if (columnIndex < 0) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "tupleValueFactory: invalid column_idx.");
    }

    //TODO: The columnName argument should be deprecated. The member is not used anywhere.
    return new TupleValueExpression(columnIndex, tableName, "");
}
Ejemplo n.º 18
0
static void raiseFunctionFactoryError(const std::string& nameString, int functionId,
                  const std::vector<AbstractExpression*>* args)
{
    char fn_message[1024];
    if (args) {
        snprintf(fn_message, sizeof(fn_message),
             "Internal Error: SQL function '%s' with ID (%d) with (%d) parameters is not implemented in VoltDB (or may have been incorrectly parsed)",
             nameString.c_str(), functionId, (int)args->size());
    }
    else {
        snprintf(fn_message, sizeof(fn_message),
             "Internal Error: SQL function '%s' with ID (%d) was serialized without its required parameters list.",
             nameString.c_str(), functionId);
    }
    DEBUG_ASSERT_OR_THROW_OR_CRASH(false, fn_message);
    throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, fn_message);
}
Ejemplo n.º 19
0
void InsertExecutor::p_execute_tuple(TableTuple &tuple) {
    // This should only be called from inlined insert executors because we have to change contexts every time
    ConditionalSynchronizedExecuteWithMpMemory possiblySynchronizedUseMpMemory(
            m_replicatedTableOperation, m_engine->isLowestSite(), &s_modifiedTuples, int64_t(-1));
    if (possiblySynchronizedUseMpMemory.okToExecute()) {
        p_execute_tuple_internal(tuple);
        s_modifiedTuples = m_modifiedTuples;
    }
    else {
        if (s_modifiedTuples == -1) {
            // An exception was thrown on the lowest site thread and we need to throw here as well so
            // all threads are in the same state
            char msg[1024];
            snprintf(msg, 1024, "Replicated table insert threw an unknown exception on other thread for table %s",
                    m_targetTable->name().c_str());
            VOLT_DEBUG("%s", msg);
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_REPLICATED_TABLE, msg);
        }
    }
}
Ejemplo n.º 20
0
bool InsertExecutor::p_execute(const NValueArray &params) {
    //
    // See p_execute_init above.  If we are inserting a
    // replicated table into an export table with no partition column,
    // we only insert on one site.  For all other sites we just
    // do nothing.
    //
    TableTuple inputTuple;
    const TupleSchema *inputSchema = m_inputTable->schema();
    {
        if (p_execute_init_internal(inputSchema, m_tmpOutputTable, inputTuple)) {
            ConditionalSynchronizedExecuteWithMpMemory possiblySynchronizedUseMpMemory(
                    m_replicatedTableOperation, m_engine->isLowestSite(), &s_modifiedTuples, int64_t(-1));
            if (possiblySynchronizedUseMpMemory.okToExecute()) {
                //
                // An insert is quite simple really. We just loop through our m_inputTable
                // and insert any tuple that we find into our targetTable. It doesn't get any easier than that!
                //
                TableIterator iterator = m_inputTable->iterator();
                while (iterator.next(inputTuple)) {
                    p_execute_tuple_internal(inputTuple);
                }
                s_modifiedTuples = m_modifiedTuples;
            }
            else {
                if (s_modifiedTuples == -1) {
                    // An exception was thrown on the lowest site thread and we need to throw here as well so
                    // all threads are in the same state
                    char msg[1024];
                    snprintf(msg, 1024, "Replicated table insert threw an unknown exception on other thread for table %s",
                            m_targetTable->name().c_str());
                    VOLT_DEBUG("%s", msg);
                    throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_REPLICATED_TABLE, msg);
                }
            }
        }
    }

    p_execute_finish();
    return true;
}
Ejemplo n.º 21
0
bool MaterializedViewMetadata::findExistingTuple(TableTuple &oldTuple, bool expected) {
    // find the key for this tuple (which is the group by columns)
    for (int i = 0; i < m_groupByColumnCount; i++)
        m_searchKey.setNValue(i, oldTuple.getNValue(m_groupByColumns[i]));

    // determine if the row exists (create the empty one if it doesn't)
    m_index->moveToKey(&m_searchKey);
    m_existingTuple = m_index->nextValueAtKey();
    if (m_existingTuple.isNullTuple()) {
        if (expected) {
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                          "MaterializedViewMetadata went"
                                          " looking for a tuple in the view and"
                                          " expected to find it but didn't");
        }
        return false;
    }
    else {
        return true;
    }
}
Ejemplo n.º 22
0
/*
 * Create an instance of an aggregator for the specified aggregate type and "distinct" flag.
 * The object is allocated from the provided memory pool.
 */
inline Agg* getAggInstance(Pool& memoryPool, ExpressionType agg_type, bool isDistinct)
{
    switch (agg_type) {
    case EXPRESSION_TYPE_AGGREGATE_COUNT_STAR:
        return new (memoryPool) CountStarAgg();
    case EXPRESSION_TYPE_AGGREGATE_MIN:
        return new (memoryPool) MinAgg(&memoryPool);
    case EXPRESSION_TYPE_AGGREGATE_MAX  :
        return new (memoryPool) MaxAgg(&memoryPool);
    case EXPRESSION_TYPE_AGGREGATE_COUNT:
        if (isDistinct) {
            return new (memoryPool) CountAgg<Distinct>(&memoryPool);
        }
        return new (memoryPool) CountAgg<NotDistinct>(&memoryPool);
    case EXPRESSION_TYPE_AGGREGATE_SUM:
        if (isDistinct) {
            return new (memoryPool) SumAgg<Distinct>();
        }
        return new (memoryPool) SumAgg<NotDistinct>();
    case EXPRESSION_TYPE_AGGREGATE_AVG:
        if (isDistinct) {
            return new (memoryPool) AvgAgg<Distinct>();
        }
        return new (memoryPool) AvgAgg<NotDistinct>();
    case EXPRESSION_TYPE_AGGREGATE_APPROX_COUNT_DISTINCT:
        return new (memoryPool) ApproxCountDistinctAgg();
    case EXPRESSION_TYPE_AGGREGATE_VALS_TO_HYPERLOGLOG:
        return new (memoryPool) ValsToHyperLogLogAgg();
    case EXPRESSION_TYPE_AGGREGATE_HYPERLOGLOGS_TO_CARD:
        return new (memoryPool) HyperLogLogsToCardAgg();
    default:
        {
            char message[128];
            snprintf(message, sizeof(message), "Unknown aggregate type %d", agg_type);
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, message);
        }
    }
}
Ejemplo n.º 23
0
void UnionPlanNode::loadFromJSONObject(PlannerDomValue obj)
{
    std::string unionTypeStr = obj.valueForKey("UNION_TYPE").asStr();
    if (unionTypeStr == "UNION") {
        m_unionType = UNION_TYPE_UNION;
    } else if (unionTypeStr == "UNION_ALL") {
        m_unionType = UNION_TYPE_UNION_ALL;
    } else if (unionTypeStr == "INTERSECT") {
        m_unionType = UNION_TYPE_INTERSECT;
    } else if (unionTypeStr == "INTERSECT_ALL") {
        m_unionType = UNION_TYPE_INTERSECT_ALL;
    } else if (unionTypeStr == "EXCEPT") {
        m_unionType = UNION_TYPE_EXCEPT;
    } else if (unionTypeStr == "EXCEPT_ALL") {
        m_unionType = UNION_TYPE_EXCEPT_ALL;
    } else if (unionTypeStr == "NOUNION") {
        m_unionType = UNION_TYPE_NOUNION;
    } else {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "UnionPlanNode::loadFromJSONObject:"
                                      " Unsupported UNION_TYPE value " +
                                      unionTypeStr);
    }
}
Ejemplo n.º 24
0
void Table::loadTuplesFrom(bool allowELT,
                            SerializeInput &serialize_io,
                            Pool *stringPool) {
    /*
     * directly receives a VoltTable buffer.
     * [00 01]   [02 03]   [04 .. 0x]
     * headersize  colcount  colcount * 1 byte (column types)
     *
     * [0x+1 .. 0y]
     * colcount * strings (column names)
     *
     * [0y+1 0y+2 0y+3 0y+4]
     * rowcount
     *
     * [0y+5 .. end]
     * rowdata
     */

    // todo: just skip ahead to this position
    serialize_io.readInt(); // rowstart
    serialize_io.readByte(); // status

    int16_t colcount = serialize_io.readShort();
    assert(colcount >= 0);

    // Store the following information so that we can provide them to the user
    // on failure
    ValueType types[colcount];
    std::string names[colcount];

    // skip the column types
    for (int i = 0; i < colcount; ++i) {
        types[i] = (ValueType) serialize_io.readEnumInSingleByte();
    }

    // skip the column names
    for (int i = 0; i < colcount; ++i) {
        names[i] = serialize_io.readTextString();
    }

    // Check if the column count matches what the temp table is expecting
    if (colcount != m_schema->columnCount()) {
        std::stringstream message(std::stringstream::in
                                  | std::stringstream::out);
        message << "Column count mismatch. Expecting "
                << m_schema->columnCount()
                << ", but " << colcount << " given" << std::endl;
        message << "Expecting the following columns:" << std::endl;
        message << debug() << std::endl;
        message << "The following columns are given:" << std::endl;
        for (int i = 0; i < colcount; i++) {
            message << "column " << i << ": " << names[i]
                    << ", type = " << getTypeName(types[i]) << std::endl;
        }
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      message.str().c_str());
    }

    int tupleCount = serialize_io.readInt();
    assert(tupleCount >= 0);

    // allocate required data blocks first to make them alligned well
    while (tupleCount + m_usedTuples > m_allocatedTuples) {
        allocateNextBlock();
    }

    for (int i = 0; i < tupleCount; ++i) {
        m_tmpTarget1.move(dataPtrForTuple((int) m_usedTuples + i));
        m_tmpTarget1.setDeletedFalse();
        m_tmpTarget1.setDirtyFalse();
        m_tmpTarget1.deserializeFrom(serialize_io, stringPool);

        processLoadedTuple( allowELT, m_tmpTarget1);
    }

    populateIndexes(tupleCount);

    m_tupleCount += tupleCount;
    m_usedTuples += tupleCount;
}
Ejemplo n.º 25
0
void Table::loadTuplesFrom(SerializeInputBE &serialInput,
                           Pool *stringPool,
                           ReferenceSerializeOutput *uniqueViolationOutput,
                           bool shouldDRStreamRow) {
    /*
     * directly receives a VoltTable buffer.
     * [00 01]   [02 03]   [04 .. 0x]
     * rowstart  colcount  colcount * 1 byte (column types)
     *
     * [0x+1 .. 0y]
     * colcount * strings (column names)
     *
     * [0y+1 0y+2 0y+3 0y+4]
     * rowcount
     *
     * [0y+5 .. end]
     * rowdata
     */

    // todo: just skip ahead to this position
    serialInput.readInt(); // rowstart

    serialInput.readByte();

    int16_t colcount = serialInput.readShort();
    assert(colcount >= 0);

    // Store the following information so that we can provide them to the user
    // on failure
    ValueType types[colcount];
    boost::scoped_array<std::string> names(new std::string[colcount]);

    // skip the column types
    for (int i = 0; i < colcount; ++i) {
        types[i] = (ValueType) serialInput.readEnumInSingleByte();
    }

    // skip the column names
    for (int i = 0; i < colcount; ++i) {
        names[i] = serialInput.readTextString();
    }

    // Check if the column count matches what the temp table is expecting
    int16_t expectedColumnCount = static_cast<int16_t>(m_schema->columnCount() + m_schema->hiddenColumnCount());
    if (colcount != expectedColumnCount) {
        std::stringstream message(std::stringstream::in
                                  | std::stringstream::out);
        message << "Column count mismatch. Expecting "
                << expectedColumnCount
                << ", but " << colcount << " given" << std::endl;
        message << "Expecting the following columns:" << std::endl;
        message << debug() << std::endl;
        message << "The following columns are given:" << std::endl;
        for (int i = 0; i < colcount; i++) {
            message << "column " << i << ": " << names[i]
                    << ", type = " << getTypeName(types[i]) << std::endl;
        }
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      message.str().c_str());
    }

    loadTuplesFromNoHeader(serialInput, stringPool, uniqueViolationOutput, shouldDRStreamRow);
}
Ejemplo n.º 26
0
/** Given an expression type and a valuetype, find the best
 * templated ctor to invoke. Several helpers, above, aid in this
 * pursuit. Each instantiated expression must consume any
 * class-specific serialization from serialize_io. */
AbstractExpression*
ExpressionUtil::expressionFactory(PlannerDomValue obj,
                  ExpressionType et, ValueType vt, int vs,
                  AbstractExpression* lc,
                  AbstractExpression* rc,
                  const std::vector<AbstractExpression*>* args)
{
    AbstractExpression *ret = NULL;

    switch (et) {

    // Casts
    case (EXPRESSION_TYPE_OPERATOR_CAST):
        ret = castFactory(vt, lc);
    break;

    // Operators
    case (EXPRESSION_TYPE_OPERATOR_PLUS):
    case (EXPRESSION_TYPE_OPERATOR_MINUS):
    case (EXPRESSION_TYPE_OPERATOR_MULTIPLY):
    case (EXPRESSION_TYPE_OPERATOR_DIVIDE):
    case (EXPRESSION_TYPE_OPERATOR_CONCAT):
    case (EXPRESSION_TYPE_OPERATOR_MOD):
    case (EXPRESSION_TYPE_OPERATOR_NOT):
    case (EXPRESSION_TYPE_OPERATOR_IS_NULL):
    case (EXPRESSION_TYPE_OPERATOR_EXISTS):
        ret = operatorFactory(et, lc, rc);
    break;

    // Comparisons
    case (EXPRESSION_TYPE_COMPARE_EQUAL):
    case (EXPRESSION_TYPE_COMPARE_NOTEQUAL):
    case (EXPRESSION_TYPE_COMPARE_LESSTHAN):
    case (EXPRESSION_TYPE_COMPARE_GREATERTHAN):
    case (EXPRESSION_TYPE_COMPARE_LESSTHANOREQUALTO):
    case (EXPRESSION_TYPE_COMPARE_GREATERTHANOREQUALTO):
    case (EXPRESSION_TYPE_COMPARE_LIKE):
    case (EXPRESSION_TYPE_COMPARE_IN):
        ret = comparisonFactory(obj, et, lc, rc);
    break;

    // Conjunctions
    case (EXPRESSION_TYPE_CONJUNCTION_AND):
    case (EXPRESSION_TYPE_CONJUNCTION_OR):
        ret = conjunctionFactory(et, lc, rc);
    break;

    // Functions and pseudo-functions
    case (EXPRESSION_TYPE_FUNCTION): {
        // add the function id
        int functionId = obj.valueForKey("FUNCTION_ID").asInt();

        if (args) {
            ret = functionFactory(functionId, args);
        }

        if ( ! ret) {
            std::string nameString;
            if (obj.hasNonNullKey("NAME")) {
                nameString = obj.valueForKey("NAME").asStr();
            }
            else {
                nameString = "?";
            }
            raiseFunctionFactoryError(nameString, functionId, args);
        }
    }
    break;

    case (EXPRESSION_TYPE_VALUE_VECTOR): {
        // Parse whatever is needed out of obj and pass the pieces to inListFactory
        // to make it easier to unit test independently of the parsing.
        // The first argument is used as the list element type.
        // If the ValueType of the list builder expression needs to be "ARRAY" or something else,
        // a separate element type attribute will have to be serialized and passed in here.
        ret = vectorFactory(vt, args);
    }
    break;

    // Constant Values, parameters, tuples
    case (EXPRESSION_TYPE_VALUE_CONSTANT):
        ret = constantValueFactory(obj, vt, et, lc, rc);
        break;

    case (EXPRESSION_TYPE_VALUE_PARAMETER):
        ret = parameterValueFactory(obj, et, lc, rc);
        break;

    case (EXPRESSION_TYPE_VALUE_TUPLE):
        ret = tupleValueFactory(obj, et, lc, rc);
        break;

    case (EXPRESSION_TYPE_VALUE_TUPLE_ADDRESS):
        ret = new TupleAddressExpression();
        break;
    case (EXPRESSION_TYPE_VALUE_SCALAR):
        ret = new ScalarValueExpression(lc);
        break;
    case (EXPRESSION_TYPE_HASH_RANGE):
        ret = hashRangeFactory(obj);
        break;
    case (EXPRESSION_TYPE_OPERATOR_CASE_WHEN):
        ret = caseWhenFactory(vt, lc, rc);
        break;
    case (EXPRESSION_TYPE_OPERATOR_ALTERNATIVE):
        ret = new OperatorAlternativeExpression(lc, rc);
        break;

    // Subquery
    case (EXPRESSION_TYPE_ROW_SUBQUERY):
    case (EXPRESSION_TYPE_SELECT_SUBQUERY):
        ret = subqueryFactory(et, obj, args);
        break;

        // must handle all known expressions in this factory
    default:

        char message[256];
        snprintf(message,256, "Invalid ExpressionType '%s' (%d) requested from factory",
                expressionToString(et).c_str(), (int)et);
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, message);
    }

    ret->setValueType(vt);
    ret->setValueSize(vs);
    // written thusly to ease testing/inspecting return content.
    VOLT_TRACE("Created expression %p", ret);
    return ret;
}
Ejemplo n.º 27
0
/** convert the enumerated value type into a concrete type for
 * constant value expressions templated ctors */
static AbstractExpression*
constantValueFactory(PlannerDomValue obj,
                     ValueType vt, ExpressionType et,
                     AbstractExpression *lc, AbstractExpression *rc)
{
    // read before ctor - can then instantiate fully init'd obj.
    NValue newvalue;
    bool isNull = obj.valueForKey("ISNULL").asBool();
    if (isNull)
    {
        newvalue = NValue::getNullValue(vt);
        return new ConstantValueExpression(newvalue);
    }

    PlannerDomValue valueValue = obj.valueForKey("VALUE");

    switch (vt) {
    case VALUE_TYPE_INVALID:
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "constantValueFactory: Value type should"
                                      " never be VALUE_TYPE_INVALID");
    case VALUE_TYPE_NULL:
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "constantValueFactory: And they should be"
                                      " never be this either! VALUE_TYPE_NULL");
    case VALUE_TYPE_TINYINT:
        newvalue = ValueFactory::getTinyIntValue(static_cast<int8_t>(valueValue.asInt64()));
        break;
    case VALUE_TYPE_SMALLINT:
        newvalue = ValueFactory::getSmallIntValue(static_cast<int16_t>(valueValue.asInt64()));
        break;
    case VALUE_TYPE_INTEGER:
        newvalue = ValueFactory::getIntegerValue(static_cast<int32_t>(valueValue.asInt64()));
        break;
    case VALUE_TYPE_BIGINT:
        newvalue = ValueFactory::getBigIntValue(static_cast<int64_t>(valueValue.asInt64()));
        break;
    case VALUE_TYPE_DOUBLE:
        newvalue = ValueFactory::getDoubleValue(static_cast<double>(valueValue.asDouble()));
        break;
    case VALUE_TYPE_VARCHAR:
        newvalue = ValueFactory::getStringValue(valueValue.asStr());
        break;
    case VALUE_TYPE_VARBINARY:
        // uses hex encoding
        newvalue = ValueFactory::getBinaryValue(valueValue.asStr());
        break;
    case VALUE_TYPE_TIMESTAMP:
        newvalue = ValueFactory::getTimestampValue(static_cast<int64_t>(valueValue.asInt64()));
        break;
    case VALUE_TYPE_DECIMAL:
        newvalue = ValueFactory::getDecimalValueFromString(valueValue.asStr());
        break;
    case VALUE_TYPE_BOOLEAN:
        newvalue = ValueFactory::getBooleanValue(valueValue.asBool());
        break;
    default:
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "constantValueFactory: Unrecognized value"
                                      " type");
    }

    return new ConstantValueExpression(newvalue);
}
Ejemplo n.º 28
0
AbstractExpression*
AbstractExpression::buildExpressionTree_recurse(json_spirit::Object &obj)
{
    // build a tree recursively from the bottom upwards.
    // when the expression node is instantiated, its type,
    // value and child types will have been discovered.

    ExpressionType peek_type = EXPRESSION_TYPE_INVALID;
    ValueType value_type = VALUE_TYPE_INVALID;
    AbstractExpression *left_child = NULL;
    AbstractExpression *right_child = NULL;

    // read the expression type
    json_spirit::Value expressionTypeValue = json_spirit::find_value(obj,
                                                                     "TYPE");
    if (expressionTypeValue == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "AbstractExpression::"
                                      "buildExpressionTree_recurse:"
                                      " Couldn't find TYPE value");
    }
    assert(stringToExpression(expressionTypeValue.get_str()) != EXPRESSION_TYPE_INVALID);
    peek_type = stringToExpression(expressionTypeValue.get_str());

    // and the value type
    json_spirit::Value valueTypeValue = json_spirit::find_value(obj,
                                                                "VALUE_TYPE");
    if (valueTypeValue == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "AbstractExpression::"
                                      "buildExpressionTree_recurse:"
                                      " Couldn't find VALUE_TYPE value");
    }
    std::string valueTypeString = valueTypeValue.get_str();
    value_type = stringToValue(valueTypeString);

    // this should be relatively safe, though it ignores overflow.
    if ((value_type == VALUE_TYPE_TINYINT)  ||
        (value_type == VALUE_TYPE_SMALLINT) ||
        (value_type == VALUE_TYPE_INTEGER))
    {
        value_type = VALUE_TYPE_BIGINT;
    }

    assert(value_type != VALUE_TYPE_INVALID);

    // add the value size
    json_spirit::Value valueSizeValue = json_spirit::find_value(obj,
                                                                "VALUE_SIZE");
    if (valueSizeValue == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "AbstractExpression::"
                                      "buildExpressionTree_recurse:"
                                      " Couldn't find VALUE_SIZE value");
    }
    int valueSize = valueSizeValue.get_int();

    // recurse to children
    try {
        json_spirit::Value leftValue = json_spirit::find_value(obj, "LEFT");
        if (!(leftValue == json_spirit::Value::null)) {
            left_child = AbstractExpression::buildExpressionTree_recurse(leftValue.get_obj());
        } else {
            left_child = NULL;
        }

        json_spirit::Value rightValue = json_spirit::find_value( obj, "RIGHT");
        if (!(rightValue == json_spirit::Value::null)) {
            right_child = AbstractExpression::buildExpressionTree_recurse(rightValue.get_obj());
        } else {
            right_child = NULL;
        }

        // invoke the factory. obviously it has to handle null children.
        // pass it the serialization stream in case a subclass has more
        // to read. yes, the per-class data really does follow the
        // child serializations.
        return expressionFactory(obj,
                                 peek_type, value_type, valueSize,
                                 left_child, right_child);
    }
    catch (SerializableEEException &ex) {
        delete left_child;
        delete right_child;
        throw;
    }
}
Ejemplo n.º 29
0
AbstractExpression*
AbstractExpression::buildExpressionTree_recurse(json_spirit::Object &obj)
{
    // build a tree recursively from the bottom upwards.
    // when the expression node is instantiated, its type,
    // value and child types will have been discovered.

    ExpressionType peek_type = EXPRESSION_TYPE_INVALID;
    ValueType value_type = VALUE_TYPE_INVALID;
    AbstractExpression *left_child = NULL;
    AbstractExpression *right_child = NULL;
    std::vector<AbstractExpression*>* argsVector = NULL;

    // read the expression type
    json_spirit::Value expressionTypeValue = json_spirit::find_value(obj,
                                                                     "TYPE");
    if (expressionTypeValue == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "AbstractExpression::"
                                      "buildExpressionTree_recurse:"
                                      " Couldn't find TYPE value");
    }
    assert(stringToExpression(expressionTypeValue.get_str()) != EXPRESSION_TYPE_INVALID);
    peek_type = stringToExpression(expressionTypeValue.get_str());

    // and the value type
    json_spirit::Value valueTypeValue = json_spirit::find_value(obj,
                                                                "VALUE_TYPE");
    if (valueTypeValue == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "AbstractExpression::"
                                      "buildExpressionTree_recurse:"
                                      " Couldn't find VALUE_TYPE value");
    }
    std::string valueTypeString = valueTypeValue.get_str();
    value_type = stringToValue(valueTypeString);

    assert(value_type != VALUE_TYPE_INVALID);

    // add the value size
    json_spirit::Value valueSizeValue = json_spirit::find_value(obj,
                                                                "VALUE_SIZE");
    if (valueSizeValue == json_spirit::Value::null) {
        throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "AbstractExpression::"
                                      "buildExpressionTree_recurse:"
                                      " Couldn't find VALUE_SIZE value");
    }
    int valueSize = valueSizeValue.get_int();

    // recurse to children
    try {
        json_spirit::Value leftValue = json_spirit::find_value(obj, "LEFT");
        if (!(leftValue == json_spirit::Value::null)) {
            left_child = AbstractExpression::buildExpressionTree_recurse(leftValue.get_obj());
        }

        json_spirit::Value rightValue = json_spirit::find_value( obj, "RIGHT");
        if (!(rightValue == json_spirit::Value::null)) {
            right_child = AbstractExpression::buildExpressionTree_recurse(rightValue.get_obj());
        }

        // NULL argsVector corresponds to a missing ARGS value
        // vs. an empty argsVector which corresponds to an empty array ARGS value.
        // Different expression types could assert either a NULL or non-NULL argsVector initializer.
        json_spirit::Value argsValue = json_spirit::find_value(obj, "ARGS");
        if (!(argsValue == json_spirit::Value::null)) {
            argsVector = new std::vector<AbstractExpression*>();

            json_spirit::Array argsArray = argsValue.get_array();
            for (int ii = 0; ii < argsArray.size(); ii++) {
                json_spirit::Value argValue = argsArray[ii];
                AbstractExpression* argExpr = AbstractExpression::buildExpressionTree_recurse(argValue.get_obj());
                argsVector->push_back(argExpr);
            }
        }
        // invoke the factory. obviously it has to handle null children.
        // pass it the serialization stream in case a subclass has more
        // to read. yes, the per-class data really does follow the
        // child serializations.
        return ExpressionUtil::expressionFactory(obj, peek_type, value_type, valueSize,
                                                 left_child, right_child, argsVector);
    }
    catch (const SerializableEEException &ex) {
        delete left_child;
        delete right_child;
        delete argsVector;
        throw;
    }
}
Ejemplo n.º 30
0
/** Function static helper templated functions to vivify an optimal
    comparison class. */
static AbstractExpression*
subqueryComparisonFactory(PlannerDomValue obj,
            ExpressionType c,
            AbstractExpression *l,
            AbstractExpression *r)
{
    QuantifierType quantifier = QUANTIFIER_TYPE_NONE;
    if (obj.hasNonNullKey("QUANTIFIER")) {
        quantifier = static_cast<QuantifierType>(obj.valueForKey("QUANTIFIER").asInt());
    }

    SubqueryExpression *l_subquery =
        dynamic_cast<SubqueryExpression*>(l);

    SubqueryExpression *r_subquery =
        dynamic_cast<SubqueryExpression*>(r);

    // OK, here we go
    if (l_subquery != NULL && r_subquery != NULL) {
        switch (c) {
        case (EXPRESSION_TYPE_COMPARE_EQUAL):
            return new VectorComparisonExpression<CmpEq, TupleExtractor, TupleExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_NOTEQUAL):
            return new VectorComparisonExpression<CmpNe, TupleExtractor, TupleExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_LESSTHAN):
            return new VectorComparisonExpression<CmpLt, TupleExtractor, TupleExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_GREATERTHAN):
            return new VectorComparisonExpression<CmpGt, TupleExtractor, TupleExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_LESSTHANOREQUALTO):
            return new VectorComparisonExpression<CmpLte, TupleExtractor, TupleExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_GREATERTHANOREQUALTO):
            return new VectorComparisonExpression<CmpGte, TupleExtractor, TupleExtractor>(c, l, r, quantifier);
        default:
            char message[256];
            snprintf(message, 256, "Invalid ExpressionType '%s' called"
                " for VectorComparisonExpression",
                expressionToString(c).c_str());
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, message);
        }
    } else if (l_subquery != NULL) {
        switch (c) {
        case (EXPRESSION_TYPE_COMPARE_EQUAL):
            return new VectorComparisonExpression<CmpEq, TupleExtractor, NValueExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_NOTEQUAL):
            return new VectorComparisonExpression<CmpNe, TupleExtractor, NValueExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_LESSTHAN):
            return new VectorComparisonExpression<CmpLt, TupleExtractor, NValueExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_GREATERTHAN):
            return new VectorComparisonExpression<CmpGt, TupleExtractor, NValueExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_LESSTHANOREQUALTO):
            return new VectorComparisonExpression<CmpLte, TupleExtractor, NValueExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_GREATERTHANOREQUALTO):
            return new VectorComparisonExpression<CmpGte, TupleExtractor, NValueExtractor>(c, l, r, quantifier);
        default:
            char message[256];
            snprintf(message, 256, "Invalid ExpressionType '%s' called"
                " for VectorComparisonExpression",
                expressionToString(c).c_str());
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, message);
        }
    } else {
        assert(r_subquery != NULL);
        switch (c) {
        case (EXPRESSION_TYPE_COMPARE_EQUAL):
            return new VectorComparisonExpression<CmpEq, NValueExtractor, TupleExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_NOTEQUAL):
            return new VectorComparisonExpression<CmpNe, NValueExtractor, TupleExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_LESSTHAN):
            return new VectorComparisonExpression<CmpLt, NValueExtractor, TupleExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_GREATERTHAN):
            return new VectorComparisonExpression<CmpGt, NValueExtractor, TupleExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_LESSTHANOREQUALTO):
            return new VectorComparisonExpression<CmpLte, NValueExtractor, TupleExtractor>(c, l, r, quantifier);
        case (EXPRESSION_TYPE_COMPARE_GREATERTHANOREQUALTO):
            return new VectorComparisonExpression<CmpGte, NValueExtractor, TupleExtractor>(c, l, r, quantifier);
        default:
            char message[256];
            snprintf(message, 256, "Invalid ExpressionType '%s' called"
                " for VectorComparisonExpression",
                expressionToString(c).c_str());
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION, message);
        }
    }
}