package jef.database.partition;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import jef.database.DbUtils;
import jef.database.annotation.PartitionKeyImpl;
import jef.database.annotation.PartitionTable;
import jef.database.annotation.PartitionTableImpl;
import jef.database.dialect.AbstractDialect;
import jef.database.dialect.DatabaseDialect;
import jef.database.dialect.MySqlDialect;
import jef.database.dialect.type.AutoIncrementMapping.GenerationResolution;
import jef.database.innerpool.PartitionSupport;
import jef.database.jsqlparser.parser.ParseException;
import jef.database.jsqlparser.parser.StSqlParser;
import jef.database.meta.ITableMetadata;
import jef.database.meta.MetaHolder;
import jef.database.meta.TableMetadata;
import jef.database.meta.TupleMetadata;
import jef.database.query.DefaultPartitionCalculator;
import jef.database.query.PartitionCalculator;
import jef.database.routing.PartitionResult;
import jef.database.routing.function.KeyFunction;
import jef.database.routing.sql.SqlAnalyzer;
import jef.database.support.MultipleDatabaseOperateException;
import jef.orm.onetable.model.TestEntity;
import jef.orm.partition.PartitionEntity;
import jef.tools.DateUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.util.Assert;
public class CalculatorTest extends org.junit.Assert{
static PartitionTableImpl config = new PartitionTableImpl();
private PartitionCalculator calc = new DefaultPartitionCalculator();
private TupleMetadata tuple = new TupleMetadata("TestPartitionTable");
private TableMetadata meta = (TableMetadata) MetaHolder.getMeta(TestEntity.class);
static Method inv;
@BeforeClass
public static void setup() throws SecurityException, NoSuchMethodException {
config.setAppender("_");
config.setKeySeparator("_");
PartitionKeyImpl[] keys = new PartitionKeyImpl[] { new PartitionKeyImpl("intField2", 1) };
// keys[0].length=2;
config.setKey(keys);
inv = TableMetadata.class.getDeclaredMethod("setPartition", PartitionTable.class);
inv.setAccessible(true);
}
private PartitionSupport supportor = new PartitionSupport() {
public Collection<String> getSubTableNames(String dbName, ITableMetadata pTable) throws SQLException {
String name = pTable.getTableName(true);
List<String> result = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
result.add(name + "0" + i);
}
return result;
}
public Collection<String> getDdcNames() {
return Arrays.asList("Database1", "Database2", "Database3", "Database4", "Database5");
}
public DatabaseDialect getProfile(String dbkey) {
return new MySqlDialect();
}
public void ensureTableExists(String db,String table,ITableMetadata meta) {
}
public PartitionResult[] getSubTableNames(ITableMetadata meta) {
PartitionResult r=new PartitionResult(meta.getTableName(true)+"_MM");
return new PartitionResult[]{r};
}
public boolean isExist(String dbName, String table, ITableMetadata meta) {
return true;
}
};
@Test
public void testTableResults() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
DatabaseDialect profile = AbstractDialect.getProfile("mariadb");
{
((PartitionKeyImpl) config.key()[0]).function = KeyFunction.RAW;
((PartitionKeyImpl) config.key()[0]).defaultWhenFieldIsNull = "aa, bb, cc";
inv.invoke(meta, config);
PartitionResult[] result = calc.toTableNames(meta, supportor,2);
System.out.println(Arrays.asList(result));
assertEquals("[test_entity_aa,test_entity_bb,test_entity_cc,test_entity]", Arrays.toString(result));
assertEquals(GenerationResolution.TABLE, meta.getFirstAutoincrementDef().getGenerationType(profile));
}
{
((PartitionKeyImpl) config.key()[0]).function = KeyFunction.MODULUS;
inv.invoke(meta, config);
PartitionResult[] result = calc.toTableNames(meta, supportor,1);
System.out.println(Arrays.asList(result));
assertEquals("[test_entity_0,test_entity_1,test_entity_2,test_entity_3,test_entity_4,test_entity_5,test_entity_6,test_entity_7,test_entity_8,test_entity_9]", Arrays.toString(result));
assertEquals(GenerationResolution.TABLE, meta.getFirstAutoincrementDef().getGenerationType(profile));
}
{
((PartitionKeyImpl) config.key()[0]).function = KeyFunction.MONTH;
inv.invoke(meta, config);
PartitionResult[] result = calc.toTableNames(meta, supportor,2);
System.out.println(Arrays.asList(result));
assertEquals("[test_entity_1,test_entity_2,test_entity_3,test_entity_4,test_entity_5,test_entity_6,test_entity_7,test_entity_8,test_entity_9,test_entity_10,test_entity_11,test_entity_12,test_entity]", Arrays.toString(result));
assertEquals(GenerationResolution.TABLE, meta.getFirstAutoincrementDef().getGenerationType(profile));
}
{
((PartitionKeyImpl) config.key()[0]).function = KeyFunction.YEAR;
inv.invoke(meta, config);
PartitionResult[] result = calc.toTableNames(meta, supportor,2);
System.out.println(Arrays.asList(result));
assertEquals("[test_entity_"+DateUtils.getYear(new Date())+",test_entity]",Arrays.toString(result));
assertEquals(GenerationResolution.TABLE, meta.getFirstAutoincrementDef().getGenerationType(profile));
}
{
System.out.println("==============MAP函数=================");
((PartitionKeyImpl) config.key()[0]).function = KeyFunction.MAPPING;
((PartitionKeyImpl) config.key()[0]).funcParams=new String[]{"00-24:1,25-49:2,50-74:3,75-99:4"};
inv.invoke(meta, config);
PartitionResult[] result = calc.toTableNames(meta, supportor,1);
System.out.println(Arrays.asList(result));
assertEquals("[test_entity_1,test_entity_2,test_entity_3,test_entity_4]", Arrays.toString(result));
assertEquals(GenerationResolution.TABLE, meta.getFirstAutoincrementDef().getGenerationType(profile));
}
{
System.out.println("==============双维度下,一个维度无法枚举,因此收缩=================");
PartitionKeyImpl[] keys = new PartitionKeyImpl[] { new PartitionKeyImpl("createTime", 1), new PartitionKeyImpl("intField2", 1) };
keys[0].function = KeyFunction.MONTH;
config.setKey(keys);
inv.invoke(meta, config);
PartitionResult[] result = calc.toTableNames(meta, supportor,2);
assertEquals("[test_entity]", Arrays.toString(result));
System.out.println(Arrays.asList(result));
}
{
((PartitionKeyImpl) config.key()[0]).function = KeyFunction.YEAR;
inv.invoke(meta, config);
PartitionResult[] result = calc.toTableNames(meta, supportor,3);
Assert.notNull(result);
System.out.println(Arrays.asList(result));
assertEquals("[test_entity_MM]",Arrays.toString(result));
assertEquals(GenerationResolution.TABLE, meta.getFirstAutoincrementDef().getGenerationType(profile));
}
}
@Test
public void testCreaterTable() {
PartitionEntity pe = new PartitionEntity();
PartitionResult[] results = DbUtils.toTableNames(pe, null, null, supportor);
assertEquals(5, results.length);
for(PartitionResult r: results){
assertEquals(12, r.tableSize());
assertEquals(18, r.getTables().get(0).length());
}
}
@Test(expected=MultipleDatabaseOperateException.class)
public void testCreaterTable2() {
PartitionEntity pe = new PartitionEntity();
PartitionResult results = DbUtils.toTableName(pe, null, null, supportor);
System.out.println(results);
}
@Test
public void testCreaterTable3() {
ITableMetadata meta=MetaHolder.getMeta(PartitionEntity.class);
PartitionResult[] results = DbUtils.toTableNames(meta, supportor,2);
for (PartitionResult r : results) {
System.out.println(r);
}
}
@AfterClass
public static void afterClz(){
MetaHolder.getCachedDynamicModels().clear();
MetaHolder.getCachedModels().clear();
}
// @Test
// public void testSql1() throws ParseException{
// MetaHolder.initMetadata(Device.class, null,null);
// String sql="Delete from DEVICE where indexcode > '100000' AND indexcode < '500000'";
// PartitionResult[] results=SqlAnalyzer.getPartitionResultOfSQL(DbUtils.parseStatement(sql), Collections.EMPTY_LIST, supportor);
// System.out.println("------------------------------------------");
// for (PartitionResult r : results) {
// System.out.println(r.getDatabase()+"||"+r.getTables());
// }
// }
//
// @Test
// public void testSql2() throws ParseException{
// MetaHolder.initMetadata(Device.class, null,null);
// String sql="update DEVICE xx set xx.name = 'ID:' || indexcode,createDate = current_timestamp where indexcode BETWEEN '1000' AND '6000'";
// PartitionResult[] results=SqlAnalyzer.getPartitionResultOfSQL(DbUtils.parseStatement(sql), Collections.EMPTY_LIST, supportor);
// System.out.println("------------------------------------------");
// for (PartitionResult r : results) {
// System.out.println(r.getDatabase()+"||"+r.getTables());
// }
// }
//
// @Test
// public void testSql3() throws ParseException{
// MetaHolder.initMetadata(Device.class, null,null);
// String sql="delete Device where (indexcode >'200000' and indexcode<'5') or (indexcode >'700000' and indexcode <'8')";
// PartitionResult[] results=SqlAnalyzer.getPartitionResultOfSQL(DbUtils.parseStatement(sql), Collections.EMPTY_LIST, supportor);
// System.out.println("------------------------------------------");
// for (PartitionResult r : results) {
// System.out.println(r.getDatabase()+"||"+r.getTables());
// }
//// {indexcode=(700000,8) || (200000,5)}
//// MapFunction maps=new MapFunction("1-1:datasource1,2-49999:datasource2,5-899999:datasource3,*:",1);
//// RangeDimension<String> r=RangeDimension.createCC("700000", "8");
//// Collection<?> objs=r.toEnumationValue(Collections.<PartitionFunction>singletonList(maps));
//// for(Object o: objs){
//// System.out.println(maps.eval(String.valueOf(o)));
//// }
// }
//
// @Test
// public void testSqlx() throws ParseException{
// MetaHolder.initMetadata(Device.class, null,null);
// String sql="delete Device where indexcode=?";
// test(sql,"199999"); //1-1不能适应
// test(sql,"2"); //
// test(sql,"20");
// test(sql,"20000");
// test(sql,"2000001");
// test(sql,"21");
// test(sql,"201");
// test(sql,"299999");
// test(sql,"3");
// test(sql,"300000");
//
// }
private void test(String sql, Object... string) throws ParseException {
StSqlParser parser=new StSqlParser(new StringReader(sql));
PartitionResult[] results=SqlAnalyzer.getPartitionResultOfSQL(parser.Statement(), Arrays.<Object>asList(string), supportor);
System.out.println("------------------------------------------");
for (PartitionResult r : results) {
System.out.println(r.getDatabase()+"||"+r.getTables());
}
}
}