| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| package org.apache.tajo.master.exec; |
| |
| import com.google.common.base.Preconditions; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.tajo.annotation.Nullable; |
| import org.apache.tajo.catalog.*; |
| import org.apache.tajo.catalog.partition.PartitionMethodDesc; |
| import org.apache.tajo.engine.query.QueryContext; |
| import org.apache.tajo.exception.DuplicateTableException; |
| import org.apache.tajo.exception.TajoException; |
| import org.apache.tajo.exception.UndefinedTableException; |
| import org.apache.tajo.master.TajoMaster; |
| import org.apache.tajo.plan.logical.CreateTableNode; |
| import org.apache.tajo.plan.util.PlannerUtil; |
| import org.apache.tajo.schema.IdentifierUtil; |
| import org.apache.tajo.storage.Tablespace; |
| import org.apache.tajo.storage.TablespaceManager; |
| import org.apache.tajo.util.Pair; |
| |
| import java.io.IOException; |
| import java.net.URI; |
| |
| /** |
| * An executor for Create Table command in QueryCoordinator |
| */ |
| public class CreateTableExecutor { |
| private static final Log LOG = LogFactory.getLog(DDLExecutor.class); |
| |
| private final CatalogService catalog; |
| |
| public CreateTableExecutor(TajoMaster.MasterContext context) { |
| this.catalog = context.getCatalog(); |
| } |
| |
| public TableDesc create(QueryContext queryContext, CreateTableNode createTable, boolean ifNotExists) |
| throws IOException, TajoException { |
| |
| TableMeta meta; |
| if (createTable.hasOptions()) { |
| meta = CatalogUtil.newTableMeta(createTable.getStorageType(), createTable.getOptions()); |
| } else { |
| meta = CatalogUtil.newTableMeta(createTable.getStorageType(), queryContext.getConf()); |
| } |
| |
| if(PlannerUtil.isFileStorageType(createTable.getStorageType()) && createTable.isExternal()){ |
| Preconditions.checkState(createTable.hasUri(), "ERROR: LOCATION must be given."); |
| } |
| |
| return create( |
| queryContext, |
| createTable.getTableName(), |
| createTable.getTableSpaceName(), |
| createTable.getTableSchema(), |
| meta, |
| createTable.getUri(), |
| createTable.isExternal(), |
| createTable.getPartitionMethod(), |
| ifNotExists); |
| } |
| |
| public TableDesc create(QueryContext queryContext, |
| String tableName, |
| @Nullable String tableSpaceName, |
| @Nullable Schema schema, |
| TableMeta meta, |
| @Nullable URI uri, |
| boolean isExternal, |
| @Nullable PartitionMethodDesc partitionDesc, |
| boolean ifNotExists) throws IOException, TajoException { |
| |
| Pair<String, String> separatedNames = getQualifiedName(queryContext.getCurrentDatabase(), tableName); |
| String databaseName = separatedNames.getFirst(); |
| String simpleTableName = separatedNames.getSecond(); |
| String qualifiedName = IdentifierUtil.buildFQName(databaseName, simpleTableName); |
| |
| // Check if the table to be created already exists |
| boolean exists = catalog.existsTable(databaseName, simpleTableName); |
| if (exists) { |
| return handlExistence(ifNotExists, qualifiedName); |
| } |
| |
| Tablespace tableSpace = getTablespaceHandler(tableSpaceName, uri); |
| |
| TableDesc desc; |
| URI tableUri = isExternal ? uri : tableSpace.getTableUri(databaseName, simpleTableName); |
| desc = new TableDesc(qualifiedName, schema, meta, tableUri, isExternal); |
| |
| if (partitionDesc != null) { |
| desc.setPartitionMethod(partitionDesc); |
| } |
| |
| tableSpace.createTable(desc, ifNotExists); |
| catalog.createTable(desc); |
| LOG.info("relation '" + qualifiedName + "' created."); |
| return desc; |
| } |
| |
| private TableDesc handlExistence(boolean ifNotExists, String qualifiedName) |
| throws DuplicateTableException, UndefinedTableException { |
| |
| if (ifNotExists) { |
| LOG.info("relation \"" + qualifiedName + "\" is already exists."); |
| return catalog.getTableDesc(qualifiedName); |
| } else { |
| throw new DuplicateTableException(qualifiedName); |
| } |
| } |
| |
| private Pair<String, String> getQualifiedName(String currentDatabase, String tableName) { |
| if (IdentifierUtil.isFQTableName(tableName)) { |
| String [] splitted = IdentifierUtil.splitFQTableName(tableName); |
| return new Pair<>(splitted[0], splitted[1]); |
| } else { |
| return new Pair<>(currentDatabase, tableName); |
| } |
| } |
| |
| private Tablespace getTablespaceHandler(@Nullable String tableSpaceName, @Nullable URI tableUri) { |
| if (tableSpaceName != null) { |
| return TablespaceManager.getByName(tableSpaceName); |
| } else if (tableUri != null) { |
| return TablespaceManager.get(tableUri); |
| } else { |
| return TablespaceManager.getDefault(); |
| } |
| } |
| } |