You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ma...@apache.org on 2016/02/02 05:00:24 UTC

[50/50] [abbrv] phoenix git commit: Sync with master; Bug fix for ResultSet object of Float type; Walkaround for PHOENIX-2647

Sync with master; Bug fix for ResultSet object of Float type; Walkaround for PHOENIX-2647


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/74409be8
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/74409be8
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/74409be8

Branch: refs/heads/calcite
Commit: 74409be82c1224b0cefee1b1e6a64bb3d0491339
Parents: beb8b81 6af7dcb
Author: maryannxue <ma...@gmail.com>
Authored: Mon Feb 1 22:59:16 2016 -0500
Committer: maryannxue <ma...@gmail.com>
Committed: Mon Feb 1 22:59:16 2016 -0500

----------------------------------------------------------------------
 phoenix-assembly/pom.xml                        |   2 +-
 phoenix-core/pom.xml                            |   2 +-
 .../apache/phoenix/calcite/BaseCalciteIT.java   |  91 ++++++++--
 .../org/apache/phoenix/calcite/CalciteIT.java   | 140 ++++++++--------
 .../apache/phoenix/calcite/CalciteIndexIT.java  |  36 ++--
 .../phoenix/end2end/CsvBulkLoadToolIT.java      |   5 +-
 .../apache/phoenix/end2end/DerivedTableIT.java  |  13 ++
 .../phoenix/end2end/StatsCollectorIT.java       |  73 ++++----
 .../phoenix/end2end/TransactionalViewIT.java    | 120 +++++++++++++
 .../phoenix/end2end/index/ImmutableIndexIT.java | 123 +++++++++-----
 .../end2end/index/MutableIndexFailureIT.java    |   6 +-
 .../apache/phoenix/execute/PartialCommitIT.java |   2 +-
 .../index/balancer/IndexLoadBalancerIT.java     |   2 +
 .../org/apache/phoenix/tx/TransactionIT.java    |  39 +----
 .../ipc/controller/MetadataRpcController.java   |   3 +-
 .../wal/BinaryCompatibleBaseDecoder.java        | 110 ++++++++++++
 .../regionserver/wal/IndexedWALEditCodec.java   |  83 ++++++++-
 .../cache/aggcache/SpillableGroupByCache.java   |  17 +-
 .../apache/phoenix/calcite/CalciteRuntime.java  |  10 +-
 .../apache/phoenix/calcite/PhoenixSchema.java   |   2 +-
 .../calcite/rel/PhoenixRelImplementorImpl.java  |   4 +-
 .../apache/phoenix/compile/FromCompiler.java    |   8 +-
 .../phoenix/compile/ListJarsQueryPlan.java      |   2 +-
 .../phoenix/compile/OrderPreservingTracker.java |   6 +-
 .../compile/PostLocalIndexDDLCompiler.java      | 104 ++++++++++++
 .../apache/phoenix/compile/TraceQueryPlan.java  |   2 +-
 .../apache/phoenix/compile/UnionCompiler.java   |   2 +-
 .../phoenix/coprocessor/BaseRegionScanner.java  |  11 +-
 .../GroupedAggregateRegionObserver.java         |  38 +----
 .../coprocessor/MetaDataEndpointImpl.java       |   7 +-
 .../coprocessor/MetaDataRegionObserver.java     |   8 +-
 .../phoenix/coprocessor/ScanRegionObserver.java |  17 +-
 .../UngroupedAggregateRegionObserver.java       |  24 +--
 .../coprocessor/generated/PTableProtos.java     | 145 +++++++++++++---
 .../phoenix/execute/ClientAggregatePlan.java    |   2 +-
 .../apache/phoenix/execute/HashJoinPlan.java    |   2 +-
 .../apache/phoenix/execute/MutationState.java   |  84 +++++-----
 .../index/write/KillServerOnFailurePolicy.java  |   5 +-
 .../index/PhoenixIndexFailurePolicy.java        |   9 +-
 .../phoenix/iterate/BaseResultIterators.java    |   2 +-
 .../apache/phoenix/jdbc/PhoenixStatement.java   |   1 -
 .../phoenix/mapreduce/AbstractBulkLoadTool.java |   2 +-
 .../mapreduce/PhoenixRecordWritable.java        |  28 ++--
 .../query/ConnectionQueryServicesImpl.java      |  82 ++-------
 .../org/apache/phoenix/query/QueryServices.java |   2 +
 .../phoenix/query/QueryServicesOptions.java     |  11 +-
 .../apache/phoenix/schema/DelegateColumn.java   |   5 +
 .../apache/phoenix/schema/MetaDataClient.java   | 133 ++++++---------
 .../java/org/apache/phoenix/schema/PColumn.java |   2 +
 .../org/apache/phoenix/schema/PColumnImpl.java  |  21 ++-
 .../apache/phoenix/schema/PMetaDataImpl.java    |   2 +-
 .../org/apache/phoenix/schema/SaltingUtil.java  |   2 +-
 .../phoenix/execute/CorrelatePlanTest.java      |   2 +-
 .../phoenix/execute/UnnestArrayPlanTest.java    |   4 +-
 .../expression/ColumnExpressionTest.java        |   8 +-
 .../phoenix/filter/SkipScanFilterTest.java      |  62 +++----
 .../iterate/AggregateResultScannerTest.java     |   4 +
 .../phoenix/query/QueryServicesTestImpl.java    |   4 +-
 phoenix-flume/pom.xml                           |   2 +-
 .../flume/serializer/RegexEventSerializer.java  |  12 +-
 phoenix-pherf/pom.xml                           |   2 +-
 phoenix-pig/pom.xml                             |   2 +-
 .../phoenix/pig/PhoenixHBaseLoaderIT.java       | 167 ++++++++++++++++++-
 .../phoenix/pig/PhoenixHBaseStorerIT.java       |  37 ++++
 .../apache/phoenix/pig/PhoenixHBaseLoader.java  |  22 +--
 .../apache/phoenix/pig/PhoenixHBaseStorage.java |  33 +++-
 .../org/apache/phoenix/pig/util/TypeUtil.java   |  49 ++++--
 .../pig/writable/PhoenixPigDBWritable.java      | 121 --------------
 .../apache/phoenix/pig/util/TypeUtilTest.java   |  39 +++--
 phoenix-protocol/src/main/MetaDataService.proto |   2 +-
 phoenix-protocol/src/main/PTable.proto          |   1 +
 phoenix-server-client/pom.xml                   |   2 +-
 phoenix-server/pom.xml                          |   2 +-
 phoenix-spark/pom.xml                           |   5 +-
 phoenix-tracing-webapp/pom.xml                  |   2 +-
 pom.xml                                         |   5 +-
 76 files changed, 1448 insertions(+), 793 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/74409be8/phoenix-core/pom.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/phoenix/blob/74409be8/phoenix-core/src/it/java/org/apache/phoenix/calcite/BaseCalciteIT.java
