private CompiledPlan getNextInsertPlan() {
        // there's really only one way to do an insert, so just
        // do it the right way once, then return null after that
        if (m_bestAndOnlyPlanWasGenerated) {
            return null;
        }
        m_bestAndOnlyPlanWasGenerated = true;

        // The child of the insert node produces rows containing values
        // from one of
        //   - A VALUES clause.  In this case the child node is a MaterializeNode
        //   - a SELECT statement as in "INSERT INTO ... SELECT ...".  In this case
        //       the child node is the root of an arbitrary subplan.

        // figure out which table we're inserting into
        assert (m_parsedInsert.m_tableList.size() == 1);
        Table targetTable = m_parsedInsert.m_tableList.get(0);
        StmtSubqueryScan subquery = m_parsedInsert.getSubqueryScan();
        CompiledPlan retval = null;
        String isContentDeterministic = null;
        if (subquery != null) {
            isContentDeterministic = subquery.calculateContentDeterminismMessage();
            if (subquery.getBestCostPlan() == null) {
                // Seems like this should really be caught earlier
                // in getBestCostPlan, above.
                throw new PlanningErrorException("INSERT INTO ... SELECT subquery could not be planned: "
                        + m_recentErrorMsg);

            }

            boolean targetIsExportTable = tableListIncludesExportOnly(m_parsedInsert.m_tableList);
            InsertSubPlanAssembler subPlanAssembler =
                    new InsertSubPlanAssembler(m_catalogDb, m_parsedInsert, m_partitioning,
                            targetIsExportTable);
            AbstractPlanNode subplan = subPlanAssembler.nextPlan();
            if (subplan == null) {
                throw new PlanningErrorException(subPlanAssembler.m_recentErrorMsg);
            }

            assert(m_partitioning.isJoinValid());

            //  Use the subquery's plan as the basis for the insert plan.
            retval = subquery.getBestCostPlan();
        }
        else {
            retval = new CompiledPlan(m_isLargeQuery);
        }
        retval.setReadOnly(false);

        // Iterate over each column in the table we're inserting into:
        //   - Make sure we're supplying values for columns that require it.
        //     For a normal INSERT, these are the usual non-nullable values that
        //     don't have a default value.
        //     For an UPSERT, the (only) required values are the primary key
        //     components. Other required values can be supplied from the
        //     existing row in "UPDATE mode". If some other value is required
        //     for an INSERT, UPSERT's "INSERT mode" will throw a runtime
        //     constraint violation as the INSERT operation tries to set the
        //     non-nullable column to null.
        //   - Set partitioning expressions for VALUES (...) case.
        //     TODO: it would be good someday to do the same kind of processing
        //      for the INSERT ... SELECT ... case, by analyzing the subquery.
        if (m_parsedInsert.m_isUpsert) {
            boolean hasPrimaryKey = false;
            for (Constraint constraint : targetTable.getConstraints()) {
                if (constraint.getType() != ConstraintType.PRIMARY_KEY.getValue()) {
                    continue;
                }

                hasPrimaryKey = true;
                boolean targetsPrimaryKey = false;
                for (ColumnRef colRef : constraint.getIndex().getColumns()) {
                    int primary = colRef.getColumn().getIndex();
                    for (Column targetCol : m_parsedInsert.m_columns.keySet()) {
                        if (targetCol.getIndex() == primary) {
                            targetsPrimaryKey = true;
                            break;
                        }
                    }
                    if (! targetsPrimaryKey) {
                        throw new PlanningErrorException("UPSERT on table \"" +
                                targetTable.getTypeName() +
                                "\" must specify a value for primary key \"" +
                                colRef.getColumn().getTypeName() + "\".");
                    }
                }
            }
            if (! hasPrimaryKey) {
                throw new PlanningErrorException("UPSERT is not allowed on table \"" +
                        targetTable.getTypeName() + "\" that has no primary key.");
            }
        }
        CatalogMap<Column> targetTableColumns = targetTable.getColumns();
        for (Column col : targetTableColumns) {
            boolean needsValue = (!m_parsedInsert.m_isUpsert) &&
                    (col.getNullable() == false) && (col.getDefaulttype() == 0);
            if (needsValue && !m_parsedInsert.m_columns.containsKey(col)) {
                // This check could be done during parsing?
                throw new PlanningErrorException("Column " + col.getName()
                        + " has no default and is not nullable.");
            }

            // hint that this statement can be executed SP.
            if (col.equals(m_partitioning.getPartitionColForDML()) && subquery == null) {
                // When AdHoc insert-into-select is supported, we'll need to be able to infer
                // partitioning of the sub-select
                AbstractExpression expr = m_parsedInsert.getExpressionForPartitioning(col);
                String fullColumnName = targetTable.getTypeName() + "." + col.getTypeName();
                m_partitioning.addPartitioningExpression(fullColumnName, expr, expr.getValueType());
            }
        }

        NodeSchema matSchema = null;
        if (subquery == null) {
            matSchema = new NodeSchema();
        }

        int[] fieldMap = new int[m_parsedInsert.m_columns.size()];
        int i = 0;

        // The insert statement's set of columns are contained in a LinkedHashMap,
        // meaning that we'll iterate over the columns here in the order that the user
        // specified them in the original SQL.  (If the statement didn't specify any
        // columns, then all the columns will be in the map in schema order.)
        //   - Build the field map, used by insert executor to build tuple to execute
        //   - For VALUES(...) insert statements, build the materialize node's schema
        for (Map.Entry<Column, AbstractExpression> e : m_parsedInsert.m_columns.entrySet()) {
            Column col = e.getKey();
            fieldMap[i] = col.getIndex();

            if (matSchema != null) {
                AbstractExpression valExpr = e.getValue();
                valExpr.setInBytes(col.getInbytes());

                // Patch over any mismatched expressions with an explicit cast.
                // Most impossible-to-cast type combinations should have already been caught by the
                // parser, but there are also runtime checks in the casting code
                // -- such as for out of range values.
                valExpr = castExprIfNeeded(valExpr, col);

                matSchema.addColumn(
                        AbstractParsedStmt.TEMP_TABLE_NAME,
                        AbstractParsedStmt.TEMP_TABLE_NAME,
                        col.getTypeName(), col.getTypeName(),
                        valExpr);
            }

            i++;
        }

        // the root of the insert plan may be an InsertPlanNode, or
        // it may be a scan plan node.  We may do an inline InsertPlanNode
        // as well.  All inlining of insert nodes will be done later,
        // in a microoptimzation.  We can't do it here, since we
        // may need to remove uneeded projection nodes.
        InsertPlanNode insertNode = new InsertPlanNode(m_parsedInsert.m_isUpsert);
        insertNode.setTargetTableName(targetTable.getTypeName());
        if (subquery != null) {
            insertNode.setSourceIsPartitioned(! subquery.getIsReplicated());
        }

        // The field map tells the insert node
        // where to put values produced by child into the row to be inserted.
        insertNode.setFieldMap(fieldMap);

        if (matSchema != null) {
            MaterializePlanNode matNode =
                    new MaterializePlanNode(matSchema);
            // connect the insert and the materialize nodes together
            insertNode.addAndLinkChild(matNode);
            retval.statementGuaranteesDeterminism(false, true, isContentDeterministic);
        }
        else {
            insertNode.addAndLinkChild(retval.rootPlanGraph);
        }

        if (m_partitioning.wasSpecifiedAsSingle() || m_partitioning.isInferredSingle()) {
            insertNode.setMultiPartition(false);
            retval.rootPlanGraph = insertNode;
            return retval;
        }

        insertNode.setMultiPartition(true);
        // Add a compensating sum of modified tuple counts or a limit 1
        // AND a send on top of a union-like receive node.
        boolean isReplicated = targetTable.getIsreplicated();
        retval.rootPlanGraph = addCoordinatorToDMLNode(insertNode, isReplicated);
        return retval;
    }
