blob: 2dbbabe76b69cb4370dc282e0d457f1a1bc8670c [file] [log] [blame]
/*
* 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.end2end.index;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.compile.QueryPlan;
import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
import org.apache.phoenix.end2end.ParallelStatsDisabledTest;
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.jdbc.PhoenixStatement;
import org.apache.phoenix.query.QueryServices;
import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.QueryUtil;
import org.apache.phoenix.util.SchemaUtil;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Properties;
import java.util.TimeZone;
import static org.apache.phoenix.schema.PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN;
import static org.apache.phoenix.schema.PTable.ImmutableStorageScheme.SINGLE_CELL_ARRAY_WITH_OFFSETS;
import static org.apache.phoenix.schema.PTable.QualifierEncodingScheme.NON_ENCODED_QUALIFIERS;
import static org.apache.phoenix.schema.PTable.QualifierEncodingScheme.TWO_BYTE_QUALIFIERS;
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;
@Category(ParallelStatsDisabledTest.class)
@RunWith(Parameterized.class)
public class SingleCellIndexIT extends ParallelStatsDisabledIT {
private static final Logger LOGGER = LoggerFactory.getLogger(SingleCellIndexIT.class);
private Properties testProps = PropertiesUtil.deepCopy(TEST_PROPERTIES);
private boolean mutable;
private final String tableDDLOptions;
@Parameterized.Parameters(name = "mutable={0}")
public static synchronized Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{true},
{false} });
}
@Before
public void setupBefore() {
testProps = PropertiesUtil.deepCopy(TEST_PROPERTIES);
testProps.put(QueryServices.DEFAULT_COLUMN_ENCODED_BYTES_ATRRIB, "0");
}
public SingleCellIndexIT(boolean mutable) {
StringBuilder optionBuilder = new StringBuilder();
this.mutable = mutable;
optionBuilder.append(" IMMUTABLE_STORAGE_SCHEME=ONE_CELL_PER_COLUMN ");
if (!mutable) {
optionBuilder.append(", IMMUTABLE_ROWS=true ");
}
this.tableDDLOptions = optionBuilder.toString();
}
@Test
public void testCreateOneCellTableAndSingleCellIndex() throws Exception {
try (Connection conn = DriverManager.getConnection(getUrl(), testProps)) {
conn.setAutoCommit(true);
String tableName = "TBL_" + generateUniqueName();
String idxName = "IND_" + generateUniqueName();
createTableAndIndex(conn, tableName, idxName, this.tableDDLOptions, false,3);
assertMetadata(conn, ONE_CELL_PER_COLUMN, NON_ENCODED_QUALIFIERS, tableName);
assertMetadata(conn, SINGLE_CELL_ARRAY_WITH_OFFSETS, TWO_BYTE_QUALIFIERS, idxName);
dumpTable(tableName);
String selectFromData = "SELECT /*+ NO_INDEX */ PK1, INT_PK, V1, V2, V4 FROM " + tableName + " where V2 >= 3 and V4 LIKE 'V4%'";
ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + selectFromData);
String actualExplainPlan = QueryUtil.getExplainPlan(rs);
assertTrue(actualExplainPlan.contains(tableName));
rs = conn.createStatement().executeQuery(selectFromData);
assertTrue(rs.next());
assertEquals("PK2", rs.getString(1));
assertEquals(2, rs.getInt(2));
assertEquals("V12", rs.getString(3));
assertEquals(3, rs.getInt(4));
assertEquals("V42", rs.getString(5));
assertTrue(rs.next());
String selectFromIndex = "SELECT PK1, INT_PK, V1, V2, V4 FROM " + tableName + " where V2 >= 3 and V4 LIKE 'V4%'";
rs = conn.createStatement().executeQuery("EXPLAIN " + selectFromIndex);
actualExplainPlan = QueryUtil.getExplainPlan(rs);
assertTrue(actualExplainPlan.contains(idxName));
rs = conn.createStatement().executeQuery(selectFromIndex);
assertTrue(rs.next());
assertEquals("PK2", rs.getString(1));
assertEquals(2, rs.getInt(2));
assertEquals("V12", rs.getString(3));
assertEquals(3, rs.getInt(4));
assertEquals("V42", rs.getString(5));
assertTrue(rs.next());
assertEquals("PK3", rs.getString(1));
assertEquals(3, rs.getInt(2));
assertEquals("V13", rs.getString(3));
assertEquals(4, rs.getInt(4));
assertEquals("V43", rs.getString(5));
assertFalse(rs.next());
}
}
@Test
public void testAddColumns() throws Exception {
try (Connection conn = DriverManager.getConnection(getUrl(), testProps)) {
conn.setAutoCommit(true);
String tableName = "TBL_" + generateUniqueName();
String idxName = "IND_" + generateUniqueName();
createTableAndIndex(conn, tableName, idxName, null, false,3);
assertMetadata(conn, ONE_CELL_PER_COLUMN, NON_ENCODED_QUALIFIERS, tableName);
assertMetadata(conn, SINGLE_CELL_ARRAY_WITH_OFFSETS, TWO_BYTE_QUALIFIERS, idxName);
String alterTable = "ALTER TABLE " + tableName + " ADD V_NEW VARCHAR CASCADE INDEX ALL";
conn.createStatement().execute(alterTable);
String upsert = "UPSERT INTO " + tableName + " (PK1,INT_PK,V1, V2, V3, V4, V5, V_NEW) VALUES ('PK99',99,'V199',100,101,'V499','V699','V_NEW99')";
conn.createStatement().executeUpdate(upsert);
conn.commit();
String selectFromIndex = "SELECT PK1, INT_PK, V1, V2, V4, V_NEW FROM " + tableName + " where V1='V199' AND V2=100";
ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + selectFromIndex);
String actualExplainPlan = QueryUtil.getExplainPlan(rs);
assertTrue(actualExplainPlan.contains(idxName));
rs = conn.createStatement().executeQuery(selectFromIndex);
assertTrue(rs.next());
assertEquals("PK99", rs.getString(1));
assertEquals(99, rs.getInt(2));
assertEquals("V199", rs.getString(3));
assertEquals(100, rs.getInt(4));
assertEquals("V499", rs.getString(5));
assertEquals("V_NEW99", rs.getString(6));
assertFalse(rs.next());
}
}
@Test
public void testDropColumns() throws Exception {
try (Connection conn = DriverManager.getConnection(getUrl(), testProps)) {
conn.setAutoCommit(true);
String tableName = "TBL_" + generateUniqueName();
String idxName = "IND_" + generateUniqueName();
createTableAndIndex(conn, tableName, idxName, null, false,1);
assertMetadata(conn, ONE_CELL_PER_COLUMN, NON_ENCODED_QUALIFIERS, tableName);
assertMetadata(conn, SINGLE_CELL_ARRAY_WITH_OFFSETS, TWO_BYTE_QUALIFIERS, idxName);
String alterTable = "ALTER TABLE " + tableName + " DROP COLUMN V2";
conn.createStatement().execute(alterTable);
String star = "SELECT * FROM " + idxName ;
ResultSet rs = conn.createStatement().executeQuery(star);
assertTrue(rs.next());
assertEquals("PK1", rs.getString(1));
assertEquals(1, rs.getInt(2));
assertEquals("V11", rs.getString(3));
assertEquals("V41", rs.getString(4));
assertFalse(rs.next());
String selectFromIndex = "SELECT PK1, INT_PK, V1, V4 FROM " + tableName + " where V1='V11'";
rs = conn.createStatement().executeQuery("EXPLAIN " + selectFromIndex);
String actualExplainPlan = QueryUtil.getExplainPlan(rs);
assertTrue(actualExplainPlan.contains(idxName));
rs = conn.createStatement().executeQuery(selectFromIndex);
assertTrue(rs.next());
assertEquals("PK1", rs.getString(1));
assertEquals(1, rs.getInt(2));
assertEquals("V11", rs.getString(3));
assertEquals("V41", rs.getString(4));
assertFalse(rs.next());
}
}
@Test
public void testTenantViewIndexes() throws Exception {
try (Connection conn = DriverManager.getConnection(getUrl(), testProps)) {
conn.setAutoCommit(true);
String tableName = "TBL_" + generateUniqueName();
String view1IndexName = "IND_" + generateUniqueName();
String divergedViewIndex = "DIND_" + generateUniqueName();
String view3IndexName = "IND_" + generateUniqueName();
String view1 = "V_" + generateUniqueName();
String divergedView = "V_" + generateUniqueName();
String view3 = "V_" + generateUniqueName();
String baseTableDDL = "CREATE TABLE " + tableName + " (TENANT_ID VARCHAR NOT NULL, PK1 VARCHAR NOT NULL, V1 VARCHAR, V2 VARCHAR, V3 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(TENANT_ID, PK1)) MULTI_TENANT = true"
+ (this.mutable ? "": ", IMMUTABLE_ROWS=true");
conn.createStatement().execute(baseTableDDL);
assertMetadata(conn, ONE_CELL_PER_COLUMN, NON_ENCODED_QUALIFIERS, tableName);
try (Connection tenant1Conn = getTenantConnection("tenant1")) {
String
view1DDL =
"CREATE VIEW " + view1 + " ( VIEW_COL1 VARCHAR, VIEW_COL2 VARCHAR) AS SELECT * FROM "
+ tableName;
tenant1Conn.createStatement().execute(view1DDL);
String indexDDL = "CREATE INDEX " + view1IndexName + " ON " + view1 + " (V1) include (VIEW_COL2, V3) IMMUTABLE_STORAGE_SCHEME=SINGLE_CELL_ARRAY_WITH_OFFSETS,COLUMN_ENCODED_BYTES=2";
tenant1Conn.createStatement().execute(indexDDL);
tenant1Conn.commit();
}
try (Connection tenant2Conn = getTenantConnection("tenant2")) {
String
divergedViewDDL =
"CREATE VIEW " + divergedView + " ( VIEW_COL1 VARCHAR, VIEW_COL2 VARCHAR) AS SELECT * FROM "
+ tableName ;
tenant2Conn.createStatement().execute(divergedViewDDL);
// Drop column V2 from the view to have it diverge from the base table
tenant2Conn.createStatement().execute("ALTER VIEW " + divergedView + " DROP COLUMN V2");
// create an index on the diverged view
String indexDDL = "CREATE INDEX " + divergedViewIndex + " ON " + divergedView + " (V1) include (VIEW_COL1, V3) IMMUTABLE_STORAGE_SCHEME=SINGLE_CELL_ARRAY_WITH_OFFSETS";
tenant2Conn.createStatement().execute(indexDDL);
tenant2Conn.commit();
}
try (Connection tenant3Conn = getTenantConnection("tenant3")) {
String
view3DDL =
"CREATE VIEW " + view3 + " ( VIEW_COL31 VARCHAR, VIEW_COL32 VARCHAR) AS SELECT * FROM "
+ tableName;
tenant3Conn.createStatement().execute(view3DDL);
String indexDDL = "CREATE INDEX " + view3IndexName + " ON " + view3 + " (V1) include (VIEW_COL32, V3)";
tenant3Conn.createStatement().execute(indexDDL);
tenant3Conn.commit();
}
String upsert = "UPSERT INTO " + view1 + " (PK1, V1, V2, V3, VIEW_COL1, VIEW_COL2) VALUES ('PK1', 'V1', 'V2', 'V3','VIEW_COL1_1','VIEW_COL2_1')";
try (Connection viewConn = getTenantConnection("tenant1")) {
viewConn.createStatement().executeUpdate(upsert);
viewConn.commit();
Statement stmt = viewConn.createStatement();
String sql = "SELECT V3, VIEW_COL2 FROM " + view1 + " WHERE V1 = 'V1'";
QueryPlan plan = stmt.unwrap(PhoenixStatement.class).optimizeQuery(sql);
assertTrue(plan.getTableRef().getTable().getName().getString().equals(SchemaUtil.normalizeIdentifier(view1IndexName)));
ResultSet rs = viewConn.createStatement().executeQuery(sql);
assertTrue(rs.next());
assertEquals("V3", rs.getString(1));
assertEquals("VIEW_COL2_1", rs.getString(2));
}
// Upsert records in diverged view. Verify that the PK column was added to the index on it.
upsert = "UPSERT INTO " + divergedView + " (PK1, V1, V3, VIEW_COL1, VIEW_COL2) VALUES ('PK1', 'V1', 'V3','VIEW_COL21_1','VIEW_COL22_1')";
try (Connection viewConn = getTenantConnection("tenant2")) {
viewConn.createStatement().executeUpdate(upsert);
viewConn.commit();
Statement stmt = viewConn.createStatement();
String sql = "SELECT V3, VIEW_COL1 FROM " + divergedView + " WHERE V1 = 'V1'";
QueryPlan plan = stmt.unwrap(PhoenixStatement.class).optimizeQuery(sql);
assertTrue(plan.getTableRef().getTable().getName().getString().equals(SchemaUtil.normalizeIdentifier(divergedViewIndex)));
ResultSet rs = viewConn.createStatement().executeQuery(sql);
assertTrue(rs.next());
assertEquals("V3", rs.getString(1));
assertEquals("VIEW_COL21_1", rs.getString(2));
}
upsert = "UPSERT INTO " + view3 + " (PK1, V1, V2, V3, VIEW_COL31, VIEW_COL32) VALUES ('PK1', 'V1', 'V2', 'V3','VIEW_COL31_1','VIEW_COL32_1')";
try (Connection viewConn = getTenantConnection("tenant3")) {
viewConn.createStatement().executeUpdate(upsert);
viewConn.commit();
Statement stmt = viewConn.createStatement();
String sql = "SELECT V3, VIEW_COL32 FROM " + view3 + " WHERE V1 = 'V1'";
QueryPlan plan = stmt.unwrap(PhoenixStatement.class).optimizeQuery(sql);
assertTrue(plan.getTableRef().getTable().getName().getString().equals(SchemaUtil.normalizeIdentifier(view3IndexName)));
ResultSet rs = viewConn.createStatement().executeQuery(sql);
assertTrue(rs.next());
assertEquals("V3", rs.getString(1));
assertEquals("VIEW_COL32_1", rs.getString(2));
}
dumpTable("_IDX_" + tableName);
}
}
@Test
public void testUpsertSelect() throws Exception {
String tableName = generateUniqueName();
String idxName = "IDX_" + generateUniqueName();
try (Connection conn = DriverManager.getConnection(getUrl(), testProps)) {
conn.setAutoCommit(true);
createTableAndIndex(conn, tableName, idxName, null, true, 2);
assertMetadata(conn, ONE_CELL_PER_COLUMN, NON_ENCODED_QUALIFIERS, tableName);
assertMetadata(conn, SINGLE_CELL_ARRAY_WITH_OFFSETS, TWO_BYTE_QUALIFIERS, idxName);
// this delete will be issued at a timestamp later than the above timestamp of the index table
conn.createStatement().execute("delete from " + tableName + " where pk1 = 'PK1'");
conn.commit();
String
sql =
"UPSERT INTO " + idxName + "(\":PK1\",\":INT_PK\",\"0:V1\",\"0:V2\",\"0:V4\") "
+ " SELECT /*+ NO_INDEX */ PK1,INT_PK, V1, V2,V4 FROM "
+ tableName;
conn.createStatement().executeUpdate(sql);
conn.commit();
// validate that delete markers were issued correctly and only ('a', '1', 'value1') was
// deleted
String query = "SELECT \":PK1\" from " + idxName + " ORDER BY \":PK1\"";
ResultSet rs = conn.createStatement().executeQuery(query);
assertTrue(rs.next());
assertEquals("PK2", rs.getString(1));
assertFalse(rs.next());
}
}
@Test
public void testMultipleColumnFamilies() throws Exception {
String tableName = generateUniqueName();
String idxName = "IDX_" + generateUniqueName();
int numOfRows = 2;
try (Connection conn = DriverManager.getConnection(getUrl(), testProps)) {
conn.setAutoCommit(true);
String createTableSql = "CREATE TABLE " + tableName +
" (PK1 VARCHAR NOT NULL, INT_PK INTEGER NOT NULL, V1 VARCHAR, A.V2 INTEGER, B.V3 INTEGER, A.V4 VARCHAR, B.V5 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(PK1, INT_PK)) ";
conn.createStatement().execute(createTableSql);
String createIndexSql = "CREATE INDEX " + idxName + " ON " + tableName + " (A.V2) include (B.V3, A.V4, B.V5) "
+ " IMMUTABLE_STORAGE_SCHEME=SINGLE_CELL_ARRAY_WITH_OFFSETS, COLUMN_ENCODED_BYTES=2";
LOGGER.debug(createIndexSql);
conn.createStatement().execute(createIndexSql);
String upsert = "UPSERT INTO " + tableName + " (PK1, INT_PK, V1, A.V2, B.V3, A.V4, B.V5) VALUES (?,?,?,?,?,?,?)";
PreparedStatement upsertStmt = conn.prepareStatement(upsert);
for (int i=1; i <= numOfRows; i++) {
upsertStmt.setString(1, "PK"+i);
upsertStmt.setInt(2, i);
upsertStmt.setString(3, "V1"+i);
upsertStmt.setInt(4, i+1);
upsertStmt.setInt(5, i+2);
upsertStmt.setString(6, "V4"+i);
upsertStmt.setString(7, "V5"+i);
upsertStmt.executeUpdate();
}
assertMetadata(conn, ONE_CELL_PER_COLUMN, NON_ENCODED_QUALIFIERS, tableName);
assertMetadata(conn, SINGLE_CELL_ARRAY_WITH_OFFSETS, TWO_BYTE_QUALIFIERS, idxName);
String query = "SELECT * from " + idxName + " ORDER BY \":PK1\"";
ResultSet rs = conn.createStatement().executeQuery(query);
assertTrue(rs.next());
assertEquals("2", rs.getString(1));
assertEquals("PK1", rs.getString(2));
assertEquals("1", rs.getString(3));
assertEquals("3", rs.getString(4));
assertEquals("V41", rs.getString(5));
assertEquals("V51", rs.getString(6));
assertTrue(rs.next());
assertEquals("3", rs.getString(1));
assertEquals("PK2", rs.getString(2));
assertEquals("2", rs.getString(3));
assertEquals("4", rs.getString(4));
assertEquals("V42", rs.getString(5));
assertEquals("V52", rs.getString(6));
String selectFromIndex = "SELECT PK1, INT_PK, A.V2, B.V3, A.V4, B.V5 FROM " + tableName + " where A.V4='V42' and B.V3 >= 3";
rs = conn.createStatement().executeQuery("EXPLAIN " + selectFromIndex);
String actualExplainPlan = QueryUtil.getExplainPlan(rs);
assertTrue(actualExplainPlan.contains(idxName));
rs = conn.createStatement().executeQuery(selectFromIndex);
assertTrue(rs.next());
assertEquals("PK2", rs.getString(1));
assertEquals("2", rs.getString(2));
assertEquals("3", rs.getString(3));
assertEquals("4", rs.getString(4));
assertEquals("V42", rs.getString(5));
assertEquals("V52", rs.getString(6));
assertFalse(rs.next());
}
}
@Test
public void testPartialUpdateSingleCellTable() throws Exception {
try (Connection conn = DriverManager.getConnection(getUrl(), testProps)) {
conn.setAutoCommit(true);
String tableName = "TBL_" + generateUniqueName();
String idxName = "IND_" + generateUniqueName();
createTableAndIndex(conn, tableName, idxName, this.tableDDLOptions, false,3);
assertMetadata(conn, ONE_CELL_PER_COLUMN, NON_ENCODED_QUALIFIERS, tableName);
assertMetadata(conn, SINGLE_CELL_ARRAY_WITH_OFFSETS, TWO_BYTE_QUALIFIERS, idxName);
// Partial update 1st row
String upsert = "UPSERT INTO " + tableName + " (PK1, INT_PK, V4) VALUES ('PK1',1,'UpdatedV4')";
conn.createStatement().execute(upsert);
conn.commit();
String selectFromData = "SELECT /*+ NO_INDEX */ PK1, INT_PK, V1, V2, V4 FROM " + tableName + " where INT_PK = 1 and V4 LIKE 'UpdatedV4'";
ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + selectFromData);
String actualExplainPlan = QueryUtil.getExplainPlan(rs);
assertTrue(actualExplainPlan.contains(tableName));
rs = conn.createStatement().executeQuery(selectFromData);
assertTrue(rs.next());
assertEquals("PK1", rs.getString(1));
assertEquals(1, rs.getInt(2));
assertEquals("V11", rs.getString(3));
assertEquals(2, rs.getInt(4));
assertFalse(rs.next());
String selectFromIndex = "SELECT PK1, INT_PK, V1, V2, V4 FROM " + tableName + " where V2 >= 2 and V4 = 'UpdatedV4'";
rs = conn.createStatement().executeQuery("EXPLAIN " + selectFromIndex);
actualExplainPlan = QueryUtil.getExplainPlan(rs);
assertTrue(actualExplainPlan.contains(idxName));
rs = conn.createStatement().executeQuery(selectFromIndex);
assertTrue(rs.next());
assertEquals("PK1", rs.getString(1));
assertEquals(1, rs.getInt(2));
assertEquals("V11", rs.getString(3));
assertEquals(2, rs.getInt(4));
assertFalse(rs.next());
}
}
private Connection getTenantConnection(String tenantId) throws Exception {
Properties tenantProps = PropertiesUtil.deepCopy(testProps);
tenantProps.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, tenantId);
return DriverManager.getConnection(getUrl(), tenantProps);
}
private void createTableAndIndex(Connection conn, String tableName, String indexName, String tableDDL, boolean async, int numOfRows)
throws SQLException {
String createTableSql = "CREATE TABLE " + tableName + " (PK1 VARCHAR NOT NULL, INT_PK INTEGER NOT NULL, V1 VARCHAR, V2 INTEGER, V3 INTEGER, V4 VARCHAR, V5 VARCHAR CONSTRAINT NAME_PK PRIMARY KEY(PK1, INT_PK)) "
+ (tableDDL == null ? "" : tableDDL);
LOGGER.debug(createTableSql);
conn.createStatement().execute(createTableSql);
String createIndexSql = "CREATE INDEX " + indexName + " ON " + tableName + " (PK1, INT_PK) include (V1,V2,V4) " + (async? "ASYNC":"")
+ " IMMUTABLE_STORAGE_SCHEME=SINGLE_CELL_ARRAY_WITH_OFFSETS, COLUMN_ENCODED_BYTES=2";
LOGGER.debug(createIndexSql);
conn.createStatement().execute(createIndexSql);
String upsert = "UPSERT INTO " + tableName + " (PK1, INT_PK, V1, V2, V3, V4, V5) VALUES (?,?,?,?,?,?,?)";
PreparedStatement upsertStmt = conn.prepareStatement(upsert);
for (int i=1; i <= numOfRows; i++) {
upsertStmt.setString(1, "PK"+i);
upsertStmt.setInt(2, i);
upsertStmt.setString(3, "V1"+i);
upsertStmt.setInt(4, i+1);
upsertStmt.setInt(5, i+2);
upsertStmt.setString(6, "V4"+i);
upsertStmt.setString(7, "V5"+i);
upsertStmt.executeUpdate();
}
}
public static void dumpTable(String tableName) throws Exception {
try (Connection conn = DriverManager.getConnection(getUrl())) {
Table
hTable = conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(tableName.getBytes());
Scan scan = new Scan();
scan.setRaw(true);
scan.readAllVersions();
LOGGER.info("***** Table Name : " + tableName);
ResultScanner scanner = hTable.getScanner(scan);
// This is the default format of to_char(timestamp)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
for (Result result = scanner.next(); result != null; result = scanner.next()) {
for (Cell cell : result.rawCells()) {
String cellString = cell.toString();
LOGGER.info(cellString + " ****** timestamp : " +
sdf.format(new Date(cell.getTimestamp())) + " ****** value : " +
Bytes.toStringBinary(CellUtil.cloneValue(cell)));
}
}
}
}
}