NihalJain commented on code in PR #2024:
URL: https://github.com/apache/phoenix/pull/2024#discussion_r2047051616
##########
phoenix-core-client/src/main/java/org/apache/phoenix/compile/CreateTableCompiler.java:
##########
@@ -84,712 +87,689 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static
org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CHILD_LINK_NAMESPACE_BYTES;
-import static
org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.SYSTEM_CHILD_LINK_NAME_BYTES;
-import static
org.apache.phoenix.query.QueryServices.DEFAULT_PHOENIX_UPDATABLE_VIEW_RESTRICTION_ENABLED;
-import static
org.apache.phoenix.query.QueryServices.PHOENIX_UPDATABLE_VIEW_RESTRICTION_ENABLED;
-
+import org.apache.phoenix.thirdparty.com.google.common.collect.Iterators;
public class CreateTableCompiler {
- private static final Logger LOGGER =
LoggerFactory.getLogger(CreateTableCompiler.class);
- private static final PDatum VARBINARY_DATUM = new VarbinaryDatum();
- private final PhoenixStatement statement;
- private final Operation operation;
-
- public CreateTableCompiler(PhoenixStatement statement, Operation
operation) {
- this.statement = statement;
- this.operation = operation;
- }
-
- public MutationPlan compile(CreateTableStatement create) throws
SQLException {
- final PhoenixConnection connection = statement.getConnection();
- ColumnResolver resolver = FromCompiler.getResolverForCreation(create,
connection);
- PTableType type = create.getTableType();
- PTable parentToBe = null;
- ViewType viewTypeToBe = null;
- Scan scan = new Scan();
- final StatementContext context = new StatementContext(statement,
resolver, scan, new SequenceManager(statement));
- // TODO: support any statement for a VIEW instead of just a WHERE
clause
- ParseNode whereNode = create.getWhereClause();
- String viewStatementToBe = null;
- byte[][] viewColumnConstantsToBe = null;
- BitSet isViewColumnReferencedToBe = null;
- Set<PColumn> pkColumnsInWhere = new HashSet<>();
- Set<PColumn> nonPkColumnsInWhere = new HashSet<>();
- byte[] rowKeyMatcher = ByteUtil.EMPTY_BYTE_ARRAY;
-
- // Check whether column families having local index column family
suffix or not if present
- // don't allow creating table.
- // Also validate the default values expressions.
- List<ColumnDef> columnDefs = create.getColumnDefs();
- List<ColumnDef> overideColumnDefs = null;
- PrimaryKeyConstraint pkConstraint = create.getPrimaryKeyConstraint();
- for (int i = 0; i < columnDefs.size(); i++) {
- ColumnDef columnDef = columnDefs.get(i);
- if (columnDef.getColumnDefName().getFamilyName()!=null &&
columnDef.getColumnDefName().getFamilyName().contains(QueryConstants.LOCAL_INDEX_COLUMN_FAMILY_PREFIX))
{
- throw new
SQLExceptionInfo.Builder(SQLExceptionCode.UNALLOWED_COLUMN_FAMILY)
- .build().buildException();
- }
- // False means we do not need the default (because it evaluated to
null)
- if (!columnDef.validateDefault(context, pkConstraint)) {
- if (overideColumnDefs == null) {
- overideColumnDefs = new ArrayList<>(columnDefs);
- }
- overideColumnDefs.set(i, new ColumnDef(columnDef, null));
- }
- }
- if (overideColumnDefs != null) {
- create = new CreateTableStatement(create,overideColumnDefs);
- }
- final CreateTableStatement finalCreate = create;
-
- if (type == PTableType.VIEW) {
- TableRef tableRef = resolver.getTables().get(0);
- int nColumns = tableRef.getTable().getColumns().size();
- isViewColumnReferencedToBe = new BitSet(nColumns);
- // Used to track column references in a view
- ExpressionCompiler expressionCompiler = new
ColumnTrackingExpressionCompiler(context, isViewColumnReferencedToBe);
- parentToBe = tableRef.getTable();
-
- // Disallow creating views on top of SYSTEM tables. See
PHOENIX-5386
- if (parentToBe.getType() == PTableType.SYSTEM) {
- throw new SQLExceptionInfo
-
.Builder(SQLExceptionCode.CANNOT_CREATE_VIEWS_ON_SYSTEM_TABLES)
- .build().buildException();
- }
- viewTypeToBe = parentToBe.getViewType() == ViewType.MAPPED ?
ViewType.MAPPED : ViewType.UPDATABLE;
- Expression where = null;
- if (whereNode == null) {
- if (parentToBe.getViewType() == ViewType.READ_ONLY) {
- viewTypeToBe = ViewType.READ_ONLY;
- }
- viewStatementToBe = parentToBe.getViewStatement();
- if (viewStatementToBe != null) {
- SelectStatement select = new
SQLParser(viewStatementToBe).parseQuery();
- whereNode = select.getWhere();
- where = whereNode.accept(expressionCompiler);
- }
- } else {
- whereNode = StatementNormalizer.normalize(whereNode, resolver);
- if (whereNode.isStateless()) {
- throw new
SQLExceptionInfo.Builder(SQLExceptionCode.VIEW_WHERE_IS_CONSTANT)
- .build().buildException();
- }
- // If our parent has a VIEW statement, combine it with this one
- if (parentToBe.getViewStatement() != null) {
- SelectStatement select = new
SQLParser(parentToBe.getViewStatement()).parseQuery().combine(whereNode);
- whereNode = select.getWhere();
- }
- where = whereNode.accept(expressionCompiler);
- if (where != null && !LiteralExpression.isTrue(where)) {
- TableName baseTableName = create.getBaseTableName();
- StringBuilder buf = new StringBuilder();
- whereNode.toSQL(resolver, buf);
- viewStatementToBe =
QueryUtil.getViewStatement(baseTableName.getSchemaName(),
baseTableName.getTableName(), buf.toString());
- }
- if (viewTypeToBe != ViewType.MAPPED) {
- viewColumnConstantsToBe = new byte[nColumns][];
- ViewWhereExpressionVisitor visitor = new
ViewWhereExpressionVisitor(parentToBe, viewColumnConstantsToBe);
- where.accept(visitor);
-
- viewTypeToBe = visitor.isUpdatable() ? ViewType.UPDATABLE
: ViewType.READ_ONLY;
- boolean updatableViewRestrictionEnabled =
connection.getQueryServices()
-
.getProps().getBoolean(PHOENIX_UPDATABLE_VIEW_RESTRICTION_ENABLED,
-
DEFAULT_PHOENIX_UPDATABLE_VIEW_RESTRICTION_ENABLED);
- if (viewTypeToBe == ViewType.UPDATABLE &&
updatableViewRestrictionEnabled) {
- ViewWhereExpressionValidatorVisitor validatorVisitor =
- new
ViewWhereExpressionValidatorVisitor(parentToBe,
- pkColumnsInWhere, nonPkColumnsInWhere);
- where.accept(validatorVisitor);
- if (!(connection.getQueryServices()
- instanceof ConnectionlessQueryServicesImpl)) {
- try {
- viewTypeToBe = setViewTypeToBe(connection,
parentToBe,
- pkColumnsInWhere, nonPkColumnsInWhere);
- LOGGER.info("VIEW type is set to {}. View
Statement: {}, " +
- "View Name: {}, " +
- "Parent Table/View Name: {}",
- viewTypeToBe, viewStatementToBe,
- create.getTableName(),
parentToBe.getName());
- } catch (IOException e) {
- throw new SQLException(e);
- }
- }
- }
-
- // If view is not updatable, viewColumnConstants should be
empty. We will still
- // inherit our parent viewConstants, but we have no
additional ones.
- if (viewTypeToBe != ViewType.UPDATABLE) {
- viewColumnConstantsToBe = null;
- }
- }
- }
- if (viewTypeToBe == ViewType.MAPPED
- && parentToBe.getPKColumns().isEmpty()) {
- validateCreateViewCompilation(connection, parentToBe,
- columnDefs, pkConstraint);
- } else if (where != null && viewTypeToBe == ViewType.UPDATABLE) {
- rowKeyMatcher = WhereOptimizer.getRowKeyMatcher(context,
create.getTableName(),
- parentToBe, where);
- }
- verifyIfAnyParentHasIndexesAndViewExtendsPk(parentToBe,
columnDefs, pkConstraint);
- }
- final ViewType viewType = viewTypeToBe;
- final String viewStatement = viewStatementToBe;
- final byte[][] viewColumnConstants = viewColumnConstantsToBe;
- final BitSet isViewColumnReferenced = isViewColumnReferencedToBe;
- List<ParseNode> splitNodes = create.getSplitNodes();
- final byte[][] splits = new byte[splitNodes.size()][];
- ImmutableBytesWritable ptr = context.getTempPtr();
- ExpressionCompiler expressionCompiler = new
ExpressionCompiler(context);
- for (int i = 0; i < splits.length; i++) {
- ParseNode node = splitNodes.get(i);
- if (node instanceof BindParseNode) {
- context.getBindManager().addParamMetaData((BindParseNode)
node, VARBINARY_DATUM);
- }
- if (node.isStateless()) {
- Expression expression = node.accept(expressionCompiler);
- if (expression.evaluate(null, ptr)) {;
- splits[i] = ByteUtil.copyKeyBytesIfNecessary(ptr);
- continue;
- }
+ private static final Logger LOGGER =
LoggerFactory.getLogger(CreateTableCompiler.class);
+ private static final PDatum VARBINARY_DATUM = new VarbinaryDatum();
+ private final PhoenixStatement statement;
+ private final Operation operation;
+
+ public CreateTableCompiler(PhoenixStatement statement, Operation operation) {
+ this.statement = statement;
+ this.operation = operation;
+ }
+
+ public MutationPlan compile(CreateTableStatement create) throws SQLException
{
+ final PhoenixConnection connection = statement.getConnection();
+ ColumnResolver resolver = FromCompiler.getResolverForCreation(create,
connection);
+ PTableType type = create.getTableType();
+ PTable parentToBe = null;
+ ViewType viewTypeToBe = null;
+ Scan scan = new Scan();
+ final StatementContext context =
+ new StatementContext(statement, resolver, scan, new
SequenceManager(statement));
+ // TODO: support any statement for a VIEW instead of just a WHERE clause
+ ParseNode whereNode = create.getWhereClause();
+ String viewStatementToBe = null;
+ byte[][] viewColumnConstantsToBe = null;
+ BitSet isViewColumnReferencedToBe = null;
+ Set<PColumn> pkColumnsInWhere = new HashSet<>();
+ Set<PColumn> nonPkColumnsInWhere = new HashSet<>();
+ byte[] rowKeyMatcher = ByteUtil.EMPTY_BYTE_ARRAY;
+
+ // Check whether column families having local index column family suffix
or not if present
+ // don't allow creating table.
+ // Also validate the default values expressions.
+ List<ColumnDef> columnDefs = create.getColumnDefs();
+ List<ColumnDef> overideColumnDefs = null;
+ PrimaryKeyConstraint pkConstraint = create.getPrimaryKeyConstraint();
+ for (int i = 0; i < columnDefs.size(); i++) {
+ ColumnDef columnDef = columnDefs.get(i);
+ if (
+ columnDef.getColumnDefName().getFamilyName() != null &&
columnDef.getColumnDefName()
+
.getFamilyName().contains(QueryConstants.LOCAL_INDEX_COLUMN_FAMILY_PREFIX)
+ ) {
+ throw new
SQLExceptionInfo.Builder(SQLExceptionCode.UNALLOWED_COLUMN_FAMILY).build()
+ .buildException();
+ }
+ // False means we do not need the default (because it evaluated to null)
+ if (!columnDef.validateDefault(context, pkConstraint)) {
+ if (overideColumnDefs == null) {
+ overideColumnDefs = new ArrayList<>(columnDefs);
+ }
+ overideColumnDefs.set(i, new ColumnDef(columnDef, null));
+ }
+ }
+ if (overideColumnDefs != null) {
+ create = new CreateTableStatement(create, overideColumnDefs);
+ }
+ final CreateTableStatement finalCreate = create;
+
+ if (type == PTableType.VIEW) {
+ TableRef tableRef = resolver.getTables().get(0);
+ int nColumns = tableRef.getTable().getColumns().size();
+ isViewColumnReferencedToBe = new BitSet(nColumns);
+ // Used to track column references in a view
+ ExpressionCompiler expressionCompiler =
+ new ColumnTrackingExpressionCompiler(context,
isViewColumnReferencedToBe);
+ parentToBe = tableRef.getTable();
+
+ // Disallow creating views on top of SYSTEM tables. See PHOENIX-5386
+ if (parentToBe.getType() == PTableType.SYSTEM) {
+ throw new
SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_CREATE_VIEWS_ON_SYSTEM_TABLES)
+ .build().buildException();
+ }
+ viewTypeToBe =
+ parentToBe.getViewType() == ViewType.MAPPED ? ViewType.MAPPED :
ViewType.UPDATABLE;
+ Expression where = null;
+ if (whereNode == null) {
+ if (parentToBe.getViewType() == ViewType.READ_ONLY) {
+ viewTypeToBe = ViewType.READ_ONLY;
+ }
+ viewStatementToBe = parentToBe.getViewStatement();
+ if (viewStatementToBe != null) {
+ SelectStatement select = new
SQLParser(viewStatementToBe).parseQuery();
+ whereNode = select.getWhere();
+ where = whereNode.accept(expressionCompiler);
+ }
+ } else {
+ whereNode = StatementNormalizer.normalize(whereNode, resolver);
+ if (whereNode.isStateless()) {
+ throw new
SQLExceptionInfo.Builder(SQLExceptionCode.VIEW_WHERE_IS_CONSTANT).build()
+ .buildException();
+ }
+ // If our parent has a VIEW statement, combine it with this one
+ if (parentToBe.getViewStatement() != null) {
+ SelectStatement select =
+ new
SQLParser(parentToBe.getViewStatement()).parseQuery().combine(whereNode);
+ whereNode = select.getWhere();
+ }
+ where = whereNode.accept(expressionCompiler);
+ if (where != null && !LiteralExpression.isTrue(where)) {
+ TableName baseTableName = create.getBaseTableName();
+ StringBuilder buf = new StringBuilder();
+ whereNode.toSQL(resolver, buf);
+ viewStatementToBe =
QueryUtil.getViewStatement(baseTableName.getSchemaName(),
+ baseTableName.getTableName(), buf.toString());
+ }
+ if (viewTypeToBe != ViewType.MAPPED) {
+ viewColumnConstantsToBe = new byte[nColumns][];
+ ViewWhereExpressionVisitor visitor =
+ new ViewWhereExpressionVisitor(parentToBe,
viewColumnConstantsToBe);
+ where.accept(visitor);
+
+ viewTypeToBe = visitor.isUpdatable() ? ViewType.UPDATABLE :
ViewType.READ_ONLY;
+ boolean updatableViewRestrictionEnabled =
connection.getQueryServices().getProps()
+ .getBoolean(PHOENIX_UPDATABLE_VIEW_RESTRICTION_ENABLED,
+ DEFAULT_PHOENIX_UPDATABLE_VIEW_RESTRICTION_ENABLED);
+ if (viewTypeToBe == ViewType.UPDATABLE &&
updatableViewRestrictionEnabled) {
+ ViewWhereExpressionValidatorVisitor validatorVisitor =
+ new ViewWhereExpressionValidatorVisitor(parentToBe,
pkColumnsInWhere,
+ nonPkColumnsInWhere);
+ where.accept(validatorVisitor);
+ if (!(connection.getQueryServices() instanceof
ConnectionlessQueryServicesImpl)) {
+ try {
+ viewTypeToBe =
+ setViewTypeToBe(connection, parentToBe, pkColumnsInWhere,
nonPkColumnsInWhere);
+ LOGGER.info(
+ "VIEW type is set to {}. View Statement: {}, " + "View Name:
{}, "
+ + "Parent Table/View Name: {}",
+ viewTypeToBe, viewStatementToBe, create.getTableName(),
parentToBe.getName());
+ } catch (IOException e) {
+ throw new SQLException(e);
+ }
}
- throw new
SQLExceptionInfo.Builder(SQLExceptionCode.SPLIT_POINT_NOT_CONSTANT)
- .setMessage("Node: " + node).build().buildException();
- }
- final MetaDataClient client = new MetaDataClient(connection);
- final PTable parent = parentToBe;
-
- return new CreateTableMutationPlan(context, client, finalCreate,
splits, parent,
- viewStatement, viewType, rowKeyMatcher,
- viewColumnConstants, isViewColumnReferenced, connection);
- }
-
- /**
- * Restrict view to be UPDATABLE if the view specification:
- * 1. uses only the PK columns;
- * 2. starts from the first PK column (ignore the prefix PK columns,
TENANT_ID and/or
- * _SALTED, if the parent table is multi-tenant and/or salted);
- * 3. PK columns should be in the order they are defined;
- * 4. uses the same set of PK columns as its sibling views' specification;
- * Otherwise, mark the view as READ_ONLY.
- *
- * @param connection The client connection
- * @param parentToBe To be parent for given view
- * @param pkColumnsInWhere Set of primary key in where clause
- * @param nonPkColumnsInWhere Set of non-primary key columns in where
clause
- * @throws IOException thrown if there is an error finding sibling views
- * @throws SQLException
- */
- private ViewType setViewTypeToBe(final PhoenixConnection connection, final
PTable parentToBe,
- final Set<PColumn> pkColumnsInWhere,
- final Set<PColumn> nonPkColumnsInWhere)
- throws IOException, SQLException {
- // 1. Check the view specification WHERE clause uses only the PK
columns
- if (!nonPkColumnsInWhere.isEmpty()) {
- LOGGER.info("Setting the view type as READ_ONLY because the view
statement contains " +
- "non-PK columns: {}", nonPkColumnsInWhere);
- return ViewType.READ_ONLY;
- }
- if (pkColumnsInWhere.isEmpty()) {
- return ViewType.UPDATABLE;
- }
+ }
+
+ // If view is not updatable, viewColumnConstants should be empty. We
will still
+ // inherit our parent viewConstants, but we have no additional ones.
+ if (viewTypeToBe != ViewType.UPDATABLE) {
+ viewColumnConstantsToBe = null;
+ }
+ }
+ }
+ if (viewTypeToBe == ViewType.MAPPED &&
parentToBe.getPKColumns().isEmpty()) {
+ validateCreateViewCompilation(connection, parentToBe, columnDefs,
pkConstraint);
+ } else if (where != null && viewTypeToBe == ViewType.UPDATABLE) {
+ rowKeyMatcher =
+ WhereOptimizer.getRowKeyMatcher(context, create.getTableName(),
parentToBe, where);
+ }
+ verifyIfAnyParentHasIndexesAndViewExtendsPk(parentToBe, columnDefs,
pkConstraint);
+ }
+ final ViewType viewType = viewTypeToBe;
+ final String viewStatement = viewStatementToBe;
+ final byte[][] viewColumnConstants = viewColumnConstantsToBe;
+ final BitSet isViewColumnReferenced = isViewColumnReferencedToBe;
+ List<ParseNode> splitNodes = create.getSplitNodes();
+ final byte[][] splits = new byte[splitNodes.size()][];
+ ImmutableBytesWritable ptr = context.getTempPtr();
+ ExpressionCompiler expressionCompiler = new ExpressionCompiler(context);
+ for (int i = 0; i < splits.length; i++) {
+ ParseNode node = splitNodes.get(i);
+ if (node instanceof BindParseNode) {
+ context.getBindManager().addParamMetaData((BindParseNode) node,
VARBINARY_DATUM);
+ }
+ if (node.isStateless()) {
+ Expression expression = node.accept(expressionCompiler);
+ if (expression.evaluate(null, ptr)) {
+ ;
+ splits[i] = ByteUtil.copyKeyBytesIfNecessary(ptr);
+ continue;
+ }
+ }
+ throw new
SQLExceptionInfo.Builder(SQLExceptionCode.SPLIT_POINT_NOT_CONSTANT)
+ .setMessage("Node: " + node).build().buildException();
+ }
+ final MetaDataClient client = new MetaDataClient(connection);
+ final PTable parent = parentToBe;
+
+ return new CreateTableMutationPlan(context, client, finalCreate, splits,
parent, viewStatement,
+ viewType, rowKeyMatcher, viewColumnConstants, isViewColumnReferenced,
connection);
+ }
+
+ /**
+ * Restrict view to be UPDATABLE if the view specification: 1. uses only the
PK columns; 2. starts
Review Comment:
fix
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]