package com.tesora.dve.sql.statement; /* * #%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 static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import com.tesora.dve.singleton.Singletons; import com.tesora.dve.sql.transexec.spi.TransientEngine; import com.tesora.dve.sql.transexec.spi.TransientEngineFactory; import org.junit.AfterClass; import org.junit.BeforeClass; import com.tesora.dve.common.catalog.TemplateMode; import com.tesora.dve.server.connectionmanager.TestHost; import com.tesora.dve.sql.ParserException.Pass; import com.tesora.dve.sql.SchemaException; import com.tesora.dve.sql.SchemaTest; import com.tesora.dve.sql.jg.CollapsedJoinGraph; import com.tesora.dve.sql.jg.UncollapsedJoinGraph; import com.tesora.dve.sql.parser.InvokeParser; import com.tesora.dve.sql.schema.SchemaContext; import com.tesora.dve.sql.schema.cache.SchemaSourceFactory; import com.tesora.dve.sql.statement.dml.MultiTableDMLStatement; import com.tesora.dve.sql.util.TestName; import com.tesora.dve.standalone.PETest; public class TransientSchemaTest extends SchemaTest { @BeforeClass public static void setup() throws Exception { TestHost.startServicesTransient(PETest.class); } @AfterClass public static void teardown() throws Exception { TestHost.stopServices(); } protected String projectName; protected String ttkern; public TransientSchemaTest(String projectName, String tempTableKern) { this.projectName = projectName; this.ttkern = tempTableKern; } public TransientSchemaTest(String projName) { this(projName,"temp"); } public String[] getPESchemaDeclarations(TestName tn, String templateDecl) { List<String> decls = new ArrayList<String>(); if (tn.isNativeCombo()) throw new SchemaException(Pass.SECOND, "No support for native combo tests in transient schema tests: " + tn); if (tn.isPESingle()) { decls.add("Create persistent site site1 url='jdbc:mysql://s1/db1' user='floyd' password='floyd'"); decls.add("create persistent group g1 add site1"); addTemplateDeclaration(templateDecl, decls); String mtmode = (tn.isMT() ? " multitenant " : " "); decls.add("create " + mtmode + "database mydb default persistent group g1 " + getTemplateDeclaration()); } else { decls.add("create persistent site site1 url='jdbc:mysql://s1/db1' user='floyd' password='floyd'"); decls.add("create persistent site site2 url='jdbc:mysql://s2/db1' user='floyd' password='floyd'"); decls.add("create persistent group g1 add site1, site2;"); decls.add("create persistent site site3 url='jdbc:mysql://s3/db1' user='floyd' password='floyd';"); decls.add("create persistent site site4 url='jdbc:mysql://s4/db1' user='floyd' password='floyd';"); decls.add("create persistent group t1 add site3, site4;"); addTemplateDeclaration(templateDecl, decls); String mtmode = (tn.isMT() ? " multitenant " : " "); decls.add("create" + mtmode + "database mydb default persistent group g1 " + getTemplateDeclaration()); } decls.add("create range openrange (int) persistent group g1;"); decls.add("use mydb;"); return decls.toArray(new String[0]); } private static void addTemplateDeclaration(final String templateDecl, final List<String> declarations) { if (templateDecl != null) { declarations.add(templateDecl); } } public String getTemplateDeclaration() { return "using template " + TemplateMode.OPTIONAL; } public SchemaContext buildSchema(TestName tn, String ...schema) throws Throwable { return buildSchema(null,tn,schema); } public SchemaContext buildSchema(String templateDecl, TestName tn,String ...schema) throws Throwable { SchemaContext pc = buildDatabase(tn,templateDecl, schema); pc.beginSaveContext(); try { pc.getCurrentPEDatabase().persistTree(pc); } finally { pc.endSaveContext(); } return pc; } public SchemaContext buildDatabase(String[] peschema, String[] sqlschema, TestName tn) throws Throwable { String[] sql = add(peschema, sqlschema); return buildDatabaseExecute(sql,tn); } public SchemaContext buildDatabase(TestName tn, String[] sqlschema) throws Throwable { return buildDatabase(tn,null,sqlschema); } public SchemaContext buildDatabase(TestName tn, String templateDecl, String[] sqlschema) throws Throwable { return buildDatabase(getPESchemaDeclarations(tn,templateDecl), sqlschema, tn); } public SchemaContext buildDatabase(TestName tn) throws Throwable { return buildDatabase(tn,(String)null); } public SchemaContext buildDatabase(TestName tn, String templateDecl) throws Throwable { return buildDatabase(getPESchemaDeclarations(tn, templateDecl), null, tn); } // mini execution engine to convert sql creates into the transient schema public SchemaContext buildDatabaseExecute(String[] in, TestName tn) throws Throwable { return buildExecutionEngine(in, tn).getPersistenceContext(); } private String[] add(String[] left, String[] right) { ArrayList<String> all = new ArrayList<String>(); all.addAll(Arrays.asList(left)); if (right != null) all.addAll(Arrays.asList(right)); String[] sql = all.toArray(new String[0]); return sql; } public final TransientEngine newExecutionEngine(TestName tn) { SchemaSourceFactory.reset(); return Singletons.require(TransientEngineFactory.class).create(ttkern); } public TransientEngine buildExecutionEngine(String[] in, TestName tn) throws Throwable { TransientEngine tee = newExecutionEngine(tn); tee.parse(in); return tee; } public List<Statement> parse(SchemaContext pc, String stmt) throws Exception { return parse(pc,stmt,Collections.emptyList()); } public List<Statement> parse(SchemaContext pc, String stmt, List<Object> params) throws Exception { SchemaSourceFactory.reset(); pc.refresh(true); return InvokeParser.parse(stmt, pc, params); } // join graph test infrastructure protected UncollapsedJoinGraph buildUncollapsed(SchemaContext db, String sql) throws Throwable { Statement s = parse(db,sql).get(0); return new UncollapsedJoinGraph(db,(MultiTableDMLStatement) s); } protected CollapsedJoinGraph buildCollapsed(SchemaContext db, String sql) throws Throwable { return new CollapsedJoinGraph(db,buildUncollapsed(db,sql)); } protected CollapsedJoinGraph buildCollapsed(SchemaContext db, UncollapsedJoinGraph ujg) throws Throwable { return new CollapsedJoinGraph(db,ujg); } protected void joinGraphTest(SchemaContext db, String sql, int nparts, int njoins) throws Throwable { CollapsedJoinGraph cjg = buildCollapsed(db,sql); if (nparts == -1) { System.out.println(sql); System.out.println(cjg.describe(db)); System.out.println("nparts=" + cjg.getPartitions().size()); System.out.println("njoins=" + cjg.getJoins().size()); } else { assertEquals("partitions should match for '" + sql + "'",nparts,cjg.getPartitions().size()); assertEquals("joins should match",njoins,cjg.getJoins().size()); } } }