Beispiel #1
0
  @Test
  public void testParallelUpsertSelect() throws Exception {
    Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
    props.setProperty(QueryServices.MUTATE_BATCH_SIZE_ATTRIB, Integer.toString(3));
    props.setProperty(QueryServices.SCAN_CACHE_SIZE_ATTRIB, Integer.toString(3));
    props.setProperty(QueryServices.SCAN_RESULT_CHUNK_SIZE, Integer.toString(3));
    Connection conn = DriverManager.getConnection(getUrl(), props);
    conn.setAutoCommit(false);
    conn.createStatement().execute("CREATE SEQUENCE S1");
    conn.createStatement()
        .execute(
            "CREATE TABLE SALTEDT1 (pk INTEGER PRIMARY KEY, val INTEGER) SALT_BUCKETS=4,TRANSACTIONAL=true");
    conn.createStatement()
        .execute("CREATE TABLE T2 (pk INTEGER PRIMARY KEY, val INTEGER) TRANSACTIONAL=true");

    for (int i = 0; i < 100; i++) {
      conn.createStatement()
          .execute("UPSERT INTO SALTEDT1 VALUES (NEXT VALUE FOR S1, " + (i % 10) + ")");
    }
    conn.commit();
    conn.setAutoCommit(true);
    int upsertCount =
        conn.createStatement().executeUpdate("UPSERT INTO T2 SELECT pk, val FROM SALTEDT1");
    assertEquals(100, upsertCount);
    conn.close();
  }
Beispiel #2
0
 @Test
 public void testRowTimestampDisabled() throws SQLException {
   Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
   try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
     conn.setAutoCommit(false);
     Statement stmt = conn.createStatement();
     try {
       stmt.execute(
           "CREATE TABLE DEMO(k VARCHAR, v VARCHAR, d DATE NOT NULL, CONSTRAINT PK PRIMARY KEY(k,d ROW_TIMESTAMP)) TRANSACTIONAL=true");
       fail();
     } catch (SQLException e) {
       assertEquals(
           SQLExceptionCode.CANNOT_CREATE_TXN_TABLE_WITH_ROW_TIMESTAMP.getErrorCode(),
           e.getErrorCode());
     }
     stmt.execute(
         "CREATE TABLE DEMO(k VARCHAR, v VARCHAR, d DATE NOT NULL, CONSTRAINT PK PRIMARY KEY(k,d ROW_TIMESTAMP))");
     try {
       stmt.execute("ALTER TABLE DEMO SET TRANSACTIONAL=true");
       fail();
     } catch (SQLException e) {
       assertEquals(
           SQLExceptionCode.CANNOT_ALTER_TO_BE_TXN_WITH_ROW_TIMESTAMP.getErrorCode(),
           e.getErrorCode());
     }
   }
 }
Beispiel #3
0
  @Test
  public void testQueryWithLimitAndStats() throws Exception {
    long ts = nextTimestamp();
    ensureTableCreated(getUrl(), KEYONLY_NAME, null, ts);
    initTableValues(ts + 1, 100);

    TestUtil.analyzeTable(getUrl(), ts + 10, KEYONLY_NAME);
    Properties props = PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES);

    props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 50));
    Connection conn = DriverManager.getConnection(getUrl(), props);
    String query = "SELECT i1 FROM KEYONLY LIMIT 1";
    ResultSet rs = conn.createStatement().executeQuery(query);
    assertTrue(rs.next());
    assertEquals(0, rs.getInt(1));
    assertFalse(rs.next());

    rs = conn.createStatement().executeQuery("EXPLAIN " + query);
    assertEquals(
        "CLIENT SERIAL 1-WAY FULL SCAN OVER KEYONLY\n"
            + "    SERVER FILTER BY FIRST KEY ONLY\n"
            + "    SERVER 1 ROW LIMIT\n"
            + "CLIENT 1 ROW LIMIT",
        QueryUtil.getExplainPlan(rs));
    conn.close();
  }
 @Test
 public void testCreateTenantSpecificTable() throws Exception {
   // ensure we didn't create a physical HBase table for the tenant-specific table
   HBaseAdmin admin =
       driver
           .getConnectionQueryServices(getUrl(), PropertiesUtil.deepCopy(TEST_PROPERTIES))
           .getAdmin();
   assertEquals(0, admin.listTables(TENANT_TABLE_NAME).length);
 }
