[Mycat1.6 table source code interpretation of loading Schema (1)]

1. Introduction to schema attributes

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="">

<table name="tab" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

<table name="user1" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

<table name="user"  dataNode="dn1,dn2,dn3" rule="auto-sharding-long"

nameSuffix=""   primaryKey=""   autoIncrement=""   needAddLimit=""   type=""   ruleRequired=""   subTables=""/>

</schema>

 

primaryKey records the primary key, which is used for subsequent routing analysis and enabling self-growing primary keys

nameSuffix route, add support for dynamic date table

Whether the autoIncrement record is automatically incremented by the primary key, the default is not, (enable the global sequence handler)

Whether the needAddLimit record needs to be added to the returned result set limit, the default needs to be added

type record type, whether it is global

Whether the ruleRequired record is bound with a sharding rule

subTables sub-table function

 

Second, source code interpretation

private void load(String dtdFile, String xmlFile) {
	InputStream dtd = null;
	InputStream xml = null;
	dtd = XMLSchemaLoader.class.getResourceAsStream(dtdFile);
	xml = XMLSchemaLoader.class.getResourceAsStream(xmlFile);
	Element root = ConfigUtil.getDocument(dtd, xml).getDocumentElement();
	//Load all DataHost first
	loadDataHosts(root);
	//Reload all DataNodes
	loadDataNodes(root);
	//Finally load all Schema 
	loadSchemas(root);	 
}

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="">
	<table name="tab" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
	<table name="user1" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
	<table name="user"  dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
