use of org.apache.phoenix.parse.BindParseNode in project phoenix by apache.
the class CreateTableCompiler method compile.
public MutationPlan compile(CreateTableStatement create) throws SQLException {
final PhoenixConnection connection = statement.getConnection();
ColumnResolver resolver = FromCompiler.getResolverForCreation(create, connection);
PTableType type = create.getTableType();
PhoenixConnection connectionToBe = connection;
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;
// 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();
viewTypeToBe = parentToBe.getViewType() == ViewType.MAPPED ? ViewType.MAPPED : ViewType.UPDATABLE;
if (whereNode == null) {
viewStatementToBe = parentToBe.getViewStatement();
} 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();
}
Expression 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) {
Long scn = connection.getSCN();
connectionToBe = (scn != null || tableRef.getTable().isTransactional()) ? connection : // clocks being in sync.
new PhoenixConnection(// on our connection.
new DelegateConnectionQueryServices(connection.getQueryServices()) {
@Override
public void addTable(PTable table, long resolvedTime) throws SQLException {
connection.addTable(table, resolvedTime);
}
}, connection, tableRef.getTimeStamp() + 1);
viewColumnConstantsToBe = new byte[nColumns][];
ViewWhereExpressionVisitor visitor = new ViewWhereExpressionVisitor(parentToBe, viewColumnConstantsToBe);
where.accept(visitor);
// If view is not updatable, viewColumnConstants should be empty. We will still
// inherit our parent viewConstants, but we have no additional ones.
viewTypeToBe = visitor.isUpdatable() ? ViewType.UPDATABLE : ViewType.READ_ONLY;
if (viewTypeToBe != ViewType.UPDATABLE) {
viewColumnConstantsToBe = null;
}
}
}
}
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(connectionToBe);
final PTable parent = parentToBe;
return new BaseMutationPlan(context, operation) {
@Override
public MutationState execute() throws SQLException {
try {
return client.createTable(finalCreate, splits, parent, viewStatement, viewType, viewColumnConstants, isViewColumnReferenced);
} finally {
if (client.getConnection() != connection) {
client.getConnection().close();
}
}
}
@Override
public ExplainPlan getExplainPlan() throws SQLException {
return new ExplainPlan(Collections.singletonList("CREATE TABLE"));
}
};
}
Aggregations