Ejemplo n.º 1
0
void
PlanNodeFragment::nodeListFromJSONObject(PlanNodeFragment *pnf, PlannerDomValue planNodesList, PlannerDomValue executeList, int stmtId)
{
    assert(pnf->m_stmtExecutionListMap.find(stmtId) == pnf->m_stmtExecutionListMap.end());
    // NODE_LIST
    std::vector<AbstractPlanNode*> planNodes;
    for (int i = 0; i < planNodesList.arrayLen(); i++) {
        AbstractPlanNode *node = AbstractPlanNode::fromJSONObject(planNodesList.valueAtIndex(i));
        assert(node);
        assert(pnf->m_idToNodeMap.find(node->getPlanNodeId()) == pnf->m_idToNodeMap.end());
        pnf->m_idToNodeMap[node->getPlanNodeId()] = node;
        planNodes.push_back(node);
    }

    // walk the plannodes and complete each plannode's id-to-node maps
    for (std::vector< AbstractPlanNode* >::const_iterator node = planNodes.begin();
         node != planNodes.end(); ++node) {
        const std::vector<CatalogId>& childIds = (*node)->getChildIds();

        for (int zz = 0; zz < childIds.size(); zz++) {
            (*node)->addChild(pnf->m_idToNodeMap[childIds[zz]]);
        }
    }

    // EXECUTE_LIST
    std::auto_ptr<std::vector<AbstractPlanNode*> > executeNodeList(new std::vector<AbstractPlanNode*>());
    for (int i = 0; i < executeList.arrayLen(); i++) {
        executeNodeList->push_back(pnf->m_idToNodeMap[executeList.valueAtIndex(i).asInt()]);
    }
    pnf->m_stmtExecutionListMap.insert(std::make_pair(stmtId, executeNodeList.get()));
    executeNodeList.release();

}
Ejemplo n.º 2
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.º 3
0
PlanNodeFragment *
PlanNodeFragment::fromJSONObject(PlannerDomValue obj)
{
    // read and construct plannodes from json object
    auto_ptr<PlanNodeFragment> pnf;
    if (obj.hasNonNullKey("PLAN_NODES_LISTS")) {
        PlannerDomValue planNodesListArray = obj.valueForKey("PLAN_NODES_LISTS");
        if (!obj.hasNonNullKey("EXECUTE_LISTS")) {
            throwFatalException("Failed to construct plan fragment. Missing EXECUTE_LISTS key");
        }
        PlannerDomValue executeListArray = obj.valueForKey("EXECUTE_LISTS");
        if (planNodesListArray.arrayLen() != executeListArray.arrayLen()) {
            throwFatalException("Failed to construct plan fragment. EXECUTE_LISTS and PLAN_NODES_LISTS do not match");
        }
        int stmtCnt = planNodesListArray.arrayLen();
        pnf.reset(new PlanNodeFragment());
        for (int i = 0; i < stmtCnt; i++) {
            int stmtId = planNodesListArray.valueAtIndex(i).valueForKey("STATEMENT_ID").asInt();
            PlannerDomValue planNodesList = planNodesListArray.valueAtIndex(i).valueForKey("PLAN_NODES");
            PlannerDomValue executeList = executeListArray.valueAtIndex(i).valueForKey("EXECUTE_LIST");
            PlanNodeFragment::nodeListFromJSONObject(pnf.get(), planNodesList, executeList, stmtId);
        }
    } else {
        pnf.reset(new PlanNodeFragment());
        PlanNodeFragment::nodeListFromJSONObject(pnf.get(), obj.valueForKey("PLAN_NODES"), obj.valueForKey("EXECUTE_LIST"), 0);
    }
    PlanNodeFragment::loadParamsFromJSONObject(pnf.get(), obj);

    PlanNodeFragment *retval = pnf.get();
    pnf.release();
    assert(retval);
    return retval;
}
Ejemplo n.º 4
0
// ----------------------------------------------------
//  Serialization Functions
// ----------------------------------------------------
AbstractPlanNode* AbstractPlanNode::fromJSONObject(PlannerDomValue obj)
{

    string typeString = obj.valueForKey("PLAN_NODE_TYPE").asStr();
    std::unique_ptr<AbstractPlanNode> node(
        plannodeutil::getEmptyPlanNode(stringToPlanNode(typeString)));

    node->m_planNodeId = obj.valueForKey("ID").asInt();

    if (obj.hasKey("INLINE_NODES")) {
        PlannerDomValue inlineNodesValue = obj.valueForKey("INLINE_NODES");
        for (int i = 0; i < inlineNodesValue.arrayLen(); i++) {
            PlannerDomValue inlineNodeObj = inlineNodesValue.valueAtIndex(i);
            AbstractPlanNode *newNode = AbstractPlanNode::fromJSONObject(inlineNodeObj);

            // todo: if this throws, new Node can be leaked.
            // As long as newNode is not NULL, this will not throw.
            assert(newNode);
            node->addInlinePlanNode(newNode);
        }
    }

    loadIntArrayFromJSONObject("CHILDREN_IDS", obj, node->m_childIds);

    // Output schema are optional -- when they can be determined by a child's copy.
    if (obj.hasKey("OUTPUT_SCHEMA")) {
        PlannerDomValue outputSchemaArray = obj.valueForKey("OUTPUT_SCHEMA");
        for (int i = 0; i < outputSchemaArray.arrayLen(); i++) {
            PlannerDomValue outputColumnValue = outputSchemaArray.valueAtIndex(i);
            SchemaColumn* outputColumn = new SchemaColumn(outputColumnValue, i);
            node->m_outputSchema.push_back(outputColumn);
        }
        node->m_validOutputColumnCount = static_cast<int>(node->m_outputSchema.size());
    }

    // Anticipate and mark the two different scenarios of missing output schema.
    // The actual output schema can be searched for on demand once the whole plan tree is loaded.
    // If there's an inline projection node,
    // one of its chief purposes is defining the parent's output schema.
    else if (node->getInlinePlanNode(PLAN_NODE_TYPE_PROJECTION)) {
        node->m_validOutputColumnCount = SCHEMA_UNDEFINED_SO_GET_FROM_INLINE_PROJECTION;
    }

    // Otherwise, the node is relying on a child's output schema, possibly several levels down,
    // OR it is just an inline node (e.g. a LIMIT) or a DML node,
    // whose output schema is known from its context or is otherwise not of any interest.
    else {
        node->m_validOutputColumnCount = SCHEMA_UNDEFINED_SO_GET_FROM_CHILD;
    }

    node->loadFromJSONObject(obj);

    AbstractPlanNode* retval = node.get();
    node.release();
    assert(retval);
    return retval;
}
Ejemplo n.º 5
0
void
AggregatePlanNode::loadFromJSONObject(PlannerDomValue obj)
{
    PlannerDomValue aggregateColumnsArray = obj.valueForKey("AGGREGATE_COLUMNS");
    for (int i = 0; i < aggregateColumnsArray.arrayLen(); i++) {
        PlannerDomValue aggregateColumnValue = aggregateColumnsArray.valueAtIndex(i);
        bool containsType = false;
        bool containsDistinct = false;
        bool containsOutputColumn = false;
        bool containsExpression = false;
        if (aggregateColumnValue.hasNonNullKey("AGGREGATE_TYPE")) {
            containsType = true;
            string aggregateColumnTypeString = aggregateColumnValue.valueForKey("AGGREGATE_TYPE").asStr();
            m_aggregates.push_back(stringToExpression(aggregateColumnTypeString));
        }
        if (aggregateColumnValue.hasNonNullKey("AGGREGATE_DISTINCT")) {
            containsDistinct = true;
            bool distinct = aggregateColumnValue.valueForKey("AGGREGATE_DISTINCT").asInt() == 1;
            m_distinctAggregates.push_back(distinct);
        }
        if (aggregateColumnValue.hasNonNullKey("AGGREGATE_OUTPUT_COLUMN")) {
            containsOutputColumn = true;
            int column = aggregateColumnValue.valueForKey("AGGREGATE_OUTPUT_COLUMN").asInt();
            m_aggregateOutputColumns.push_back(column);
        }
        if (aggregateColumnValue.hasNonNullKey("AGGREGATE_EXPRESSION")) {
            containsExpression = true;
            PlannerDomValue exprDom = aggregateColumnValue.valueForKey("AGGREGATE_EXPRESSION");
            m_aggregateInputExpressions.push_back(AbstractExpression::buildExpressionTree(exprDom));
        }

        if(!(containsType && containsDistinct && containsOutputColumn)) {
            throw SerializableEEException(VOLT_EE_EXCEPTION_TYPE_EEEXCEPTION,
                                      "AggregatePlanNode::loadFromJSONObject:"
                                      " Missing type, distinct, or outputcolumn.");
        }
        if ( ! containsExpression) {
            m_aggregateInputExpressions.push_back(NULL);
        }
    }

    if (obj.hasNonNullKey("GROUPBY_EXPRESSIONS")) {
        PlannerDomValue groupByExpressionsArray = obj.valueForKey("GROUPBY_EXPRESSIONS");
        for (int i = 0; i < groupByExpressionsArray.arrayLen(); i++) {
            m_groupByExpressions.push_back(AbstractExpression::buildExpressionTree(groupByExpressionsArray.valueAtIndex(i)));
        }
    }

    if (obj.hasNonNullKey("PRE_PREDICATE")) {
        m_prePredicate = AbstractExpression::buildExpressionTree(obj.valueForKey("PRE_PREDICATE"));
    }

    if (obj.hasNonNullKey("POST_PREDICATE")) {
        m_postPredicate = AbstractExpression::buildExpressionTree(obj.valueForKey("POST_PREDICATE"));
    }
}
Ejemplo n.º 6
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.º 7
0
/** Parse JSON parameters to create a hash range expression */
static AbstractExpression*
hashRangeFactory(PlannerDomValue obj) {
    PlannerDomValue hashColumnValue = obj.valueForKey("HASH_COLUMN");

    PlannerDomValue rangesArray = obj.valueForKey("RANGES");

    srange_type *ranges = new srange_type[rangesArray.arrayLen()];
    for (int ii = 0; ii < rangesArray.arrayLen(); ii++) {
        PlannerDomValue arrayObject = rangesArray.valueAtIndex(ii);
        PlannerDomValue rangeStartValue = arrayObject.valueForKey("RANGE_START");
        PlannerDomValue rangeEndValue = arrayObject.valueForKey("RANGE_END");

        ranges[ii] = srange_type(rangeStartValue.asInt(), rangeEndValue.asInt());
    }
    return new HashRangeExpression(hashColumnValue.asInt(), ranges, static_cast<int>(rangesArray.arrayLen()));
}
Ejemplo n.º 8
0
PlanNodeFragment *
PlanNodeFragment::fromJSONObject(PlannerDomValue obj)
{
    auto_ptr<PlanNodeFragment> pnf(new PlanNodeFragment());

    // read and construct plannodes from json object
    PlannerDomValue planNodesArray = obj.valueForKey("PLAN_NODES");

    for (int i = 0; i < planNodesArray.arrayLen(); i++) {
        AbstractPlanNode *node = NULL;
        node = AbstractPlanNode::fromJSONObject(planNodesArray.valueAtIndex(i));
        assert(node);

        pnf->m_planNodes.push_back(node);
        pnf->m_idToNodeMap[node->getPlanNodeId()] = node;
    }

    // walk the plannodes and complete each plannode's id-to-node maps
    for (std::vector< AbstractPlanNode* >::const_iterator node = pnf->m_planNodes.begin();
         node != pnf->m_planNodes.end(); ++node) {
        const std::vector<CatalogId> childIds = (*node)->getChildIds();
        for (int zz = 0; zz < childIds.size(); zz++) {
            (*node)->addChild(pnf->m_idToNodeMap[childIds[zz]]);
        }
    }
    pnf->loadFromJSONObject(obj);

    PlanNodeFragment *retval = pnf.get();
    pnf.release();
    assert(retval);
    return retval;
}
Ejemplo n.º 9
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.º 10
0
/**
 * Parse and save predicates.
 */