Beispiel #5
0
  @Test
  public void testCreateTableToBeTransactional() throws Exception {
    Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
    Connection conn = DriverManager.getConnection(getUrl(), props);
    String ddl = "CREATE TABLE TEST_TRANSACTIONAL_TABLE (k varchar primary key) transactional=true";
    conn.createStatement().execute(ddl);
    PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);
    PTable table = pconn.getTable(new PTableKey(null, "TEST_TRANSACTIONAL_TABLE"));
    HTableInterface htable =
        pconn.getQueryServices().getTable(Bytes.toBytes("TEST_TRANSACTIONAL_TABLE"));
    assertTrue(table.isTransactional());
    assertTrue(
        htable
            .getTableDescriptor()
            .getCoprocessors()
            .contains(TransactionProcessor.class.getName()));

    try {
      ddl = "ALTER TABLE TEST_TRANSACTIONAL_TABLE SET transactional=false";
      conn.createStatement().execute(ddl);
      fail();
    } catch (SQLException e) {
      assertEquals(SQLExceptionCode.TX_MAY_NOT_SWITCH_TO_NON_TX.getErrorCode(), e.getErrorCode());
    }

    HBaseAdmin admin = pconn.getQueryServices().getAdmin();
    HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("TXN_TEST_EXISTING"));
    desc.addFamily(new HColumnDescriptor(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES));
    admin.createTable(desc);
    ddl = "CREATE TABLE TXN_TEST_EXISTING (k varchar primary key) transactional=true";
    conn.createStatement().execute(ddl);
    assertEquals(
        Boolean.TRUE.toString(),
        admin
            .getTableDescriptor(TableName.valueOf("TXN_TEST_EXISTING"))
            .getValue(TxConstants.READ_NON_TX_DATA));

    // Should be ok, as HBase metadata should match existing metadata.
    ddl = "CREATE TABLE IF NOT EXISTS TEST_TRANSACTIONAL_TABLE (k varchar primary key)";
    try {
      conn.createStatement().execute(ddl);
      fail();
    } catch (SQLException e) {
      assertEquals(SQLExceptionCode.TX_MAY_NOT_SWITCH_TO_NON_TX.getErrorCode(), e.getErrorCode());
    }
    ddl += " transactional=true";
    conn.createStatement().execute(ddl);
    table = pconn.getTable(new PTableKey(null, "TEST_TRANSACTIONAL_TABLE"));
    htable = pconn.getQueryServices().getTable(Bytes.toBytes("TEST_TRANSACTIONAL_TABLE"));
    assertTrue(table.isTransactional());
    assertTrue(
        htable
            .getTableDescriptor()
            .getCoprocessors()
            .contains(TransactionProcessor.class.getName()));
  }
 private static void startServer(String url) throws Exception {
   assertNull(driver);
   // only load the test driver if we are testing locally - for integration tests, we want to
   // test on a wider scale
   if (PhoenixEmbeddedDriver.isTestUrl(url)) {
     driver = initDriver(ReadOnlyProps.EMPTY_PROPS);
     assertTrue(DriverManager.getDriver(url) == driver);
     driver.connect(url, PropertiesUtil.deepCopy(TEST_PROPERTIES));
   }
 }
Beispiel #7
0
 @Test
 public void testFalseOrFalse() throws SQLException {
   Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
   Connection conn = DriverManager.getConnection(getUrl(), props);
   ResultSet rs =
       conn.createStatement()
           .executeQuery("SELECT (FALSE OR FALSE) AS B FROM SYSTEM.CATALOG LIMIT 1");
   assertTrue(rs.next());
   assertFalse(rs.getBoolean(1));
   conn.close();
 }
Beispiel #8
0
  protected static void initTableValues(long ts, int nRows) throws Exception {
    String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=" + ts;
    Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
    Connection conn = DriverManager.getConnection(url, props);
    PreparedStatement stmt = conn.prepareStatement("upsert into " + "KEYONLY VALUES (?, ?)");
    for (int i = 0; i < nRows; i++) {
      stmt.setInt(1, i);
      stmt.setInt(2, i + 1);
      stmt.execute();
    }

    conn.commit();
    conn.close();
  }
Beispiel #9
0
  public static PhoenixTestDriver registerDriver(String url, ReadOnlyProps props) throws Exception {
    PhoenixTestDriver newDriver = new PhoenixTestDriver(props);
    DriverManager.registerDriver(newDriver);
    Driver oldDriver = DriverManager.getDriver(url);

    if (oldDriver != newDriver) {
      destroyDriver(oldDriver);
    }

    Properties driverProps = PropertiesUtil.deepCopy(TEST_PROPERTIES);
    Connection conn = newDriver.connect(url, driverProps);
    conn.close();
    return newDriver;
  }