----------------------------------------------------------------------
diff --cc phoenix-core/src/it/java/org/apache/phoenix/calcite/BaseCalciteIT.java
index 55865f0,0000000..9afddab
mode 100644,000000..100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/calcite/BaseCalciteIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/calcite/BaseCalciteIT.java
@@@ -1,440 -1,0 +1,503 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +package org.apache.phoenix.calcite;
 +
 +import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
 +import static org.junit.Assert.assertEquals;
 +import static org.junit.Assert.assertFalse;
 +import static org.junit.Assert.assertTrue;
 +import static org.junit.Assert.fail;
 +
 +import java.io.File;
 +import java.io.FileWriter;
 +import java.io.PrintWriter;
 +import java.sql.Connection;
 +import java.sql.DriverManager;
 +import java.sql.PreparedStatement;
 +import java.sql.ResultSet;
 +import java.sql.SQLException;
 +import java.sql.Statement;
 +import java.util.Arrays;
 +import java.util.List;
++import java.util.Map;
 +import java.util.Properties;
 +
 +import org.apache.calcite.avatica.util.ArrayImpl;
 +import org.apache.calcite.config.CalciteConnectionProperty;
 +import org.apache.phoenix.end2end.BaseClientManagedTimeIT;
++import org.apache.phoenix.query.QueryServices;
 +import org.apache.phoenix.schema.TableAlreadyExistsException;
 +import org.apache.phoenix.util.PhoenixRuntime;
 +import org.apache.phoenix.util.PropertiesUtil;
