/* * 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 com.akiban.sql.types.DataTypeDescriptor; /** * A ColumnDefinitionNode represents a column definition in a DDL statement. * There will be a ColumnDefinitionNode for each column in a CREATE TABLE * statement, and for the column in an ALTER TABLE ADD COLUMN statement. * */ public class ColumnDefinitionNode extends TableElementNode { boolean isAutoincrement; /** * The data type of this column. */ DataTypeDescriptor type; DefaultNode defaultNode; boolean keepCurrentDefault; GenerationClauseNode generationClauseNode; long autoincrementIncrement; long autoincrementStart; //This variable tells if the autoincrement column is participating //in create or alter table. And if it is participating in alter //table, then it further knows if it is represting a change in //increment value or a change in start value. //This information is later used to make sure that the autoincrement //column's increment value is not 0 at the time of create, or is not //getting set to 0 at the time of increment value modification. long autoinc_create_or_modify_Start_Increment; boolean autoincrementVerify; //autoinc_create_or_modify_Start_Increment will be set to one of the //following 3 values. //CREATE_AUTOINCREMENT - this autoincrement column definition is for create table public static final int CREATE_AUTOINCREMENT = 0; //MODIFY_AUTOINCREMENT_RESTART_VALUE - this column definition is for //alter table command to change the start value of the column public static final int MODIFY_AUTOINCREMENT_RESTART_VALUE = 1; //MODIFY_AUTOINCREMENT_INC_VALUE - this column definition is for //alter table command to change the increment value of the column public static final int MODIFY_AUTOINCREMENT_INC_VALUE = 2; /** * Initializer for a ColumnDefinitionNode * * @param name The name of the column * @param defaultNode The default value of the column * @param type A DataTypeDescriptor telling the type of the column * @param autoIncrementInfo Info for autoincrement columns * */ public void init(Object name, Object defaultNode, Object type, Object autoIncrementInfo) throws StandardException { super.init(name); this.type = (DataTypeDescriptor)type; if (defaultNode instanceof UntypedNullConstantNode) { // TODO: Can make properly typed null using this.type now. } else if (defaultNode instanceof GenerationClauseNode) { generationClauseNode = (GenerationClauseNode)defaultNode; } else { assert (defaultNode == null || (defaultNode instanceof DefaultNode)); this.defaultNode = (DefaultNode)defaultNode; if (autoIncrementInfo != null) { long[] aii = (long[])autoIncrementInfo; autoincrementStart = aii[QueryTreeNode.AUTOINCREMENT_START_INDEX]; autoincrementIncrement = aii[QueryTreeNode.AUTOINCREMENT_INC_INDEX]; //Parser has passed the info about autoincrement column's status in the //following array element. It will tell if the autoinc column is part of //a create table or if is a part of alter table. And if it is part of //alter table, is it for changing the increment value or for changing //the start value? autoinc_create_or_modify_Start_Increment = aii[QueryTreeNode.AUTOINCREMENT_CREATE_MODIFY]; /* * If using DB2 syntax to set increment value, will need to check if column * is already created for autoincrement. */ autoincrementVerify = (aii[QueryTreeNode.AUTOINCREMENT_IS_AUTOINCREMENT_INDEX] > 0) ? false : true; isAutoincrement = true; // an autoincrement column cannot be null-- setting // non-nullability for this column is needed because // you could create a column with ai default, add data, drop // the default, and try to add it back again you'll get an // error because the column is marked nullable. if (type != null) setNullability(false); } } // ColumnDefinitionNode instances can be subclassed by // ModifyColumnNode for use in ALTER TABLE .. ALTER COLUMN // statements, in which case the node represents the intended // changes to the column definition. For such a case, we // record whether or not the statement specified that the // column's default value should be changed. If we are to // keep the current default, ModifyColumnNode will re-read // the current default from the system catalogs prior to // performing the column alteration. See DERBY-4006 // for more discussion of this behavior. this.keepCurrentDefault = (defaultNode == null); } /** * Fill this node with a deep copy of the given node. */ public void copyFrom(QueryTreeNode node) throws StandardException { super.copyFrom(node); ColumnDefinitionNode other = (ColumnDefinitionNode)node; this.isAutoincrement = other.isAutoincrement; this.type = other.type; this.defaultNode = (DefaultNode) getNodeFactory().copyNode(other.defaultNode, getParserContext()); this.keepCurrentDefault = other.keepCurrentDefault; this.generationClauseNode = (GenerationClauseNode) getNodeFactory().copyNode(other.generationClauseNode, getParserContext()); this.autoincrementIncrement = other.autoincrementIncrement; this.autoincrementStart = other.autoincrementStart; this.autoinc_create_or_modify_Start_Increment = other.autoinc_create_or_modify_Start_Increment; this.autoincrementVerify = other.autoincrementVerify; } /** * 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() { return "type: " + getType() + "\n" + (!isAutoincrementColumn() ? "" : ( "autoIncrementStart: " + getAutoincrementStart() + "\n" + "autoIncrementIncrement: " + getAutoincrementIncrement() + "\n" )) + super.toString(); } /** * Returns the unqualified name of the column being defined. * * @return the name of the column */ public String getColumnName() { return this.name; } /** * Returns the data type of the column being defined. * * @return the data type of the column */ public final DataTypeDescriptor getType() { return type; } /** Set the type of this column */ public void setType(DataTypeDescriptor dts) { type = dts; } /** * Set the nullability of the column definition node. */ void setNullability(boolean nullable) { type = getType().getNullabilityType(nullable); } /** * Return the DefaultNode, if any, associated with this node. * * @return The DefaultNode, if any, associated with this node. */ public DefaultNode getDefaultNode() { return defaultNode; } /** * Return true if this column has a generation clause. */ public boolean hasGenerationClause() { return (generationClauseNode != null); } /** * Get the generation clause. */ public GenerationClauseNode getGenerationClauseNode() { return generationClauseNode; } /** * Is this an autoincrement column? * * @return Whether or not this is an autoincrement column. */ public boolean isAutoincrementColumn() { return isAutoincrement; } /** * Get the autoincrement start value * * @return Autoincrement start value. */ public long getAutoincrementStart() { return autoincrementStart; } /** * Get the autoincrement increment value * * @return Autoincrement increment value. */ public long getAutoincrementIncrement() { return autoincrementIncrement; } /** * Get the status of this autoincrement column * * @return ColumnDefinitionNode.CREATE_AUTOINCREMENT - * if this definition is for autoincrement column creatoin * ColumnDefinitionNode.MODIFY_AUTOINCREMENT_RESTART_VALUE - * if this definition is for alter sutoincrement column to change the start value * ColumnDefinitionNode.MODIFY_AUTOINCREMENT_INC_VALUE * if this definition is for alter autoincrement column to change the increment value */ public long getAutoinc_create_or_modify_Start_Increment() { return autoinc_create_or_modify_Start_Increment; } /** * Prints the sub-nodes of this object. See QueryTreeNode.java for * how tree printing is supposed to work. * * @param depth The depth of this node in the tree */ public void printSubNodes(int depth) { super.printSubNodes(depth); if (defaultNode != null) { printLabel(depth, "default: "); defaultNode.treePrint(depth + 1); } if (generationClauseNode != null) { printLabel(depth, "generationClause: "); generationClauseNode.treePrint(depth + 1); } } }