/* * Copyright 2014-2015 the original author or authors * * Licensed under the Apache License, Version 2.0 (the “License”); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an “AS IS” BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // Created on 2015年4月12日 // $Id$ package com.wplatform.ddal.excutor.ddl; import java.util.ArrayList; import java.util.Map; import com.wplatform.ddal.command.CommandInterface; import com.wplatform.ddal.command.ddl.AlterTableAddConstraint; import com.wplatform.ddal.command.ddl.CreateIndex; import com.wplatform.ddal.command.ddl.CreateTable; import com.wplatform.ddal.command.ddl.DefineCommand; import com.wplatform.ddal.command.dml.Insert; import com.wplatform.ddal.command.dml.Query; import com.wplatform.ddal.command.expression.Expression; import com.wplatform.ddal.dbobject.schema.Sequence; import com.wplatform.ddal.dbobject.table.Column; import com.wplatform.ddal.dbobject.table.IndexColumn; import com.wplatform.ddal.dbobject.table.TableMate; import com.wplatform.ddal.dispatch.rule.TableNode; import com.wplatform.ddal.message.DbException; import com.wplatform.ddal.message.ErrorCode; import com.wplatform.ddal.util.New; import com.wplatform.ddal.util.StatementBuilder; import com.wplatform.ddal.util.StringUtils; import com.wplatform.ddal.value.DataType; /** * @author <a href="mailto:jorgie.mail@gmail.com">jorgie li</a> */ public class CreateTableExecutor extends DefineCommandExecutor<CreateTable> { /** * @param prepared */ public CreateTableExecutor(CreateTable prepared) { super(prepared); } @Override public int executeUpdate() { String tableName = prepared.getTableName(); TableMate tableMate = getTableMate(tableName); if (tableMate == null) { throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableName); } if (!tableMate.isInited()) { if (prepared.isIfNotExists()) { return 0; } throw DbException.get(ErrorCode.TABLE_OR_VIEW_ALREADY_EXISTS_1, tableName); } Query query = prepared.getQuery(); if (query != null) { query.prepare(); if (prepared.getColumnCount() == 0) { generateColumnsFromQuery(); } else if (prepared.getColumnCount() != query.getColumnCount()) { throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH); } } ArrayList<Sequence> sequences = New.arrayList(); for (Column c : tableMate.getColumns()) { if (c.isAutoIncrement()) { c.convertAutoIncrementToSequence(session, database.getSchema(session.getCurrentSchemaName()), tableMate.getId(), prepared.isTemporary()); } Sequence seq = c.getSequence(); if (seq != null) { sequences.add(seq); } } try { for (Column c : tableMate.getColumns()) { c.prepareExpression(session); } for (Sequence sequence : sequences) { tableMate.addSequence(sequence); } for (DefineCommand command : prepared.getConstraintCommands()) { if(command.getType() == CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_REFERENTIAL) { AlterTableAddConstraint stmt = (AlterTableAddConstraint)command; String refTableName = stmt.getRefTableName(); TableMate refTable = getTableMate(refTableName); if(refTable != null && refTable.getPartitionNode().length > 1) { TableNode[] tableNodes = tableMate.getPartitionNode(); TableNode[] refTableNodes = refTable.getPartitionNode(); Map<TableNode, TableNode> symmetryRelation = getSymmetryRelation(tableNodes, refTableNodes); if (symmetryRelation == null) { throw DbException.get(ErrorCode.CHECK_CONSTRAINT_INVALID, "Create foreign key for table,the original table and the reference table should be symmetrical."); } } } } TableNode[] nodes = tableMate.getPartitionNode(); execute(nodes); if (query != null) { Insert insert = new Insert(session); insert.setSortedInsertMode(prepared.isSortedInsertMode()); insert.setQuery(query); insert.setTable(tableMate); insert.setInsertFromSelect(true); insert.prepare(); insert.update(); } } catch (DbException e) { throw e; } tableMate.loadMataData(session); return 0; } private void generateColumnsFromQuery() { int columnCount = prepared.getQuery().getColumnCount(); ArrayList<Expression> expressions = prepared.getQuery().getExpressions(); for (int i = 0; i < columnCount; i++) { Expression expr = expressions.get(i); int type = expr.getType(); String name = expr.getAlias(); long precision = expr.getPrecision(); int displaySize = expr.getDisplaySize(); DataType dt = DataType.getDataType(type); if (precision > 0 && (dt.defaultPrecision == 0 || (dt.defaultPrecision > precision && dt.defaultPrecision < Byte.MAX_VALUE))) { // dont' set precision to MAX_VALUE if this is the default precision = dt.defaultPrecision; } int scale = expr.getScale(); if (scale > 0 && (dt.defaultScale == 0 || (dt.defaultScale > scale && dt.defaultScale < precision))) { scale = dt.defaultScale; } if (scale > precision) { precision = scale; } Column col = new Column(name, type, precision, scale, displaySize); prepared.addColumn(col); } } @Override protected String doTranslate(TableNode tableNode) { StatementBuilder buff = new StatementBuilder("CREATE "); if (prepared.isTemporary()) { buff.append("TEMPORARY "); } buff.append("TABLE "); if (prepared.isIfNotExists()) { buff.append("IF NOT EXISTS "); } buff.append(identifier(tableNode.getCompositeObjectName())); if (prepared.getComment() != null) { //buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(prepared.getComment())); } buff.append("("); for (Column column : prepared.getColumns()) { buff.appendExceptFirst(", "); buff.append(column.getCreateSQL()); } for (DefineCommand command : prepared.getConstraintCommands()) { buff.appendExceptFirst(", "); int type = command.getType(); switch (type) { case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY: { AlterTableAddConstraint stmt = (AlterTableAddConstraint)command; buff.append(" CONSTRAINT PRIMARY KEY"); if (stmt.isPrimaryKeyHash()) { buff.append(" USING HASH"); } buff.resetCount(); buff.append("("); for (IndexColumn c : stmt.getIndexColumns()) { buff.appendExceptFirst(", "); buff.append(identifier(c.columnName)); } buff.append(")"); break; } case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_UNIQUE: { AlterTableAddConstraint stmt = (AlterTableAddConstraint)command; buff.append(" CONSTRAINT UNIQUE KEY"); buff.resetCount(); buff.append("("); for (IndexColumn c : stmt.getIndexColumns()) { buff.appendExceptFirst(", "); buff.append(identifier(c.columnName)); } buff.append(")"); break; } case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_CHECK: { AlterTableAddConstraint stmt = (AlterTableAddConstraint)command; String enclose = StringUtils.enclose(stmt.getCheckExpression().getSQL()); buff.append(" CHECK").append(enclose); break; } case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_REFERENTIAL: { AlterTableAddConstraint stmt = (AlterTableAddConstraint)command; String refTableName = stmt.getRefTableName(); TableMate table = getTableMate(stmt.getTableName()); TableMate refTable = getTableMate(refTableName); if(refTable != null) { TableNode[] partitionNode = refTable.getPartitionNode(); if(partitionNode.length > 1) { TableNode[] tableNodes = table.getPartitionNode(); TableNode[] refTableNodes = partitionNode; Map<TableNode, TableNode> symmetryRelation = getSymmetryRelation(tableNodes, refTableNodes); TableNode relation = symmetryRelation.get(tableNode); if (relation == null) { throw DbException.get(ErrorCode.CHECK_CONSTRAINT_INVALID, "The original table and reference table should be symmetrical."); } refTableName = relation.getCompositeObjectName(); } else if(partitionNode.length == 1){ refTableName = partitionNode[0].getCompositeObjectName(); } } IndexColumn[] cols = stmt.getIndexColumns(); IndexColumn[] refCols = stmt.getRefIndexColumns(); buff.resetCount(); buff.append(" CONSTRAINT FOREIGN KEY("); for (IndexColumn c : cols) { buff.appendExceptFirst(", "); buff.append(c.columnName); } buff.append(")"); buff.append(" REFERENCES "); buff.append(identifier(refTableName)).append("("); buff.resetCount(); for (IndexColumn r : refCols) { buff.appendExceptFirst(", "); buff.append(r.columnName); } buff.append(")"); break; } case CommandInterface.CREATE_INDEX: { CreateIndex stmt = (CreateIndex)command; if(stmt.isSpatial()) { buff.append(" SPATIAL INDEX"); } else { buff.append(" INDEX"); if (stmt.isHash()) { buff.append(" USING HASH"); } } buff.resetCount(); buff.append("("); for (IndexColumn c : stmt.getIndexColumns()) { buff.appendExceptFirst(", "); buff.append(identifier(c.columnName)); } buff.append(")"); break; } default: throw DbException.throwInternalError("type=" + type); } } buff.append(")"); if (prepared.getTableEngine() != null) { buff.append(" ENGINE = "); buff.append(prepared.getTableEngine()); } ArrayList<String> tableEngineParams = prepared.getTableEngineParams(); if (tableEngineParams != null && tableEngineParams.isEmpty()) { buff.append("WITH "); buff.resetCount(); for (String parameter : tableEngineParams) { buff.appendExceptFirst(", "); buff.append(StringUtils.quoteIdentifier(parameter)); } } if(prepared.getCharset() != null) { buff.append(" DEFAULT CHARACTER SET = "); buff.append(prepared.getCharset()); } return buff.toString(); } }