++import org.apache.phoenix.util.ReadOnlyProps;
++import org.junit.BeforeClass;
 +
 +import com.google.common.collect.Lists;
 +
 +public class BaseCalciteIT extends BaseClientManagedTimeIT {
 +    
++    @BeforeClass
++    public static void doSetup() throws Exception {
++        Map<String,String> props = getDefaultProps();
++        props.put(QueryServices.RUN_UPDATE_STATS_ASYNC, Boolean.FALSE.toString());
++        props.put(QueryServices.STATS_GUIDEPOST_WIDTH_BYTES_ATTRIB, Long.toString(1000));
++        setUpTestDriver(new ReadOnlyProps(props.entrySet().iterator()));
++    }
++    
 +    public static Start start(boolean materializationEnabled) {
 +        return new Start(getConnectionProps(materializationEnabled));
 +    }
 +    
 +    public static Start start(Properties props) {
 +        return new Start(props);
 +    }
 +
 +    public static class Start {
 +        protected final Properties props;
 +        private Connection connection;
 +        
 +        Start(Properties props) {
 +            this.props = props;
 +        }
 +
 +        Connection createConnection() throws Exception {
 +            return DriverManager.getConnection(
 +                    "jdbc:phoenixcalcite:" 
 +                            + getUrl().substring(PhoenixRuntime.JDBC_PROTOCOL.length() + 1), 
 +                    props);
 +        }
 +
 +        public Sql sql(String sql) {
 +            return new Sql(this, sql);
 +        }
 +
 +        public Connection getConnection() {
 +            if (connection == null) {
 +                try {
 +                    connection = createConnection();
 +                } catch (Exception e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +            return connection;
 +        }
 +
 +        public void close() {
 +            if (connection != null) {
 +                try {
 +                    connection.close();
 +                } catch (SQLException e) {
 +                    throw new RuntimeException(e);
 +                }
 +            }
 +        }
 +    }
 +
 +    /** Fluid class for a test that has specified a SQL query. */
 +    static class Sql {
 +        private final Start start;
 +        private final String sql;
 +
 +        public Sql(Start start, String sql) {
 +            this.start = start;
 +            this.sql = sql;
 +        }
 +
 +        public static List<Object[]> getResult(ResultSet resultSet) throws SQLException {
 +            final List<Object[]> list = Lists.newArrayList();
 +            populateResult(resultSet, list);
 +            return list;
 +        }
 +
 +        private static void populateResult(ResultSet resultSet, List<Object[]> list) throws SQLException {
 +            final int columnCount = resultSet.getMetaData().getColumnCount();
 +            while (resultSet.next()) {
 +                Object[] row = new Object[columnCount];
 +                for (int i = 0; i < columnCount; i++) {
 +                    row[i] = resultSet.getObject(i + 1);
 +                }
 +                list.add(row);
 +            }
 +        }
 +
 +        public Sql explainIs(String expected) throws SQLException {
 +            final List<Object[]> list = getResult("explain plan for " + sql);
 +            if (list.size() != 1) {
 +                fail("explain should return 1 row, got " + list.size());
 +            }
 +            String explain = (String) (list.get(0)[0]);
 +            assertEquals(explain, expected);
 +            return this;
 +        }
 +
 +
 +        public boolean execute() throws SQLException {
 +            final Statement statement = start.getConnection().createStatement();
 +            final boolean execute = statement.execute(sql);
 +            statement.close();
 +            return execute;
 +        }
 +
 +        public List<Object[]> getResult(String sql) throws SQLException {
 +            final Statement statement = start.getConnection().createStatement();
 +            final ResultSet resultSet = statement.executeQuery(sql);
 +            List<Object[]> list = getResult(resultSet);
 +            resultSet.close();
 +            statement.close();
 +            return list;
 +        }
 +
 +        public void close() {
 +            start.close();
 +        }
 +
-         public Sql resultIs(Object[]... expected) throws SQLException {
++        public Sql resultIs(boolean ordered, Object[][] expected) throws SQLException {
 +            final Statement statement = start.getConnection().createStatement();
 +            final ResultSet resultSet = statement.executeQuery(sql);
-             for (int i = 0; i < expected.length; i++) {
-                 assertTrue(resultSet.next());
++            if (ordered) {
++                checkResultOrdered(resultSet, expected);
++            } else {
++                checkResultUnordered(resultSet, expected);
++            }
++            resultSet.close();
++            statement.close();
++            return this;
++        }
++        
++        private void checkResultOrdered(ResultSet resultSet, Object[][] expected) throws SQLException {
++            int expectedCount = expected.length;
++            int count = 0;
++            for (int i = 0; i < expectedCount; i++) {
++                assertTrue(
++                        "Expected " + expectedCount + " rows, but got " + count + " rows.",
++                        resultSet.next());
++                count++;
 +                Object[] row = expected[i];
 +                for (int j = 0; j < row.length; j++) {
 +                    Object obj = resultSet.getObject(j + 1);
-                     if (obj instanceof ArrayImpl) {
-                         assertEquals(
-                                 Arrays.toString((Object[]) row[j]),
-                                 obj.toString());
-                     } else {
-                         assertEquals(row[j], obj);
-                     }
++                    assertEquals(canonicalize(row[j]), canonicalize(obj));
 +                }
 +            }
-             assertFalse(resultSet.next());
-             resultSet.close();
-             statement.close();
-             return this;
++            assertFalse("Got more rows than expected.", resultSet.next());            
++        }
++        
++        private void checkResultUnordered(ResultSet resultSet, Object[][] expected) throws SQLException {
++            List<List<Object>> expectedResults = Lists.newArrayList();
++            List<List<Object>> actualResults = Lists.newArrayList();
++            List<List<Object>> errorResults = Lists.newArrayList();
++            int columnCount = expected.length > 0 ? expected[0].length : 0;
++            for (Object[] e : expected) {
++                List<Object> row = Lists.newArrayList();
++                for (Object o : e) {
++                    row.add(canonicalize(o));
++                }
++                expectedResults.add(row);
++            }
++            while (resultSet.next()) {
++                List<Object> result = Lists.newArrayList();
++                for (int i = 0; i < columnCount; i++) {
++                    result.add(canonicalize(resultSet.getObject(i+1)));
++                }
++                if (!expectedResults.remove(result)) {
++                    errorResults.add(result);
++                }
++                actualResults.add(result);
++            }
++            assertTrue(
++                    (expectedResults.isEmpty() ? "" : ("Count not find " + expectedResults + " in actual results: " + actualResults + ".\n")) +
++                    (errorResults.isEmpty() ? "" : "Could not find " + errorResults + " in expected results.\n"),
++                    errorResults.isEmpty() && expectedResults.isEmpty());
++        }
++        
++        private Object canonicalize(Object obj) {
++            if (obj == null) {
++                return obj;
++            }
++            
++            if (obj instanceof ArrayImpl) {
++                return obj.toString();
++            }
++            
++            if (obj.getClass().isArray()) {
++                return Arrays.toString((Object[]) obj);
++            }
++            
++            return obj;
 +        }
 +    }
 +
 +    private static final String FOODMART_SCHEMA = "     {\n"
 +            + "       type: 'jdbc',\n"
 +            + "       name: 'foodmart',\n"
 +            + "       jdbcDriver: 'org.hsqldb.jdbcDriver',\n"
 +            + "       jdbcUser: 'FOODMART',\n"
 +            + "       jdbcPassword: 'FOODMART',\n"
 +            + "       jdbcUrl: 'jdbc:hsqldb:res:foodmart',\n"
 +            + "       jdbcCatalog: null,\n"
 +            + "       jdbcSchema: 'foodmart'\n"
 +            + "     }";
 +    
 +    private static final String getPhoenixSchema() {
 +        return "    {\n"
 +            + "      name: 'phoenix',\n"
 +            + "      type: 'custom',\n"
 +            + "      factory: 'org.apache.phoenix.calcite.PhoenixSchema$Factory',\n"
 +            + "      operand: {\n"
 +            + "        url: \"" + getUrl() + "\"\n"
 +            + "      }\n"
 +            + "    }";
 +    }
 +
 +    protected static Connection connectUsingModel(Properties props) throws Exception {
 +        final File file = File.createTempFile("model", ".json");
 +        final String url = getUrl();
 +        final PrintWriter pw = new PrintWriter(new FileWriter(file));
 +        pw.print(
 +            "{\n"
 +                + "  version: '1.0',\n"
 +                + "  defaultSchema: 'HR',\n"
 +                + "  schemas: [\n"
 +                + "    {\n"
 +                + "      name: 'HR',\n"
 +                + "      type: 'custom',\n"
 +                + "      factory: 'org.apache.phoenix.calcite.PhoenixSchema$Factory',\n"
 +                + "      operand: {\n"
 +                + "        url: \"" + url + "\",\n"
 +                + "        user: \"scott\",\n"
 +                + "        password: \"tiger\"\n"
 +                + "      }\n"
 +                + "    }\n"
 +                + "  ]\n"
 +                + "}\n");
 +        pw.close();
 +        final Connection connection =
 +            DriverManager.getConnection("jdbc:phoenixcalcite:model=" + file.getAbsolutePath(), props);
 +        return connection;
 +    }
 +
 +    protected static Connection connectWithHsqldbUsingModel(Properties props) throws Exception {
 +        final File file = File.createTempFile("model", ".json");
 +        final PrintWriter pw = new PrintWriter(new FileWriter(file));
 +        pw.print(
 +            "{\n"
 +                + "  version: '1.0',\n"
 +                + "  defaultSchema: 'phoenix',\n"
 +                + "  schemas: [\n"
 +                + getPhoenixSchema() + ",\n"
 +                + FOODMART_SCHEMA + "\n"
 +                + "  ]\n"
 +                + "}\n");
 +        pw.close();
 +        final Connection connection =
 +            DriverManager.getConnection("jdbc:phoenixcalcite:model=" + file.getAbsolutePath(), props);
 +        return connection;
 +    }
 +
 +    protected static Properties getConnectionProps(boolean enableMaterialization) {
 +        Properties props = new Properties();
 +        props.setProperty(
 +                CalciteConnectionProperty.MATERIALIZATIONS_ENABLED.camelName(),
 +                Boolean.toString(enableMaterialization));
 +        props.setProperty(
 +                CalciteConnectionProperty.CREATE_MATERIALIZATIONS.camelName(),
 +                Boolean.toString(false));
 +        return props;
 +    }
 +    
 +    protected static final String SCORES_TABLE_NAME = "scores";
 +    
 +    protected void initArrayTable() throws Exception {
 +        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
 +        Connection conn = DriverManager.getConnection(getUrl(), props);
 +        try {
 +            conn.createStatement().execute(
 +                    "CREATE TABLE " + SCORES_TABLE_NAME
 +                    + "(student_id INTEGER NOT NULL, subject_id INTEGER NOT NULL, scores INTEGER[] CONSTRAINT pk PRIMARY KEY (student_id, subject_id))");
 +            PreparedStatement stmt = conn.prepareStatement(
 +                    "UPSERT INTO " + SCORES_TABLE_NAME
 +                    + " VALUES(?, ?, ?)");
 +            stmt.setInt(1, 1);
 +            stmt.setInt(2, 1);
 +            stmt.setArray(3, conn.createArrayOf("INTEGER", new Integer[] {85, 80, 82}));
 +            stmt.execute();
 +            stmt.setInt(1, 2);
 +            stmt.setInt(2, 1);
 +            stmt.setArray(3, null);
 +            stmt.execute();
 +            stmt.setInt(1, 3);
 +            stmt.setInt(2, 2);
 +            stmt.setArray(3, conn.createArrayOf("INTEGER", new Integer[] {87, 88, 80}));
 +            stmt.execute();
 +            conn.commit();
 +        } catch (TableAlreadyExistsException e) {
 +        }
 +        conn.close();        
 +    }
 +    
 +    protected static final String NOSALT_TABLE_NAME = "nosalt_test_table";
 +    protected static final String NOSALT_TABLE_SALTED_INDEX_NAME = "idxsalted_nosalt_test_table";
 +    protected static final String SALTED_TABLE_NAME = "salted_test_table";
 +    protected static final String SALTED_TABLE_NOSALT_INDEX_NAME = "idx_salted_test_table";
 +    protected static final String SALTED_TABLE_SALTED_INDEX_NAME = "idxsalted_salted_test_table";
 +    
 +    protected void initSaltedTables(String index) throws SQLException {
 +        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
 +        Connection conn = DriverManager.getConnection(getUrl(), props);
 +        try {
 +            conn.createStatement().execute(
 +                    "CREATE TABLE " + NOSALT_TABLE_NAME + " (mypk0 INTEGER NOT NULL, mypk1 INTEGER NOT NULL, col0 INTEGER, col1 INTEGER CONSTRAINT pk PRIMARY KEY (mypk0, mypk1))");
 +            PreparedStatement stmt = conn.prepareStatement(
 +                    "UPSERT INTO " + NOSALT_TABLE_NAME
 +                    + " VALUES(?, ?, ?, ?)");
 +            stmt.setInt(1, 1);
 +            stmt.setInt(2, 2);
 +            stmt.setInt(3, 3);
 +            stmt.setInt(4, 4);
 +            stmt.execute();
 +            stmt.setInt(1, 2);
 +            stmt.setInt(2, 3);
 +            stmt.setInt(3, 4);
 +            stmt.setInt(4, 5);
 +            stmt.execute();
 +            stmt.setInt(1, 3);
 +            stmt.setInt(2, 4);
 +            stmt.setInt(3, 5);
 +            stmt.setInt(4, 6);
 +            stmt.execute();
 +            conn.commit();
 +            
 +            if (index != null) {
 +                conn.createStatement().execute("CREATE " + index + " " + NOSALT_TABLE_SALTED_INDEX_NAME + " ON " + NOSALT_TABLE_NAME + " (col0) SALT_BUCKETS=4");
 +                conn.commit();
 +            }
 +            
 +            conn.createStatement().execute(
 +                    "CREATE TABLE " + SALTED_TABLE_NAME + " (mypk0 INTEGER NOT NULL, mypk1 INTEGER NOT NULL, col0 INTEGER, col1 INTEGER CONSTRAINT pk PRIMARY KEY (mypk0, mypk1)) SALT_BUCKETS=4");
 +            stmt = conn.prepareStatement(
 +                    "UPSERT INTO " + SALTED_TABLE_NAME
 +                    + " VALUES(?, ?, ?, ?)");
 +            stmt.setInt(1, 1);
 +            stmt.setInt(2, 2);
 +            stmt.setInt(3, 3);
 +            stmt.setInt(4, 4);
 +            stmt.execute();
 +            stmt.setInt(1, 2);
 +            stmt.setInt(2, 3);
 +            stmt.setInt(3, 4);
 +            stmt.setInt(4, 5);
 +            stmt.execute();
 +            stmt.setInt(1, 3);
 +            stmt.setInt(2, 4);
 +            stmt.setInt(3, 5);
 +            stmt.setInt(4, 6);
 +            stmt.execute();
 +            conn.commit();
 +            
 +            if (index != null) {
 +                conn.createStatement().execute("CREATE " + index + " " + SALTED_TABLE_NOSALT_INDEX_NAME + " ON " + SALTED_TABLE_NAME + " (col0)");
 +                conn.createStatement().execute("CREATE " + index + " " + SALTED_TABLE_SALTED_INDEX_NAME + " ON " + SALTED_TABLE_NAME + " (col1) INCLUDE (col0) SALT_BUCKETS=4");
 +                conn.commit();
 +            }
 +        } catch (TableAlreadyExistsException e) {
 +        }
 +        conn.close();        
 +    }
 +    
 +    protected static final String MULTI_TENANT_TABLE = "multitenant_test_table";
 +    protected static final String MULTI_TENANT_TABLE_INDEX = "idx_multitenant_test_table";
 +    protected static final String MULTI_TENANT_VIEW1 = "s1.multitenant_test_view1";
 +    protected static final String MULTI_TENANT_VIEW1_INDEX = "idx_multitenant_test_view1";
 +    protected static final String MULTI_TENANT_VIEW2 = "s2.multitenant_test_view2";
 +    protected static final String MULTI_TENANT_VIEW2_INDEX = "idx_multitenant_test_view2";
 +    
 +    protected void initMultiTenantTables(String index) throws SQLException {
 +        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
 +        Connection conn = DriverManager.getConnection(getUrl(), props);
 +        try {
 +            conn.createStatement().execute(
 +                    "CREATE TABLE " + MULTI_TENANT_TABLE + " (tenant_id VARCHAR NOT NULL, id VARCHAR NOT NULL, col0 INTEGER, col1 INTEGER, col2 INTEGER CONSTRAINT pk PRIMARY KEY (tenant_id, id)) MULTI_TENANT=true");
 +            PreparedStatement stmt = conn.prepareStatement(
 +                    "UPSERT INTO " + MULTI_TENANT_TABLE
 +                    + " VALUES(?, ?, ?, ?, ?)");
 +            stmt.setString(1, "10");
 +            stmt.setString(2, "2");
 +            stmt.setInt(3, 3);
 +            stmt.setInt(4, 4);
 +            stmt.setInt(5, 5);
 +            stmt.execute();
 +            stmt.setString(1, "15");
 +            stmt.setString(2, "3");
 +            stmt.setInt(3, 4);
 +            stmt.setInt(4, 5);
 +            stmt.setInt(5, 6);
 +            stmt.execute();
 +            stmt.setString(1, "20");
 +            stmt.setString(2, "4");
 +            stmt.setInt(3, 5);
 +            stmt.setInt(4, 6);
 +            stmt.setInt(5, 7);
 +            stmt.execute();
 +            stmt.setString(1, "20");
 +            stmt.setString(2, "5");
 +            stmt.setInt(3, 6);
 +            stmt.setInt(4, 7);
 +            stmt.setInt(5, 8);
 +            stmt.execute();
 +            conn.commit();
 +            
 +            if (index != null) {
 +                conn.createStatement().execute(
 +                        "CREATE " + index + " " + MULTI_TENANT_TABLE_INDEX
 +                        + " ON " + MULTI_TENANT_TABLE + "(col1) INCLUDE (col0, col2)");
 +                conn.commit();
 +            }
 +            
 +            conn.close();
 +            props.setProperty("TenantId", "10");
 +            conn = DriverManager.getConnection(getUrl(), props);
 +            conn.createStatement().execute("CREATE VIEW " + MULTI_TENANT_VIEW1
 +                    + " AS select * from " + MULTI_TENANT_TABLE);
 +            conn.commit();
 +            
 +            if (index != null) {
 +                conn.createStatement().execute(
 +                        "CREATE " + index + " " + MULTI_TENANT_VIEW1_INDEX
 +                        + " ON " + MULTI_TENANT_VIEW1 + "(col0)");
 +                conn.commit();
 +            }
 +            
 +            conn.close();
 +            props.setProperty("TenantId", "20");
 +            conn = DriverManager.getConnection(getUrl(), props);
 +            conn.createStatement().execute("CREATE VIEW " + MULTI_TENANT_VIEW2
 +                    + " AS select * from " + MULTI_TENANT_TABLE + " where col2 > 7");
 +            conn.commit();
 +            
 +            if (index != null) {
 +                conn.createStatement().execute(
 +                        "CREATE " + index + " " + MULTI_TENANT_VIEW2_INDEX
 +                        + " ON " + MULTI_TENANT_VIEW2 + "(col0)");
 +                conn.commit();
 +            }
 +        } catch (TableAlreadyExistsException e) {
 +        } finally {
 +            conn.close();
 +        }
 +    }
 +
 +}