package com.tesora.dve.sql; /* * #%L * Tesora Inc. * Database Virtualization Engine * %% * Copyright (C) 2011 - 2014 Tesora Inc. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import java.util.ArrayList; import java.util.List; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import com.tesora.dve.sql.util.MirrorProc; import com.tesora.dve.sql.util.MirrorTest; import com.tesora.dve.sql.util.NativeDDL; import com.tesora.dve.sql.util.PEDDL; import com.tesora.dve.sql.util.ProjectDDL; import com.tesora.dve.sql.util.ResourceResponse; import com.tesora.dve.sql.util.StorageGroupDDL; import com.tesora.dve.sql.util.TestResource; public class AggBugsTest extends SchemaMirrorTest { private static final int SITES = 5; static final ProjectDDL sysDDL = new PEDDL("sysdb", new StorageGroupDDL("sys",SITES,"sysg"), "schema"); static final ProjectDDL checkDDL = new PEDDL("checkdb", new StorageGroupDDL("check",1,"checkg"), "schema"); static final NativeDDL nativeDDL = new NativeDDL("cdb"); @Override protected ProjectDDL getMultiDDL() { return sysDDL; } @Override protected ProjectDDL getSingleDDL() { return checkDDL; } @Override protected ProjectDDL getNativeDDL() { return nativeDDL; } @BeforeClass public static void setup() throws Throwable { setup(sysDDL, checkDDL, nativeDDL, getPopulate()); } private static final TestRange pe287Range = new TestRange("pe287range","varchar(256), varchar(256)"); private static final TestTable pe287 = new TestTable("pe287", "fname varchar(256), caller varchar(256), callee varchar(256), " + "ct int, wt int, cputime int, mu int, pmu int", "fname, callee", pe287Range) .withTuple("'506c7fbc8a9e9.nonpar.xhprof', 'main()', 'getcwd', 1, 9, 0, 604, 604") .withTuple("'506c7fbc8a9e9.nonpar.xhprof', 'main()', 'define', 1, 28, 0, 604, 604") .withTuple("'506c7fbc8a9e9.nonpar.xhprof', 'main()', 'load::includes/bootstrap.inc', 1, 249, 0, 64076, 64076") .withTuple("'506c7fbc8a9e9.nonpar.xhprof', 'run_init::includes/bootstrap.inc', 'define', 37, 39, 0, 820, 820 ") .withTuple("'506c7fbc8a9e9.nonpar.xhprof', 'main()', 'run_init::includes/bootstrap.inc', 1, 155, 0, 4580, 4420 ") .withTuple("'506c7fbc8a9e9.nonpar.xhprof', 'bootstrap', 'array_shift', 6, 7, 0, 468, 468 ") .withTuple("'506c7fbc8a9e9.nonpar.xhprof', 'bootstrap_configuration', 'set_error_handler', 1, 5, 0, 672, 672") .withTuple( "'506c7fbc8a9e9.nonpar.xhprof', 'bootstrap_configuration', 'set_exception_handler', 1, 2, 0, 628, 628 ") .withTuple("'506c7fbc8a9e9.nonpar.xhprof', 'environment_initialize', 'strtolower', 1, 2, 0, 664, 664 ") .withTuple("'506c7fbc8a9e9.nonpar.xhprof', 'valid_http_host', 'preg_match', 1, 14, 0, 632, 632"); private static final TestRange pe773Range = new TestRange("pe773range","varchar(10)"); private static final TestTable pe773 = new TestTable("pe773", "c1 varchar(10), c2 varchar(10)", "c1", pe773Range) .withTuple("'001', 'Same Value'") .withTuple("'002', 'Same Value'"); private static final TestRange pe865Range = new TestRange("pe865range","int"); private static final TestTable pe865 = new TestTable("pe865", "id int auto_increment, n int, s varchar(32), fp int, primary key(id)", "id",pe865Range) .withInsertString("(n,s,fp)") .withTuple("1,'one',1").withTuple("2,'two',2").withTuple("3,'three',3").withTuple("4,'four',2") .withTuple("5,'five',5").withTuple("6,'six',2").withTuple("7,'seven',7").withTuple("8,'eight',2") .withTuple("9,'nine',3").withTuple("10,'ten',2").withTuple("11,'eleven',11").withTuple("12,'twelve',2") .withTuple("13,'thirteen',13").withTuple("14,'fourteen',2").withTuple("15,'fifteen',3") .withTuple("16,'sixteen',2").withTuple("17,'seventeen',17").withTuple("18,'eighteen',2") .withTuple("19,'nineteen',19").withTuple("20,'twenty',2").withTuple("21,'twentyone',3") .withTuple("22,'twentytwo',2").withTuple("23,'twentythree',23").withTuple("24,'twentyfour',2") .withTuple("25,'twentyfive',5"); private static final TestRange pe1370Range = new TestRange("pe1370range","int"); private static final TestTable pe1370 = new TestTable("pe1370", "col1 int, col2 tinyint unsigned", "col1", pe1370Range) .withInsertString("(col1, col2)") .withTuple("1,255") .withTuple("2,255") .withTuple("3,255"); static TestRange[] ranges = new TestRange[] { pe287Range, pe773Range, pe865Range, pe1370Range }; private static final TestTable[] tables = new TestTable[] { pe287, pe773, pe865, pe1370 }; private static List<MirrorTest> getPopulate() { ArrayList<MirrorTest> out = new ArrayList<MirrorTest>(); out.add(new MirrorProc() { @Override public ResourceResponse execute(TestResource mr) throws Throwable { if (mr == null) return null; boolean ext = !nativeDDL.equals(mr.getDDL()); String dbname = mr.getDDL().getDatabases().get(0).getDatabaseName(); // declare the tables ResourceResponse rr = null; if (ext) { // declare the ranges for(TestRange tr : ranges) { rr = mr.getConnection().execute(tr.getDeclaration(mr.getDDL().getPersistentGroup().getName(), dbname)); } } // declare the tables for(TestTable tt : tables) { String[] decls = tt.getTableDecls(ext, dbname); for(String d : decls) rr = mr.getConnection().execute(d); } return rr; } }); for(TestTable tt : tables) { for(String tabName : tt.getTableNames()) { out.add(new StatementMirrorProc("insert into " + tabName + " " + tt.getInsertBody())); } } return out; } @Ignore @Test public void testPE287() throws Throwable { ArrayList<MirrorTest> tests = new ArrayList<MirrorTest>(); for(String tn : pe287.getTableNames()) { tests.add(new StatementMirrorFun(true, "select fname, caller, max(wt/ct) from " + tn + " where caller = 'main()'")); } runTest(tests); } @Ignore @Test public void testPE773() throws Throwable { ArrayList<MirrorTest> tests = new ArrayList<MirrorTest>(); for(String tableName : pe773.getTableNames()) { tests.add(new StatementMirrorFun(true, "select c1, count(distinct c2) from " + tableName + " group by c2")); } runTest(tests); } @Ignore @Test public void testPE865() throws Throwable { ArrayList<MirrorTest> tests = new ArrayList<MirrorTest>(); String[] tabNames = pe865.getTableNames(); String[] testNames = tabNames; for(String tableName : testNames) { tests.add(new StatementMirrorFun(true, true, "select fp, group_concat(s SEPARATOR ' ') from " + tableName + " group by fp order by fp")); tests.add(new StatementMirrorFun(true, true, "select fp, group_concat(n), avg(n) from " + tableName + " group by fp order by fp")); tests.add(new StatementMirrorFun(true, true, "select group_concat(s SEPARATOR ' ') from " + tableName)); tests.add(new StatementMirrorFun(true, "select s from " + tableName)); } runTest(tests); } @Test public void testPE1370() throws Throwable { ArrayList<MirrorTest> tests = new ArrayList<MirrorTest>(); String[] tblNames = pe1370.getTableNames(); for(String tableName : tblNames) { tests.add(new StatementMirrorFun(true, true, "select col1, col2 from " + tableName + " order by col1")); } runTest(tests); } public static final String[] distsuffix = new String [] { "B", "S", "R", "A" }; public static final String[] distnames = new String[] { "broadcast", "static", "range", "random" }; // we need more infrastructure to handle these test cases. generally we want to test some agg fun on some data where the data // is distributed each of the 4 ways. public static class TestTable { protected String kern; protected String distColumns; protected String body; protected TestRange range; protected String insertHeader; protected List<String> insertTuples = new ArrayList<String>(); public TestTable(String name, String body, String distOn, TestRange theRange) { kern = name; distColumns = distOn; this.body = body; range = theRange; } public TestTable withInsertString(String s) { insertHeader = s; return this; } public TestTable withTuple(String t) { insertTuples.add(t); return this; } public String getInsertBody() { StringBuffer buf = new StringBuffer(); if (insertHeader != null) buf.append(insertHeader); buf.append("values "); for(int i = 0; i < insertTuples.size(); i++) { if (i > 0) buf.append(", "); buf.append("(").append(insertTuples.get(i)).append(")"); } return buf.toString(); } public String[] getTableNames() { String[] out = new String[distsuffix.length]; for(int i = 0; i < distsuffix.length; i++) out[i] = kern + distsuffix[i]; return out; } public String[] getTableDecls(boolean ext, String rangePrefix) { String[] out = new String[distsuffix.length]; for(int i = 0; i < distsuffix.length; i++) { StringBuilder buf = new StringBuilder(); buf.append("create table `").append(kern).append(distsuffix[i]).append("` (") .append(body).append(")"); if (ext) { buf.append(" ").append(distnames[i]).append(" distribute"); if ("S".equals(distsuffix[i]) || "R".equals(distsuffix[i])) { buf.append(" on (").append(distColumns).append(")"); if ("R".equals(distsuffix[i])) { buf.append(" using ").append(range.getName(rangePrefix)); } } } out[i] = buf.toString(); } return out; } } public static class TestRange { protected String name; protected String signature; public TestRange(String name, String sig) { this.name = name; this.signature = sig; } public String getDeclaration(String sgname, String prefix) { return "create range " + prefix + name + " (" + signature + ") persistent group " + sgname; } public String getName(String prefix) { return prefix + name; } } }