You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ja...@apache.org on 2014/10/20 02:19:47 UTC

[2/3] git commit: PHOENIX-1271 hide tenant column in tenant-specific connections (Bruno Dumon)

PHOENIX-1271 hide tenant column in tenant-specific
 connections (Bruno Dumon)


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

Branch: refs/heads/4.0
Commit: bed96f15d80d4565dd116b57a2677bb8f3b65a31
Parents: b90f518
Author: James Taylor <jt...@salesforce.com>
Authored: Sun Oct 19 15:47:39 2014 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Sun Oct 19 17:24:11 2014 -0700

----------------------------------------------------------------------
 .../end2end/TenantSpecificTablesDDLIT.java      |  6 +-
 .../phoenix/jdbc/PhoenixDatabaseMetaData.java   | 86 +++++++++++++++++++-
 2 files changed, 84 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/bed96f15/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
index a9fa412..589e963 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/TenantSpecificTablesDDLIT.java
@@ -556,8 +556,7 @@ public class TenantSpecificTablesDDLIT extends BaseTenantSpecificTablesIT {
             assertTrue(rs.next());
             assertColumnMetaData(rs, null, TENANT_TABLE_NAME, "user");
             assertTrue(rs.next());
-            assertColumnMetaData(rs, null, TENANT_TABLE_NAME, "tenant_id");
-            assertTrue(rs.next());
+            // (tenant_id column is not visible in tenant-specific connection)
             assertColumnMetaData(rs, null, TENANT_TABLE_NAME, "tenant_type_id");
             assertTrue(rs.next());
             assertColumnMetaData(rs, null, TENANT_TABLE_NAME, "id");
@@ -566,8 +565,7 @@ public class TenantSpecificTablesDDLIT extends BaseTenantSpecificTablesIT {
             assertTrue(rs.next());
             assertColumnMetaData(rs, null, TENANT_TABLE_NAME_NO_TENANT_TYPE_ID, "user");
             assertTrue(rs.next());
-            assertColumnMetaData(rs, null, TENANT_TABLE_NAME_NO_TENANT_TYPE_ID, "tenant_id");
-            assertTrue(rs.next());
+            // (tenant_id column is not visible in tenant-specific connection)
             assertColumnMetaData(rs, null, TENANT_TABLE_NAME_NO_TENANT_TYPE_ID, "id");
             assertTrue(rs.next());
             assertColumnMetaData(rs, null, TENANT_TABLE_NAME_NO_TENANT_TYPE_ID, "tenant_col");

http://git-wip-us.apache.org/repos/asf/phoenix/blob/bed96f15/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
index 7a1f2be..54dfae3 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixDatabaseMetaData.java
@@ -42,7 +42,9 @@ import org.apache.phoenix.expression.function.SQLIndexTypeFunction;
 import org.apache.phoenix.expression.function.SQLTableTypeFunction;
 import org.apache.phoenix.expression.function.SQLViewTypeFunction;
 import org.apache.phoenix.expression.function.SqlTypeNameFunction;
+import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
 import org.apache.phoenix.hbase.index.util.VersionUtil;
+import org.apache.phoenix.iterate.DelegateResultIterator;
 import org.apache.phoenix.iterate.MaterializedResultIterator;
 import org.apache.phoenix.iterate.ResultIterator;
 import org.apache.phoenix.parse.HintNode.Hint;
@@ -372,7 +374,7 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho
     }
 
     private static void appendConjunction(StringBuilder buf) {
-        buf.append(buf.length() == 0 ? " where " : " and ");
+        buf.append(buf.length() == 0 ? "" : " and ");
     }
     
     @Override
@@ -404,7 +406,9 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho
                 ARRAY_SIZE + "," +
                 COLUMN_FAMILY + "," +
                 DATA_TYPE + " " + TYPE_ID + "," +// raw type id for potential internal consumption
-                VIEW_CONSTANT +
+                VIEW_CONSTANT + "," +
+                MULTI_TENANT + "," +
+                KEY_SEQ +
                 " from " + SYSTEM_CATALOG + " " + SYSTEM_CATALOG_ALIAS);
         StringBuilder where = new StringBuilder();
         addTenantIdFilter(where, catalog);
