Commit 0e82afe3 authored by terrymanu's avatar terrymanu
Browse files

move refresh metadata to metadata package

parent 183504f3
Loading
Loading
Loading
Loading
+156 −0
Original line number Diff line number Diff line
/*
 * Copyright 2016-2018 shardingsphere.io.
 * <p>
 * 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.
 * </p>
 */

package io.shardingsphere.core.metadata.table;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import io.shardingsphere.core.parsing.antlr.sql.segment.definition.column.ColumnDefinitionSegment;
import io.shardingsphere.core.parsing.antlr.sql.segment.definition.column.position.ColumnAfterPositionSegment;
import io.shardingsphere.core.parsing.antlr.sql.segment.definition.column.position.ColumnFirstPositionSegment;
import io.shardingsphere.core.parsing.antlr.sql.segment.definition.column.position.ColumnPositionSegment;
import io.shardingsphere.core.parsing.antlr.sql.statement.ddl.AlterTableStatement;
import io.shardingsphere.core.parsing.antlr.sql.statement.ddl.CreateTableStatement;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * Table meta data factory.
 *
 * @author zhangliang
 */
public final class TableMetaDataFactory {
    
    /**
     * New instance of table meta data.
     * 
     * @param createTableStatement create table statement
     * @return instance of table meta data
     */
    public static TableMetaData newInstance(final CreateTableStatement createTableStatement) {
        return new TableMetaData(Lists.transform(createTableStatement.getColumnDefinitions(), new Function<ColumnDefinitionSegment, ColumnMetaData>() {
            
            @Override
            public ColumnMetaData apply(final ColumnDefinitionSegment input) {
                return new ColumnMetaData(input.getColumnName(), input.getDataType(), input.isPrimaryKey());
            }
        }));
    }
    
    /**
     * New instance of table meta data.
     *
     * @param alterTableStatement alter table statement
     * @param oldTableMetaData old table meta data
     * @return instance of table meta data
     */
    public static TableMetaData newInstance(final AlterTableStatement alterTableStatement, final TableMetaData oldTableMetaData) {
        List<ColumnMetaData> columnMetaDataList = createNewColumnMetaDataList(alterTableStatement, oldTableMetaData);
        fillAddedColumnDefinitions(alterTableStatement, columnMetaDataList);
        changeColumnDefinitionPositions(alterTableStatement, columnMetaDataList);
        dropColumnDefinitions(alterTableStatement, columnMetaDataList);
        return new TableMetaData(columnMetaDataList);
    }
    
    private static List<ColumnMetaData> createNewColumnMetaDataList(final AlterTableStatement alterTableStatement, final TableMetaData oldTableMetaData) {
        List<ColumnMetaData> result = new LinkedList<>();
        for (ColumnMetaData each : oldTableMetaData.getColumnMetaDataList()) {
            String columnName;
            String dataType;
            boolean primaryKey;
            if (alterTableStatement.getModifiedColumnDefinitions().containsKey(each.getColumnName())) {
                ColumnDefinitionSegment modifiedColumnDefinition = alterTableStatement.getModifiedColumnDefinitions().get(each.getColumnName());
                columnName = modifiedColumnDefinition.getColumnName();
                dataType = modifiedColumnDefinition.getDataType();
                primaryKey = !alterTableStatement.isDropPrimaryKey() && modifiedColumnDefinition.isPrimaryKey();
            } else {
                columnName = each.getColumnName();
                dataType = each.getDataType();
                primaryKey = !alterTableStatement.isDropPrimaryKey() && each.isPrimaryKey();
            }
            result.add(new ColumnMetaData(columnName, dataType, primaryKey));
        }
        return result;
    }
    
    private static void fillAddedColumnDefinitions(final AlterTableStatement alterTableStatement, final List<ColumnMetaData> columnMetaDataList) {
        for (ColumnDefinitionSegment each : alterTableStatement.getAddedColumnDefinitions()) {
            columnMetaDataList.add(new ColumnMetaData(each.getColumnName(), each.getDataType(), !alterTableStatement.isDropPrimaryKey() && each.isPrimaryKey()));
        }
    }
    
