Package org.voltdb.planner

Source Code of org.voltdb.planner.ParsedInsertStmt

/* This file is part of VoltDB.
* Copyright (C) 2008-2014 VoltDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.voltdb.planner;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;

import org.hsqldb_voltpatches.VoltXMLElement;
import org.voltdb.VoltType;
import org.voltdb.catalog.Column;
import org.voltdb.catalog.Database;
import org.voltdb.catalog.Table;
import org.voltdb.expressions.AbstractExpression;
import org.voltdb.expressions.ConstantValueExpression;
import org.voltdb.expressions.FunctionExpression;
import org.voltdb.planner.parseinfo.StmtSubqueryScan;

/**
*
*
*/
public class ParsedInsertStmt extends AbstractParsedStmt {

    /**
     * A hash of the columns that were provided in the insert stmt,
     * and the corresponding values that were provided.  It is a
     * linked hash map so we retain the order in which the user
     * specified the columns.
     */
    public LinkedHashMap<Column, AbstractExpression> m_columns = new LinkedHashMap<Column, AbstractExpression>();

    /**
     * The SELECT statement for INSERT INTO ... SELECT.
     */
    private StmtSubqueryScan m_subquery = null;



    /**
    * Class constructor
    * @param paramValues
    * @param db
    */
    public ParsedInsertStmt(String[] paramValues, Database db) {
        super(paramValues, db);
    }

    @Override
    void parse(VoltXMLElement stmtNode) {
        // An INSERT statement may have table scans if its an INSERT INTO ... SELECT,
        // but those table scans will belong to the corresponding ParsedSelectStmt
        assert(m_tableList.isEmpty());

        String tableName = stmtNode.attributes.get("table");
        Table table = getTableFromDB(tableName);

        m_tableList.add(table);

        for (VoltXMLElement node : stmtNode.children) {
            if (node.name.equalsIgnoreCase("columns")) {
                parseTargetColumns(node, table, m_columns);
            }
            else if (node.name.equalsIgnoreCase(SELECT_NODE_NAME)) {
                m_subquery = new StmtSubqueryScan (parseSubquery(node), "__VOLT_INSERT_SUBQUERY__");
            }
            else if (node.name.equalsIgnoreCase(UNION_NODE_NAME)) {
                throw new PlanningErrorException(
                        "INSERT INTO ... SELECT is not supported for UNION or other set operations.");
            }
        }
    }

    @Override
    public String toString() {
        String retval = super.toString() + "\n";

        retval += "COLUMNS:\n";
        for (Entry<Column, AbstractExpression> col : m_columns.entrySet()) {
            retval += "\tColumn: " + col.getKey().getTypeName();
            if (col.getValue() != null) {
                retval += ": " + col.getValue().toString();
            }
            retval += "\n";
        }

        if (getSubselectStmt() != null) {
            retval += "SUBSELECT:\n";
            retval += getSubselectStmt().toString();
        }
        return retval;
    }

    private AbstractExpression defaultValueToExpr(Column column) {
        AbstractExpression expr = null;

        boolean isConstantValue = true;
        if (column.getDefaulttype() == VoltType.TIMESTAMP.getValue()) {

            boolean isFunctionFormat = true;
            String timeValue = column.getDefaultvalue();
            try {
                Long.parseLong(timeValue);
                isFunctionFormat = false;
            } catch (NumberFormatException  e) {}
            if (isFunctionFormat) {
                try {
                    java.sql.Timestamp.valueOf(timeValue);
                    isFunctionFormat = false;
                } catch (IllegalArgumentException e) {}
            }

            if (isFunctionFormat) {
                String name = timeValue.split(":")[0];
                int id = Integer.parseInt(timeValue.split(":")[1]);

                FunctionExpression funcExpr = new FunctionExpression();
                funcExpr.setAttributes(name, name , id);

                funcExpr.setValueType(VoltType.TIMESTAMP);
                funcExpr.setValueSize(VoltType.TIMESTAMP.getMaxLengthInBytes());

                expr = funcExpr;
                isConstantValue = false;
            }
        }
        if (isConstantValue) {
            // Not Default sql function.
            ConstantValueExpression const_expr = new ConstantValueExpression();
            expr = const_expr;
            if (column.getDefaulttype() != 0) {
                const_expr.setValue(column.getDefaultvalue());
                const_expr.refineValueType(VoltType.get((byte) column.getDefaulttype()), column.getSize());
            }
            else {
                const_expr.setValue(null);
                const_expr.refineValueType(VoltType.get((byte) column.getType()), column.getSize());
            }
        }

        assert(expr != null);
        return expr;
    }

    public AbstractExpression getExpressionForPartitioning(Column column) {
        AbstractExpression expr = null;
        if (getSubselectStmt() != null) {
            // This method is used by statement partitioning to help infer single partition statements.
            // Caller expects a constant or parameter to be returned.
            return null;
        }
        else {
            expr = m_columns.get(column);
            if (expr == null) {
                expr = defaultValueToExpr(column);
            }
        }

        assert(expr != null);
        return expr;
    }

    public boolean isInsertWithSubquery() {
        if (m_subquery != null) {
            return true;
        }
        return false;
    }

    /**
     * Return the subqueries for this statement.  For INSERT statements,
     * there can be only one.
     */
    @Override
    public List<StmtSubqueryScan> getSubqueries() {
        List<StmtSubqueryScan> subqueries = new ArrayList<>();

        if (m_subquery != null) {
            subqueries.add(m_subquery);
        }

        return subqueries;
    }

    /**
     * @return the subquery for the insert stmt if there is one, null otherwise
     */
    private ParsedSelectStmt getSubselectStmt() {
        if (m_subquery != null) {
            return (ParsedSelectStmt)(m_subquery.getSubqueryStmt());
        }
        return null;
    }

    @Override
    public boolean isOrderDeterministicInSpiteOfUnorderedSubqueries() {
        assert(getSubselectStmt() != null);
        return getSubselectStmt().isOrderDeterministicInSpiteOfUnorderedSubqueries();
    }
}
TOP

Related Classes of org.voltdb.planner.ParsedInsertStmt

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.