use of com.actiontech.dble.config.model.TableConfig in project dble by actiontech.
the class DruidInsertParser method visitorParse.
@Override
public SchemaConfig visitorParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt, ServerSchemaStatVisitor visitor, ServerConnection sc) throws SQLException {
MySqlInsertStatement insert = (MySqlInsertStatement) stmt;
String schemaName = schema == null ? null : schema.getName();
SQLExprTableSource tableSource = insert.getTableSource();
SchemaInfo schemaInfo = SchemaUtil.getSchemaInfo(sc.getUser(), schemaName, tableSource);
if (!ServerPrivileges.checkPrivilege(sc, schemaInfo.getSchema(), schemaInfo.getTable(), CheckType.INSERT)) {
String msg = "The statement DML privilege check is not passed, sql:" + stmt;
throw new SQLNonTransientException(msg);
}
schema = schemaInfo.getSchemaConfig();
String tableName = schemaInfo.getTable();
if (parserNoSharding(sc, schemaName, schemaInfo, rrs, insert)) {
return schema;
}
if (insert.getQuery() != null) {
// insert into .... select ....
String msg = "`INSERT ... SELECT Syntax` is not supported!";
LOGGER.info(msg);
throw new SQLNonTransientException(msg);
}
TableConfig tc = schema.getTables().get(tableName);
if (tc == null) {
String msg = "Table '" + schema.getName() + "." + tableName + "' doesn't exist";
throw new SQLException(msg, "42S02", ErrorCode.ER_NO_SUCH_TABLE);
}
if (tc.isGlobalTable()) {
String sql = rrs.getStatement();
if (tc.isAutoIncrement() || GlobalTableUtil.useGlobalTableCheck()) {
sql = convertInsertSQL(schemaInfo, insert, sql, tc, GlobalTableUtil.useGlobalTableCheck());
} else {
sql = RouterUtil.removeSchema(sql, schemaInfo.getSchema());
}
rrs.setStatement(sql);
RouterUtil.routeToMultiNode(false, rrs, tc.getDataNodes(), tc.isGlobalTable());
rrs.setFinishedRoute(true);
return schema;
}
if (tc.isAutoIncrement()) {
String sql = convertInsertSQL(schemaInfo, insert, rrs.getStatement(), tc, false);
rrs.setStatement(sql);
SQLStatementParser parser = new MySqlStatementParser(sql);
stmt = parser.parseStatement();
insert = (MySqlInsertStatement) stmt;
}
// insert childTable will finished router while parser
if (tc.getParentTC() != null) {
parserChildTable(schemaInfo, rrs, insert, sc);
return schema;
}
String partitionColumn = tc.getPartitionColumn();
if (partitionColumn != null) {
if (isMultiInsert(insert)) {
parserBatchInsert(schemaInfo, rrs, partitionColumn, insert);
} else {
parserSingleInsert(schemaInfo, rrs, partitionColumn, insert);
}
} else {
rrs.setStatement(RouterUtil.removeSchema(rrs.getStatement(), schemaInfo.getSchema()));
ctx.addTable(tableName);
}
return schema;
}
use of com.actiontech.dble.config.model.TableConfig in project dble by actiontech.
the class DruidInsertParser method parserSingleInsert.
/**
* @param schemaInfo SchemaInfo
* @param rrs RouteResultset
* @param partitionColumn partitionColumn
* @param insertStmt insertStmt
* @throws SQLNonTransientException if not find an valid data node
*/
private void parserSingleInsert(SchemaInfo schemaInfo, RouteResultset rrs, String partitionColumn, MySqlInsertStatement insertStmt) throws SQLNonTransientException {
int shardingColIndex = tryGetShardingColIndex(schemaInfo, insertStmt, partitionColumn);
SQLExpr valueExpr = insertStmt.getValues().getValues().get(shardingColIndex);
String shardingValue = shardingValueToSting(valueExpr);
TableConfig tableConfig = schemaInfo.getSchemaConfig().getTables().get(schemaInfo.getTable());
AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
Integer nodeIndex = algorithm.calculate(shardingValue);
if (nodeIndex == null || nodeIndex >= tableConfig.getDataNodes().size()) {
String msg = "can't find any valid data node :" + schemaInfo.getTable() + " -> " + partitionColumn + " -> " + shardingValue;
LOGGER.info(msg);
throw new SQLNonTransientException(msg);
}
RouteResultsetNode[] nodes = new RouteResultsetNode[1];
nodes[0] = new RouteResultsetNode(tableConfig.getDataNodes().get(nodeIndex), rrs.getSqlType(), RouterUtil.removeSchema(insertStmt.toString(), schemaInfo.getSchema()));
// INSERT INTO TABLEName (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;
if (insertStmt.getDuplicateKeyUpdate() != null) {
List<SQLExpr> updateList = insertStmt.getDuplicateKeyUpdate();
for (SQLExpr expr : updateList) {
SQLBinaryOpExpr opExpr = (SQLBinaryOpExpr) expr;
String column = StringUtil.removeBackQuote(opExpr.getLeft().toString().toUpperCase());
if (column.equals(partitionColumn)) {
String msg = "Sharding column can't be updated: " + schemaInfo.getTable() + " -> " + partitionColumn;
LOGGER.info(msg);
throw new SQLNonTransientException(msg);
}
}
}
rrs.setNodes(nodes);
rrs.setFinishedRoute(true);
}
use of com.actiontech.dble.config.model.TableConfig in project dble by actiontech.
the class DruidLockTableParser method visitorParse.
@Override
public SchemaConfig visitorParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt, ServerSchemaStatVisitor visitor, ServerConnection sc) throws SQLNonTransientException {
// for lock tables table1 write, table2
// DruidParser can only parser table1,
// use "," to judge
String sql = rrs.getStatement();
sql = sql.replaceAll("\n", " ").replaceAll("\t", " ");
String[] stmts = SplitUtil.split(sql, ',', true);
// contains ","
if (stmts.length > 1) {
String tmpStmt = null;
String[] tmpWords = null;
for (int i = 1; i < stmts.length; i++) {
tmpStmt = stmts[i];
tmpWords = SplitUtil.split(tmpStmt, ' ', true);
if (tmpWords.length == 2 && ("READ".equalsIgnoreCase(tmpWords[1]) || "WRITE".equalsIgnoreCase(tmpWords[1]))) {
// unsupport lock multi-table
continue;
} else {
// unsupport lock multi-table
throw new SQLNonTransientException("You have an error in your SQL syntax, don't support lock multi tables!");
}
}
LOGGER.info("can't lock multi-table");
throw new SQLNonTransientException("can't lock multi-table");
}
MySqlLockTableStatement lockTableStat = (MySqlLockTableStatement) stmt;
String table = lockTableStat.getTableSource().toString();
if (DbleServer.getInstance().getSystemVariables().isLowerCaseTableNames()) {
table = table.toLowerCase();
}
TableConfig tableConfig = schema.getTables().get(table);
if (tableConfig == null) {
String msg = "can't find table define of " + table + " in schema:" + schema.getName();
LOGGER.info(msg);
throw new SQLNonTransientException(msg);
}
LockType lockType = lockTableStat.getLockType();
if (LockType.WRITE != lockType && LockType.READ != lockType) {
String msg = "lock type must be write or read";
LOGGER.info(msg);
throw new SQLNonTransientException(msg);
}
List<String> dataNodes = tableConfig.getDataNodes();
RouteResultsetNode[] nodes = new RouteResultsetNode[dataNodes.size()];
for (int i = 0; i < dataNodes.size(); i++) {
nodes[i] = new RouteResultsetNode(dataNodes.get(i), ServerParse.LOCK, stmt.toString());
}
rrs.setNodes(nodes);
rrs.setFinishedRoute(true);
return schema;
}
use of com.actiontech.dble.config.model.TableConfig in project dble by actiontech.
the class DruidReplaceParser method parserBatchInsert.
/**
* insert into .... select .... OR insert into table() values (),(),....
*
* @param schemaInfo SchemaInfo
* @param rrs RouteResultset
* @param partitionColumn partitionColumn
* @param replace MySqlReplaceStatement
* @throws SQLNonTransientException if the column size of values is not correct
*/
private void parserBatchInsert(SchemaInfo schemaInfo, RouteResultset rrs, String partitionColumn, MySqlReplaceStatement replace) throws SQLNonTransientException {
// insert into table() values (),(),....
SchemaConfig schema = schemaInfo.getSchemaConfig();
String tableName = schemaInfo.getTable();
// column number
int columnNum = getTableColumns(schemaInfo, replace.getColumns());
int shardingColIndex = tryGetShardingColIndex(schemaInfo, replace, partitionColumn);
List<SQLInsertStatement.ValuesClause> valueClauseList = replace.getValuesList();
Map<Integer, List<SQLInsertStatement.ValuesClause>> nodeValuesMap = new HashMap<>();
TableConfig tableConfig = schema.getTables().get(tableName);
AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
for (SQLInsertStatement.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);
// no part find for this record
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<SQLInsertStatement.ValuesClause>());
}
nodeValuesMap.get(nodeIndex).add(valueClause);
}
RouteResultsetNode[] nodes = new RouteResultsetNode[nodeValuesMap.size()];
int count = 0;
for (Map.Entry<Integer, List<SQLInsertStatement.ValuesClause>> node : nodeValuesMap.entrySet()) {
Integer nodeIndex = node.getKey();
List<SQLInsertStatement.ValuesClause> valuesList = node.getValue();
ReplaceTemp temp = new ReplaceTemp(replace);
temp.setValuesList(valuesList);
nodes[count] = new RouteResultsetNode(tableConfig.getDataNodes().get(nodeIndex), rrs.getSqlType(), RouterUtil.removeSchema(temp.toString(), schemaInfo.getSchema()));
count++;
}
rrs.setNodes(nodes);
rrs.setFinishedRoute(true);
}
use of com.actiontech.dble.config.model.TableConfig in project dble by actiontech.
the class DruidReplaceParser method visitorParse.
@Override
public SchemaConfig visitorParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt, ServerSchemaStatVisitor visitor, ServerConnection sc) throws SQLException {
// data & object prepare
MySqlReplaceStatement replace = (MySqlReplaceStatement) stmt;
String schemaName = schema == null ? null : schema.getName();
SQLExprTableSource tableSource = replace.getTableSource();
SchemaInfo schemaInfo = SchemaUtil.getSchemaInfo(sc.getUser(), schemaName, tableSource);
// privilege check
if (!ServerPrivileges.checkPrivilege(sc, schemaInfo.getSchema(), schemaInfo.getTable(), ServerPrivileges.CheckType.INSERT)) {
String msg = "The statement DML privilege check is not passed, sql:" + stmt;
throw new SQLNonTransientException(msg);
}
// No sharding table check
schema = schemaInfo.getSchemaConfig();
String tableName = schemaInfo.getTable();
if (parserNoSharding(sc, schemaName, schemaInfo, rrs, replace)) {
return schema;
}
if (replace.getQuery() != null) {
// replace into ...select with sharding not supported
String msg = "`INSERT ... SELECT Syntax` is not supported!";
LOGGER.info(msg);
throw new SQLNonTransientException(msg);
}
// check the config of target table
TableConfig tc = schema.getTables().get(tableName);
if (tc == null) {
String msg = "Table '" + schema.getName() + "." + tableName + "' doesn't exist";
throw new SQLException(msg, "42S02", ErrorCode.ER_NO_SUCH_TABLE);
}
// if the target table is global table than
if (tc.isGlobalTable()) {
String sql = rrs.getStatement();
if (tc.isAutoIncrement() || GlobalTableUtil.useGlobalTableCheck()) {
sql = convertReplaceSQL(schemaInfo, replace, sql, tc, GlobalTableUtil.useGlobalTableCheck(), sc);
} else {
sql = RouterUtil.removeSchema(sql, schemaInfo.getSchema());
}
rrs.setStatement(sql);
RouterUtil.routeToMultiNode(false, rrs, tc.getDataNodes(), tc.isGlobalTable());
rrs.setFinishedRoute(true);
return schema;
}
if (tc.isAutoIncrement()) {
String sql = convertReplaceSQL(schemaInfo, replace, rrs.getStatement(), tc, false, sc);
rrs.setStatement(sql);
SQLStatementParser parser = new MySqlStatementParser(sql);
stmt = parser.parseStatement();
replace = (MySqlReplaceStatement) stmt;
}
// childTable can be route in this part
if (tc.getParentTC() != null) {
parserChildTable(schemaInfo, rrs, replace, sc);
return schema;
}
String partitionColumn = tc.getPartitionColumn();
if (partitionColumn != null) {
if (isMultiReplace(replace)) {
parserBatchInsert(schemaInfo, rrs, partitionColumn, replace);
} else {
parserSingleInsert(schemaInfo, rrs, partitionColumn, replace);
}
} else {
rrs.setStatement(RouterUtil.removeSchema(rrs.getStatement(), schemaInfo.getSchema()));
ctx.addTable(tableName);
}
return schema;
}
Aggregations