use of com.alibaba.cobar.config.model.rule.TableRuleConfig in project cobar by alibaba.
the class XMLSchemaLoader method loadTables.
private Map<String, TableConfig> loadTables(Element node) {
Map<String, TableConfig> tables = new HashMap<String, TableConfig>();
NodeList nodeList = node.getElementsByTagName("table");
for (int i = 0; i < nodeList.getLength(); i++) {
Element tableElement = (Element) nodeList.item(i);
String name = tableElement.getAttribute("name").toUpperCase();
String dataNode = tableElement.getAttribute("dataNode");
TableRuleConfig tableRule = null;
if (tableElement.hasAttribute("rule")) {
String ruleName = tableElement.getAttribute("rule");
tableRule = tableRules.get(ruleName);
if (tableRule == null) {
throw new ConfigException("rule " + ruleName + " is not found!");
}
}
boolean ruleRequired = false;
if (tableElement.hasAttribute("ruleRequired")) {
ruleRequired = Boolean.parseBoolean(tableElement.getAttribute("ruleRequired"));
}
String[] tableNames = SplitUtil.split(name, ',', true);
for (String tableName : tableNames) {
TableConfig table = new TableConfig(tableName, dataNode, tableRule, ruleRequired);
checkDataNodeExists(table.getDataNodes());
if (tables.containsKey(table.getName())) {
throw new ConfigException("table " + tableName + " duplicated!");
}
tables.put(table.getName(), table);
}
}
return tables;
}
use of com.alibaba.cobar.config.model.rule.TableRuleConfig 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.config.model.rule.TableRuleConfig in project cobar by alibaba.
the class TableConfig method buildColumnIndex.
private static Set<String> buildColumnIndex(TableRuleConfig rule) {
if (rule == null) {
return Collections.emptySet();
}
List<RuleConfig> rs = rule.getRules();
if (rs == null || rs.isEmpty()) {
return Collections.emptySet();
}
Set<String> columnIndex = new HashSet<String>();
for (RuleConfig r : rs) {
List<String> columns = r.getColumns();
if (columns != null) {
for (String col : columns) {
if (col != null) {
columnIndex.add(col.toUpperCase());
}
}
}
}
return columnIndex;
}
use of com.alibaba.cobar.config.model.rule.TableRuleConfig in project cobar by alibaba.
the class XMLRuleLoader method loadTableRules.
private void loadTableRules(Element root) throws SQLSyntaxErrorException {
NodeList list = root.getElementsByTagName("tableRule");
for (int i = 0, n = list.getLength(); i < n; ++i) {
Node node = list.item(i);
if (node instanceof Element) {
Element e = (Element) node;
String name = e.getAttribute("name");
if (tableRules.containsKey(name)) {
throw new ConfigException("table rule " + name + " duplicated!");
}
NodeList ruleNodes = e.getElementsByTagName("rule");
int length = ruleNodes.getLength();
List<RuleConfig> ruleList = new ArrayList<RuleConfig>(length);
for (int j = 0; j < length; ++j) {
RuleConfig rule = loadRule((Element) ruleNodes.item(j));
ruleList.add(rule);
rules.add(rule);
}
tableRules.put(name, new TableRuleConfig(name, ruleList));
}
}
}
Aggregations