/* * Copyright (c) 2013, OpenCloudDB/MyCAT and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software;Designed and Developed mainly by many Chinese * opensource volunteers. you can redistribute it and/or modify it under the * terms of the GNU General Public License version 2 only, as published by the * Free Software Foundation. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Any questions about this component can be directed to it's project Web address * https://code.google.com/p/opencloudb/. * */ package com.akiban.sql.parser; import com.akiban.sql.StandardException; import java.util.Properties; /** * A CreateTableNode is the root of a QueryTree that represents a CREATE TABLE or DECLARE GLOBAL TEMPORARY TABLE * statement. * */ public class CreateTableNode extends DDLStatementNode { public static final int BASE_TABLE_TYPE = 0; public static final int SYSTEM_TABLE_TYPE = 1; public static final int VIEW_TYPE = 2; public static final int GLOBAL_TEMPORARY_TABLE_TYPE = 3; public static final int SYNONYM_TYPE = 4; public static final int VTI_TYPE = 5; public static final char ROW_LOCK_GRANULARITY = 'R'; public static final char TABLE_LOCK_GRANULARITY = 'T'; public static final char DEFAULT_LOCK_GRANULARITY = ROW_LOCK_GRANULARITY; private char lockGranularity; private boolean onCommitDeleteRows; //If true, on commit delete rows else on commit preserve rows of temporary table. private boolean onRollbackDeleteRows; //If true, on rollback delete rows from temp table if it was logically modified in that UOW. true is the only supported value private Properties properties; private TableElementList tableElementList; protected int tableType; //persistent table or global temporary table private ResultColumnList resultColumns; private ResultSetNode queryExpression; private boolean withData; private ExistenceCheck existenceCheck; /** * Initializer for a CreateTableNode for a base table * * @param newObjectName The name of the new object being created (ie base table) * @param tableElementList The elements of the table: columns, * constraints, etc. * @param properties The optional list of properties associated with * the table. * @param lockGranularity The lock granularity. * * @exception StandardException Thrown on error */ public void init(Object newObjectName, Object tableElementList, Object properties, Object lockGranularity, Object existenceCheck) throws StandardException { tableType = BASE_TABLE_TYPE; this.lockGranularity = ((Character)lockGranularity).charValue(); implicitCreateSchema = true; assert (this.lockGranularity == TABLE_LOCK_GRANULARITY || this.lockGranularity == ROW_LOCK_GRANULARITY); initAndCheck(newObjectName); this.tableElementList = (TableElementList)tableElementList; this.properties = (Properties)properties; this.existenceCheck = (ExistenceCheck)existenceCheck; } /** * Initializer for a CreateTableNode for a global temporary table * * @param newObjectName The name of the new object being declared (ie temporary table) * @param tableElementList The elements of the table: columns, * constraints, etc. * @param properties The optional list of properties associated with * the table. * @param onCommitDeleteRows If true, on commit delete rows else on commit preserve rows of temporary table. * @param onRollbackDeleteRows If true, on rollback, delete rows from temp tables which were logically modified. true is the only supported value * * @exception StandardException Thrown on error */ public void init(Object newObjectName, Object tableElementList, Object properties, Object onCommitDeleteRows, Object onRollbackDeleteRows, Object existenceCheck) throws StandardException { tableType = GLOBAL_TEMPORARY_TABLE_TYPE; newObjectName = tempTableSchemaNameCheck(newObjectName); this.onCommitDeleteRows = ((Boolean)onCommitDeleteRows).booleanValue(); this.onRollbackDeleteRows = ((Boolean)onRollbackDeleteRows).booleanValue(); initAndCheck(newObjectName); this.tableElementList = (TableElementList)tableElementList; this.properties = (Properties)properties; this.existenceCheck = (ExistenceCheck)existenceCheck; assert this.onRollbackDeleteRows; } /** * Initializer for a CreateTableNode for a base table create from a query * * @param newObjectName The name of the new object being created * (ie base table). * @param resultColumns The optional column list. * @param queryExpression The query expression for the table. */ public void init(Object newObjectName, Object resultColumns, Object queryExpression, Object c) throws StandardException { tableType = BASE_TABLE_TYPE; lockGranularity = DEFAULT_LOCK_GRANULARITY; implicitCreateSchema = true; initAndCheck(newObjectName); this.resultColumns = (ResultColumnList)resultColumns; this.queryExpression = (ResultSetNode)queryExpression; this.existenceCheck = (ExistenceCheck) c; } /** * Fill this node with a deep copy of the given node. */ public void copyFrom(QueryTreeNode node) throws StandardException { super.copyFrom(node); CreateTableNode other = (CreateTableNode)node; this.lockGranularity = other.lockGranularity; this.onCommitDeleteRows = other.onCommitDeleteRows; this.onRollbackDeleteRows = other.onRollbackDeleteRows; this.properties = other.properties; // TODO: Clone? this.tableElementList = (TableElementList) getNodeFactory().copyNode(other.tableElementList, getParserContext()); this.tableType = other.tableType; this.resultColumns = (ResultColumnList) getNodeFactory().copyNode(other.resultColumns, getParserContext()); this.queryExpression = (ResultSetNode) getNodeFactory().copyNode(other.queryExpression, getParserContext()); this.withData = other.withData; this.existenceCheck = other.existenceCheck; } /** * If no schema name specified for global temporary table, SESSION is the implicit schema. * Otherwise, make sure the specified schema name for global temporary table is SESSION. * @param objectName The name of the new object being declared (ie temporary table) */ private Object tempTableSchemaNameCheck(Object objectName) throws StandardException { TableName tempTableName = (TableName)objectName; if (tempTableName != null) { if (tempTableName.getSchemaName() == null) tempTableName.setSchemaName("SESSION"); //If no schema specified, SESSION is the implicit schema. else if (!"SESSION".equals(tempTableName.getSchemaName())) throw new StandardException("Must specify SESSION schema"); } return(tempTableName); } /** * Convert this object to a String. See comments in QueryTreeNode.java * for how this should be done for tree printing. * * @return This object as a String */ public String toString() { String tempString = ""; if (tableType == GLOBAL_TEMPORARY_TABLE_TYPE) { tempString = tempString + "onCommitDeleteRows: " + "\n" + onCommitDeleteRows + "\n"; tempString = tempString + "onRollbackDeleteRows: " + "\n" + onRollbackDeleteRows + "\n"; } else tempString = tempString + (properties != null ? "properties: " + "\n" + properties + "\n" : "") + (withData ? "withData: " + withData + "\n" : "") + "lockGranularity: " + lockGranularity + "\n"; tempString += "existenceCheck: " + existenceCheck + "\n"; return super.toString() + tempString; } public TableElementList getTableElementList() { return tableElementList; } public ResultSetNode getQueryExpression() { return queryExpression; } public boolean isWithData() { return withData; } public void markWithData() { withData = true; } public ExistenceCheck getExistenceCheck() { return existenceCheck; } /** * Prints the sub-nodes of this object. See QueryTreeNode.java for * how tree printing is supposed to work. * @param depth The depth to indent the sub-nodes */ public void printSubNodes(int depth) { if (tableElementList != null) { printLabel(depth, "tableElementList: "); tableElementList.treePrint(depth + 1); } if (queryExpression != null) { printLabel(depth, "queryExpression: "); queryExpression.treePrint(depth + 1); } } public String statementToString() { if (tableType == GLOBAL_TEMPORARY_TABLE_TYPE) return "DECLARE GLOBAL TEMPORARY TABLE"; else return "CREATE TABLE"; } /** * Accept the visitor for all visitable children of this node. * * @param v the visitor * * @exception StandardException on error */ void acceptChildren(Visitor v) throws StandardException { super.acceptChildren(v); if (tableElementList != null) { tableElementList.accept(v); } if (queryExpression != null) { queryExpression.accept(v); } } }