@@ -443,12 +447,86 @@ public class PhoenixDatabaseMetaData implements DatabaseMetaData, org.apache.pho
             appendConjunction(where);
             where.append(COLUMN_NAME + " is not null" );
         }
-        buf.append(where);
+        boolean isTenantSpecificConnection = connection.getTenantId() != null;
+        if (isTenantSpecificConnection) {
+            buf.append(" where (" + where + ") OR ("
+                    + COLUMN_FAMILY + " is null AND " +  COLUMN_NAME + " is null)");
+        } else {
+            buf.append(" where " + where);
+        }
         buf.append(" order by " + TENANT_ID + "," + TABLE_SCHEM + "," + TABLE_NAME + "," + ORDINAL_POSITION);
-        Statement stmt = connection.createStatement();
+
+        Statement stmt;
+        if (isTenantSpecificConnection) {
+            stmt = connection.createStatement(new PhoenixStatementFactory() {
+                @Override
+                public PhoenixStatement newStatement(PhoenixConnection connection) {
+                    return new PhoenixStatement(connection) {
+                        @Override
+                        protected PhoenixResultSet newResultSet(ResultIterator iterator, RowProjector projector)
+                                throws SQLException {
+                            return new PhoenixResultSet(
+                                    new TenantColumnFilteringIterator(iterator, projector),
+                                    projector, this);
+                        }
+                    };
+                }
+            });
+        } else {
+            stmt = connection.createStatement();
+        }
         return stmt.executeQuery(buf.toString());
     }
 
+    /**
+     * Filters the tenant id column out of a column metadata result set (thus, where each row is a column definition).
+     * The tenant id is by definition the first column of the primary key, but the primary key does not necessarily
+     * start at the first column. Assumes columns are sorted on ordinal position.
+     */
+    private static class TenantColumnFilteringIterator extends DelegateResultIterator {
+        private final RowProjector rowProjector;
+        private final int columnFamilyIndex;
+        private final int columnNameIndex;
+        private final int multiTenantIndex;
+        private final int keySeqIndex;
+        private boolean inMultiTenantTable;
+
+        private TenantColumnFilteringIterator(ResultIterator delegate, RowProjector rowProjector) throws SQLException {
+            super(delegate);
+            this.rowProjector = rowProjector;
+            this.columnFamilyIndex = rowProjector.getColumnIndex(COLUMN_FAMILY);
+            this.columnNameIndex = rowProjector.getColumnIndex(COLUMN_NAME);
+            this.multiTenantIndex = rowProjector.getColumnIndex(MULTI_TENANT);
+            this.keySeqIndex = rowProjector.getColumnIndex(KEY_SEQ);
+        }
+
+        @Override
+        public Tuple next() throws SQLException {
+            Tuple tuple = super.next();
+
+            while (tuple != null
+                    && getColumn(tuple, columnFamilyIndex) == null && getColumn(tuple, columnNameIndex) == null) {
+                // new table, check if it is multitenant
+                inMultiTenantTable = getColumn(tuple, multiTenantIndex) == Boolean.TRUE;
+                // skip row representing table
+                tuple = super.next();
+            }
+
+            if (tuple != null && inMultiTenantTable && new Short((short)1).equals(getColumn(tuple, keySeqIndex))) {
+                // skip tenant id primary key column
+                return next();
+            }
+
+            return tuple;
+        }
+
+        private Object getColumn(Tuple tuple, int index) throws SQLException {
+            ColumnProjector projector = this.rowProjector.getColumnProjector(index);
+            PDataType type = projector.getExpression().getDataType();
+            return projector.getValue(tuple, type, new ImmutableBytesPtr());
+        }
+    }
+
     @Override
     public Connection getConnection() throws SQLException {
         return connection;