void ElasticContext::updatePredicates(const std::vector<std::string> &predicateStrings) {
    //If there is already a predicate and thus presumably an index, make sure the request is a subset of what exists
    //That should always be the case, but wrong answers will follow if we are wrong
    if (m_predicates.size() > 0 && dynamic_cast<HashRangeExpression*>(&m_predicates[0]) != NULL && predicateStrings.size() > 0) {
        PlannerDomRoot domRoot(predicateStrings[0].c_str());
        if (!domRoot.isNull()) {
            PlannerDomValue predicateObject = domRoot.rootObject();
            HashRangeExpression *expression = dynamic_cast<HashRangeExpression*>(&m_predicates[0]);
            if (predicateObject.hasKey("predicateExpression")) {
                PlannerDomValue predicateExpression = predicateObject.valueForKey("predicateExpression");
                PlannerDomValue rangesArray = predicateExpression.valueForKey("RANGES");
                for (int ii = 0; ii < rangesArray.arrayLen(); ii++) {
                    PlannerDomValue arrayObject = rangesArray.valueAtIndex(ii);
                    PlannerDomValue rangeStartValue = arrayObject.valueForKey("RANGE_START");
                    PlannerDomValue rangeEndValue = arrayObject.valueForKey("RANGE_END");
                    if (!expression->binarySearch(rangeStartValue.asInt()).isTrue()) {
                        throwFatalException("ElasticContext activate failed because a context already existed with conflicting ranges, conflicting range start is %d", rangeStartValue.asInt());
                    }
                    if (!expression->binarySearch(rangeEndValue.asInt()).isTrue()) {
                        throwFatalException("ElasticContext activate failed because a context already existed with conflicting ranges, conflicting range end is %d", rangeStartValue.asInt());
                    }
                }
            }
        }
    }
    m_predicateStrings = predicateStrings; // retain for possible clone after TRUNCATE TABLE
    TableStreamerContext::updatePredicates(predicateStrings);
}
Ejemplo n.º 11
0
void
PlanNodeFragment::loadFromJSONObject(PlannerDomValue obj)
{
    PlannerDomValue executeListArray = obj.valueForKey("EXECUTE_LIST");
    for (int i = 0; i < executeListArray.arrayLen(); i++) {
        m_executionList.push_back(m_idToNodeMap[executeListArray.valueAtIndex(i).asInt()]);
    }

    if (obj.hasKey("PARAMETERS")) {
        PlannerDomValue parametersArray = obj.valueForKey("PARAMETERS");
        for (int i = 0; i < parametersArray.arrayLen(); i++) {
            PlannerDomValue parameterArray = parametersArray.valueAtIndex(i);
            int index = parameterArray.valueAtIndex(0).asInt();
            std::string typeString = parameterArray.valueAtIndex(1).asStr();
            parameters.push_back(std::pair< int, voltdb::ValueType>(index, stringToValue(typeString)));
        }
    }
}
Ejemplo n.º 12
0
void ExpressionUtil::loadIndexedExprsFromJson(std::vector<AbstractExpression*>& indexed_exprs, const std::string& jsonarraystring)
{
    PlannerDomRoot domRoot(jsonarraystring.c_str());
    PlannerDomValue expressionsArray = domRoot.rootObject();
    for (int i = 0; i < expressionsArray.arrayLen(); i++) {
        PlannerDomValue exprValue = expressionsArray.valueAtIndex(i);
        AbstractExpression *expr = AbstractExpression::buildExpressionTree(exprValue);
        indexed_exprs.push_back(expr);
    }
}
Ejemplo n.º 13
0
void AbstractPlanNode::loadIntArrayFromJSONObject(const char* label,
        PlannerDomValue obj, std::vector<int>& result)
{
    if (obj.hasNonNullKey(label)) {
        PlannerDomValue intArray = obj.valueForKey(label);
        for (int i = 0; i < intArray.arrayLen(); i++) {
            result.push_back(intArray.valueAtIndex(i).asInt());
        }
    }
}
Ejemplo n.º 14
0
// Load boolean array from JSON object.
// In IndexScanPlanNode (indexscannode.h and indexscannode.cpp),
//   we added a boolean vector "m_compare_not_distinct"
//   to indicate whether null values should be skipped for each search key column.
// This function is used to deseralize that boolean vector. (ENG-11096)
void AbstractPlanNode::loadBooleanArrayFromJSONObject(const char* label,
                                                      PlannerDomValue obj,
                                                      std::vector<bool>& result)
{
    if (obj.hasNonNullKey(label)) {
        PlannerDomValue stringArray = obj.valueForKey(label);
        int len = stringArray.arrayLen();
        for (int i = 0; i < len; ++i) {
            result.push_back(stringArray.valueAtIndex(i).asBool());
        }
    }
}
Ejemplo n.º 15
0
void AbstractPlanNode::OwningExpressionVector::loadExpressionArrayFromJSONObject(const char* label,
                                                                                 PlannerDomValue obj)
{
    clear();
    if ( ! obj.hasNonNullKey(label)) {
        return;
    }
    PlannerDomValue arrayObj = obj.valueForKey(label);
    for (int i = 0; i < arrayObj.arrayLen(); i++) {
        AbstractExpression *expr = AbstractExpression::buildExpressionTree(arrayObj.valueAtIndex(i));
        push_back(expr);
    }
}
Ejemplo n.º 16
0
void
PlanNodeFragment::loadParamsFromJSONObject(PlanNodeFragment *pnf, PlannerDomValue obj)
{
    if (obj.hasKey("PARAMETERS")) {
        PlannerDomValue parametersArray = obj.valueForKey("PARAMETERS");
        for (int i = 0; i < parametersArray.arrayLen(); i++) {
            PlannerDomValue parameterArray = parametersArray.valueAtIndex(i);
            int index = parameterArray.valueAtIndex(0).asInt();
            std::string typeString = parameterArray.valueAtIndex(1).asStr();
            pnf->m_parameters.push_back(std::pair< int, voltdb::ValueType>(index, stringToValue(typeString)));
        }
    }
}
Ejemplo n.º 17
0
void InsertPlanNode::loadFromJSONObject(PlannerDomValue obj)
{
    AbstractOperationPlanNode::loadFromJSONObject(obj);
    m_multiPartition = obj.valueForKey("MULTI_PARTITION").asBool();
    if (obj.hasNonNullKey("FIELD_MAP")) {
        PlannerDomValue fieldMap = obj.valueForKey("FIELD_MAP");
        for (int i = 0; i < fieldMap.arrayLen(); ++i) {
          m_fieldMap.push_back(fieldMap.valueAtIndex(i).asInt());
        }
    }
    m_isUpsert = false;
    if (obj.hasNonNullKey("UPSERT")) {
        m_isUpsert = true;
    }
    m_sourceIsPartitioned = false;
    if (obj.hasNonNullKey("SOURCE_IS_PARTITIONED")) {
        m_sourceIsPartitioned = true;
    }
}
Ejemplo n.º 18
0
// ----------------------------------------------------
//  Serialization Functions
// ----------------------------------------------------
AbstractPlanNode*
AbstractPlanNode::fromJSONObject(PlannerDomValue obj) {

    string typeString = obj.valueForKey("PLAN_NODE_TYPE").asStr();

    //FIXME: EVEN if this leak guard is warranted --
    // like we EXPECT to be catching plan deserialization exceptions
    // and our biggest concern will be the memory this may leak? --
    // we don't need to be mediating all the node
    // pointer dereferences through the smart pointer.
    // Why not just get() it and forget it until .release() time?
    // As is, it just makes single-step debugging awkward.
    std::auto_ptr<AbstractPlanNode> node(
        plannodeutil::getEmptyPlanNode(stringToPlanNode(typeString)));

    node->m_planNodeId = obj.valueForKey("ID").asInt();

    PlannerDomValue inlineNodesValue = obj.valueForKey("INLINE_NODES");
    for (int i = 0; i < inlineNodesValue.arrayLen(); i++) {
        PlannerDomValue inlineNodeObj = inlineNodesValue.valueAtIndex(i);
        AbstractPlanNode *newNode = AbstractPlanNode::fromJSONObject(inlineNodeObj);

        // todo: if this throws, new Node can be leaked.
        // As long as newNode is not NULL, this will not throw.
        assert(newNode);
        node->addInlinePlanNode(newNode);
    }

    PlannerDomValue parentIdsArray = obj.valueForKey("PARENT_IDS");
    for (int i = 0; i < parentIdsArray.arrayLen(); i++) {
        int32_t parentNodeId = parentIdsArray.valueAtIndex(i).asInt();
        node->m_parentIds.push_back(parentNodeId);
    }

    PlannerDomValue childNodeIdsArray = obj.valueForKey("CHILDREN_IDS");
    for (int i = 0; i < childNodeIdsArray.arrayLen(); i++) {
        int32_t childNodeId = childNodeIdsArray.valueAtIndex(i).asInt();
        node->m_childIds.push_back(childNodeId);
    }

    // Output schema are optional -- when they can be determined by a child's copy.
    if (obj.hasKey("OUTPUT_SCHEMA")) {
        PlannerDomValue outputSchemaArray = obj.valueForKey("OUTPUT_SCHEMA");
        for (int i = 0; i < outputSchemaArray.arrayLen(); i++) {
            PlannerDomValue outputColumnValue = outputSchemaArray.valueAtIndex(i);
            SchemaColumn* outputColumn = new SchemaColumn(outputColumnValue);
            node->m_outputSchema.push_back(outputColumn);
        }
        node->m_validOutputColumnCount = static_cast<int>(node->m_outputSchema.size());
    }

    // Anticipate and mark the two different scenarios of missing output schema.
    // The actual output schema can be searched for on demand once the whole plan tree is loaded.
    // If there's an inline projection node,
    // one of its chief purposes is defining the parent's output schema.
    else if (node->getInlinePlanNode(PLAN_NODE_TYPE_PROJECTION)) {
        node->m_validOutputColumnCount = SCHEMA_UNDEFINED_SO_GET_FROM_INLINE_PROJECTION;
    }

    // Otherwise, the node is relying on a child's output schema, possibly several levels down,
    // OR it is just an inline node (e.g. a LIMIT) or a DML node,
    // whose output schema is known from its context or is otherwise not of any interest.
    else {
        node->m_validOutputColumnCount = SCHEMA_UNDEFINED_SO_GET_FROM_CHILD;
    }

    node->loadFromJSONObject(obj);

    AbstractPlanNode* retval = node.get();
    node.release();
    assert(retval);
    return retval;
}
Ejemplo n.º 19
0
AbstractExpression*
AbstractExpression::buildExpressionTree_recurse(PlannerDomValue 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;
    bool inBytes = false;
    AbstractExpression *left_child = NULL;
    AbstractExpression *right_child = NULL;
    std::vector<AbstractExpression*>* argsVector = NULL;

    // read the expression type
    peek_type = static_cast<ExpressionType>(obj.valueForKey("TYPE").asInt());
    assert(peek_type != EXPRESSION_TYPE_INVALID);

    if (obj.hasNonNullKey("VALUE_TYPE")) {
        int32_t value_type_int = obj.valueForKey("VALUE_TYPE").asInt();
        value_type = static_cast<ValueType>(value_type_int);
        assert(value_type != VALUE_TYPE_INVALID);

        if (obj.hasNonNullKey("IN_BYTES")) {
            inBytes = true;
        }
    }

    // add the value size
    int valueSize = -1;
    if (obj.hasNonNullKey("VALUE_SIZE")) {
        valueSize = obj.valueForKey("VALUE_SIZE").asInt();
    } else {
        // This value size should be consistent with VoltType.java
        valueSize = NValue::getTupleStorageSize(value_type);
    }

    // recurse to children
    try {
        if (obj.hasNonNullKey("LEFT")) {
            PlannerDomValue leftValue = obj.valueForKey("LEFT");
            left_child = AbstractExpression::buildExpressionTree_recurse(leftValue);
        }
        if (obj.hasNonNullKey("RIGHT")) {
            PlannerDomValue rightValue = obj.valueForKey("RIGHT");
            right_child = AbstractExpression::buildExpressionTree_recurse(rightValue);
        }

        // 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.
        if (obj.hasNonNullKey("ARGS")) {
            PlannerDomValue argsArray = obj.valueForKey("ARGS");
            argsVector = new std::vector<AbstractExpression*>();
            for (int i = 0; i < argsArray.arrayLen(); i++) {
                PlannerDomValue argValue = argsArray.valueAtIndex(i);
                AbstractExpression* argExpr = AbstractExpression::buildExpressionTree_recurse(argValue);
                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.
        AbstractExpression* finalExpr = ExpressionUtil::expressionFactory(obj, peek_type, value_type, valueSize,
                left_child, right_child, argsVector);

        finalExpr->setInBytes(inBytes);

        return finalExpr;
    }
    catch (const SerializableEEException &ex) {
        delete left_child;
        delete right_child;
        delete argsVector;
        throw;
    }
}