/*
* Copyright (c) 2013, OpenCloudDB/MyCAT and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software;Designed and Developed mainly by many Chinese
* opensource volunteers. you can redistribute it and/or modify it under the
* terms of the GNU General Public License version 2 only, as published by the
* Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Any questions about this component can be directed to it's project Web address
* https://code.google.com/p/opencloudb/.
*
*/
package io.mycat.server.config.node;
import com.google.common.base.Strings;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.Set;
import io.mycat.util.SplitUtil;
/**
* @author mycat
*/
public class TableConfig {
public static final int TYPE_GLOBAL_TABLE = 1;
public static final int TYPE_GLOBAL_DEFAULT = 0;
private String name;
private String primaryKey;
private boolean autoIncrement;
private boolean needAddLimit;
private Set<String> dbTypes;
private int tableType;
private ArrayList<String> dataNodes;
private RuleConfig rule;
private String ruleName;
private String partitionColumn;
private boolean ruleRequired;
private TableConfig parentTC;
private boolean childTable;
private String joinKey;
private String parentKey;
private String locateRTableKeySql;
// only has one level of parent
private boolean secondLevel;
private boolean partionKeyIsPrimaryKey;
private Random rand = new Random();
public void setName(String name) {
if (name == null) {
throw new IllegalArgumentException("table name is null");
}
this.name = name.toUpperCase();
}
public void setPrimaryKey(String primaryKey) {
this.primaryKey = primaryKey;
}
public void setAutoIncrement(boolean autoIncrement) {
this.autoIncrement = autoIncrement;
}
public void setNeedAddLimit(boolean needAddLimit) {
this.needAddLimit = needAddLimit;
}
public void setDbTypes(Set<String> dbTypes) {
this.dbTypes = dbTypes;
}
public void setTableType(int tableType) {
this.tableType = TableConfig.TYPE_GLOBAL_DEFAULT == tableType ?
TableConfig.TYPE_GLOBAL_DEFAULT : TableConfig.TYPE_GLOBAL_TABLE;
}
public void setDataNode(String dataNode) {
if (Strings.isNullOrEmpty(dataNode)) {
throw new IllegalArgumentException("dataNode name is null");
}
String theDataNodes[] = SplitUtil.split(dataNode, ',', '$', '-');
if (theDataNodes == null || theDataNodes.length <= 0) {
throw new IllegalArgumentException("invalid table dataNodes: " + dataNode);
}
this.dataNodes = new ArrayList<>(Arrays.asList(theDataNodes));
}
public void setRule(RuleConfig rule) {
this.partitionColumn = (rule == null) ? null : rule.getColumn();
this.partionKeyIsPrimaryKey = (this.partitionColumn == null) ?
this.primaryKey == null : this.partitionColumn.equals(this.primaryKey);
this.rule = rule;
}
public void setRuleRequired(boolean ruleRequired) {
this.ruleRequired = ruleRequired;
}
public void setParentTC(TableConfig parentTC) {
this.parentTC = parentTC;
if (this.parentTC != null) {
this.locateRTableKeySql = genLocateRootParentSQL();
this.secondLevel = (parentTC.parentTC == null);
}
}
public void setChildTable(boolean childTable) {
this.childTable = childTable;
}
public void setJoinKey(String joinKey) {
this.joinKey = joinKey;
}
public void setParentKey(String parentKey) {
this.parentKey = parentKey;
}
public TableConfig(){
super();
}
public TableConfig(String name, String primaryKey, boolean autoIncrement, boolean needAddLimit,
int tableType, String dataNode, Set<String> dbType, RuleConfig rule,
boolean ruleRequired, TableConfig parentTC, boolean isChildTable, String joinKey,
String parentKey) {
super();
this.setName(name);
this.setDataNode(dataNode);
this.setRule(rule);
this.setParentTC(parentTC);
this.primaryKey = primaryKey;
this.autoIncrement = autoIncrement;
this.needAddLimit = needAddLimit;
this.tableType = tableType;
this.dbTypes = dbType;
this.ruleRequired = ruleRequired;
this.childTable = isChildTable;
this.joinKey = joinKey;
this.parentKey = parentKey;
this.parentTC = parentTC;
this.checkConfig();
}
public String getPrimaryKey() {
return primaryKey;
}
public Set<String> getDbTypes()
{
return dbTypes;
}
public boolean isAutoIncrement() {
return autoIncrement;
}
public boolean isNeedAddLimit() {
return needAddLimit;
}
public boolean isSecondLevel() {
return secondLevel;
}
public String getLocateRTableKeySql() {
return locateRTableKeySql;
}
public boolean isGlobalTable() {
return this.tableType == TableConfig.TYPE_GLOBAL_TABLE;
}
public String genLocateRootParentSQL() {
TableConfig tb = this;
StringBuilder tableSb = new StringBuilder();
StringBuilder condition = new StringBuilder();
TableConfig prevTC = null;
int level = 0;
String latestCond = null;
while (tb.parentTC != null) {
tableSb.append(tb.parentTC.name).append(',');
String relation = null;
if (level == 0) {
latestCond = " " + tb.parentTC.getName() + '.' + tb.parentKey
+ "=";
} else {
relation = tb.parentTC.getName() + '.' + tb.parentKey + '='
+ tb.name + '.' + tb.joinKey;
condition.append(relation).append(" AND ");
}
level++;
prevTC = tb;
tb = tb.parentTC;
}
String sql = "SELECT "
+ prevTC.parentTC.name
+ '.'
+ prevTC.parentKey
+ " FROM "
+ tableSb.substring(0, tableSb.length() - 1)
+ " WHERE "
+ ((level < 2) ? latestCond : condition.toString() + latestCond);
// System.out.println(this.name+" sql " + sql);
return sql;
}
public String getPartitionColumn() {
return partitionColumn;
}
public int getTableType() {
return tableType;
}
/**
* get root parent
*
* @return
*/
public TableConfig getRootParent() {
if (parentTC == null) {
return null;
}
TableConfig preParent = parentTC;
TableConfig parent = preParent.getParentTC();
while (parent != null) {
preParent = parent;
parent = parent.getParentTC();
}
return preParent;
}
public TableConfig getParentTC() {
return parentTC;
}
public boolean isChildTable() {
return childTable;
}
public String getJoinKey() {
return joinKey;
}
public String getParentKey() {
return parentKey;
}
/**
* @return upper-case
*/
public String getName() {
return name;
}
public ArrayList<String> getDataNodes() {
return dataNodes;
}
public String getRandomDataNode() {
int index = Math.abs(rand.nextInt()) % dataNodes.size();
return dataNodes.get(index);
}
public boolean isRuleRequired() {
return ruleRequired;
}
public RuleConfig getRule() {
return rule;
}
public boolean primaryKeyIsPartionKey() {
return partionKeyIsPrimaryKey;
}
public void checkConfig(){
if (this.ruleRequired && this.rule == null) {
throw new IllegalArgumentException("ruleRequired but rule is null");
}
}
public String getRuleName() {
return ruleName;
}
public void setRuleName(String ruleName) {
this.ruleName = ruleName;
}
}