use of com.alibaba.cobar.parser.ast.stmt.SQLStatement in project cobar by alibaba.
the class MySQLDataNode method setHeartbeat.
private void setHeartbeat(String heartbeat) {
if (heartbeat == null) {
heartbeatAST = null;
placeHolderToStringer = null;
return;
}
try {
final Set<PlaceHolder> plist = new HashSet<PlaceHolder>(1, 1);
SQLStatement ast = SQLParserDelegate.parse(heartbeat);
ast.accept(new EmptySQLASTVisitor() {
@Override
public void visit(PlaceHolder node) {
plist.add(node);
}
});
if (plist.isEmpty()) {
heartbeatAST = null;
placeHolderToStringer = null;
return;
}
Map<PlaceHolder, Object> phm = new HashMap<PlaceHolder, Object>(plist.size(), 1);
for (PlaceHolder ph : plist) {
final String content = ph.getName();
final int low = Integer.parseInt(content.substring(content.indexOf('(') + 1, content.indexOf(',')).trim());
final int high = Integer.parseInt(content.substring(content.indexOf(',') + 1, content.indexOf(')')).trim());
phm.put(ph, new Object() {
private Random rnd = new Random();
@Override
public String toString() {
return String.valueOf(rnd.nextInt(high - low + 1) + low);
}
});
}
heartbeatAST = ast;
placeHolderToStringer = phm;
} catch (SQLSyntaxErrorException e) {
throw new ConfigException("heartbeat syntax err: " + heartbeat, e);
}
}
use of com.alibaba.cobar.parser.ast.stmt.SQLStatement in project cobar by alibaba.
the class ServerRouter method route.
public static RouteResultset route(SchemaConfig schema, String stmt, String charset, Object info) throws SQLNonTransientException {
RouteResultset rrs = new RouteResultset(stmt);
// 检查是否含有cobar hint
int prefixIndex = HintRouter.indexOfPrefix(stmt);
if (prefixIndex >= 0) {
HintRouter.routeFromHint(info, schema, rrs, prefixIndex, stmt);
return rrs;
}
// 检查schema是否含有拆分库
if (schema.isNoSharding()) {
if (schema.isKeepSqlSchema()) {
SQLStatement ast = SQLParserDelegate.parse(stmt, charset == null ? MySQLParser.DEFAULT_CHARSET : charset);
PartitionKeyVisitor visitor = new PartitionKeyVisitor(schema.getTables());
visitor.setTrimSchema(schema.getName());
ast.accept(visitor);
if (visitor.isSchemaTrimmed()) {
stmt = genSQL(ast, stmt);
}
}
RouteResultsetNode[] nodes = new RouteResultsetNode[1];
nodes[0] = new RouteResultsetNode(schema.getDataNode(), stmt);
rrs.setNodes(nodes);
return rrs;
}
// 生成和展开AST
SQLStatement ast = SQLParserDelegate.parse(stmt, charset == null ? MySQLParser.DEFAULT_CHARSET : charset);
PartitionKeyVisitor visitor = new PartitionKeyVisitor(schema.getTables());
visitor.setTrimSchema(schema.isKeepSqlSchema() ? schema.getName() : null);
ast.accept(visitor);
// 如果sql包含用户自定义的schema,则路由到default节点
if (schema.isKeepSqlSchema() && visitor.isCustomedSchema()) {
if (visitor.isSchemaTrimmed()) {
stmt = genSQL(ast, stmt);
}
RouteResultsetNode[] nodes = new RouteResultsetNode[1];
nodes[0] = new RouteResultsetNode(schema.getDataNode(), stmt);
rrs.setNodes(nodes);
return rrs;
}
// 元数据语句路由
if (visitor.isTableMetaRead()) {
MetaRouter.routeForTableMeta(rrs, schema, ast, visitor, stmt);
if (visitor.isNeedRewriteField()) {
rrs.setFlag(RouteResultset.REWRITE_FIELD);
}
return rrs;
}
// 匹配规则
TableConfig matchedTable = null;
RuleConfig rule = null;
Map<String, List<Object>> columnValues = null;
Map<String, Map<String, List<Object>>> astExt = visitor.getColumnValue();
Map<String, TableConfig> tables = schema.getTables();
ft: for (Entry<String, Map<String, List<Object>>> e : astExt.entrySet()) {
Map<String, List<Object>> col2Val = e.getValue();
TableConfig tc = tables.get(e.getKey());
if (tc == null) {
continue;
}
if (matchedTable == null) {
matchedTable = tc;
}
if (col2Val == null || col2Val.isEmpty()) {
continue;
}
TableRuleConfig tr = tc.getRule();
if (tr != null) {
for (RuleConfig rc : tr.getRules()) {
boolean match = true;
for (String ruleColumn : rc.getColumns()) {
match &= col2Val.containsKey(ruleColumn);
}
if (match) {
columnValues = col2Val;
rule = rc;
matchedTable = tc;
break ft;
}
}
}
}
// 规则匹配处理,表级别和列级别。
if (matchedTable == null) {
String sql = visitor.isSchemaTrimmed() ? genSQL(ast, stmt) : stmt;
RouteResultsetNode[] rn = new RouteResultsetNode[1];
if ("".equals(schema.getDataNode()) && isSystemReadSQL(ast)) {
rn[0] = new RouteResultsetNode(schema.getRandomDataNode(), sql);
} else {
rn[0] = new RouteResultsetNode(schema.getDataNode(), sql);
}
rrs.setNodes(rn);
return rrs;
}
if (rule == null) {
if (matchedTable.isRuleRequired()) {
throw new IllegalArgumentException("route rule for table " + matchedTable.getName() + " is required: " + stmt);
}
String[] dataNodes = matchedTable.getDataNodes();
String sql = visitor.isSchemaTrimmed() ? genSQL(ast, stmt) : stmt;
RouteResultsetNode[] rn = new RouteResultsetNode[dataNodes.length];
for (int i = 0; i < dataNodes.length; ++i) {
rn[i] = new RouteResultsetNode(dataNodes[i], sql);
}
rrs.setNodes(rn);
setGroupFlagAndLimit(rrs, visitor);
return rrs;
}
// 规则计算
validateAST(ast, matchedTable, rule, visitor);
Map<Integer, List<Object[]>> dnMap = ruleCalculate(matchedTable, rule, columnValues);
if (dnMap == null || dnMap.isEmpty()) {
throw new IllegalArgumentException("No target dataNode for rule " + rule);
}
// 判断路由结果是单库还是多库
if (dnMap.size() == 1) {
String dataNode = matchedTable.getDataNodes()[dnMap.keySet().iterator().next()];
String sql = visitor.isSchemaTrimmed() ? genSQL(ast, stmt) : stmt;
RouteResultsetNode[] rn = new RouteResultsetNode[1];
rn[0] = new RouteResultsetNode(dataNode, sql);
rrs.setNodes(rn);
} else {
RouteResultsetNode[] rn = new RouteResultsetNode[dnMap.size()];
if (ast instanceof DMLInsertReplaceStatement) {
DMLInsertReplaceStatement ir = (DMLInsertReplaceStatement) ast;
dispatchInsertReplace(rn, ir, rule.getColumns(), dnMap, matchedTable, stmt, visitor);
} else {
dispatchWhereBasedStmt(rn, ast, rule.getColumns(), dnMap, matchedTable, stmt, visitor);
}
rrs.setNodes(rn);
setGroupFlagAndLimit(rrs, visitor);
}
return rrs;
}
use of com.alibaba.cobar.parser.ast.stmt.SQLStatement in project cobar by alibaba.
the class SQLParserDelegateTest method testProperlyEnd.
public void testProperlyEnd() throws SQLSyntaxErrorException {
String sql = "select * from tb1;";
SQLStatement stmt = SQLParserDelegate.parse(sql);
Assert.assertEquals(DMLSelectStatement.class, stmt.getClass());
sql = "select * from tb1 ;;; ";
stmt = SQLParserDelegate.parse(sql);
Assert.assertEquals(DMLSelectStatement.class, stmt.getClass());
sql = "select * from tb1 /***/ ";
stmt = SQLParserDelegate.parse(sql);
Assert.assertEquals(DMLSelectStatement.class, stmt.getClass());
sql = "select * from tb1 , ";
try {
stmt = SQLParserDelegate.parse(sql);
Assert.fail("should detect inproperly end");
} catch (SQLSyntaxErrorException e) {
}
sql = "select * from tb1 ;, ";
try {
stmt = SQLParserDelegate.parse(sql);
Assert.fail("should detect inproperly end");
} catch (SQLSyntaxErrorException e) {
}
}
use of com.alibaba.cobar.parser.ast.stmt.SQLStatement in project cobar by alibaba.
the class MySQLDALParserTest method testSet.
public void testSet() throws Exception {
String sql = "seT sysVar1 = ? ";
MySQLLexer lexer = new MySQLLexer(sql);
MySQLDALParser parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
SQLStatement set = (DALSetStatement) parser.set();
parser.match(MySQLToken.EOF);
String output = output2MySQL(set, sql);
Assert.assertEquals("SET @@sysVar1 = ?", output);
sql = "SET `sysVar1` = ?, @@gloBal . `var2` :=1 ";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (DALSetStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET @@`sysVar1` = ?, @@global.`var2` = 1", output);
sql = "SET @usrVar1 := ?, @@`var2` =1, @@var3:=?, @'var\\'3'=? ";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (DALSetStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET @usrVar1 = ?, @@`var2` = 1, @@var3 = ?, @'var\\'3' = ?", output);
sql = "SET GLOBAL var1=1, SESSION var2:=2";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (DALSetStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET @@global.var1 = 1, @@var2 = 2", output);
sql = "SET @@GLOBAL. var1=1, SESSION var2:=2";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (DALSetStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET @@global.var1 = 1, @@var2 = 2", output);
sql = "SET transaction ISOLATION LEVEL READ UNCOMMITTED ";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (MTSSetTransactionStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED", output);
sql = "SET global transaction ISOLATION LEVEL READ COMMITTED ";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (MTSSetTransactionStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED", output);
sql = "SET transaction ISOLATION LEVEL REPEATABLE READ ";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (MTSSetTransactionStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ", output);
sql = "SET session transaction ISOLATION LEVEL SERIALIZABLE ";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (MTSSetTransactionStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE", output);
sql = "SET names default ";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (DALSetNamesStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET NAMES DEFAULT", output);
sql = "SET NAMEs 'utf8' collatE \"latin1_danish_ci\" ";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (DALSetNamesStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET NAMES utf8 COLLATE latin1_danish_ci", output);
sql = "SET NAMEs utf8 ";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (DALSetNamesStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET NAMES utf8", output);
sql = "SET CHARACTEr SEt 'utf8' ";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (DALSetCharacterSetStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET CHARACTER SET utf8", output);
sql = "SET CHARACTEr SEt DEFaULT ";
lexer = new MySQLLexer(sql);
parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
set = (DALSetCharacterSetStatement) parser.set();
parser.match(MySQLToken.EOF);
output = output2MySQL(set, sql);
Assert.assertEquals("SET CHARACTER SET DEFAULT", output);
}
use of com.alibaba.cobar.parser.ast.stmt.SQLStatement in project cobar by alibaba.
the class ServerRouteTest method testRouteInsertLong.
public void testRouteInsertLong() throws Exception {
StringBuilder sb = new StringBuilder("insert into offer_detail (offer_id, gmt) values ");
for (int i = 0; i < 1024; ++i) {
if (i > 0)
sb.append(", ");
sb.append("(" + i + ", now())");
}
SchemaConfig schema = schemaMap.get("cndb");
RouteResultset rrs = ServerRouter.route(schema, sb.toString(), null, null);
Assert.assertEquals(-1l, rrs.getLimitSize());
Map<String, RouteResultsetNode> nodeMap = getNodeMap(rrs, 128);
IndexedNodeNameAsserter nameAsserter = new IndexedNodeNameAsserter("detail_dn", 0, 128);
nameAsserter.assertRouteNodeNames(nodeMap.keySet());
RouteNodeAsserter asserter = new RouteNodeAsserter(nameAsserter, new ParseredSQLAsserter() {
@Override
protected void assertAST(SQLStatement stmt, int nodeIndex) {
DMLInsertStatement insert = (DMLInsertStatement) stmt;
List<RowExpression> rows = insert.getRowList();
Assert.assertNotNull(rows);
Assert.assertEquals(8, rows.size());
List<Integer> vals = new ArrayList<Integer>(8);
for (RowExpression row : rows) {
int val = ((Number) row.getRowExprList().get(0).evaluation(null)).intValue();
vals.add(val);
}
Assert.assertEquals(8, vals.size());
for (int i = 8 * nodeIndex; i < 8 * nodeIndex + 8; ++i) {
Assert.assertTrue(vals.contains(i));
}
}
});
for (RouteResultsetNode node : nodeMap.values()) {
asserter.assertNode(node);
}
}
Aggregations