Beispiel #10
0
  @Test
  public void testCheckpointAndRollback() throws Exception {
    Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
    Connection conn = DriverManager.getConnection(getUrl(), props);
    conn.setAutoCommit(false);
    try {
      String fullTableName = "T";
      Statement stmt = conn.createStatement();
      stmt.execute(
          "CREATE TABLE "
              + fullTableName
              + "(k VARCHAR PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) TRANSACTIONAL=true");
      stmt.executeUpdate("upsert into " + fullTableName + " values('x', 'a', 'a')");
      conn.commit();

      stmt.executeUpdate(
          "upsert into " + fullTableName + "(k,v1) SELECT k,v1||'a' FROM " + fullTableName);
      ResultSet rs = stmt.executeQuery("select k, v1, v2 from " + fullTableName);
      assertTrue(rs.next());
      assertEquals("x", rs.getString(1));
      assertEquals("aa", rs.getString(2));
      assertEquals("a", rs.getString(3));
      assertFalse(rs.next());

      stmt.executeUpdate(
          "upsert into " + fullTableName + "(k,v1) SELECT k,v1||'a' FROM " + fullTableName);

      rs = stmt.executeQuery("select k, v1, v2 from " + fullTableName);
      assertTrue(rs.next());
      assertEquals("x", rs.getString(1));
      assertEquals("aaa", rs.getString(2));
      assertEquals("a", rs.getString(3));
      assertFalse(rs.next());

      conn.rollback();

      // assert original row exists in fullTableName1
      rs = stmt.executeQuery("select k, v1, v2 from " + fullTableName);
      assertTrue(rs.next());
      assertEquals("x", rs.getString(1));
      assertEquals("a", rs.getString(2));
      assertEquals("a", rs.getString(3));
      assertFalse(rs.next());

    } finally {
      conn.close();
    }
  }
Beispiel #11
0
 @Test
 public void testReCreateTxnTableAfterDroppingExistingNonTxnTable() throws SQLException {
   Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
   Connection conn = DriverManager.getConnection(getUrl(), props);
   conn.setAutoCommit(false);
   Statement stmt = conn.createStatement();
   stmt.execute("CREATE TABLE DEMO(k VARCHAR PRIMARY KEY, v1 VARCHAR, v2 VARCHAR)");
   stmt.execute("DROP TABLE DEMO");
   stmt.execute(
       "CREATE TABLE DEMO(k VARCHAR PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) TRANSACTIONAL=true");
   stmt.execute("CREATE INDEX DEMO_IDX ON DEMO (v1) INCLUDE(v2)");
   assertTrue(
       conn.unwrap(PhoenixConnection.class)
           .getTable(new PTableKey(null, "DEMO"))
           .isTransactional());
   assertTrue(
       conn.unwrap(PhoenixConnection.class)
           .getTable(new PTableKey(null, "DEMO_IDX"))
           .isTransactional());
 }
  @Test
  public void testGetSplitsWithSkipScanFilter() throws Exception {
    byte[][] splits = new byte[][] {Ka1A, Ka1B, Ka1E, Ka1G, Ka1I, Ka2A};
    createTestTable(getUrl(), DDL, splits, null);
    Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
    Connection conn = DriverManager.getConnection(getUrl(), props);
    PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);

    PTable table =
        pconn.getMetaDataCache().getTable(new PTableKey(pconn.getTenantId(), TABLE_NAME));
    TableRef tableRef = new TableRef(table);
    List<HRegionLocation> regions =
        pconn
            .getQueryServices()
            .getAllTableRegions(tableRef.getTable().getPhysicalName().getBytes());
    List<KeyRange> ranges = getSplits(tableRef, scan, regions, scanRanges);
    assertEquals(
        "Unexpected number of splits: " + ranges.size(), expectedSplits.size(), ranges.size());
    for (int i = 0; i < expectedSplits.size(); i++) {
      assertEquals(expectedSplits.get(i), ranges.get(i));
    }
  }
  // TODO: share this with ConnectionQueryServicesImpl
  @Override
  public void init(String url, Properties props) throws SQLException {
    if (initialized) {
      if (initializationException != null) {
        throw initializationException;
      }
      return;
    }
    synchronized (this) {
      if (initialized) {
        if (initializationException != null) {
          throw initializationException;
        }
        return;
      }
      SQLException sqlE = null;
      PhoenixConnection metaConnection = null;
      try {
        Properties scnProps = PropertiesUtil.deepCopy(props);
        scnProps.setProperty(
            PhoenixRuntime.CURRENT_SCN_ATTRIB,
            Long.toString(MetaDataProtocol.MIN_SYSTEM_TABLE_TIMESTAMP));
        scnProps.remove(PhoenixRuntime.TENANT_ID_ATTRIB);
        String globalUrl = JDBCUtil.removeProperty(url, PhoenixRuntime.TENANT_ID_ATTRIB);
        metaConnection = new PhoenixConnection(this, globalUrl, scnProps, newEmptyMetaData());
        try {
          metaConnection.createStatement().executeUpdate(QueryConstants.CREATE_TABLE_METADATA);
        } catch (TableAlreadyExistsException ignore) {
          // Ignore, as this will happen if the SYSTEM.TABLE already exists at this fixed timestamp.
          // A TableAlreadyExistsException is not thrown, since the table only exists *after* this
          // fixed timestamp.
        }
        try {
          int nSaltBuckets = getSequenceSaltBuckets();
          String createTableStatement = Sequence.getCreateTableStatement(nSaltBuckets);
          metaConnection.createStatement().executeUpdate(createTableStatement);
        } catch (NewerTableAlreadyExistsException ignore) {
          // Ignore, as this will happen if the SYSTEM.SEQUENCE already exists at this fixed
          // timestamp.
          // A TableAlreadyExistsException is not thrown, since the table only exists *after* this
          // fixed timestamp.
        }
        try {
          metaConnection
              .createStatement()
              .executeUpdate(QueryConstants.CREATE_STATS_TABLE_METADATA);
        } catch (NewerTableAlreadyExistsException ignore) {
          // Ignore, as this will happen if the SYSTEM.SEQUENCE already exists at this fixed
          // timestamp.
          // A TableAlreadyExistsException is not thrown, since the table only exists *after* this
          // fixed timestamp.
        }

        try {
          metaConnection.createStatement().executeUpdate(QueryConstants.CREATE_FUNCTION_METADATA);
        } catch (NewerTableAlreadyExistsException ignore) {
        }
      } catch (SQLException e) {
        sqlE = e;
      } finally {
        try {
          if (metaConnection != null) metaConnection.close();
        } catch (SQLException e) {
          if (sqlE != null) {
            sqlE.setNextException(e);
          } else {
            sqlE = e;
          }
        } finally {
          try {
            if (sqlE != null) {
              initializationException = sqlE;
              throw sqlE;
            }
          } finally {
            initialized = true;
          }
        }
      }
    }
  }
