提交 790e0403 编写于 作者: C codefairy08

generate alter table meta data

上级 fcbe90d5
......@@ -34,6 +34,15 @@ public final class ShardingTableMetaData {
private final Map<String, TableMetaData> tableMetaDataMap;
/**
* Get table meta data by table name.
* @param logicTableName logicTableName logic table name
* @return table mata data
*/
public TableMetaData get(final String logicTableName) {
return tableMetaDataMap.get(logicTableName);
}
/**
* Add table meta data.
*
......
/*
* 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.parsing.antler.phrase.visitor.mysql;
import java.util.List;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import io.shardingsphere.core.parsing.antler.sql.ddl.AlterTableStatement;
import io.shardingsphere.core.parsing.antler.sql.ddl.ColumnDefinition;
import io.shardingsphere.core.parsing.antler.sql.ddl.mysql.MySQLAlterTableStatement;
import io.shardingsphere.core.parsing.antler.utils.TreeUtils;
import io.shardingsphere.core.parsing.parser.sql.SQLStatement;
public class MySQLAddColumnVisitor extends MySQLColumnPositionVisitor {
/** Visit add column node.
* @param rootNode root node of ast
* @param statement sql statement
*/
@Override
public void visit(final ParserRuleContext rootNode, final SQLStatement statement) {
AlterTableStatement alterStatement = (AlterTableStatement) statement;
List<ParseTree> addColumnCtxs = TreeUtils.getAllDescendantByRuleName(rootNode, "addColumn");
if (null == addColumnCtxs) {
return;
}
for (ParseTree each : addColumnCtxs) {
List<ParseTree> columnDefinitionCtxs = TreeUtils.getAllDescendantByRuleName(each, "columnDefinition");
if (null == columnDefinitionCtxs) {
continue;
}
for (ParseTree columnDefinitionCtx : columnDefinitionCtxs) {
ColumnDefinition column = parseColumnDefinition(columnDefinitionCtx);
if (null != column) {
alterStatement.getAddColumns().add(column);
visitFirstOrAfter((ParserRuleContext) each, (MySQLAlterTableStatement)alterStatement, column.getName());
}
}
}
}
}
/*
* 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.parsing.antler.phrase.visitor.mysql;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import io.shardingsphere.core.parsing.antler.phrase.visitor.ColumnDefinitionVisitor;
import io.shardingsphere.core.parsing.antler.sql.ddl.ColumnPosition;
import io.shardingsphere.core.parsing.antler.sql.ddl.mysql.MySQLAlterTableStatement;
import io.shardingsphere.core.parsing.antler.utils.TreeUtils;
public class MySQLColumnPositionVisitor extends ColumnDefinitionVisitor {
protected void visitFirstOrAfter(ParserRuleContext ancestorNode, MySQLAlterTableStatement alterStatement,
String columnName) {
ParserRuleContext firstOrAfterColumnCtx = (ParserRuleContext) TreeUtils.getFirstChildByRuleName(ancestorNode,
"firstOrAfterColumn");
if (null == firstOrAfterColumnCtx) {
return;
}
ParseTree columnNameCtx = TreeUtils.getFirstChildByRuleName(firstOrAfterColumnCtx, "columnName");
ColumnPosition columnPosition = new ColumnPosition();
columnPosition.setStartIndex(firstOrAfterColumnCtx.getStart().getStartIndex());
if (columnNameCtx != null) {
columnPosition.setColumnName(columnName);
columnPosition.setAfterColumn(columnNameCtx.getText());
}else {
columnPosition.setFirstColumn(columnName);
}
alterStatement.getPositionChangedColumns().add(columnPosition);
}
}
/*
* 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.parsing.antler.phrase.visitor.mysql;
import java.util.List;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import io.shardingsphere.core.parsing.antler.sql.ddl.AlterTableStatement;
import io.shardingsphere.core.parsing.antler.sql.ddl.ColumnDefinition;
import io.shardingsphere.core.parsing.antler.sql.ddl.mysql.MySQLAlterTableStatement;
import io.shardingsphere.core.parsing.antler.utils.TreeUtils;
import io.shardingsphere.core.parsing.parser.sql.SQLStatement;
public class MySQLModifyColumnVisitor extends MySQLColumnPositionVisitor {
/** Visit modify column node.
* @param rootNode root node of ast
* @param statement sql statement
*/
@Override
public void visit(final ParserRuleContext rootNode, final SQLStatement statement) {
AlterTableStatement alterStatement = (AlterTableStatement) statement;
List<ParseTree> modifyColumnCtxs = TreeUtils.getAllDescendantByRuleName(rootNode, "modifyColumn");
if (null == modifyColumnCtxs) {
return;
}
for (ParseTree each : modifyColumnCtxs) {
// it`s not columndefinition, but can call this method
ColumnDefinition column = parseColumnDefinition(each);
if (null != column) {
alterStatement.getUpdateColumns().put(column.getName(), column);
visitFirstOrAfter((ParserRuleContext) each, (MySQLAlterTableStatement)alterStatement, column.getName());
}
}
}
}
......@@ -22,6 +22,8 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import io.shardingsphere.core.metadata.table.ShardingTableMetaData;
import io.shardingsphere.core.metadata.table.TableMetaData;
import io.shardingsphere.core.parsing.parser.sql.ddl.DDLStatement;
import lombok.Getter;
import lombok.Setter;
......@@ -40,5 +42,9 @@ public class AlterTableStatement extends DDLStatement {
private boolean dropPrimaryKey;
private String newTableName;
private ShardingTableMetaData tableMetaDataMap;
private TableMetaData tableMetaData;
}
/*
* 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.parsing.antler.sql.ddl;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ColumnPosition implements Comparable<ColumnPosition>{
private int startIndex;
private String firstColumn;
private String columnName;
private String afterColumn;
@Override
public int compareTo(ColumnPosition o) {
if(o == null) {
return -1;
}
return this.getStartIndex() - o.getStartIndex();
}
}
/*
* 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.parsing.antler.sql.ddl.mysql;
import java.util.ArrayList;
import java.util.List;
import io.shardingsphere.core.parsing.antler.sql.ddl.AlterTableStatement;
import io.shardingsphere.core.parsing.antler.sql.ddl.ColumnPosition;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(callSuper = true)
public class MySQLAlterTableStatement extends AlterTableStatement{
private final List<ColumnPosition> positionChangedColumns = new ArrayList<>();
}
......@@ -22,6 +22,7 @@ import java.util.List;
import org.antlr.v4.runtime.ParserRuleContext;
import io.shardingsphere.core.metadata.table.ShardingTableMetaData;
import io.shardingsphere.core.parsing.antler.phrase.visitor.PhraseVisitor;
import io.shardingsphere.core.parsing.parser.sql.SQLStatement;
......@@ -33,15 +34,23 @@ public abstract class AbstractStatementVisitor implements StatementVisitor {
* @return sql statement
*/
@Override
public SQLStatement visit(final ParserRuleContext rootNode) {
SQLStatement statement = newStatement();
public SQLStatement visit(final ParserRuleContext rootNode, final ShardingTableMetaData shardingTableMetaData) {
SQLStatement statement = newStatement(shardingTableMetaData);
for (PhraseVisitor each : visitors) {
each.visit(rootNode, statement);
}
postVisit(statement);
return statement;
}
/** process after visit.
* @param statement sql statement
*/
protected void postVisit(SQLStatement statement) {
}
/** Add visitor.
* @param visitor phrase visitor for filling statement
......@@ -54,5 +63,15 @@ public abstract class AbstractStatementVisitor implements StatementVisitor {
* @return empty sql statment
*/
protected abstract SQLStatement newStatement();
/** Use shardingTableMetaData create SQLStatement.
* @param shardingTableMetaData table metadata
* @return
*/
protected SQLStatement newStatement(ShardingTableMetaData shardingTableMetaData) {
return newStatement();
}
}
......@@ -17,11 +17,18 @@
package io.shardingsphere.core.parsing.antler.statement.visitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.AddColumnVisitor;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import io.shardingsphere.core.metadata.table.ColumnMetaData;
import io.shardingsphere.core.metadata.table.ShardingTableMetaData;
import io.shardingsphere.core.metadata.table.TableMetaData;
import io.shardingsphere.core.parsing.antler.phrase.visitor.DropColumnVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.RenameTableVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.TableNameVisitor;
import io.shardingsphere.core.parsing.antler.sql.ddl.AlterTableStatement;
import io.shardingsphere.core.parsing.antler.sql.ddl.ColumnDefinition;
import io.shardingsphere.core.parsing.parser.sql.SQLStatement;
public abstract class AlterTableVisitor extends AbstractStatementVisitor {
......@@ -29,15 +36,107 @@ public abstract class AlterTableVisitor extends AbstractStatementVisitor {
public AlterTableVisitor() {
addVisitor(new TableNameVisitor());
addVisitor(new RenameTableVisitor());
addVisitor(new AddColumnVisitor());
addVisitor(new DropColumnVisitor());
}
/** Create alter table statement.
/** process after visit.
* @param statement sql statement
*/
protected void postVisit(SQLStatement statement) {
AlterTableStatement alterStatement = (AlterTableStatement)statement;
TableMetaData oldTableMeta = alterStatement.getTableMetaDataMap().get(alterStatement.getTables().getSingleTableName());
if(null == oldTableMeta) {
return;
}
List<ColumnMetaData> newColumnMeta = updateColumn(alterStatement, oldTableMeta);
addColumn(alterStatement, newColumnMeta);
adjustColumn(alterStatement, newColumnMeta);
dropColumn(alterStatement, newColumnMeta);
alterStatement.setTableMetaData(new TableMetaData(newColumnMeta));
}
/**Adjust column position.
* @param alterStatement alter table statement
* @param newColumnMeta
*/
protected void adjustColumn(final AlterTableStatement alterStatement, final List<ColumnMetaData> newColumnMeta) {
}
/**Update column info.
* @param alterStatement alter table statement
* @param oldTableMeta table meta data before update
* @return update column info
*/
private List<ColumnMetaData> updateColumn(final AlterTableStatement alterStatement, final TableMetaData oldTableMeta) {
List<ColumnMetaData> newColumnMeta = new LinkedList<>();
for (ColumnMetaData each : oldTableMeta.getColumnMetaData()) {
ColumnDefinition columnDefinition = alterStatement.getUpdateColumns().get(each.getColumnName());
String columnName;
String columnType;
boolean primaryKey = false;
if (null == columnDefinition) {
columnName = each.getColumnName();
columnType = each.getColumnType();
primaryKey = each.isPrimaryKey();
} else {
columnName = columnDefinition.getName();
columnType = columnDefinition.getType();
if (columnDefinition.isPrimaryKey()) {
primaryKey = columnDefinition.isPrimaryKey();
}
}
if (each.isPrimaryKey() && alterStatement.isDropPrimaryKey()) {
primaryKey = false;
}
newColumnMeta.add(new ColumnMetaData(columnName, columnType, primaryKey));
}
return newColumnMeta;
}
/**Add column meta data.
* @param alterStatement alter table statement
* @param newColumnMeta new column meta data
*/
private void addColumn(final AlterTableStatement alterStatement, final List<ColumnMetaData> newColumnMeta) {
for (ColumnDefinition each : alterStatement.getAddColumns()) {
newColumnMeta.add(new ColumnMetaData(each.getName(), each.getType(), each.isPrimaryKey()));
}
}
/**Drop column meta data.
* @param alterStatement alter table statement
* @param newColumnMeta new column meta data
*/
private void dropColumn(final AlterTableStatement alterStatement, final List<ColumnMetaData> newColumnMeta) {
Iterator<ColumnMetaData> it = newColumnMeta.iterator();
while (it.hasNext()) {
ColumnMetaData eachMeata = it.next();
if (alterStatement.getDropColumns().contains(eachMeata.getColumnName())) {
it.remove();
}
}
}
/** Use shardingTableMetaData create SQLStatement.
* @param shardingTableMetaData table metadata
* @return
*/
protected SQLStatement newStatement(final ShardingTableMetaData shardingTableMetaData) {
AlterTableStatement statement = (AlterTableStatement)newStatement();
statement.setTableMetaDataMap(shardingTableMetaData);
return statement;
}
/** Create statement.
* @return empty sql statment
*/
@Override
protected SQLStatement newStatement() {
return new AlterTableStatement();
}
}
......@@ -19,6 +19,7 @@ package io.shardingsphere.core.parsing.antler.statement.visitor;
import org.antlr.v4.runtime.ParserRuleContext;
import io.shardingsphere.core.metadata.table.ShardingTableMetaData;
import io.shardingsphere.core.parsing.parser.sql.SQLStatement;
public interface StatementVisitor {
......@@ -27,5 +28,5 @@ public interface StatementVisitor {
* @param rootNode root node of ast
* @return sql statement
*/
SQLStatement visit(ParserRuleContext rootNode);
SQLStatement visit(ParserRuleContext rootNode, final ShardingTableMetaData shardingTableMetaData);
}
......@@ -17,18 +17,28 @@
package io.shardingsphere.core.parsing.antler.visitor.mysql;
import java.util.Iterator;
import java.util.List;
import edu.emory.mathcs.backport.java.util.Collections;
import io.shardingsphere.core.metadata.table.ColumnMetaData;
import io.shardingsphere.core.parsing.antler.phrase.visitor.AddPrimaryKeyVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.DropPrimaryKeyVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.ModifyColumnVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.RenameIndexVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.mysql.MySQLAddColumnVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.mysql.MySQLAddIndexVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.mysql.MySQLChangeColumnVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.mysql.MySQLDropIndexVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.mysql.MySQLModifyColumnVisitor;
import io.shardingsphere.core.parsing.antler.sql.ddl.AlterTableStatement;
import io.shardingsphere.core.parsing.antler.sql.ddl.ColumnPosition;
import io.shardingsphere.core.parsing.antler.sql.ddl.mysql.MySQLAlterTableStatement;
import io.shardingsphere.core.parsing.antler.statement.visitor.AlterTableVisitor;
import io.shardingsphere.core.parsing.parser.sql.SQLStatement;
public class MySQLAlterTableVisitor extends AlterTableVisitor {
public MySQLAlterTableVisitor() {
super();
addVisitor(new MySQLAddColumnVisitor());
addVisitor(new MySQLAddIndexVisitor());
addVisitor(new MySQLDropIndexVisitor());
addVisitor(new RenameIndexVisitor());
......@@ -37,6 +47,87 @@ public class MySQLAlterTableVisitor extends AlterTableVisitor {
addVisitor(new DropPrimaryKeyVisitor());
addVisitor(new MySQLChangeColumnVisitor());
addVisitor(new ModifyColumnVisitor());
addVisitor(new MySQLModifyColumnVisitor());
}
/** Create statement.
* @return empty sql statment
*/
protected SQLStatement newStatement() {
return new MySQLAlterTableStatement();
}
/**Adjust column position.
* @param alterStatement alter table statement
* @param newColumnMeta
*/
protected void adjustColumn(final AlterTableStatement alterStatement, final List<ColumnMetaData> newColumnMeta) {
MySQLAlterTableStatement mysqlAlter = (MySQLAlterTableStatement)alterStatement;
if (mysqlAlter.getPositionChangedColumns().isEmpty()) {
return;
}
if (mysqlAlter.getPositionChangedColumns().size() > 1) {
Collections.sort(mysqlAlter.getPositionChangedColumns());
}
for (ColumnPosition each : mysqlAlter.getPositionChangedColumns()) {
if (each.getFirstColumn() != null) {
adjustFirst(newColumnMeta, each.getFirstColumn());
} else {
adjustAfter(newColumnMeta, each);
}
}
}
/** Adjust column to first.
* @param newColumnMeta new columns meta
* @param columnName first column name
*/
private void adjustFirst(final List<ColumnMetaData> newColumnMeta, final String columnName) {
ColumnMetaData firstMeta = null;
Iterator<ColumnMetaData> it = newColumnMeta.iterator();
while (it.hasNext()) {
ColumnMetaData eachMeata = it.next();
if (eachMeata.getColumnName().equals(columnName)) {
firstMeta = eachMeata;
it.remove();
break;
}
}
if (null != firstMeta) {
newColumnMeta.add(0, firstMeta);
}
}
/**Adjust column to after column.
* @param newColumnMeta
* @param columnPosition column position
*/
private void adjustAfter(final List<ColumnMetaData> newColumnMeta, final ColumnPosition columnPosition) {
int afterIndex = -1;
int adjustColumnIndex = -1;
for (int i = 0; i < newColumnMeta.size(); i++) {
if (newColumnMeta.get(i).getColumnName().equals(columnPosition.getColumnName())) {
adjustColumnIndex = i;
}
if (newColumnMeta.get(i).getColumnName().equals(columnPosition.getAfterColumn())) {
afterIndex = i;
}
if(adjustColumnIndex >= 0 && afterIndex >= 0) {
break;
}
}
if (adjustColumnIndex >= 0 && afterIndex >= 0 && adjustColumnIndex != afterIndex +1) {
ColumnMetaData adjustColumn = newColumnMeta.remove(adjustColumnIndex);
if (afterIndex < adjustColumnIndex) {
afterIndex = afterIndex + 1;
}
newColumnMeta.add(afterIndex, adjustColumn);
}
}
}
......@@ -17,6 +17,7 @@
package io.shardingsphere.core.parsing.antler.visitor.oracle;
import io.shardingsphere.core.parsing.antler.phrase.visitor.AddColumnVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.AddPrimaryKeyVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.RenameColumnVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.oracle.OracleDropPrimaryKeyVisitor;
......@@ -25,7 +26,7 @@ import io.shardingsphere.core.parsing.antler.statement.visitor.AlterTableVisitor
public class OracleAlterTableVisitor extends AlterTableVisitor {
public OracleAlterTableVisitor() {
super();
addVisitor(new AddColumnVisitor());
addVisitor(new OracleModifyColumnVisitor());
addVisitor(new RenameColumnVisitor());
addVisitor(new AddPrimaryKeyVisitor("addConstraintClause"));
......
......@@ -17,6 +17,7 @@
package io.shardingsphere.core.parsing.antler.visitor.postgre;
import io.shardingsphere.core.parsing.antler.phrase.visitor.AddColumnVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.AddPrimaryKeyVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.ModifyColumnVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.RenameColumnVisitor;
......@@ -24,7 +25,7 @@ import io.shardingsphere.core.parsing.antler.statement.visitor.AlterTableVisitor
public class PostgreAlterTableVisitor extends AlterTableVisitor {
public PostgreAlterTableVisitor() {
super();
addVisitor(new AddColumnVisitor());
addVisitor(new AddPrimaryKeyVisitor("alterTableAddConstraint"));
addVisitor(new ModifyColumnVisitor());
addVisitor(new RenameColumnVisitor());
......
......@@ -17,6 +17,7 @@
package io.shardingsphere.core.parsing.antler.visitor.sqlserver;
import io.shardingsphere.core.parsing.antler.phrase.visitor.AddColumnVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.sqlserver.SQLServerAddIndexVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.sqlserver.SQLServerAddPrimaryKeyVisitor;
import io.shardingsphere.core.parsing.antler.phrase.visitor.sqlserver.SQLServerDropIndexVisitor;
......@@ -24,6 +25,7 @@ import io.shardingsphere.core.parsing.antler.statement.visitor.AlterTableVisitor
public class SQLServerAlterTableVisitor extends AlterTableVisitor {
public SQLServerAlterTableVisitor() {
addVisitor(new AddColumnVisitor());
addVisitor(new SQLServerAddIndexVisitor());
addVisitor(new SQLServerDropIndexVisitor());
addVisitor(new SQLServerAddPrimaryKeyVisitor());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册