Search in sources :

Example 1 with DelegateConnectionQueryServices

use of org.apache.phoenix.query.DelegateConnectionQueryServices in project phoenix by apache.

the class UpgradeIT method testUpgradingConnectionBypassesUpgradeRequiredCheck.

@Test
public void testUpgradingConnectionBypassesUpgradeRequiredCheck() throws Exception {
    String tableName = generateUniqueName();
    try (Connection conn = getConnection(false, null)) {
        conn.createStatement().execute("CREATE TABLE " + tableName + " (PK1 VARCHAR NOT NULL, PK2 VARCHAR, KV1 VARCHAR, KV2 VARCHAR CONSTRAINT PK PRIMARY KEY(PK1, PK2))");
        final ConnectionQueryServices delegate = conn.unwrap(PhoenixConnection.class).getQueryServices();
        ConnectionQueryServices servicesWithUpgrade = new DelegateConnectionQueryServices(delegate) {

            @Override
            public boolean isUpgradeRequired() {
                return true;
            }
        };
        try (PhoenixConnection phxConn = new PhoenixConnection(servicesWithUpgrade, conn.unwrap(PhoenixConnection.class), HConstants.LATEST_TIMESTAMP)) {
            // Because upgrade is required, this SQL should fail.
            try {
                phxConn.createStatement().executeQuery("SELECT * FROM " + tableName);
                fail("SELECT should have failed with UpgradeRequiredException");
            } catch (UpgradeRequiredException expected) {
            }
            // Marking connection as the one running upgrade should let SQL execute fine.
            phxConn.setRunningUpgrade(true);
            phxConn.createStatement().execute("UPSERT INTO " + tableName + " VALUES ('PK1', 'PK2', 'KV1', 'KV2')");
            phxConn.commit();
            try (ResultSet rs = phxConn.createStatement().executeQuery("SELECT * FROM " + tableName)) {
                assertTrue(rs.next());
                assertFalse(rs.next());
            }
        }
    }
}
Also used : UpgradeRequiredException(org.apache.phoenix.exception.UpgradeRequiredException) PhoenixConnection(org.apache.phoenix.jdbc.PhoenixConnection) Connection(java.sql.Connection) PhoenixConnection(org.apache.phoenix.jdbc.PhoenixConnection) ResultSet(java.sql.ResultSet) DelegateConnectionQueryServices(org.apache.phoenix.query.DelegateConnectionQueryServices) DelegateConnectionQueryServices(org.apache.phoenix.query.DelegateConnectionQueryServices) ConnectionQueryServices(org.apache.phoenix.query.ConnectionQueryServices) Test(org.junit.Test)

Example 2 with DelegateConnectionQueryServices

use of org.apache.phoenix.query.DelegateConnectionQueryServices in project phoenix by apache.

the class UpgradeIT method testUpgradeRequiredPreventsSQL.

@Test
public void testUpgradeRequiredPreventsSQL() throws SQLException {
    String tableName = generateUniqueName();
    try (Connection conn = getConnection(false, null)) {
        conn.createStatement().execute("CREATE TABLE " + tableName + " (PK1 VARCHAR NOT NULL, PK2 VARCHAR, KV1 VARCHAR, KV2 VARCHAR CONSTRAINT PK PRIMARY KEY(PK1, PK2))");
        final ConnectionQueryServices delegate = conn.unwrap(PhoenixConnection.class).getQueryServices();
        ConnectionQueryServices servicesWithUpgrade = new DelegateConnectionQueryServices(delegate) {

            @Override
            public boolean isUpgradeRequired() {
                return true;
            }
        };
        try (PhoenixConnection phxConn = new PhoenixConnection(servicesWithUpgrade, conn.unwrap(PhoenixConnection.class), HConstants.LATEST_TIMESTAMP)) {
            try {
                phxConn.createStatement().execute("CREATE TABLE " + generateUniqueName() + " (k1 VARCHAR NOT NULL, k2 VARCHAR, CONSTRAINT PK PRIMARY KEY(K1,K2))");
                fail("CREATE TABLE should have failed with UpgradeRequiredException");
            } catch (UpgradeRequiredException expected) {
            }
            try {
                phxConn.createStatement().execute("SELECT * FROM " + tableName);
                fail("SELECT should have failed with UpgradeRequiredException");
            } catch (UpgradeRequiredException expected) {
            }
            try {
                phxConn.createStatement().execute("DELETE FROM " + tableName);
                fail("DELETE should have failed with UpgradeRequiredException");
            } catch (UpgradeRequiredException expected) {
            }
            try {
                phxConn.createStatement().execute("CREATE INDEX " + tableName + "_IDX ON " + tableName + " (KV1) INCLUDE (KV2)");
                fail("CREATE INDEX should have failed with UpgradeRequiredException");
            } catch (UpgradeRequiredException expected) {
            }
            try {
                phxConn.createStatement().execute("UPSERT INTO " + tableName + " VALUES ('PK1', 'PK2', 'KV1', 'KV2')");
                fail("UPSERT VALUES should have failed with UpgradeRequiredException");
            } catch (UpgradeRequiredException expected) {
            }
        }
    }
}
Also used : UpgradeRequiredException(org.apache.phoenix.exception.UpgradeRequiredException) PhoenixConnection(org.apache.phoenix.jdbc.PhoenixConnection) Connection(java.sql.Connection) PhoenixConnection(org.apache.phoenix.jdbc.PhoenixConnection) DelegateConnectionQueryServices(org.apache.phoenix.query.DelegateConnectionQueryServices) DelegateConnectionQueryServices(org.apache.phoenix.query.DelegateConnectionQueryServices) ConnectionQueryServices(org.apache.phoenix.query.ConnectionQueryServices) Test(org.junit.Test)