Beispiel #14
0
  @Test
  public void testPKOrNotPKInOREvaluation() throws SQLException {
    Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
    Connection conn = DriverManager.getConnection(getUrl(), props);
    conn.setAutoCommit(false);

    String create = "CREATE TABLE DIE ( ID INTEGER NOT NULL PRIMARY KEY,NAME VARCHAR(50))";
    PreparedStatement createStmt = conn.prepareStatement(create);
    createStmt.execute();
    PreparedStatement stmt = conn.prepareStatement("upsert into " + "DIE VALUES (?, ?)");

    stmt.setInt(1, 1);
    stmt.setString(2, "Tester1");
    stmt.execute();

    stmt.setInt(1, 2);
    stmt.setString(2, "Tester2");
    stmt.execute();

    stmt.setInt(1, 3);
    stmt.setString(2, "Tester3");
    stmt.execute();

    stmt.setInt(1, 4);
    stmt.setString(2, "LikeTester1");
    stmt.execute();

    stmt.setInt(1, 5);
    stmt.setString(2, "LikeTester2");
    stmt.execute();

    stmt.setInt(1, 6);
    stmt.setString(2, "LikeTesterEnd");
    stmt.execute();

    stmt.setInt(1, 7);
    stmt.setString(2, "LikeTesterEnd2");
    stmt.execute();

    stmt.setInt(1, 8);
    stmt.setString(2, "Tester3");
    stmt.execute();

    stmt.setInt(1, 9);
    stmt.setString(2, "Tester4");
    stmt.execute();

    stmt.setInt(1, 10);
    stmt.setString(2, "Tester5");
    stmt.execute();

    stmt.setInt(1, 11);
    stmt.setString(2, "Tester6");
    stmt.execute();

    stmt.setInt(1, 12);
    stmt.setString(2, "tester6");
    stmt.execute();

    stmt.setInt(1, 13);
    stmt.setString(2, "lester1");
    stmt.execute();

    stmt.setInt(1, 14);
    stmt.setString(2, "le50ster1");
    stmt.execute();

    stmt.setInt(1, 15);
    stmt.setString(2, "LE50ster1");
    stmt.execute();

    stmt.setInt(1, 16);
    stmt.setString(2, "LiketesterEnd");
    stmt.execute();

    stmt.setInt(1, 17);
    stmt.setString(2, "la50ster1");
    stmt.execute();

    stmt.setInt(1, 18);
    stmt.setString(2, "lA50ster0");
    stmt.execute();

    stmt.setInt(1, 19);
    stmt.setString(2, "lA50ster2");
    stmt.execute();

    stmt.setInt(1, 20);
    stmt.setString(2, "la50ster0");
    stmt.execute();

    stmt.setInt(1, 21);
    stmt.setString(2, "la50ster2");
    stmt.execute();

    stmt.setInt(1, 22);
    stmt.setString(2, "La50ster3");
    stmt.execute();

    stmt.setInt(1, 23);
    stmt.setString(2, "la50ster3");
    stmt.execute();

    stmt.setInt(1, 24);
    stmt.setString(2, "l[50ster3");
    stmt.execute();

    stmt.setInt(1, 25);
    stmt.setString(2, "Tester1");
    stmt.execute();

    stmt.setInt(1, 26);
    stmt.setString(2, "Tester100");
    stmt.execute();
    conn.commit();

    String select = "Select * from DIE where ID=6 or Name between 'Tester1' and 'Tester3'";
    ResultSet rs;
    rs = conn.createStatement().executeQuery(select);
    assertTrue(rs.next());
    assertEquals(1, rs.getInt(1));
    assertTrue(rs.next());
    assertEquals(2, rs.getInt(1));
    assertTrue(rs.next());
    assertEquals(3, rs.getInt(1));
    assertTrue(rs.next());
    assertEquals(6, rs.getInt(1));
    assertTrue(rs.next());
    assertEquals(8, rs.getInt(1));
    assertTrue(rs.next());
    assertEquals(25, rs.getInt(1));
    assertTrue(rs.next());
    assertEquals(26, rs.getInt(1));
    conn.close();
  }