    private static void changeColumnDefinitionPositions(final AlterTableStatement alterTableStatement, final List<ColumnMetaData> columnMetaDataList) {
        for (ColumnPositionSegment each : alterTableStatement.getChangedPositionColumns()) {
            if (each instanceof ColumnFirstPositionSegment) {
                adjustFirst(columnMetaDataList, (ColumnFirstPositionSegment) each);
            } else {
                adjustAfter(columnMetaDataList, (ColumnAfterPositionSegment) each);
            }
        }
    }
    
    private static void adjustFirst(final List<ColumnMetaData> columnMetaDataList, final ColumnFirstPositionSegment columnFirstPositionSegment) {
        ColumnMetaData firstColumnMetaData = null;
        Iterator<ColumnMetaData> iterator = columnMetaDataList.iterator();
        while (iterator.hasNext()) {
            ColumnMetaData each = iterator.next();
            if (each.getColumnName().equals(columnFirstPositionSegment.getColumnName())) {
                firstColumnMetaData = each;
                iterator.remove();
                break;
            }
        }
        if (null != firstColumnMetaData) {
            columnMetaDataList.add(0, firstColumnMetaData);
        }
    }
    
    private static void adjustAfter(final List<ColumnMetaData> columnMetaDataList, final ColumnAfterPositionSegment columnAfterPositionSegment) {
        int afterIndex = -1;
        int adjustColumnIndex = -1;
        for (int i = 0; i < columnMetaDataList.size(); i++) {
            if (columnMetaDataList.get(i).getColumnName().equals(columnAfterPositionSegment.getColumnName())) {
                adjustColumnIndex = i;
            }
            if (columnMetaDataList.get(i).getColumnName().equals(columnAfterPositionSegment.getAfterColumnName())) {
                afterIndex = i;
            }
            if (adjustColumnIndex >= 0 && afterIndex >= 0) {
                break;
            }
        }
        if (adjustColumnIndex >= 0 && afterIndex >= 0 && adjustColumnIndex != afterIndex + 1) {
            ColumnMetaData adjustColumnMetaData = columnMetaDataList.remove(adjustColumnIndex);
            if (afterIndex < adjustColumnIndex) {
                afterIndex = afterIndex + 1;
            }
            columnMetaDataList.add(afterIndex, adjustColumnMetaData);
        }
    }
    
    private static void dropColumnDefinitions(final AlterTableStatement alterTableStatement, final List<ColumnMetaData> newColumnMetaData) {
        Iterator<ColumnMetaData> iterator = newColumnMetaData.iterator();
        while (iterator.hasNext()) {
            ColumnMetaData each = iterator.next();
            if (alterTableStatement.getDropColumnNames().contains(each.getColumnName())) {
                iterator.remove();
            }
        }
    }
}
+11 −123
Original line number Diff line number Diff line
@@ -17,18 +17,12 @@