private CompiledPlan getNextInsertPlan ( ) { if ( m_bestAndOnlyPlanWasGenerated ) { return null ; } m_bestAndOnlyPlanWasGenerated = true ; assert ( m_parsedInsert . m_tableList . size ( ) == 1 ) ; Table targetTable = m_parsedInsert . m_tableList . get ( 0 ) ; StmtSubqueryScan subquery = m_parsedInsert . getSubqueryScan ( ) ; CompiledPlan retval = null ; String isContentDeterministic = null ; if ( subquery != null ) { isContentDeterministic = subquery . calculateContentDeterminismMessage ( ) ; if ( subquery . getBestCostPlan ( ) == null ) { throw new PlanningErrorException ( "INSERT INTO ... SELECT subquery could not be planned: " + m_recentErrorMsg ) ; } boolean targetIsExportTable = tableListIncludesExportOnly ( m_parsedInsert . m_tableList ) ; InsertSubPlanAssembler subPlanAssembler = new InsertSubPlanAssembler ( m_catalogDb , m_parsedInsert , m_partitioning , targetIsExportTable ) ; AbstractPlanNode subplan = subPlanAssembler . nextPlan ( ) ; if ( subplan == null ) { throw new PlanningErrorException ( subPlanAssembler . m_recentErrorMsg ) ; } assert ( m_partitioning . isJoinValid ( ) ) ; retval = subquery . getBestCostPlan ( ) ; } else { retval = new CompiledPlan ( m_isLargeQuery ) ; } retval . setReadOnly ( false ) ; if ( m_parsedInsert . m_isUpsert ) { boolean hasPrimaryKey = false ; for ( Constraint constraint : targetTable . getConstraints ( ) ) { if ( constraint . getType ( ) != ConstraintType . PRIMARY_KEY . getValue ( ) ) { continue ; } hasPrimaryKey = true ; boolean targetsPrimaryKey = false ; for ( ColumnRef colRef : constraint . getIndex ( ) . getColumns ( ) ) { int primary = colRef . getColumn ( ) . getIndex ( ) ; for ( Column targetCol : m_parsedInsert . m_columns . keySet ( ) ) { if ( targetCol . getIndex ( ) == primary ) { targetsPrimaryKey = true ; break ; } } if ( ! targetsPrimaryKey ) { throw new PlanningErrorException ( "UPSERT on table \"" + targetTable . getTypeName ( ) + "\" must specify a value for primary key \"" + colRef . getColumn ( ) . getTypeName ( ) + "\"." ) ; } } } if ( ! hasPrimaryKey ) { throw new PlanningErrorException ( "UPSERT is not allowed on table \"" + targetTable . getTypeName ( ) + "\" that has no primary key." ) ; } } CatalogMap < Column > targetTableColumns = targetTable . getColumns ( ) ; for ( Column col : targetTableColumns ) { boolean needsValue = ( ! m_parsedInsert . m_isUpsert ) && ( col . getNullable ( ) == false ) && ( col . getDefaulttype ( ) == 0 ) ; if ( needsValue && ! m_parsedInsert . m_columns . containsKey ( col ) ) { throw new PlanningErrorException ( "Column " + col . getName ( ) + " has no default and is not nullable." ) ; } if ( col . equals ( m_partitioning . getPartitionColForDML ( ) ) && subquery == null ) { AbstractExpression expr = m_parsedInsert . getExpressionForPartitioning ( col ) ; String fullColumnName = targetTable . getTypeName ( ) + "." + col . getTypeName ( ) ; m_partitioning . addPartitioningExpression ( fullColumnName , expr , expr . getValueType ( ) ) ; } } NodeSchema matSchema = null ; if ( subquery == null ) { matSchema = new NodeSchema ( ) ; } int [ ] fieldMap = new int [ m_parsedInsert . m_columns . size ( ) ] ; int i = 0 ; for ( Map . Entry < Column , AbstractExpression > e : m_parsedInsert . m_columns . entrySet ( ) ) { Column col = e . getKey ( ) ; fieldMap [ i ] = col . getIndex ( ) ; if ( matSchema != null ) { AbstractExpression valExpr = e . getValue ( ) ; valExpr . setInBytes ( col . getInbytes ( ) ) ; valExpr = castExprIfNeeded ( valExpr , col ) ; matSchema . addColumn ( AbstractParsedStmt . TEMP_TABLE_NAME , AbstractParsedStmt . TEMP_TABLE_NAME , col . getTypeName ( ) , col . getTypeName ( ) , valExpr ) ; } i ++ ; } InsertPlanNode insertNode = new InsertPlanNode ( m_parsedInsert . m_isUpsert ) ; insertNode . setTargetTableName ( targetTable . getTypeName ( ) ) ; if ( subquery != null ) { insertNode . setSourceIsPartitioned ( ! subquery . getIsReplicated ( ) ) ; } insertNode . setFieldMap ( fieldMap ) ; if ( matSchema != null ) { MaterializePlanNode matNode = new MaterializePlanNode ( matSchema ) ; insertNode . addAndLinkChild ( matNode ) ; retval . statementGuaranteesDeterminism ( false , true , isContentDeterministic ) ; } else { insertNode . addAndLinkChild ( retval . rootPlanGraph ) ; } if ( m_partitioning . wasSpecifiedAsSingle ( ) || m_partitioning . isInferredSingle ( ) ) { insertNode . setMultiPartition ( false ) ; retval . rootPlanGraph = insertNode ; return retval ; } insertNode . setMultiPartition ( true ) ; boolean isReplicated = targetTable . getIsreplicated ( ) ; retval . rootPlanGraph = addCoordinatorToDMLNode ( insertNode , isReplicated ) ; return retval ; }
Get the next (only) plan for a SQL insertion. Inserts are pretty simple
and this will only generate a single plan.

@return The next (only) plan for a given insert statement, then null.