Beispiel #15
0
  @Test
  public void testExternalTxContext() throws Exception {
    ResultSet rs;
    Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
    Connection conn = DriverManager.getConnection(getUrl(), props);
    conn.setAutoCommit(false);
    PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);

    TransactionSystemClient txServiceClient = pconn.getQueryServices().getTransactionSystemClient();

    String fullTableName = "T";
    Statement stmt = conn.createStatement();
    stmt.execute(
        "CREATE TABLE "
            + fullTableName
            + "(K VARCHAR PRIMARY KEY, V1 VARCHAR, V2 VARCHAR) TRANSACTIONAL=true");
    HTableInterface htable = pconn.getQueryServices().getTable(Bytes.toBytes(fullTableName));
    stmt.executeUpdate("upsert into " + fullTableName + " values('x', 'a', 'a')");
    conn.commit();

    try (Connection newConn = DriverManager.getConnection(getUrl(), props)) {
      rs = newConn.createStatement().executeQuery("select count(*) from " + fullTableName);
      assertTrue(rs.next());
      assertEquals(1, rs.getInt(1));
    }

    // Use HBase level Tephra APIs to start a new transaction
    TransactionAwareHTable txAware =
        new TransactionAwareHTable(htable, TxConstants.ConflictDetection.ROW);
    TransactionContext txContext = new TransactionContext(txServiceClient, txAware);
    txContext.start();

    // Use HBase APIs to add a new row
    Put put = new Put(Bytes.toBytes("z"));
    put.addColumn(
        QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES,
        QueryConstants.EMPTY_COLUMN_BYTES,
        QueryConstants.EMPTY_COLUMN_VALUE_BYTES);
    put.addColumn(
        QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, Bytes.toBytes("V1"), Bytes.toBytes("b"));
    txAware.put(put);

    // Use Phoenix APIs to add new row (sharing the transaction context)
    pconn.setTransactionContext(txContext);
    conn.createStatement().executeUpdate("upsert into " + fullTableName + " values('y', 'c', 'c')");

    // New connection should not see data as it hasn't been committed yet
    try (Connection newConn = DriverManager.getConnection(getUrl(), props)) {
      rs = newConn.createStatement().executeQuery("select count(*) from " + fullTableName);
      assertTrue(rs.next());
      assertEquals(1, rs.getInt(1));
    }

    // Use new connection to create a row with a conflict
    Connection connWithConflict = DriverManager.getConnection(getUrl(), props);
    connWithConflict
        .createStatement()
        .execute("upsert into " + fullTableName + " values('z', 'd', 'd')");

    // Existing connection should see data even though it hasn't been committed yet
    rs = conn.createStatement().executeQuery("select count(*) from " + fullTableName);
    assertTrue(rs.next());
    assertEquals(3, rs.getInt(1));

    // Use Tephra APIs directly to finish (i.e. commit) the transaction
    txContext.finish();

    // Confirm that attempt to commit row with conflict fails
    try {
      connWithConflict.commit();
      fail();
    } catch (SQLException e) {
      assertEquals(
          SQLExceptionCode.TRANSACTION_CONFLICT_EXCEPTION.getErrorCode(), e.getErrorCode());
    } finally {
      connWithConflict.close();
    }

    // New connection should now see data as it has been committed
    try (Connection newConn = DriverManager.getConnection(getUrl(), props)) {
      rs = newConn.createStatement().executeQuery("select count(*) from " + fullTableName);
      assertTrue(rs.next());
      assertEquals(3, rs.getInt(1));
    }

    // Repeat the same as above, but this time abort the transaction
    txContext = new TransactionContext(txServiceClient, txAware);
    txContext.start();

    // Use HBase APIs to add a new row
    put = new Put(Bytes.toBytes("j"));
    put.addColumn(
        QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES,
        QueryConstants.EMPTY_COLUMN_BYTES,
        QueryConstants.EMPTY_COLUMN_VALUE_BYTES);
    put.addColumn(
        QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, Bytes.toBytes("V1"), Bytes.toBytes("e"));
    txAware.put(put);

    // Use Phoenix APIs to add new row (sharing the transaction context)
    pconn.setTransactionContext(txContext);
    conn.createStatement().executeUpdate("upsert into " + fullTableName + " values('k', 'f', 'f')");

    // Existing connection should see data even though it hasn't been committed yet
    rs = conn.createStatement().executeQuery("select count(*) from " + fullTableName);
    assertTrue(rs.next());
    assertEquals(5, rs.getInt(1));

    connWithConflict
        .createStatement()
        .execute("upsert into " + fullTableName + " values('k', 'g', 'g')");
    rs = connWithConflict.createStatement().executeQuery("select count(*) from " + fullTableName);
    assertTrue(rs.next());
    assertEquals(4, rs.getInt(1));

    // Use Tephra APIs directly to abort (i.e. rollback) the transaction
    txContext.abort();

    rs = conn.createStatement().executeQuery("select count(*) from " + fullTableName);
    assertTrue(rs.next());
    assertEquals(3, rs.getInt(1));

    // Should succeed since conflicting row was aborted
    connWithConflict.commit();

    // New connection should now see data as it has been committed
    try (Connection newConn = DriverManager.getConnection(getUrl(), props)) {
      rs = newConn.createStatement().executeQuery("select count(*) from " + fullTableName);
      assertTrue(rs.next());
      assertEquals(4, rs.getInt(1));
    }

    // Even using HBase APIs directly, we shouldn't find 'j' since a delete marker would have been
    // written to hide it.
    Result result = htable.get(new Get(Bytes.toBytes("j")));
    assertTrue(result.isEmpty());
  }