Example 3 with DelegateConnectionQueryServices

use of org.apache.phoenix.query.DelegateConnectionQueryServices 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"));
        }
    };
}
Also used : PhoenixConnection(org.apache.phoenix.jdbc.PhoenixConnection) SQLException(java.sql.SQLException) DelegateConnectionQueryServices(org.apache.phoenix.query.DelegateConnectionQueryServices) PTable(org.apache.phoenix.schema.PTable) SelectStatement(org.apache.phoenix.parse.SelectStatement) BindParseNode(org.apache.phoenix.parse.BindParseNode) ColumnParseNode(org.apache.phoenix.parse.ColumnParseNode) ParseNode(org.apache.phoenix.parse.ParseNode) SQLExceptionInfo(org.apache.phoenix.exception.SQLExceptionInfo) MetaDataClient(org.apache.phoenix.schema.MetaDataClient) ImmutableBytesWritable(org.apache.hadoop.hbase.io.ImmutableBytesWritable) PTableType(org.apache.phoenix.schema.PTableType) CreateTableStatement(org.apache.phoenix.parse.CreateTableStatement) BitSet(java.util.BitSet) ColumnDef(org.apache.phoenix.parse.ColumnDef) PrimaryKeyConstraint(org.apache.phoenix.parse.PrimaryKeyConstraint) PrimaryKeyConstraint(org.apache.phoenix.parse.PrimaryKeyConstraint) TableName(org.apache.phoenix.parse.TableName) SQLParser(org.apache.phoenix.parse.SQLParser) KeyValueColumnExpression(org.apache.phoenix.expression.KeyValueColumnExpression) Expression(org.apache.phoenix.expression.Expression) SingleCellColumnExpression(org.apache.phoenix.expression.SingleCellColumnExpression) LiteralExpression(org.apache.phoenix.expression.LiteralExpression) RowKeyColumnExpression(org.apache.phoenix.expression.RowKeyColumnExpression) IsNullExpression(org.apache.phoenix.expression.IsNullExpression) AndExpression(org.apache.phoenix.expression.AndExpression) ComparisonExpression(org.apache.phoenix.expression.ComparisonExpression) Scan(org.apache.hadoop.hbase.client.Scan) ViewType(org.apache.phoenix.schema.PTable.ViewType) TableRef(org.apache.phoenix.schema.TableRef) BindParseNode(org.apache.phoenix.parse.BindParseNode)

Aggregations

PhoenixConnection (org.apache.phoenix.jdbc.PhoenixConnection)3 DelegateConnectionQueryServices (org.apache.phoenix.query.DelegateConnectionQueryServices)3 Connection (java.sql.Connection)2 UpgradeRequiredException (org.apache.phoenix.exception.UpgradeRequiredException)2 ConnectionQueryServices (org.apache.phoenix.query.ConnectionQueryServices)2 Test (org.junit.Test)2 ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1 BitSet (java.util.BitSet)1 Scan (org.apache.hadoop.hbase.client.Scan)1 ImmutableBytesWritable (org.apache.hadoop.hbase.io.ImmutableBytesWritable)1 SQLExceptionInfo (org.apache.phoenix.exception.SQLExceptionInfo)1 AndExpression (org.apache.phoenix.expression.AndExpression)1 ComparisonExpression (org.apache.phoenix.expression.ComparisonExpression)1 Expression (org.apache.phoenix.expression.Expression)1 IsNullExpression (org.apache.phoenix.expression.IsNullExpression)1 KeyValueColumnExpression (org.apache.phoenix.expression.KeyValueColumnExpression)1 LiteralExpression (org.apache.phoenix.expression.LiteralExpression)1 RowKeyColumnExpression (org.apache.phoenix.expression.RowKeyColumnExpression)1 SingleCellColumnExpression (org.apache.phoenix.expression.SingleCellColumnExpression)1