use of com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause in project druid by alibaba.
the class MySqlStatementParser method parseValueClause.
private void parseValueClause(List<ValuesClause> valueClauseList, int columnSize) {
for (int i = 0; ; ++i) {
if (lexer.token() != Token.LPAREN) {
throw new ParserException("syntax error, expect ')'");
}
lexer.nextTokenValue();
if (lexer.token() != Token.RPAREN) {
List<SQLExpr> valueExprList;
if (columnSize > 0) {
valueExprList = new ArrayList<SQLExpr>(columnSize);
} else {
valueExprList = new ArrayList<SQLExpr>();
}
for (; ; ) {
SQLExpr expr;
if (lexer.token() == Token.LITERAL_INT) {
expr = new SQLIntegerExpr(lexer.integerValue());
lexer.nextTokenComma();
} else if (lexer.token() == Token.LITERAL_CHARS) {
expr = new SQLCharExpr(lexer.stringVal());
lexer.nextTokenComma();
} else if (lexer.token() == Token.LITERAL_NCHARS) {
expr = new SQLNCharExpr(lexer.stringVal());
lexer.nextTokenComma();
} else {
expr = exprParser.expr();
}
if (lexer.token() == Token.COMMA) {
valueExprList.add(expr);
lexer.nextTokenValue();
continue;
} else if (lexer.token() == Token.RPAREN) {
valueExprList.add(expr);
break;
} else {
expr = this.exprParser.primaryRest(expr);
if (lexer.token() != Token.COMMA && lexer.token() != Token.RPAREN) {
expr = this.exprParser.exprRest(expr);
}
valueExprList.add(expr);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
} else {
break;
}
}
}
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(valueExprList);
valueClauseList.add(values);
} else {
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(new ArrayList<SQLExpr>(0));
valueClauseList.add(values);
}
if (lexer.token() != Token.RPAREN) {
throw new ParserException("syntax error");
}
if (!parseCompleteValues && valueClauseList.size() >= parseValuesSize) {
lexer.skipToEOF();
break;
}
lexer.nextTokenComma();
if (lexer.token() == Token.COMMA) {
lexer.nextTokenLParen();
continue;
} else {
break;
}
}
}
use of com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause in project Mycat_plus by coderczp.
the class GlobalTableUtil method convertInsertSQL.
/**
* Syntax:
* INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
* [INTO] tbl_name
* [PARTITION (partition_name,...)]
* [(col_name,...)]
* {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
* [ ON DUPLICATE KEY UPDATE
* col_name=expr
* [, col_name=expr] ... ]
*
* Or:
*
* INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
* [INTO] tbl_name
* [PARTITION (partition_name,...)]
* SET col_name={expr | DEFAULT}, ...
* [ ON DUPLICATE KEY UPDATE
* col_name=expr
* [, col_name=expr] ... ]
*
* Or:
*
* INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
* [INTO] tbl_name
* [PARTITION (partition_name,...)]
* [(col_name,...)]
* SELECT ...
* [ ON DUPLICATE KEY UPDATE
* col_name=expr
* [, col_name=expr] ... ]
* mysql> insert user value (33333333,'ddd');
* mysql> insert into user value (333333,'ddd');
* mysql> insert user values (3333,'ddd');
* insert into user(id,name) valueS(1111,'dig'),
* (1111, 'dig'), (1111,'dig') ,(1111,'dig');
* @param sql
* @return
*/
private static String convertInsertSQL(String sql) {
try {
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement statement = parser.parseStatement();
MySqlInsertStatement insert = (MySqlInsertStatement) statement;
String tableName = StringUtil.removeBackquote(insert.getTableName().getSimpleName());
if (!isGlobalTable(tableName))
return sql;
if (!isInnerColExist(tableName))
return sql;
if (// insert into tab select
insert.getQuery() != null)
return sql;
StringBuilder sb = // 指定初始容量可以提高性能
new StringBuilder(200).append("insert into ").append(tableName);
List<SQLExpr> columns = insert.getColumns();
int idx = -1;
int colSize = -1;
if (columns == null || columns.size() <= 0) {
// insert 没有带列名:insert into t values(xxx,xxx)
String columnsList = tableColumsMap.get(tableName.toUpperCase());
if (StringUtils.isNotBlank(columnsList)) {
// "id,name,_mycat_op_time"
// newSQL = "insert into t(id,name,_mycat_op_time)";
// 构建一个虚拟newSQL来寻找 内部列的索引位置
String newSQL = "insert into " + tableName + "(" + columnsList + ")";
MySqlStatementParser newParser = new MySqlStatementParser(newSQL);
SQLStatement newStatement = newParser.parseStatement();
MySqlInsertStatement newInsert = (MySqlInsertStatement) newStatement;
List<SQLExpr> newColumns = newInsert.getColumns();
for (int i = 0; i < newColumns.size(); i++) {
String column = StringUtil.removeBackquote(newInsert.getColumns().get(i).toString());
if (column.equalsIgnoreCase(GLOBAL_TABLE_MYCAT_COLUMN))
// 找到 内部列的索引位置
idx = i;
}
colSize = newColumns.size();
sb.append("(").append(columnsList).append(")");
} else {
// tableName 是全局表,但是 tableColumsMap 没有其对应的列list,这种情况不应该存在
LOGGER.warn("you'd better do not use 'insert into t values(a,b)' Syntax (without column list) on global table, " + "If you do. Then you must make sure inner column '_mycat_op_time' is last column of global table: " + tableName + " in all database. Good luck. ^_^");
// 我们假定 内部列位于表中所有列的最后,后面我们在values 子句的最后 给他附加上时间戳
}
} else {
// insert 语句带有 列名
sb.append("(");
for (int i = 0; i < columns.size(); i++) {
if (i < columns.size() - 1)
sb.append(columns.get(i).toString()).append(",");
else
sb.append(columns.get(i).toString());
String column = StringUtil.removeBackquote(insert.getColumns().get(i).toString());
if (column.equalsIgnoreCase(GLOBAL_TABLE_MYCAT_COLUMN))
idx = i;
}
if (idx <= -1)
sb.append(",").append(GLOBAL_TABLE_MYCAT_COLUMN);
sb.append(")");
colSize = columns.size();
}
sb.append(" values");
List<ValuesClause> vcl = insert.getValuesList();
if (vcl != null && vcl.size() > 1) {
// 批量insert
for (int j = 0; j < vcl.size(); j++) {
if (j != vcl.size() - 1)
appendValues(vcl.get(j).getValues(), sb, idx, colSize).append(",");
else
appendValues(vcl.get(j).getValues(), sb, idx, colSize);
}
} else {
// 非批量 insert
List<SQLExpr> valuse = insert.getValues().getValues();
appendValues(valuse, sb, idx, colSize);
}
List<SQLExpr> dku = insert.getDuplicateKeyUpdate();
if (dku != null && dku.size() > 0) {
sb.append(" on duplicate key update ");
for (int i = 0; i < dku.size(); i++) {
SQLExpr exp = dku.get(i);
if (exp != null) {
if (i < dku.size() - 1)
sb.append(exp.toString()).append(",");
else
sb.append(exp.toString());
}
}
}
return sb.toString();
} catch (Exception e) {
// 发生异常,则返回原始 sql
LOGGER.warn(e.getMessage());
return sql;
}
}
use of com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause in project dble by actiontech.
the class DruidInsertParser method parserBatchInsert.
/**
* insert into .... select .... or insert into table() values (),(),....
*
* @param schemaInfo SchemaInfo
* @param rrs RouteResultset
* @param partitionColumn partitionColumn
* @param insertStmt insertStmt
* @throws SQLNonTransientException if the column size of values is not correct
*/
private void parserBatchInsert(SchemaInfo schemaInfo, RouteResultset rrs, String partitionColumn, MySqlInsertStatement insertStmt) throws SQLNonTransientException {
// insert into table() values (),(),....
SchemaConfig schema = schemaInfo.getSchemaConfig();
String tableName = schemaInfo.getTable();
// the size of columns
int columnNum = getTableColumns(schemaInfo, insertStmt.getColumns());
int shardingColIndex = tryGetShardingColIndex(schemaInfo, insertStmt, partitionColumn);
List<ValuesClause> valueClauseList = insertStmt.getValuesList();
Map<Integer, List<ValuesClause>> nodeValuesMap = new HashMap<>();
TableConfig tableConfig = schema.getTables().get(tableName);
AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
for (ValuesClause valueClause : valueClauseList) {
if (valueClause.getValues().size() != columnNum) {
String msg = "bad insert sql columnSize != valueSize:" + columnNum + " != " + valueClause.getValues().size() + "values:" + valueClause;
LOGGER.info(msg);
throw new SQLNonTransientException(msg);
}
SQLExpr expr = valueClause.getValues().get(shardingColIndex);
String shardingValue = shardingValueToSting(expr);
Integer nodeIndex = algorithm.calculate(shardingValue);
// null means can't find any valid index
if (nodeIndex == null) {
String msg = "can't find any valid datanode :" + tableName + " -> " + partitionColumn + " -> " + shardingValue;
LOGGER.info(msg);
throw new SQLNonTransientException(msg);
}
if (nodeValuesMap.get(nodeIndex) == null) {
nodeValuesMap.put(nodeIndex, new ArrayList<ValuesClause>());
}
nodeValuesMap.get(nodeIndex).add(valueClause);
}
RouteResultsetNode[] nodes = new RouteResultsetNode[nodeValuesMap.size()];
int count = 0;
for (Map.Entry<Integer, List<ValuesClause>> node : nodeValuesMap.entrySet()) {
Integer nodeIndex = node.getKey();
List<ValuesClause> valuesList = node.getValue();
insertStmt.setValuesList(valuesList);
nodes[count] = new RouteResultsetNode(tableConfig.getDataNodes().get(nodeIndex), rrs.getSqlType(), RouterUtil.removeSchema(insertStmt.toString(), schemaInfo.getSchema()));
count++;
}
rrs.setNodes(nodes);
rrs.setFinishedRoute(true);
}
use of com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause in project Mycat-Server by MyCATApache.
the class GlobalTableUtil method convertInsertSQL.
/**
* Syntax:
* INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
* [INTO] tbl_name
* [PARTITION (partition_name,...)]
* [(col_name,...)]
* {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
* [ ON DUPLICATE KEY UPDATE
* col_name=expr
* [, col_name=expr] ... ]
*
* Or:
*
* INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
* [INTO] tbl_name
* [PARTITION (partition_name,...)]
* SET col_name={expr | DEFAULT}, ...
* [ ON DUPLICATE KEY UPDATE
* col_name=expr
* [, col_name=expr] ... ]
*
* Or:
*
* INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
* [INTO] tbl_name
* [PARTITION (partition_name,...)]
* [(col_name,...)]
* SELECT ...
* [ ON DUPLICATE KEY UPDATE
* col_name=expr
* [, col_name=expr] ... ]
* mysql> insert user value (33333333,'ddd');
* mysql> insert into user value (333333,'ddd');
* mysql> insert user values (3333,'ddd');
* insert into user(id,name) valueS(1111,'dig'),
* (1111, 'dig'), (1111,'dig') ,(1111,'dig');
* @param sql
* @return
*/
private static String convertInsertSQL(String sql) {
try {
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement statement = parser.parseStatement();
MySqlInsertStatement insert = (MySqlInsertStatement) statement;
String tableName = StringUtil.removeBackquote(insert.getTableName().getSimpleName());
if (!isGlobalTable(tableName))
return sql;
if (!isInnerColExist(tableName))
return sql;
if (// insert into tab select
insert.getQuery() != null)
return sql;
StringBuilder sb = // 指定初始容量可以提高性能
new StringBuilder(200).append("insert into ").append(tableName);
List<SQLExpr> columns = insert.getColumns();
int idx = -1;
int colSize = -1;
if (columns == null || columns.size() <= 0) {
// insert 没有带列名:insert into t values(xxx,xxx)
String columnsList = tableColumsMap.get(tableName.toUpperCase());
if (StringUtils.isNotBlank(columnsList)) {
// "id,name,_mycat_op_time"
// newSQL = "insert into t(id,name,_mycat_op_time)";
// 构建一个虚拟newSQL来寻找 内部列的索引位置
String newSQL = "insert into " + tableName + "(" + columnsList + ")";
MySqlStatementParser newParser = new MySqlStatementParser(newSQL);
SQLStatement newStatement = newParser.parseStatement();
MySqlInsertStatement newInsert = (MySqlInsertStatement) newStatement;
List<SQLExpr> newColumns = newInsert.getColumns();
for (int i = 0; i < newColumns.size(); i++) {
String column = StringUtil.removeBackquote(newInsert.getColumns().get(i).toString());
if (column.equalsIgnoreCase(GLOBAL_TABLE_MYCAT_COLUMN))
// 找到 内部列的索引位置
idx = i;
}
colSize = newColumns.size();
sb.append("(").append(columnsList).append(")");
} else {
// tableName 是全局表,但是 tableColumsMap 没有其对应的列list,这种情况不应该存在
LOGGER.warn("you'd better do not use 'insert into t values(a,b)' Syntax (without column list) on global table, " + "If you do. Then you must make sure inner column '_mycat_op_time' is last column of global table: " + tableName + " in all database. Good luck. ^_^");
// 我们假定 内部列位于表中所有列的最后,后面我们在values 子句的最后 给他附加上时间戳
}
} else {
// insert 语句带有 列名
sb.append("(");
for (int i = 0; i < columns.size(); i++) {
if (i < columns.size() - 1)
sb.append(columns.get(i).toString()).append(",");
else
sb.append(columns.get(i).toString());
String column = StringUtil.removeBackquote(insert.getColumns().get(i).toString());
if (column.equalsIgnoreCase(GLOBAL_TABLE_MYCAT_COLUMN))
idx = i;
}
if (idx <= -1)
sb.append(",").append(GLOBAL_TABLE_MYCAT_COLUMN);
sb.append(")");
colSize = columns.size();
}
sb.append(" values");
List<ValuesClause> vcl = insert.getValuesList();
if (vcl != null && vcl.size() > 1) {
// 批量insert
for (int j = 0; j < vcl.size(); j++) {
if (j != vcl.size() - 1)
appendValues(vcl.get(j).getValues(), sb, idx, colSize).append(",");
else
appendValues(vcl.get(j).getValues(), sb, idx, colSize);
}
} else {
// 非批量 insert
List<SQLExpr> valuse = insert.getValues().getValues();
appendValues(valuse, sb, idx, colSize);
}
List<SQLExpr> dku = insert.getDuplicateKeyUpdate();
if (dku != null && dku.size() > 0) {
sb.append(" on duplicate key update ");
for (int i = 0; i < dku.size(); i++) {
SQLExpr exp = dku.get(i);
if (exp != null) {
if (i < dku.size() - 1)
sb.append(exp.toString()).append(",");
else
sb.append(exp.toString());
}
}
}
return sb.toString();
} catch (Exception e) {
// 发生异常,则返回原始 sql
LOGGER.warn(e.getMessage());
return sql;
}
}
use of com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause in project druid by alibaba.
the class SQLInsertInto method cloneTo.
public void cloneTo(SQLInsertInto x) {
if (tableSource != null) {
x.setTableSource(tableSource.clone());
}
for (SQLExpr column : columns) {
SQLExpr column2 = column.clone();
column2.setParent(x);
x.columns.add(column2);
}
if (query != null) {
x.setQuery(query.clone());
}
for (ValuesClause v : valuesList) {
ValuesClause v2 = v.clone();
v2.setParent(x);
x.valuesList.add(v2);
}
if (hint != null) {
x.setHint(hint.clone());
}
x.overwrite = overwrite;
if (partitions != null) {
for (SQLAssignItem item : partitions) {
x.addPartition(item.clone());
}
}
}
Aggregations