Beispiel #16
0
  @Test
  public void testKeyOnly() throws Exception {
    long ts = nextTimestamp();
    ensureTableCreated(getUrl(), KEYONLY_NAME, null, ts);
    initTableValues(ts + 1);
    Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
    props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 30));
    Connection conn3 = DriverManager.getConnection(getUrl(), props);
    analyzeTable(conn3, KEYONLY_NAME);
    conn3.close();

    props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 50));
    Connection conn5 = DriverManager.getConnection(getUrl(), props);
    String query = "SELECT i1, i2 FROM KEYONLY";
    PreparedStatement statement = conn5.prepareStatement(query);
    ResultSet rs = statement.executeQuery();
    assertTrue(rs.next());
    assertEquals(1, rs.getInt(1));
    assertEquals(2, rs.getInt(2));
    assertTrue(rs.next());
    assertEquals(3, rs.getInt(1));
    assertEquals(4, rs.getInt(2));
    assertFalse(rs.next());
    List<KeyRange> splits = getAllSplits(conn5, "KEYONLY");
    assertEquals(2, splits.size());
    conn5.close();

    props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 60));
    Connection conn6 = DriverManager.getConnection(getUrl(), props);
    conn6.createStatement().execute("ALTER TABLE KEYONLY ADD s1 varchar");
    conn6.close();

    props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 70));
    Connection conn7 = DriverManager.getConnection(getUrl(), props);
    PreparedStatement stmt = conn7.prepareStatement("upsert into " + "KEYONLY VALUES (?, ?, ?)");
    stmt.setInt(1, 5);
    stmt.setInt(2, 6);
    stmt.setString(3, "foo");
    stmt.execute();
    conn7.commit();
    conn7.close();

    props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 80));
    Connection conn8 = DriverManager.getConnection(getUrl(), props);
    analyzeTable(conn8, KEYONLY_NAME);
    conn8.close();

    props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 90));
    Connection conn9 = DriverManager.getConnection(getUrl(), props);
    query = "SELECT i1 FROM KEYONLY";
    statement = conn9.prepareStatement(query);
    rs = statement.executeQuery();
    assertTrue(rs.next());
    assertEquals(1, rs.getInt(1));
    assertTrue(rs.next());
    assertEquals(3, rs.getInt(1));
    assertTrue(rs.next());
    assertEquals(5, rs.getInt(1));
    assertFalse(rs.next());

    query = "SELECT i1,s1 FROM KEYONLY";
    statement = conn9.prepareStatement(query);
    rs = statement.executeQuery();
    assertTrue(rs.next());
    assertEquals(1, rs.getInt(1));
    assertEquals(null, rs.getString(2));
    assertTrue(rs.next());
    assertEquals(3, rs.getInt(1));
    assertEquals(null, rs.getString(2));
    assertTrue(rs.next());
    assertEquals(5, rs.getInt(1));
    assertEquals("foo", rs.getString(2));
    assertFalse(rs.next());

    conn9.close();
  }
