org.apache.phoenix.util.PhoenixRuntimeTest.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.phoenix.util.PhoenixRuntimeTest.java

Source

/*
 * 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.util;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.expression.Expression;
import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
import org.apache.phoenix.query.BaseConnectionlessQueryTest;
import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.schema.TableNotFoundException;
import org.apache.phoenix.schema.types.PDataType;
import org.junit.Test;

import com.google.common.collect.ImmutableList;

public class PhoenixRuntimeTest extends BaseConnectionlessQueryTest {
    @Test
    public void testParseArguments_MinimalCase() {
        PhoenixRuntime.ExecutionCommand execCmd = PhoenixRuntime.ExecutionCommand
                .parseArgs(new String[] { "localhost", "test.csv" });

        assertEquals("localhost", execCmd.getConnectionString());

        assertEquals(ImmutableList.of("test.csv"), execCmd.getInputFiles());

        assertEquals(',', execCmd.getFieldDelimiter());
        assertEquals('"', execCmd.getQuoteCharacter());
        assertNull(execCmd.getEscapeCharacter());

        assertNull(execCmd.getTableName());

        assertNull(execCmd.getColumns());

        assertFalse(execCmd.isStrict());

        assertEquals(CSVCommonsLoader.DEFAULT_ARRAY_ELEMENT_SEPARATOR, execCmd.getArrayElementSeparator());
    }

    @Test
    public void testParseArguments_FullOption() {
        PhoenixRuntime.ExecutionCommand execCmd = PhoenixRuntime.ExecutionCommand
                .parseArgs(new String[] { "-t", "mytable", "myzkhost:2181", "--strict", "file1.sql", "test.csv",
                        "file2.sql", "--header", "one, two,three", "-a", "!", "-d", ":", "-q", "3", "-e", "4" });

        assertEquals("myzkhost:2181", execCmd.getConnectionString());

        assertEquals(ImmutableList.of("file1.sql", "test.csv", "file2.sql"), execCmd.getInputFiles());

        assertEquals(':', execCmd.getFieldDelimiter());
        assertEquals('3', execCmd.getQuoteCharacter());
        assertEquals(Character.valueOf('4'), execCmd.getEscapeCharacter());

        assertEquals("mytable", execCmd.getTableName());

        assertEquals(ImmutableList.of("one", "two", "three"), execCmd.getColumns());
        assertTrue(execCmd.isStrict());
        assertEquals("!", execCmd.getArrayElementSeparator());
    }

    @Test
    public void testGetPkColsDataTypes() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl(), new Properties());
        int i = 0;
        PDataType[] pTypes = PDataType.values();
        int size = pTypes.length;
        StringBuilder sb = null;
        try {
            for (i = 0; i < size; i++) {
                PDataType pType = pTypes[i];
                String sqlTypeName = pType.getSqlTypeName();
                if (sqlTypeName.equalsIgnoreCase("VARBINARY ARRAY")) {
                    // we don't support VARBINARY ARRAYS yet
                    // JIRA - https://issues.apache.org/jira/browse/PHOENIX-1329
                    continue;
                }
                if (pType.isArrayType() && PDataType.arrayBaseType(pType).isFixedWidth()
                        && PDataType.arrayBaseType(pType).getByteSize() == null) {
                    // Need to treat array type whose base type is of fixed width whose byte size is not known as a special case. 
                    // Cannot just use the sql type name returned by PDataType.getSqlTypeName().
                    String baseTypeName = PDataType.arrayBaseType(pType).getSqlTypeName();
                    sqlTypeName = baseTypeName + "(15)" + " " + PDataType.ARRAY_TYPE_SUFFIX;
                } else if (pType.isFixedWidth() && pType.getByteSize() == null) {
                    sqlTypeName = sqlTypeName + "(15)";
                }
                String columnName = "col" + i;
                String tableName = "t" + i;

                sb = new StringBuilder(100);

                // create a table by using the type name as returned by PDataType
                sb.append("CREATE TABLE " + tableName + " (");
                sb.append(columnName + " " + sqlTypeName + " NOT NULL PRIMARY KEY, V1 VARCHAR)");
                conn.createStatement().execute(sb.toString());

                // generate the optimized query plan by going through the pk of the table.
                PreparedStatement stmt = conn
                        .prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnName + " = ?");
                Integer maxLength = pType.isFixedWidth() && pType.getByteSize() == null ? 15 : null;
                stmt.setObject(1, pType.getSampleValue(maxLength));
                QueryPlan plan = PhoenixRuntime.getOptimizedQueryPlan(stmt);

                // now go through the utility method, get column name and type name and
                // try creating another table with the returned info. Use the query plan generated above.
                // If table can be created with the returned sql type name, then great!
                // It would mean "Roundtrip" of column data type name works.
                List<Pair<String, String>> pkCols = new ArrayList<Pair<String, String>>();
                List<String> dataTypes = new ArrayList<String>();
                PhoenixRuntime.getPkColsDataTypesForSql(pkCols, dataTypes, plan, conn, true);

                tableName = "newt" + i;
                columnName = "newCol" + i;
                String roundTripSqlTypeName = dataTypes.get(0);

                // create a table by using the type name as returned by the utility method
                sb = new StringBuilder(100);
                sb.append("CREATE TABLE " + tableName + " (");
                sb.append(columnName + " " + roundTripSqlTypeName + " NOT NULL PRIMARY KEY)");
                conn.createStatement().execute(sb.toString());
            }
        } catch (Exception e) {
            fail("Failed sql: " + sb.toString() + ExceptionUtils.getStackTrace(e));
        }
    }

    @Test
    public void testGetTenantIdExpression() throws Exception {
        Connection conn = DriverManager.getConnection(getUrl());
        Expression e1 = PhoenixRuntime.getTenantIdExpression(conn, PhoenixDatabaseMetaData.SYSTEM_STATS_NAME);
        assertNull(e1);
        Expression e2 = PhoenixRuntime.getTenantIdExpression(conn, PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME);
        assertNotNull(e2);

        Expression e3 = PhoenixRuntime.getTenantIdExpression(conn, PhoenixDatabaseMetaData.SEQUENCE_FULLNAME);
        assertNotNull(e3);

        conn.createStatement().execute("CREATE TABLE FOO (k VARCHAR PRIMARY KEY)");
        Expression e4 = PhoenixRuntime.getTenantIdExpression(conn, "FOO");
        assertNull(e4);

        conn.createStatement().execute(
                "CREATE TABLE A.BAR (k1 VARCHAR NOT NULL, k2 VARCHAR, CONSTRAINT PK PRIMARY KEY(K1,K2)) MULTI_TENANT=true");
        Expression e5 = PhoenixRuntime.getTenantIdExpression(conn, "A.BAR");
        assertNotNull(e5);

        conn.createStatement().execute("CREATE INDEX I1 ON A.BAR (K2)");
        Expression e5A = PhoenixRuntime.getTenantIdExpression(conn, "A.I1");
        assertNotNull(e5A);

        conn.createStatement().execute(
                "CREATE TABLE BAS (k1 VARCHAR NOT NULL, k2 VARCHAR, CONSTRAINT PK PRIMARY KEY(K1,K2)) MULTI_TENANT=true, SALT_BUCKETS=3");
        Expression e6 = PhoenixRuntime.getTenantIdExpression(conn, "BAS");
        assertNotNull(e6);

        conn.createStatement().execute("CREATE INDEX I2 ON BAS (K2)");
        Expression e6A = PhoenixRuntime.getTenantIdExpression(conn, "I2");
        assertNotNull(e6A);

        try {
            PhoenixRuntime.getTenantIdExpression(conn, "NOT.ATABLE");
            fail();
        } catch (TableNotFoundException e) {
            // Expected
        }

        Properties props = PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES);
        props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, "t1");
        Connection tsconn = DriverManager.getConnection(getUrl(), props);
        tsconn.createStatement().execute("CREATE VIEW V(V1 VARCHAR) AS SELECT * FROM BAS");
        Expression e7 = PhoenixRuntime.getTenantIdExpression(tsconn, "V");
        assertNotNull(e7);
        tsconn.createStatement().execute("CREATE LOCAL INDEX I3 ON V (V1)");
        try {
            PhoenixRuntime.getTenantIdExpression(tsconn, "I3");
            fail();
        } catch (SQLFeatureNotSupportedException e) {
            // Expected
        }
    }

    @Test
    public void testTableNameWithoutSchema() throws Exception {
        String tableName = "tableName";
        String tableNameNormalized = tableName.toUpperCase();

        getTableTester(tableNameNormalized, tableName);
    }

    @Test
    public void testTableNameWithSchema() throws Exception {
        String tableName = "tableName";
        String schemaName = "schemaName";
        String fullName = schemaName + "." + tableName;
        String fullNameNormalized = fullName.toUpperCase();

        getTableTester(fullNameNormalized, fullName);
    }

    @Test
    public void testCaseSensitiveTableNameWithoutSchema() throws Exception {
        String caseSensitiveTableName = "tableName";

        getTableTester(caseSensitiveTableName, quoteString(caseSensitiveTableName));
    }

    @Test
    public void testCaseSensitiveTableNameWithSchema() throws Exception {
        String caseSensitiveTableName = "tableName";
        String schemaName = "schemaName";
        String fullNameNormalized = schemaName.toUpperCase() + "." + caseSensitiveTableName;
        String fullNameQuoted = schemaName + "." + quoteString(caseSensitiveTableName);

        getTableTester(fullNameNormalized, fullNameQuoted);
    }

    @Test
    public void testCaseSensitiveTableNameWithCaseSensitiveSchema() throws Exception {
        String caseSensitiveTableName = "tableName";
        String caseSensitiveSchemaName = "schemaName";
        String fullName = caseSensitiveSchemaName + "." + caseSensitiveTableName;
        String fullNameQuoted = quoteString(caseSensitiveSchemaName) + "." + quoteString(caseSensitiveTableName);

        getTableTester(fullName, fullNameQuoted);
    }

    @Test
    public void testCaseSensitiveTableNameWithCaseSensitiveSchemaWithPeriod() throws Exception {
        String caseSensitiveTableName = "tableName";
        String caseSensitiveSchemaName = "schema.Name";
        String fullName = caseSensitiveSchemaName + "." + caseSensitiveTableName;
        String fullNameQuoted = quoteString(caseSensitiveSchemaName) + "." + quoteString(caseSensitiveTableName);

        getTableTester(fullName, fullNameQuoted);
    }

    private void getTableTester(String normalizedName, String sqlStatementName) throws SQLException {
        Connection conn = DriverManager.getConnection(getUrl());
        try {
            conn.createStatement().execute("CREATE TABLE " + sqlStatementName + " (k VARCHAR PRIMARY KEY)");
            PTable aTable = PhoenixRuntime.getTable(conn, normalizedName);
            assertNotNull(aTable);
        } finally {
            if (null != conn) {
                conn.createStatement().execute("DROP TABLE IF EXISTS " + sqlStatementName);
            }
        }
    }

    private String quoteString(String string) {
        return "\"" + string + "\"";
    }

}