package com.tesora.dve.client; /* * #%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.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import java.io.IOException; import java.io.InputStream; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.Properties; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.tesora.dve.common.DBHelper; import com.tesora.dve.common.PEConstants; import com.tesora.dve.common.PEFileUtils; import com.tesora.dve.common.ShowSchema; import com.tesora.dve.common.catalog.TestCatalogHelper; import com.tesora.dve.exceptions.PEException; import com.tesora.dve.server.bootstrap.BootstrapHost; import com.tesora.dve.server.global.HostService; import com.tesora.dve.singleton.Singletons; import com.tesora.dve.sql.template.TemplateBuilder; import com.tesora.dve.sql.util.ProxyConnectionResource; import com.tesora.dve.standalone.PETest; import com.tesora.dve.test.simplequery.SimpleQueryTest; @Test(groups = { "NonSmokeTest" }) public class ClientTestNG extends PETest { static DBHelper dbHelper; @BeforeClass public static void startup() throws Throwable { TestCatalogHelper.createTestCatalog(PETest.class); BootstrapHost.startServices(PETest.class); SimpleQueryTest.cleanupSites(6, "TestDB","d7test"); ProxyConnectionResource pcr = new ProxyConnectionResource(); SimpleQueryTest.createSites(2, pcr); SimpleQueryTest.createGroupAndTestDB(2, pcr); pcr.execute("create table alltypes ( bit_column bit,tinyint_column tinyint,bigint_column bigint," +"longvarb_column long varbinary,varb_column varbinary(200),binary_column binary(10)," +"text_column text, char_column char(10),num_column numeric(10,2),dec_column decimal(5,4)," +"int_column integer,smallint_column smallint,float_column float,double_column double," +"varchar_column varchar(10),date_column date,time_column time, datetime_column datetime," +"intu_column integer unsigned, bigintu_column bigint unsigned " +") engine=innodb random distribute"); pcr.disconnect(); // populateMetadata(ClientTestNG.class, Singletons.require(HostService.class).getProperties()); populateSites(ClientTestNG.class, Singletons.require(HostService.class).getProperties()); } @AfterClass public static void shutdown() throws Exception { BootstrapHost.stopServices(); } @BeforeMethod public void preTestSetup() throws PEException { Properties peProps = PEFileUtils.loadPropertiesFile(ClientTestNG.class, PEConstants.CONFIG_FILE_NAME); dbHelper = new DBHelper(peProps.getProperty(PEConstants.PROP_JDBC_URL) + "/TestDB?zeroDateTimeBehavior=convertToNull", peProps.getProperty(PEConstants.PROP_JDBC_USER), peProps.getProperty(PEConstants.PROP_JDBC_PASSWORD)); dbHelper.connect(); } @AfterMethod public void postTestTeardown() { dbHelper.disconnect(); } @Test public void SimpleSelectTest1() throws Exception { dbHelper.executeQuery("SELECT * FROM alltypes"); int rows = countResultSetRows(dbHelper.getResultSet()); assertEquals(2, rows); } @Test public void showTypesTest1() throws Exception { int rows = countResultSetRows(dbHelper.getConnection().getMetaData().getTypeInfo()); // TODO this is mysql specific...... // assertEquals(40, rows); } @Test public void createTableTest() throws Exception { assertFalse(dbHelper.executeQuery("CREATE TABLE client_test1 ( col1 int, col2 varchar(10))")); assertTrue(dbHelper.executeQuery("SELECT * from client_test1")); } @Test public void simpleInsertTest() throws Exception { assertFalse(dbHelper.executeQuery("CREATE TABLE client_test2 ( col1 int, col2 varchar(10))")); assertFalse(dbHelper.executeQuery("INSERT INTO client_test2 VALUES (1,'row1 col2')")); assertTrue(dbHelper.executeQuery("SELECT * FROM client_test2")); int rows = countResultSetRows(dbHelper.getResultSet()); assertEquals(1, rows); } @Test public void multipleTupleInsertTest() throws Exception { assertFalse(dbHelper.executeQuery("CREATE TABLE client_test ( col1 int, col2 varchar(10))")); assertFalse(dbHelper.executeQuery("INSERT INTO client_test VALUES (1,'row1 col2'),(2,'row2 col2')")); assertTrue(dbHelper.executeQuery("SELECT * FROM client_test")); int rows = countResultSetRows(dbHelper.getResultSet()); assertEquals(2, rows); } @Test public void aliasingTest() throws Exception { assertFalse(dbHelper .executeQuery("CREATE TABLE atest1 (id int not null, rpart int not null, ipart int not null)")); assertFalse(dbHelper .executeQuery("insert into atest1 (id, rpart, ipart) values (1,1,0), (2,0,1),(3,1,1),(4,0,0)")); verifyMetadata("select * from atest1", new String[] { "id", "id", "rpart", "rpart", "ipart", "ipart" }); verifyMetadata("select id di, rpart trapr, ipart trapi from atest1", new String[] { "id", "di", "rpart", "trapr", "ipart", "trapi" }); verifyMetadata("select id di, rpart from atest1", new String[] { "id", "di", "rpart", "rpart" }); verifyMetadata("select id, rpart + ipart from atest1", new String[] { "id", "id", "rpart + ipart", "rpart + ipart" }); verifyMetadata("select id, rpart + ipart as s from atest1", new String[] { "id", "id", "s", "s" }); verifyMetadata("select atest1.id, atest1.rpart, atest1.ipart as prati from atest1", new String[] { "id", "id", "rpart", "rpart", "ipart", "prati" }); verifyMetadata("select a.id, case a.id when 0 then a.rpart else a.ipart end as cs from atest1 a", new String[] { "id", "id", "cs", "cs" }); } @Test public void templateTest() throws Exception { dbHelper.executeQuery(new TemplateBuilder("drupal7_commons") .withRequirement("create range if not exists block_range (int) persistent group #sg#") .withRequirement("create range if not exists field_range (varchar,int) persistent group #sg#") .toCreateStatement()); assertFalse(dbHelper.executeQuery("CREATE DATABASE d7test USING TEMPLATE drupal7_commons STRICT")); assertTrue(dbHelper.executeQuery("SHOW RANGES")); assertEquals(2, countResultSetRows(dbHelper.getResultSet())); } @Test public void broadcastDeleteTest() throws Exception { assertFalse(dbHelper.executeQuery("CREATE TABLE foo_delete(col1 int) BROADCAST DISTRIBUTE")); assertFalse(dbHelper.executeQuery("INSERT INTO foo_delete VALUES (1)")); assertTrue(dbHelper.executeQuery("SELECT * FROM foo_delete")); assertEquals(1, countResultSetRows(dbHelper.getResultSet())); assertFalse(dbHelper.executeQuery("DELETE FROM foo_delete WHERE col1=1")); assertTrue(dbHelper.executeQuery("SELECT * FROM foo_delete")); assertEquals(0, countResultSetRows(dbHelper.getResultSet())); } @Test public void rollbackAfterStmtFailureTest() throws Exception { // This is to reproduce the // "commitTransaction called when no transaction in progress" // exception that occurs when a txn is inflight and a parser error // occurs. dbHelper.executeQuery("START TRANSACTION"); try { dbHelper.executeQuery("SELECT 1 FROM WHERE cid=null"); } catch (SQLException se) { // expected - ignore } dbHelper.executeQuery("ROLLBACK"); } @Test public void defaultAndAutoIncrInsertTest() throws Exception { StringBuffer query = new StringBuffer().append("CREATE TABLE simpletest_test_id (") .append("`test_id` INT NOT NULL auto_increment,").append("`last_prefix` VARCHAR(60) NULL DEFAULT '',") .append("`null_column` VARCHAR(10) NULL,").append(" PRIMARY KEY (`test_id`))"); dbHelper.executeQuery(query.toString()); assertFalse(dbHelper.executeQuery("INSERT INTO simpletest_test_id (test_id) VALUES (default)")); assertFalse(dbHelper .executeQuery("INSERT INTO simpletest_test_id (last_prefix, null_column) VALUES (default, NULL), (default, 'nonull')")); assertFalse(dbHelper .executeQuery("INSERT INTO simpletest_test_id (test_id, last_prefix) VALUES (10,'hi'), (default,'there'), (default, default)")); assertEquals(3, dbHelper.getLastInsertID()); assertTrue(dbHelper.executeQuery("SELECT * FROM simpletest_test_id")); int rows = countResultSetRows(dbHelper.getResultSet()); assertEquals(6, rows); } @Test public void escapeProcessingTest() throws Exception { StringBuffer query = new StringBuffer().append("CREATE TABLE test_variable (") .append("`name` VARCHAR(128) NOT NULL,").append("`value` LONGBLOB NULL,") .append(" PRIMARY KEY (`name`)) BROADCAST DISTRIBUTE"); dbHelper.executeQuery(query.toString()); assertFalse(dbHelper.executeQuery("INSERT INTO test_variable (name) VALUES('drupal_test_email_collector')")); StringBuilder value = new StringBuilder().append('\\').append('\\').append("''").append("''").append("{`") .append('\\').append('\\').append('\\').append("'").append(";}}"); String valueExp = StringEscapeUtils.unescapeJava(value.toString()).replaceAll("''", "'"); StringBuilder update = new StringBuilder().append("UPDATE test_variable SET value='").append(value) .append("' WHERE ( (name = 'drupal_test_email_collector' ) )"); assertFalse(dbHelper.executeQuery(update.toString())); assertTrue(dbHelper.executeQuery("SELECT value FROM test_variable WHERE name = 'drupal_test_email_collector'")); dbHelper.getResultSet().next(); String valueFromDB = dbHelper.getResultSet().getString(1); assertTrue(StringUtils.equals(valueExp, valueFromDB)); } @Test // Repro for PE-102 public void largeInsertTest() throws Exception { final int NUM_TUPLES = 3300; final String ONE_TUPLE = "(0,' ', 'qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt')"; StringBuffer query = new StringBuffer().append("CREATE TABLE sbtest (") .append("id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,") .append("k INTEGER UNSIGNED DEFAULT '0' NOT NULL,").append("c char(120) DEFAULT '' NOT NULL,") .append("pad char(60) DEFAULT '' NOT NULL,").append(" PRIMARY KEY (id))"); dbHelper.executeQuery(query.toString()); StringBuffer insert = new StringBuffer().append("INSERT INTO sbtest (k, c, pad) VALUES "); boolean doneFirst = false; for (int i = 0; i < NUM_TUPLES; i++) { if (doneFirst) insert.append(","); else doneFirst = true; insert.append(ONE_TUPLE); } insert.append(";"); dbHelper.executeQuery(insert.toString()); dbHelper.executeQuery("SELECT COUNT(*) FROM sbtest"); dbHelper.getResultSet().next(); assertEquals(NUM_TUPLES, dbHelper.getResultSet().getLong(1)); } // repro for PE-268 @Test public void dateTypeTest() throws Exception { final String dateValue = "2012-10-03"; final String timeValue = "15:49:36"; final String dateTimeValue = dateValue + " " + timeValue + ".0"; // need a .0 for mS on the end of datetime StringBuffer query = new StringBuffer().append("CREATE TABLE test_date (").append("`datecol` date NULL,") .append("`timecol` time NULL, ").append("`datetimecol` datetime NULL)"); dbHelper.executeQuery(query.toString()); query = new StringBuffer().append("INSERT INTO test_date VALUES ('").append(dateValue).append("','") .append(timeValue).append("','").append(dateTimeValue).append("')"); dbHelper.executeQuery(query.toString()); dbHelper.executeQuery("SELECT * FROM test_date"); ResultSet rs = dbHelper.getResultSet(); rs.next(); assertEquals(dateValue, rs.getString(1)); assertEquals(timeValue, rs.getString(2)); assertEquals(dateTimeValue, rs.getString(3)); } // repro for PE-337 @Test public void zeroDateTest() throws Exception { final String zeroDateTime = "0000-00-00 00:00:00"; final String zeroDate = "0000-00-00"; final String zeroTime = "00:00:00"; StringBuffer query = new StringBuffer().append("CREATE TABLE wp_posts (") .append("ID bigint(20) unsigned NOT NULL,").append("post_datetime datetime NOT NULL default '") .append(zeroDateTime).append("',").append("post_date date NOT NULL default '").append(zeroDate) .append("',").append("post_time time NOT NULL default '").append(zeroTime).append("',") .append("post_timestamp timestamp NOT NULL default '").append(zeroDateTime).append("')"); dbHelper.executeQuery(query.toString()); dbHelper.executeQuery("insert into wp_posts (ID) values (1)"); dbHelper.executeQuery("select post_datetime, post_date, post_time, post_timestamp from wp_posts"); ResultSet rs = dbHelper.getResultSet(); rs.next(); assertNull(rs.getString(1)); assertNull(rs.getString(2)); assertEquals(zeroTime, rs.getString(3)); assertNull(rs.getString(4)); } private static void verifyMetadata(String query, String[] namesAndAliases) throws Exception { assertTrue(dbHelper.executeQuery(query)); ResultSetMetaData rsmd = dbHelper.getResultSet().getMetaData(); verifyMetadata(rsmd, namesAndAliases); } private static void verifyMetadata(ResultSetMetaData rsmd, String[] namesAndAliases) throws SQLException { if (namesAndAliases == null) { for (int i = 1; i <= rsmd.getColumnCount(); i++) { System.out.println(rsmd.getColumnName(i) + " as " + rsmd.getColumnLabel(i)); } return; } int ncolumns = namesAndAliases.length / 2; assertEquals(ncolumns, rsmd.getColumnCount()); for (int i = 0; i < ncolumns; i++) { String ename = namesAndAliases[2 * i]; String ealias = namesAndAliases[2 * i + 1]; assertEquals(ename, rsmd.getColumnName(i + 1)); assertEquals(ealias, rsmd.getColumnLabel(i + 1)); } } @Test public void infoSchemaColumnMetadataTest() throws Exception { StringBuffer query = new StringBuffer().append("SHOW DATABASES"); dbHelper.executeQuery(query.toString()); ResultSet rs = dbHelper.getResultSet(); ResultSetMetaData rsmd = rs.getMetaData(); // make sure the column header is not empty assertTrue(!StringUtils.isEmpty(rsmd.getColumnLabel(1))); assertEquals(ShowSchema.Database.NAME, rsmd.getColumnLabel(1)); } private void loadSQLFile(Class<?> testClass, String fileName) throws Exception { InputStream is = testClass.getResourceAsStream(fileName); if (is != null) { logger.info("Reading SQL statements from " + fileName); dbHelper.setDisconnectAfterProcess(false); dbHelper.executeFromStream(is); try { is.close(); } catch (IOException e) { } } } // repro for PE-481 @Test(enabled = false) public void generationAddTest() throws Exception { loadSQLFile(ClientTestNG.class, "large-table-load.sql"); dbHelper.executeQuery("ALTER PERSISTENT GROUP " + PEConstants.DEFAULT_GROUP_NAME + " ADD GENERATION site3,site4,site5,site6"); dbHelper.executeQuery("SHOW GENERATION SITES WHERE persistent_group='" + PEConstants.DEFAULT_GROUP_NAME + "'"); assertEquals(6, countResultSetRows(dbHelper.getResultSet())); } @Test public void pe1428Test() throws Exception { dbHelper.executeQuery("CREATE RANGE test1range (int) persistent group " + PEConstants.DEFAULT_GROUP_NAME); dbHelper.executeQuery("CREATE TABLE test1(col1 int) RANGE DISTRIBUTE ON (col1) USING test1range"); dbHelper.executeQuery("INSERT INTO test1 VALUES (1),(2),(3),(4),(5)"); dbHelper.executeQuery("SELECT count(*), @dve_sitename FROM test1 GROUP BY 2"); assertEquals(2, countResultSetRows(dbHelper.getResultSet())); dbHelper.executeQuery("DROP TABLE test1"); dbHelper.executeQuery("DROP RANGE test1range"); } }