</schema>
private void loadSchemas(Element root) {
	NodeList list = root.getElementsByTagName("schema");
	for (int i = 0, n = list.getLength(); i < n; i++) {
		Element schemaElement = (Element) list.item(i);
		//read each property
		String name = schemaElement.getAttribute("name");
		String dataNode = schemaElement.getAttribute("dataNode");
		String checkSQLSchemaStr = schemaElement.getAttribute("checkSQLschema");
		String sqlMaxLimitStr = schemaElement.getAttribute("sqlMaxLimit");
		int sqlMaxLimit = -1;
		//Read sql return result set limit
		if (sqlMaxLimitStr != null && !sqlMaxLimitStr.isEmpty()) {
			sqlMaxLimit = Integer.parseInt(sqlMaxLimitStr);
		}
		
		// check dataNode already exists or not, see if there is a datanode in the schema tag
		String defaultDbType = null;
		//Check and add dataNode
		if (dataNode != null && !dataNode.isEmpty()) {
			List dataNodeLst = new ArrayList(1);
			dataNodeLst.add(dataNode);
			checkDataNodeExists(dataNodeLst);
			String dataHost = dataNodes.get(dataNode).getDataHost();
			defaultDbType = dataHosts.get(dataHost).getDbType();
		} else {
			dataNode = null;
		}
		//Load all tables under schema 
		Map<String, TableConfig> tables = loadTables (schemaElement);
		/ / Determine whether the schema is repeated
		if (schemas.containsKey(name)) {
			throw new ConfigException("schema " + name + " duplicated!");
		}

		// If the table is set, you do not need to set the dataNode attribute, and if the table is not set, the dataNode attribute must be set.
		if (dataNode == null && tables.size() == 0) {
			throw new ConfigException(
					"schema " + name + " didn't config tables,so you must set dataNode property!");
		}

		SchemaConfig schemaConfig = new SchemaConfig(name, dataNode,
				tables, sqlMaxLimit, "true".equalsIgnoreCase(checkSQLSchemaStr));

		//Set the DB type, which is helpful for the subsequent sql statement routing analysis
		if (defaultDbType != null) {
			schemaConfig.setDefaultDataNodeDbType(defaultDbType);
			if (!"mysql".equalsIgnoreCase(defaultDbType)) {
				schemaConfig.setNeedSupportMultiDBType(true);
			}
		}

		// Determine whether there is a database type that is not mysql, which is convenient for parsing to determine whether to enable multi-database paging syntax parsing
		for (TableConfig tableConfig : tables.values()) {
			if (isHasMultiDbType(tableConfig)) {
				schemaConfig.setNeedSupportMultiDBType(true);
				break;
			}
		}
		//Record the DB type of each dataNode
		Map<String, String> dataNodeDbTypeMap = new HashMap<>();
		for (String dataNodeName : dataNodes.keySet()) {
			DataNodeConfig dataNodeConfig = dataNodes.get(dataNodeName);
			String dataHost = dataNodeConfig.getDataHost();
			DataHostConfig dataHostConfig = dataHosts.get(dataHost);
			if (dataHostConfig != null) {
				String dbType = dataHostConfig.getDbType();
				dataNodeDbTypeMap.put(dataNodeName, dbType);
			}
		}
		schemaConfig.setDataNodeDbTypeMap(dataNodeDbTypeMap);
		schemas.put(name, schemaConfig);
	}
}
private Map<String, TableConfig> loadTables(Element node) {
	// Map<String, TableConfig> tables = new HashMap<String, TableConfig>();
	// Support quotes [`] BEN GONG in table names
	Map<String, TableConfig> tables = new TableConfigMap();
	NodeList nodeList = node.getElementsByTagName("table");
	for (int i = 0; i < nodeList.getLength(); i++) {
		Element tableElement = (Element) nodeList.item(i);
		String tableNameElement = tableElement.getAttribute("name").toUpperCase();

		//TODO: Routing, add support for dynamic date table 
		String tableNameSuffixElement = tableElement.getAttribute(" nameSuffix ").toUpperCase();
		if ( !"".equals( tableNameSuffixElement ) ) {				
			
			if( tableNameElement.split(",").length > 1 ) {
				throw new ConfigException("nameSuffix " +
tableNameSuffixElement + ", require name parameter cannot multiple breaks!");
			}
			//The prefix is ​​used to indicate the date format 
			tableNameElement = doTableNameSuffix (tableNameElement, tableNameSuffixElement);
		}
		//Record the primary key for subsequent routing analysis and enable self-increasing primary keys
		String[] tableNames = tableNameElement.split(",");
		String primaryKey = tableElement.hasAttribute("primaryKey") ? 
tableElement.getAttribute("primaryKey").toUpperCase() : null;
		//Whether the primary key of the record is auto-incremented, the default is not, (enable the global sequence handler)
		boolean autoIncrement = false;
		if (tableElement.hasAttribute("autoIncrement")) {
			autoIncrement = Boolean.parseBoolean(tableElement.getAttribute("autoIncrement"));
		}
		//Whether the record needs to be added to the returned result set limit, the default needs to be added
		boolean needAddLimit = true;
		if (tableElement.hasAttribute("needAddLimit")) {
			needAddLimit = Boolean.parseBoolean (tableElement.getAttribute ("needAddLimit"));
		}
		//Record type, whether it is global
		String tableTypeStr = tableElement.hasAttribute("type") ? 
tableElement.getAttribute("type") : null;
		int tableType = TableConfig.TYPE_GLOBAL_DEFAULT;
		if ("global".equalsIgnoreCase(tableTypeStr)) {
			tableType = TableConfig.TYPE_GLOBAL_TABLE;
		}
		//Record dataNode, which dataNode is distributed on
		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;
		//Record whether there is a sharding rule bound
		if (tableElement.hasAttribute("ruleRequired")) {
			ruleRequired = Boolean.parseBoolean (tableElement.getAttribute ("ruleRequired"));
		}

		if (tableNames == null) {
			throw new ConfigException("table name is not found!");
		}
		//distribute function, rearrange dataNode
		String distPrex = "distribute(";
		boolean distTableDns = dataNode.startsWith(distPrex);
		if (distTableDns) {
			dataNode = dataNode.substring(distPrex.length(), dataNode.length() - 1);
		}
		// sub-table function
		String subTables = tableElement.getAttribute("subTables");
		
		for (int j = 0; j < tableNames.length; j++) {

			String tableName = tableNames[j];
			TableRuleConfig tableRuleConfig=tableRule ;
			  if(tableRuleConfig!=null) {
				//Special processing for the function that implements TableRuleAware Create a new instance according to each table
				  RuleConfig rule= tableRuleConfig.getRule();
				  if(rule.getRuleAlgorithm() instanceof TableRuleAware)  {
					  tableRuleConfig = (TableRuleConfig) ObjectUtil.copyObject(tableRuleConfig);
					  tableRules.remove(tableRuleConfig.getName())   ;
					  String newRuleName = tableRuleConfig.getName() + "_" + tableName;
					  tableRuleConfig. setName(newRuleName);
					  TableRuleAware tableRuleAware= (TableRuleAware)
tableRuleConfig.getRule().getRuleAlgorithm();
					  tableRuleAware.setRuleName(newRuleName);
					  tableRuleAware.setTableName(tableName);
					  tableRuleConfig.getRule().getRuleAlgorithm().init();
					  tableRules.put(newRuleName,tableRuleConfig);
				  }
			  }

			TableConfig table = new TableConfig(tableName, primaryKey,
					autoIncrement, needAddLimit, tableType, dataNode,
					getDbType(dataNode),
					(tableRuleConfig != null) ? tableRuleConfig.getRule() : null,
					ruleRequired, null, false, null, null,subTables);
			
			checkDataNodeExists(table.getDataNodes());
			// Check whether the sharding table sharding rule configuration is legal
			if(table.getRule() != null) {
				checkRuleSuitTable(table);
			}
			
			if (distTableDns) {
				distributeDataNodes(table.getDataNodes());
			}
			//check for deduplication
			if (tables.containsKey(table.getName())) {
				throw new ConfigException("table " + tableName + " duplicated!");
			}
			// put in map
			tables.put(table.getName(), table);
		}
		//Only when tableName is configured with a single table (without commas) can there be subtables
		if (tableNames.length == 1) {
			TableConfig table = tables.get(tableNames[0]);
			// process child tables   recursively calls 
			processChildTables (tables, table, dataNode, tableElement);
		}
	}
	return tables;
}
	
	
/**
* Process dynamic date table, support YYYYMM, YYYYMMDD two formats
*
* YYYYMM format: yyyymm,2015,01,60   
* YYYYMMDD format: yyyymmdd,2015,01,10,50
*
* @param tableNameElement
* @param tableNameSuffixElement
 * @return
 */