Beispiel #17
0
  private void testGetTenantIdExpression(boolean isSalted) throws Exception {
    Connection conn = DriverManager.getConnection(getUrl());
    conn.setAutoCommit(true);
    String tableName = "FOO_" + (isSalted ? "SALTED" : "UNSALTED");
    conn.createStatement()
        .execute(
            "CREATE TABLE "
                + tableName
                + " (k1 VARCHAR NOT NULL, k2 VARCHAR, CONSTRAINT PK PRIMARY KEY(K1,K2)) MULTI_TENANT=true"
                + (isSalted ? ",SALT_BUCKETS=3" : ""));
    conn.createStatement().execute("CREATE SEQUENCE s1");
    conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('t1','x')");
    conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('t2','y')");

    Properties props = PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES);
    props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, "t1");
    Connection tsconn = DriverManager.getConnection(getUrl(), props);
    tsconn.createStatement().execute("CREATE SEQUENCE s1");
    Expression e1 =
        PhoenixRuntime.getTenantIdExpression(tsconn, PhoenixDatabaseMetaData.SYSTEM_SEQUENCE_NAME);
    HTableInterface htable1 =
        tsconn
            .unwrap(PhoenixConnection.class)
            .getQueryServices()
            .getTable(PhoenixDatabaseMetaData.SYSTEM_SEQUENCE_NAME_BYTES);
    assertTenantIds(e1, htable1, new FirstKeyOnlyFilter(), new String[] {"", "t1"});

    tsconn.createStatement().execute("CREATE VIEW A.BAR(V1 VARCHAR) AS SELECT * FROM " + tableName);
    Expression e2 =
        PhoenixRuntime.getTenantIdExpression(tsconn, PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME);
    HTableInterface htable2 =
        conn.unwrap(PhoenixConnection.class)
            .getQueryServices()
            .getTable(PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME_BYTES);
    assertTenantIds(e2, htable2, getUserTableAndViewsFilter(), new String[] {"", "t1"});

    Expression e3 = PhoenixRuntime.getTenantIdExpression(conn, tableName);
    HTableInterface htable3 =
        conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes(tableName));
    assertTenantIds(e3, htable3, new FirstKeyOnlyFilter(), new String[] {"t1", "t2"});

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

    tsconn.createStatement().execute("CREATE INDEX I1 ON A.BAR(V1)");
    Expression e5 = PhoenixRuntime.getTenantIdExpression(tsconn, "A.I1");
    HTableInterface htable5 =
        tsconn
            .unwrap(PhoenixConnection.class)
            .getQueryServices()
            .getTable(Bytes.toBytes(MetaDataUtil.VIEW_INDEX_TABLE_PREFIX + tableName));
    assertTenantIds(e5, htable5, new FirstKeyOnlyFilter(), new String[] {"t1"});

    conn.createStatement().execute("CREATE INDEX I2 ON " + tableName + "(k2)");
    Expression e6 = PhoenixRuntime.getTenantIdExpression(conn, "I2");
    HTableInterface htable6 =
        conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes("I2"));
    assertTenantIds(e6, htable6, new FirstKeyOnlyFilter(), new String[] {"t1", "t2"});

    tableName = "BAR_" + (isSalted ? "SALTED" : "UNSALTED");
    conn.createStatement()
        .execute(
            "CREATE TABLE "
                + tableName
                + " (k1 VARCHAR NOT NULL, k2 VARCHAR, CONSTRAINT PK PRIMARY KEY(K1,K2)) "
                + (isSalted ? "SALT_BUCKETS=3" : ""));
    conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('t1','x')");
    conn.createStatement().execute("UPSERT INTO " + tableName + " VALUES('t2','y')");
    Expression e7 = PhoenixRuntime.getFirstPKColumnExpression(conn, tableName);
    HTableInterface htable7 =
        conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes(tableName));
    assertTenantIds(e7, htable7, new FirstKeyOnlyFilter(), new String[] {"t1", "t2"});
  }
  private static List<KeyRange> getSplits(
      final TableRef tableRef,
      final Scan scan,
      final List<HRegionLocation> regions,
      final ScanRanges scanRanges)
      throws SQLException {
    final List<TableRef> tableRefs = Collections.singletonList(tableRef);
    ColumnResolver resolver =
        new ColumnResolver() {

          @Override
          public List<PFunction> getFunctions() {
            return Collections.emptyList();
          }

          @Override
          public List<TableRef> getTables() {
            return tableRefs;
          }

          @Override
          public TableRef resolveTable(String schemaName, String tableName) throws SQLException {
            throw new UnsupportedOperationException();
          }

          @Override
          public ColumnRef resolveColumn(String schemaName, String tableName, String colName)
              throws SQLException {
            throw new UnsupportedOperationException();
          }

          @Override
          public PFunction resolveFunction(String functionName) throws SQLException {
            throw new UnsupportedOperationException();
          }

          @Override
          public boolean hasUDFs() {
            return false;
          }
        };
    PhoenixConnection connection =
        DriverManager.getConnection(getUrl(), PropertiesUtil.deepCopy(TEST_PROPERTIES))
            .unwrap(PhoenixConnection.class);
    final PhoenixStatement statement = new PhoenixStatement(connection);
    final StatementContext context =
        new StatementContext(statement, resolver, scan, new SequenceManager(statement));
    context.setScanRanges(scanRanges);
    ParallelIterators parallelIterators =
        new ParallelIterators(
            new QueryPlan() {

              @Override
              public StatementContext getContext() {
                return context;
              }

              @Override
              public ParameterMetaData getParameterMetaData() {
                return PhoenixParameterMetaData.EMPTY_PARAMETER_META_DATA;
              }

              @Override
              public ExplainPlan getExplainPlan() throws SQLException {
                return ExplainPlan.EMPTY_PLAN;
              }

              @Override
              public ResultIterator iterator(ParallelScanGrouper scanGrouper) throws SQLException {
                return ResultIterator.EMPTY_ITERATOR;
              }

              @Override
              public ResultIterator iterator() throws SQLException {
                return ResultIterator.EMPTY_ITERATOR;
              }

              @Override
              public long getEstimatedSize() {
                return 0;
              }

              @Override
              public TableRef getTableRef() {
                return tableRef;
              }

              @Override
              public RowProjector getProjector() {
                return RowProjector.EMPTY_PROJECTOR;
              }

              @Override
              public Integer getLimit() {
                return null;
              }

              @Override
              public OrderBy getOrderBy() {
                return OrderBy.EMPTY_ORDER_BY;
              }

              @Override
              public GroupBy getGroupBy() {
                return GroupBy.EMPTY_GROUP_BY;
              }

              @Override
              public List<KeyRange> getSplits() {
                return null;
              }

              @Override
              public FilterableStatement getStatement() {
                return SelectStatement.SELECT_ONE;
              }

              @Override
              public boolean isDegenerate() {
                return false;
              }

              @Override
              public boolean isRowKeyOrdered() {
                return true;
              }

              @Override
              public List<List<Scan>> getScans() {
                return null;
              }

              @Override
              public boolean useRoundRobinIterator() {
                return false;
              }
            },
            null,
            new SpoolingResultIterator.SpoolingResultIteratorFactory(
                context.getConnection().getQueryServices()));
    List<KeyRange> keyRanges = parallelIterators.getSplits();
    return keyRanges;
  }