Repository: phoenix Updated Branches: refs/heads/calcite 50e4406db -> 413247da5
PHOENIX-2416 Implement multi-tenant tables in Phoenix/Calcite integration Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/413247da Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/413247da Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/413247da Branch: refs/heads/calcite Commit: 413247da5618803e0f61bd9a6661bcc4bb5e4d34 Parents: 50e4406 Author: maryannxue <[email protected]> Authored: Tue Nov 17 00:15:40 2015 -0500 Committer: maryannxue <[email protected]> Committed: Tue Nov 17 00:15:40 2015 -0500 ---------------------------------------------------------------------- .../org/apache/phoenix/calcite/CalciteIT.java | 45 ++++++++++++++++++++ .../apache/phoenix/calcite/PhoenixSchema.java | 5 ++- .../apache/phoenix/calcite/PhoenixTable.java | 5 ++- .../phoenix/calcite/rel/PhoenixTableScan.java | 21 ++++----- 4 files changed, 62 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/413247da/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteIT.java b/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteIT.java index 2d904ef..8daf255 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/calcite/CalciteIT.java @@ -268,6 +268,7 @@ public class CalciteIT extends BaseClientManagedTimeIT { initJoinTableValues(url, null, null); initArrayTable(); initSaltedTables(); + initMultiTenantTables(); createIndices( "CREATE INDEX IDX1 ON aTable (a_string) INCLUDE (b_string, x_integer)", "CREATE INDEX IDX2 ON aTable (b_string) INCLUDE (a_string, y_integer)", @@ -395,6 +396,39 @@ public class CalciteIT extends BaseClientManagedTimeIT { conn.close(); } + protected static final String MULTI_TENANT_TABLE = "multitenant_test_table"; + + protected void initMultiTenantTables() 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 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.execute(); + stmt.setString(1, "15"); + stmt.setString(2, "3"); + stmt.setInt(3, 4); + stmt.setInt(4, 5); + stmt.execute(); + stmt.setString(1, "20"); + stmt.setString(2, "4"); + stmt.setInt(3, 5); + stmt.setInt(4, 6); + stmt.execute(); + conn.commit(); + } catch (TableAlreadyExistsException e) { + } finally { + conn.close(); + } + } + @Test public void testTableScan() throws Exception { start(false).sql("select * from aTable where a_string = 'a'") .explainIs("PhoenixToEnumerableConverter\n" + @@ -1522,6 +1556,17 @@ public class CalciteIT extends BaseClientManagedTimeIT { {2, 3, 4, 5, 2, 3, 4, 5}}) .close(); } + + @Test public void testMultiTenant() { + Properties props = getConnectionProps(false); + props.setProperty("TenantId", "15"); + start(props).sql("select * from " + MULTI_TENANT_TABLE) + .explainIs("PhoenixToEnumerableConverter\n" + + " PhoenixTableScan(table=[[phoenix, MULTITENANT_TEST_TABLE]])\n") + .resultIs(new Object[][] { + {"3", 4, 5}}) + .close(); + } /** Tests a simple command that is defined in Phoenix's extended SQL parser. */ @Ignore http://git-wip-us.apache.org/repos/asf/phoenix/blob/413247da/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java index 01913b9..40afe5f 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java @@ -96,7 +96,9 @@ public class PhoenixSchema implements Schema { while (rs.next()) { String tableName = rs.getString(PhoenixDatabaseMetaData.TABLE_NAME); String tableType = rs.getString(PhoenixDatabaseMetaData.TABLE_TYPE); - if (!tableType.equals(PTableType.VIEW.getValue().getString())) { + String viewType = rs.getString(PhoenixDatabaseMetaData.VIEW_TYPE); + if (!tableType.equals(PTableType.VIEW.getValue().getString()) + || ViewType.MAPPED.name().equals(viewType)) { ColumnResolver x = FromCompiler.getResolver( NamedTableNode.create( null, @@ -107,7 +109,6 @@ public class PhoenixSchema implements Schema { tableMap.put(tableName, tables.get(0).getTable()); } else { String viewSql = rs.getString(PhoenixDatabaseMetaData.VIEW_STATEMENT); - String viewType = rs.getString(PhoenixDatabaseMetaData.VIEW_TYPE); viewDefMap.put(tableName, new ViewDef(viewSql, viewType.equals(ViewType.UPDATABLE.name()))); } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/413247da/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java index cb07a7c..df6e338 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixTable.java @@ -50,8 +50,9 @@ public class PhoenixTable extends AbstractTable implements TranslatableTable { this.pTable = Preconditions.checkNotNull(pTable); List<Integer> pkPositions = Lists.<Integer> newArrayList(); List<RelFieldCollation> fieldCollations = Lists.<RelFieldCollation> newArrayList(); - for (PColumn column : pTable.getPKColumns()) { - int position = column.getPosition(); + int start = getStartingColumnPosition(pTable); + for (PColumn column : pTable.getPKColumns().subList(start, pTable.getPKColumns().size())) { + int position = column.getPosition() - start; SortOrder sortOrder = column.getSortOrder(); pkPositions.add(position); fieldCollations.add(new RelFieldCollation(position, sortOrder == SortOrder.ASC ? Direction.ASCENDING : Direction.DESCENDING)); http://git-wip-us.apache.org/repos/asf/phoenix/blob/413247da/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixTableScan.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixTableScan.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixTableScan.java index 1933ccb..864b4ca 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixTableScan.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/rel/PhoenixTableScan.java @@ -239,20 +239,21 @@ public class PhoenixTableScan extends TableScan implements PhoenixRel { StatementContext context = new StatementContext(stmt, resolver, new Scan(), new SequenceManager(stmt)); SelectStatement select = SelectStatement.SELECT_ONE; ImmutableIntList columnRefList = implementor.getCurrentContext().columnRefList; + Expression filterExpr = LiteralExpression.newConstant(Boolean.TRUE); Expression dynamicFilter = null; if (filter != null) { ImmutableBitSet bitSet = InputFinder.analyze(filter).inputBitSet.addAll(columnRefList).build(); columnRefList = ImmutableIntList.copyOf(bitSet.asList()); - Expression filterExpr = CalciteUtils.toExpression(filter, implementor); - filterExpr = WhereOptimizer.pushKeyExpressionsToScan(context, select, filterExpr); - WhereCompiler.setScanFilter(context, select, filterExpr, true, false); - // TODO This is not absolutely strict. We may have a filter like: - // pk = '0' and pk = $cor0 where $cor0 happens to get a sample value - // as '0', thus making the below test return false and adding an - // unnecessary dynamic filter. This would only be a performance bug though. - if (!context.getScanRanges().equals(this.scanRanges)) { - dynamicFilter = filterExpr; - } + filterExpr = CalciteUtils.toExpression(filter, implementor); + } + filterExpr = WhereOptimizer.pushKeyExpressionsToScan(context, select, filterExpr); + WhereCompiler.setScanFilter(context, select, filterExpr, true, false); + // TODO This is not absolutely strict. We may have a filter like: + // pk = '0' and pk = $cor0 where $cor0 happens to get a sample value + // as '0', thus making the below test return false and adding an + // unnecessary dynamic filter. This would only be a performance bug though. + if (filter != null && !context.getScanRanges().equals(this.scanRanges)) { + dynamicFilter = filterExpr; } projectColumnFamilies(context.getScan(), phoenixTable.getTable(), columnRefList); if (implementor.getCurrentContext().forceProject) {