private String doTableNameSuffix(String tableNameElement, String tableNameSuffixElement) {
		
	String newTableName = tableNameElement;
	
	String[] params = tableNameSuffixElement.split(",");			
	String suffixFormat = params[0].toUpperCase();		
	if ( suffixFormat.equals("YYYYMM") ) {
		
		//read parameters
		int yyyy = Integer.parseInt( params[1] );
		int mm = Integer.parseInt( params[2] );					
		int mmEndIdx =  Integer.parseInt( params[3] );
		
		// date processing
		SimpleDateFormat yyyyMMSDF = new SimpleDateFormat("yyyyMM");
		
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, yyyy );
		cal.set(Calendar.MONTH, mm - 1 );
		cal.set(Calendar.DATE, 0 );
		
		//rewrite table name
		StringBuffer tableNameBuffer = new StringBuffer();
		for(int mmIdx = 0; mmIdx <= mmEndIdx; mmIdx++) {						
			tableNameBuffer.append( tableNameElement );
			tableNameBuffer.append( yyyyMMSDF.format(cal.getTime()) );							
			cal.add(Calendar.MONTH, 1);
			
			if ( mmIdx != mmEndIdx) {
				tableNameBuffer.append(",");
			}						
		}
                //A batch of table names separated by commas A1, B2, C3	 				
		newTableName  = tableNameBuffer.toString();

	} else if ( suffixFormat.equals("YYYYMMDD") ) {
		
		//read parameters
		int yyyy = Integer.parseInt( params[1] );
		int mm = Integer.parseInt( params[2] );
		int dd =  Integer.parseInt( params[3] );
		int ddEndIdx =  Integer.parseInt( params[4] );
		
		// date processing
		SimpleDateFormat yyyyMMddSDF = new SimpleDateFormat("yyyyMMdd");
		
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, yyyy );
		cal.set(Calendar.MONTH, mm - 1 );
		cal.set(Calendar.DATE, dd );
		
		//rewrite table name
		StringBuffer tableNameBuffer = new StringBuffer();
		for(int ddIdx = 0; ddIdx <= ddEndIdx; ddIdx++) {					
			tableNameBuffer.append( tableNameElement );
			tableNameBuffer.append( yyyyMMddSDF.format(cal.getTime()) );
			
			cal.add(Calendar.DATE, 1);	
			
			if ( ddIdx != ddEndIdx) {
				tableNameBuffer.append(",");
			}
		}
               //A batch of table names separated by commas A1, B2, C3					
		 newTableName = tableNameBuffer.toString();
	}				
	return newTableName;		
}

 

Three, dynamic date table demonstration



<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">

<table name="tab" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

<table name="user1" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

<table name="user"  dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

 

<!-- 2015--January starts from December 2014, and accumulates to 24 months-->

<table name="test"  dataNode="dn1,dn2,dn3" rule="auto-sharding-long" nameSuffix="yyyymm,2015,01,24" />

<!-- Starting from January 1, 2015, the total accumulated to 100 days -->

<table name="demo"  dataNode="dn1,dn2,dn3" rule="auto-sharding-long" nameSuffix="yyyymmdd,2015,01,01,100" />

</schema>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326462802&siteId=291194637