package io.shardingsphere.shardingjdbc.jdbc.adapter;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import io.shardingsphere.core.constant.SQLType;
import io.shardingsphere.core.constant.properties.ShardingPropertiesConstant;
import io.shardingsphere.core.metadata.table.ColumnMetaData;
import io.shardingsphere.core.metadata.table.TableMetaData;
import io.shardingsphere.core.metadata.table.TableMetaDataFactory;
import io.shardingsphere.core.metadata.table.executor.TableMetaDataLoader;
import io.shardingsphere.core.parsing.antlr.sql.segment.definition.column.ColumnDefinitionSegment;
import io.shardingsphere.core.parsing.antlr.sql.segment.definition.column.position.ColumnAfterPositionSegment;
import io.shardingsphere.core.parsing.antlr.sql.segment.definition.column.position.ColumnFirstPositionSegment;
import io.shardingsphere.core.parsing.antlr.sql.segment.definition.column.position.ColumnPositionSegment;
import io.shardingsphere.core.parsing.antlr.sql.statement.ddl.AlterTableStatement;
import io.shardingsphere.core.parsing.antlr.sql.statement.ddl.CreateTableStatement;
import io.shardingsphere.core.routing.SQLRouteResult;
@@ -43,9 +37,6 @@ import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * Adapter for {@code Statement}.
@@ -253,122 +244,19 @@ public abstract class AbstractStatementAdapter extends AbstractUnsupportedOperat
        if (null != routeResult && null != connection && SQLType.DDL == routeResult.getSqlStatement().getType() && !routeResult.getSqlStatement().getTables().isEmpty()) {
            String logicTableName = routeResult.getSqlStatement().getTables().getSingleTableName();
            if (routeResult.getSqlStatement() instanceof CreateTableStatement) {
                createTable(logicTableName, connection, (CreateTableStatement) routeResult.getSqlStatement());
                connection.getShardingContext().getMetaData().getTable().put(logicTableName, TableMetaDataFactory.newInstance((CreateTableStatement) routeResult.getSqlStatement()));
            } else if (routeResult.getSqlStatement() instanceof AlterTableStatement) {
                alterTable(logicTableName, connection, (AlterTableStatement) routeResult.getSqlStatement());
            } else {
                doOther(logicTableName, connection);
            }
        }
    }
    
    private void createTable(final String logicTableName, final ShardingConnection connection, final CreateTableStatement createTableStatement) {
        TableMetaData tableMetaData = new TableMetaData(Lists.transform(createTableStatement.getColumnDefinitions(), new Function<ColumnDefinitionSegment, ColumnMetaData>() {
            
            @Override
            public ColumnMetaData apply(final ColumnDefinitionSegment input) {
                return new ColumnMetaData(input.getColumnName(), input.getDataType(), input.isPrimaryKey());
            }
        }));
        connection.getShardingContext().getMetaData().getTable().put(logicTableName, tableMetaData);
    }
    
    private void alterTable(final String logicTableName, final ShardingConnection connection, final AlterTableStatement alterTableStatement) {
        List<ColumnMetaData> columnMetaDataList = createNewColumnMetaDataList(alterTableStatement, connection.getShardingContext().getMetaData().getTable().get(logicTableName));
        fillAddedColumnDefinitions(alterTableStatement, columnMetaDataList);
        changeColumnDefinitionPositions(alterTableStatement, columnMetaDataList);
        dropColumnDefinitions(alterTableStatement, columnMetaDataList);
        Optional<String> newTableName = alterTableStatement.getNewTableName();
                TableMetaData newTableMetaData = TableMetaDataFactory.newInstance((AlterTableStatement) routeResult.getSqlStatement(), 
                        connection.getShardingContext().getMetaData().getTable().get(logicTableName));
                Optional<String> newTableName = ((AlterTableStatement) routeResult.getSqlStatement()).getNewTableName();
                if (newTableName.isPresent()) {
                    connection.getShardingContext().getMetaData().getTable().put(newTableName.get(), newTableMetaData);
                    connection.getShardingContext().getMetaData().getTable().remove(logicTableName);
            connection.getShardingContext().getMetaData().getTable().put(newTableName.get(), new TableMetaData(columnMetaDataList));
        } else {
            connection.getShardingContext().getMetaData().getTable().put(logicTableName, new TableMetaData(columnMetaDataList));
        }
    }
    
    private List<ColumnMetaData> createNewColumnMetaDataList(final AlterTableStatement alterTableStatement, final TableMetaData oldTableMetaData) {
        List<ColumnMetaData> result = new LinkedList<>();
        for (ColumnMetaData each : oldTableMetaData.getColumnMetaDataList()) {
            String columnName;
            String dataType;
            boolean primaryKey;
            if (alterTableStatement.getModifiedColumnDefinitions().containsKey(each.getColumnName())) {
                ColumnDefinitionSegment modifiedColumnDefinition = alterTableStatement.getModifiedColumnDefinitions().get(each.getColumnName());
                columnName = modifiedColumnDefinition.getColumnName();
                dataType = modifiedColumnDefinition.getDataType();
                primaryKey = !alterTableStatement.isDropPrimaryKey() && modifiedColumnDefinition.isPrimaryKey();
                } else {
                columnName = each.getColumnName();
                dataType = each.getDataType();
                primaryKey = !alterTableStatement.isDropPrimaryKey() && each.isPrimaryKey();
            }
            result.add(new ColumnMetaData(columnName, dataType, primaryKey));
        }
        return result;
    }
    
    private void fillAddedColumnDefinitions(final AlterTableStatement alterTableStatement, final List<ColumnMetaData> columnMetaDataList) {
        for (ColumnDefinitionSegment each : alterTableStatement.getAddedColumnDefinitions()) {
            columnMetaDataList.add(new ColumnMetaData(each.getColumnName(), each.getDataType(), !alterTableStatement.isDropPrimaryKey() && each.isPrimaryKey()));
                    connection.getShardingContext().getMetaData().getTable().put(logicTableName, newTableMetaData);
                }
    }
    
    private void changeColumnDefinitionPositions(final AlterTableStatement alterTableStatement, final List<ColumnMetaData> columnMetaDataList) {
        for (ColumnPositionSegment each : alterTableStatement.getChangedPositionColumns()) {
            if (each instanceof ColumnFirstPositionSegment) {
                adjustFirst(columnMetaDataList, (ColumnFirstPositionSegment) each);
            } else {
                adjustAfter(columnMetaDataList, (ColumnAfterPositionSegment) each);
            }
        }
    }
    
    private void adjustFirst(final List<ColumnMetaData> columnMetaDataList, final ColumnFirstPositionSegment columnFirstPositionSegment) {
        ColumnMetaData firstColumnMetaData = null;
        Iterator<ColumnMetaData> iterator = columnMetaDataList.iterator();
        while (iterator.hasNext()) {
            ColumnMetaData each = iterator.next();
            if (each.getColumnName().equals(columnFirstPositionSegment.getColumnName())) {
                firstColumnMetaData = each;
                iterator.remove();
                break;
            }
        }
        if (null != firstColumnMetaData) {
            columnMetaDataList.add(0, firstColumnMetaData);
        }
    }
    
    private void adjustAfter(final List<ColumnMetaData> columnMetaDataList, final ColumnAfterPositionSegment columnAfterPositionSegment) {
        int afterIndex = -1;
        int adjustColumnIndex = -1;
        for (int i = 0; i < columnMetaDataList.size(); i++) {
            if (columnMetaDataList.get(i).getColumnName().equals(columnAfterPositionSegment.getColumnName())) {
                adjustColumnIndex = i;
            }
            if (columnMetaDataList.get(i).getColumnName().equals(columnAfterPositionSegment.getAfterColumnName())) {
                afterIndex = i;
            }
            if (adjustColumnIndex >= 0 && afterIndex >= 0) {
                break;
            }
        }
        if (adjustColumnIndex >= 0 && afterIndex >= 0 && adjustColumnIndex != afterIndex + 1) {
            ColumnMetaData adjustColumnMetaData = columnMetaDataList.remove(adjustColumnIndex);
            if (afterIndex < adjustColumnIndex) {
                afterIndex = afterIndex + 1;
            }
            columnMetaDataList.add(afterIndex, adjustColumnMetaData);
        }
    }
    
    private void dropColumnDefinitions(final AlterTableStatement alterTableStatement, final List<ColumnMetaData> newColumnMetaData) {
        Iterator<ColumnMetaData> iterator = newColumnMetaData.iterator();
        while (iterator.hasNext()) {
            ColumnMetaData each = iterator.next();
            if (alterTableStatement.getDropColumnNames().contains(each.getColumnName())) {
                iterator.remove();
                doOther(logicTableName, connection);
            }
        }
    }