Search in sources :

Example 26 with PhoenixStatement

use of org.apache.phoenix.jdbc.PhoenixStatement in project phoenix by apache.

the class SerialIteratorsIT method testConcatenatingSerialIterators.

@Test
public void testConcatenatingSerialIterators() throws Exception {
    Connection conn;
    conn = getConnection();
    createTestTable(getUrl(), ddl);
    initTableValues(conn);
    String query = "SELECT t_id from " + tableName + " order by t_id desc limit " + 10;
    PhoenixStatement stmt = conn.createStatement().unwrap(PhoenixStatement.class);
    ResultSet rs = stmt.executeQuery(query);
    int i = 25;
    while (i >= 16) {
        assertTrue(rs.next());
        assertEquals(strings[i--], rs.getString(1));
    }
    query = "SELECT t_id from " + tableName + " order by t_id limit " + 10;
    stmt = conn.createStatement().unwrap(PhoenixStatement.class);
    rs = stmt.executeQuery(query);
    i = 0;
    while (i < 10) {
        assertTrue(rs.next());
        assertEquals(strings[i++], rs.getString(1));
    }
    conn.close();
}
Also used : Connection(java.sql.Connection) ResultSet(java.sql.ResultSet) PhoenixStatement(org.apache.phoenix.jdbc.PhoenixStatement) Test(org.junit.Test)

Example 27 with PhoenixStatement

use of org.apache.phoenix.jdbc.PhoenixStatement in project phoenix by apache.

the class TestUtil method getSingleSumAggregator.

public static ClientAggregators getSingleSumAggregator(String url, Properties props) throws SQLException {
    try (PhoenixConnection pconn = DriverManager.getConnection(url, props).unwrap(PhoenixConnection.class)) {
        PhoenixStatement statement = new PhoenixStatement(pconn);
        StatementContext context = new StatementContext(statement, null, new Scan(), new SequenceManager(statement));
        AggregationManager aggregationManager = context.getAggregationManager();
        SumAggregateFunction func = new SumAggregateFunction(Arrays.<Expression>asList(new KeyValueColumnExpression(new PLongColumn() {

            @Override
            public PName getName() {
                return SINGLE_COLUMN_NAME;
            }

            @Override
            public PName getFamilyName() {
                return SINGLE_COLUMN_FAMILY_NAME;
            }

            @Override
            public int getPosition() {
                return 0;
            }

            @Override
            public SortOrder getSortOrder() {
                return SortOrder.getDefault();
            }

            @Override
            public Integer getArraySize() {
                return 0;
            }

            @Override
            public byte[] getViewConstant() {
                return null;
            }

            @Override
            public boolean isViewReferenced() {
                return false;
            }

            @Override
            public String getExpressionStr() {
                return null;
            }

            @Override
            public boolean isRowTimestamp() {
                return false;
            }

            @Override
            public boolean isDynamic() {
                return false;
            }

            @Override
            public byte[] getColumnQualifierBytes() {
                return SINGLE_COLUMN_NAME.getBytes();
            }
        })), null);
        aggregationManager.setAggregators(new ClientAggregators(Collections.<SingleAggregateFunction>singletonList(func), 1));
        ClientAggregators aggregators = aggregationManager.getAggregators();
        return aggregators;
    }
}
Also used : PhoenixConnection(org.apache.phoenix.jdbc.PhoenixConnection) ClientAggregators(org.apache.phoenix.expression.aggregator.ClientAggregators) SortOrder(org.apache.phoenix.schema.SortOrder) PhoenixStatement(org.apache.phoenix.jdbc.PhoenixStatement) SequenceManager(org.apache.phoenix.compile.SequenceManager) StatementContext(org.apache.phoenix.compile.StatementContext) AggregationManager(org.apache.phoenix.compile.AggregationManager) PName(org.apache.phoenix.schema.PName) SumAggregateFunction(org.apache.phoenix.expression.function.SumAggregateFunction) Scan(org.apache.hadoop.hbase.client.Scan) PLongColumn(org.apache.phoenix.schema.PLongColumn) SingleAggregateFunction(org.apache.phoenix.expression.function.SingleAggregateFunction) KeyValueColumnExpression(org.apache.phoenix.expression.KeyValueColumnExpression)

Example 28 with PhoenixStatement

use of org.apache.phoenix.jdbc.PhoenixStatement in project phoenix by apache.

the class MetaDataClient method createIndex.

/**
     * Create an index table by morphing the CreateIndexStatement into a CreateTableStatement and calling
     * MetaDataClient.createTable. In doing so, we perform the following translations:
     * 1) Change the type of any columns being indexed to types that support null if the column is nullable.
     *    For example, a BIGINT type would be coerced to a DECIMAL type, since a DECIMAL type supports null
     *    when it's in the row key while a BIGINT does not.
     * 2) Append any row key column from the data table that is not in the indexed column list. Our indexes
     *    rely on having a 1:1 correspondence between the index and data rows.
     * 3) Change the name of the columns to include the column family. For example, if you have a column
     *    named "B" in a column family named "A", the indexed column name will be "A:B". This makes it easy
     *    to translate the column references in a query to the correct column references in an index table
     *    regardless of whether the column reference is prefixed with the column family name or not. It also
     *    has the side benefit of allowing the same named column in different column families to both be
     *    listed as an index column.
     * @param statement
     * @param splits
     * @return MutationState from population of index table from data table
     * @throws SQLException
     */
public MutationState createIndex(CreateIndexStatement statement, byte[][] splits) throws SQLException {
    IndexKeyConstraint ik = statement.getIndexConstraint();
    TableName indexTableName = statement.getIndexTableName();
    Map<String, Object> tableProps = Maps.newHashMapWithExpectedSize(statement.getProps().size());
    Map<String, Object> commonFamilyProps = Maps.newHashMapWithExpectedSize(statement.getProps().size() + 1);
    populatePropertyMaps(statement.getProps(), tableProps, commonFamilyProps);
    List<Pair<ParseNode, SortOrder>> indexParseNodeAndSortOrderList = ik.getParseNodeAndSortOrderList();
    List<ColumnName> includedColumns = statement.getIncludeColumns();
    TableRef tableRef = null;
    PTable table = null;
    int numRetries = 0;
    boolean allocateIndexId = false;
    boolean isLocalIndex = statement.getIndexType() == IndexType.LOCAL;
    int hbaseVersion = connection.getQueryServices().getLowestClusterHBaseVersion();
    if (isLocalIndex) {
        if (!connection.getQueryServices().getProps().getBoolean(QueryServices.ALLOW_LOCAL_INDEX_ATTRIB, QueryServicesOptions.DEFAULT_ALLOW_LOCAL_INDEX)) {
            throw new SQLExceptionInfo.Builder(SQLExceptionCode.UNALLOWED_LOCAL_INDEXES).setTableName(indexTableName.getTableName()).build().buildException();
        }
        if (!connection.getQueryServices().supportsFeature(Feature.LOCAL_INDEX)) {
            throw new SQLExceptionInfo.Builder(SQLExceptionCode.NO_LOCAL_INDEXES).setTableName(indexTableName.getTableName()).build().buildException();
        }
    }
    while (true) {
        try {
            ColumnResolver resolver = FromCompiler.getResolver(statement, connection, statement.getUdfParseNodes());
            tableRef = resolver.getTables().get(0);
            Date asyncCreatedDate = null;
            if (statement.isAsync()) {
                asyncCreatedDate = new Date(tableRef.getTimeStamp());
            }
            PTable dataTable = tableRef.getTable();
            boolean isTenantConnection = connection.getTenantId() != null;
            if (isTenantConnection) {
                if (dataTable.getType() != PTableType.VIEW) {
                    throw new SQLFeatureNotSupportedException("An index may only be created for a VIEW through a tenant-specific connection");
                }
            }
            if (!dataTable.isImmutableRows()) {
                if (hbaseVersion < PhoenixDatabaseMetaData.MUTABLE_SI_VERSION_THRESHOLD) {
                    throw new SQLExceptionInfo.Builder(SQLExceptionCode.NO_MUTABLE_INDEXES).setTableName(indexTableName.getTableName()).build().buildException();
                }
                if (!connection.getQueryServices().hasIndexWALCodec() && !dataTable.isTransactional()) {
                    throw new SQLExceptionInfo.Builder(SQLExceptionCode.INVALID_MUTABLE_INDEX_CONFIG).setTableName(indexTableName.getTableName()).build().buildException();
                }
            }
            int posOffset = 0;
            List<PColumn> pkColumns = dataTable.getPKColumns();
            Set<RowKeyColumnExpression> unusedPkColumns;
            if (dataTable.getBucketNum() != null) {
                // Ignore SALT column
                unusedPkColumns = Sets.newLinkedHashSetWithExpectedSize(pkColumns.size() - 1);
                posOffset++;
            } else {
                unusedPkColumns = Sets.newLinkedHashSetWithExpectedSize(pkColumns.size());
            }
            for (int i = posOffset; i < pkColumns.size(); i++) {
                PColumn column = pkColumns.get(i);
                unusedPkColumns.add(new RowKeyColumnExpression(column, new RowKeyValueAccessor(pkColumns, i), "\"" + column.getName().getString() + "\""));
            }
            List<ColumnDefInPkConstraint> allPkColumns = Lists.newArrayListWithExpectedSize(unusedPkColumns.size());
            List<ColumnDef> columnDefs = Lists.newArrayListWithExpectedSize(includedColumns.size() + indexParseNodeAndSortOrderList.size());
            /*
                 * Allocate an index ID in two circumstances:
                 * 1) for a local index, as all local indexes will reside in the same HBase table
                 * 2) for a view on an index.
                 */
            if (isLocalIndex || (dataTable.getType() == PTableType.VIEW && dataTable.getViewType() != ViewType.MAPPED)) {
                allocateIndexId = true;
                PDataType dataType = MetaDataUtil.getViewIndexIdDataType();
                ColumnName colName = ColumnName.caseSensitiveColumnName(MetaDataUtil.getViewIndexIdColumnName());
                allPkColumns.add(new ColumnDefInPkConstraint(colName, SortOrder.getDefault(), false));
                columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), false, null, null, false, SortOrder.getDefault(), null, false));
            }
            if (dataTable.isMultiTenant()) {
                PColumn col = dataTable.getPKColumns().get(posOffset);
                RowKeyColumnExpression columnExpression = new RowKeyColumnExpression(col, new RowKeyValueAccessor(pkColumns, posOffset), col.getName().getString());
                unusedPkColumns.remove(columnExpression);
                PDataType dataType = IndexUtil.getIndexColumnDataType(col);
                ColumnName colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(col));
                allPkColumns.add(new ColumnDefInPkConstraint(colName, col.getSortOrder(), false));
                columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), col.isNullable(), col.getMaxLength(), col.getScale(), false, SortOrder.getDefault(), col.getName().getString(), col.isRowTimestamp()));
            }
            PhoenixStatement phoenixStatment = new PhoenixStatement(connection);
            StatementContext context = new StatementContext(phoenixStatment, resolver);
            IndexExpressionCompiler expressionIndexCompiler = new IndexExpressionCompiler(context);
            Set<ColumnName> indexedColumnNames = Sets.newHashSetWithExpectedSize(indexParseNodeAndSortOrderList.size());
            for (Pair<ParseNode, SortOrder> pair : indexParseNodeAndSortOrderList) {
                ParseNode parseNode = pair.getFirst();
                // normalize the parse node
                parseNode = StatementNormalizer.normalize(parseNode, resolver);
                // compile the parseNode to get an expression
                expressionIndexCompiler.reset();
                Expression expression = parseNode.accept(expressionIndexCompiler);
                if (expressionIndexCompiler.isAggregate()) {
                    throw new SQLExceptionInfo.Builder(SQLExceptionCode.AGGREGATE_EXPRESSION_NOT_ALLOWED_IN_INDEX).build().buildException();
                }
                if (expression.getDeterminism() != Determinism.ALWAYS) {
                    throw new SQLExceptionInfo.Builder(SQLExceptionCode.NON_DETERMINISTIC_EXPRESSION_NOT_ALLOWED_IN_INDEX).build().buildException();
                }
                if (expression.isStateless()) {
                    throw new SQLExceptionInfo.Builder(SQLExceptionCode.STATELESS_EXPRESSION_NOT_ALLOWED_IN_INDEX).build().buildException();
                }
                unusedPkColumns.remove(expression);
                // Go through parse node to get string as otherwise we
                // can lose information during compilation
                StringBuilder buf = new StringBuilder();
                parseNode.toSQL(resolver, buf);
                // need to escape backslash as this expression will be re-parsed later
                String expressionStr = StringUtil.escapeBackslash(buf.toString());
                ColumnName colName = null;
                ColumnRef colRef = expressionIndexCompiler.getColumnRef();
                boolean isRowTimestamp = false;
                if (colRef != null) {
                    // if this is a regular column
                    PColumn column = colRef.getColumn();
                    String columnFamilyName = column.getFamilyName() != null ? column.getFamilyName().getString() : null;
                    colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(columnFamilyName, column.getName().getString()));
                    isRowTimestamp = column.isRowTimestamp();
                    if (colRef.getColumn().getExpressionStr() != null) {
                        expressionStr = colRef.getColumn().getExpressionStr();
                    }
                } else {
                    // if this is an expression
                    // TODO column names cannot have double quotes, remove this once this PHOENIX-1621 is fixed
                    String name = expressionStr.replaceAll("\"", "'");
                    colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(null, name));
                }
                indexedColumnNames.add(colName);
                PDataType dataType = IndexUtil.getIndexColumnDataType(expression.isNullable(), expression.getDataType());
                allPkColumns.add(new ColumnDefInPkConstraint(colName, pair.getSecond(), isRowTimestamp));
                columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), expression.isNullable(), expression.getMaxLength(), expression.getScale(), false, pair.getSecond(), expressionStr, isRowTimestamp));
            }
            // Next all the PK columns from the data table that aren't indexed
            if (!unusedPkColumns.isEmpty()) {
                for (RowKeyColumnExpression colExpression : unusedPkColumns) {
                    PColumn col = dataTable.getPKColumns().get(colExpression.getPosition());
                    // we don't need these in the index
                    if (col.getViewConstant() == null) {
                        ColumnName colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(col));
                        allPkColumns.add(new ColumnDefInPkConstraint(colName, colExpression.getSortOrder(), col.isRowTimestamp()));
                        PDataType dataType = IndexUtil.getIndexColumnDataType(colExpression.isNullable(), colExpression.getDataType());
                        columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), colExpression.isNullable(), colExpression.getMaxLength(), colExpression.getScale(), false, colExpression.getSortOrder(), colExpression.toString(), col.isRowTimestamp()));
                    }
                }
            }
            // Last all the included columns (minus any PK columns)
            for (ColumnName colName : includedColumns) {
                PColumn col = resolver.resolveColumn(null, colName.getFamilyName(), colName.getColumnName()).getColumn();
                colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(col));
                // Check for duplicates between indexed and included columns
                if (indexedColumnNames.contains(colName)) {
                    throw new SQLExceptionInfo.Builder(SQLExceptionCode.COLUMN_EXIST_IN_DEF).build().buildException();
                }
                if (!SchemaUtil.isPKColumn(col) && col.getViewConstant() == null) {
                    // Need to re-create ColumnName, since the above one won't have the column family name
                    colName = ColumnName.caseSensitiveColumnName(isLocalIndex ? IndexUtil.getLocalIndexColumnFamily(col.getFamilyName().getString()) : col.getFamilyName().getString(), IndexUtil.getIndexColumnName(col));
                    columnDefs.add(FACTORY.columnDef(colName, col.getDataType().getSqlTypeName(), col.isNullable(), col.getMaxLength(), col.getScale(), false, col.getSortOrder(), col.getExpressionStr(), col.isRowTimestamp()));
                }
            }
            // We need this in the props so that the correct column family is created
            if (dataTable.getDefaultFamilyName() != null && dataTable.getType() != PTableType.VIEW && !allocateIndexId) {
                statement.getProps().put("", new Pair<String, Object>(DEFAULT_COLUMN_FAMILY_NAME, dataTable.getDefaultFamilyName().getString()));
            }
            PrimaryKeyConstraint pk = FACTORY.primaryKey(null, allPkColumns);
            tableProps.put(MetaDataUtil.DATA_TABLE_NAME_PROP_NAME, dataTable.getName().getString());
            CreateTableStatement tableStatement = FACTORY.createTable(indexTableName, statement.getProps(), columnDefs, pk, statement.getSplitNodes(), PTableType.INDEX, statement.ifNotExists(), null, null, statement.getBindCount(), null);
            table = createTableInternal(tableStatement, splits, dataTable, null, null, null, null, allocateIndexId, statement.getIndexType(), asyncCreatedDate, tableProps, commonFamilyProps);
            break;
        } catch (ConcurrentTableMutationException e) {
            // Can happen if parent data table changes while above is in progress
            if (numRetries < 5) {
                numRetries++;
                continue;
            }
            throw e;
        }
    }
    if (table == null) {
        return new MutationState(0, 0, connection);
    }
    if (logger.isInfoEnabled())
        logger.info("Created index " + table.getName().getString() + " at " + table.getTimeStamp());
    boolean asyncIndexBuildEnabled = connection.getQueryServices().getProps().getBoolean(QueryServices.INDEX_ASYNC_BUILD_ENABLED, QueryServicesOptions.DEFAULT_INDEX_ASYNC_BUILD_ENABLED);
    // In async process, we return immediately as the MR job needs to be triggered .
    if (statement.isAsync() && asyncIndexBuildEnabled) {
        return new MutationState(0, 0, connection);
    }
    // connection so that our new index table is visible.
    if (connection.getSCN() != null) {
        return buildIndexAtTimeStamp(table, statement.getTable());
    }
    return buildIndex(table, tableRef);
}
Also used : SQLFeatureNotSupportedException(java.sql.SQLFeatureNotSupportedException) PhoenixStatement(org.apache.phoenix.jdbc.PhoenixStatement) StatementContext(org.apache.phoenix.compile.StatementContext) PDataType(org.apache.phoenix.schema.types.PDataType) ParseNode(org.apache.phoenix.parse.ParseNode) SQLExceptionInfo(org.apache.phoenix.exception.SQLExceptionInfo) ColumnResolver(org.apache.phoenix.compile.ColumnResolver) Pair(org.apache.hadoop.hbase.util.Pair) CreateTableStatement(org.apache.phoenix.parse.CreateTableStatement) IndexKeyConstraint(org.apache.phoenix.parse.IndexKeyConstraint) ColumnDef(org.apache.phoenix.parse.ColumnDef) ColumnDefInPkConstraint(org.apache.phoenix.parse.ColumnDefInPkConstraint) RowKeyColumnExpression(org.apache.phoenix.expression.RowKeyColumnExpression) IndexKeyConstraint(org.apache.phoenix.parse.IndexKeyConstraint) PrimaryKeyConstraint(org.apache.phoenix.parse.PrimaryKeyConstraint) ColumnDefInPkConstraint(org.apache.phoenix.parse.ColumnDefInPkConstraint) PDate(org.apache.phoenix.schema.types.PDate) Date(java.sql.Date) PrimaryKeyConstraint(org.apache.phoenix.parse.PrimaryKeyConstraint) TableName(org.apache.phoenix.parse.TableName) ColumnName(org.apache.phoenix.parse.ColumnName) MutationState(org.apache.phoenix.execute.MutationState) RowKeyColumnExpression(org.apache.phoenix.expression.RowKeyColumnExpression) Expression(org.apache.phoenix.expression.Expression) IndexExpressionCompiler(org.apache.phoenix.compile.IndexExpressionCompiler)

Example 29 with PhoenixStatement

use of org.apache.phoenix.jdbc.PhoenixStatement in project phoenix by apache.

the class PTableImpl method newKey.

@Override
public int newKey(ImmutableBytesWritable key, byte[][] values) {
    List<PColumn> columns = getPKColumns();
    int nValues = values.length;
    while (nValues > 0 && (values[nValues - 1] == null || values[nValues - 1].length == 0)) {
        nValues--;
    }
    for (PColumn column : columns) {
        if (column.getExpressionStr() != null) {
            nValues++;
        }
    }
    int i = 0;
    TrustedByteArrayOutputStream os = new TrustedByteArrayOutputStream(SchemaUtil.estimateKeyLength(this));
    try {
        Integer bucketNum = this.getBucketNum();
        if (bucketNum != null) {
            // Write place holder for salt byte
            i++;
            os.write(QueryConstants.SEPARATOR_BYTE_ARRAY);
        }
        int nColumns = columns.size();
        PDataType type = null;
        SortOrder sortOrder = null;
        boolean wasNull = false;
        while (i < nValues && i < nColumns) {
            // Separate variable length column values in key with zero byte
            if (type != null && !type.isFixedWidth()) {
                os.write(SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable(), wasNull, sortOrder));
            }
            PColumn column = columns.get(i);
            sortOrder = column.getSortOrder();
            type = column.getDataType();
            // This will throw if the value is null and the type doesn't allow null
            byte[] byteValue = values[i++];
            if (byteValue == null) {
                if (column.getExpressionStr() != null) {
                    try {
                        String url = PhoenixRuntime.JDBC_PROTOCOL + PhoenixRuntime.JDBC_PROTOCOL_SEPARATOR + PhoenixRuntime.CONNECTIONLESS;
                        PhoenixConnection conn = DriverManager.getConnection(url).unwrap(PhoenixConnection.class);
                        StatementContext context = new StatementContext(new PhoenixStatement(conn));
                        ExpressionCompiler compiler = new ExpressionCompiler(context);
                        ParseNode defaultParseNode = new SQLParser(column.getExpressionStr()).parseExpression();
                        Expression defaultExpression = defaultParseNode.accept(compiler);
                        defaultExpression.evaluate(null, key);
                        column.getDataType().coerceBytes(key, null, defaultExpression.getDataType(), defaultExpression.getMaxLength(), defaultExpression.getScale(), defaultExpression.getSortOrder(), column.getMaxLength(), column.getScale(), column.getSortOrder());
                        byteValue = ByteUtil.copyKeyBytesIfNecessary(key);
                    } catch (SQLException e) {
                        // should not be possible
                        throw new ConstraintViolationException(name.getString() + "." + column.getName().getString() + " failed to compile default value expression of " + column.getExpressionStr());
                    }
                } else {
                    byteValue = ByteUtil.EMPTY_BYTE_ARRAY;
                }
            }
            wasNull = byteValue.length == 0;
            // here.
            if (byteValue.length == 0 && !column.isNullable()) {
                throw new ConstraintViolationException(name.getString() + "." + column.getName().getString() + " may not be null");
            }
            Integer maxLength = column.getMaxLength();
            Integer scale = column.getScale();
            key.set(byteValue);
            if (!type.isSizeCompatible(key, null, type, sortOrder, null, null, maxLength, scale)) {
                throw new DataExceedsCapacityException(name.getString() + "." + column.getName().getString() + " may not exceed " + maxLength + " (" + SchemaUtil.toString(type, byteValue) + ")");
            }
            key.set(byteValue);
            type.pad(key, maxLength, sortOrder);
            byteValue = ByteUtil.copyKeyBytesIfNecessary(key);
            os.write(byteValue, 0, byteValue.length);
        }
        // Need trailing byte for DESC columns
        if (type != null && !type.isFixedWidth() && SchemaUtil.getSeparatorByte(rowKeyOrderOptimizable(), wasNull, sortOrder) == QueryConstants.DESC_SEPARATOR_BYTE) {
            os.write(QueryConstants.DESC_SEPARATOR_BYTE);
        }
        // If some non null pk values aren't set, then throw
        if (i < nColumns) {
            PColumn column = columns.get(i);
            if (column.getDataType().isFixedWidth() || !column.isNullable()) {
                throw new ConstraintViolationException(name.getString() + "." + column.getName().getString() + " may not be null");
            }
        }
        if (nValues == 0) {
            throw new ConstraintViolationException("Primary key may not be null (" + name.getString() + ")");
        }
        byte[] buf = os.getBuffer();
        int size = os.size();
        if (bucketNum != null) {
            buf[0] = SaltingUtil.getSaltingByte(buf, 1, size - 1, bucketNum);
        }
        key.set(buf, 0, size);
        return i;
    } finally {
        try {
            os.close();
        } catch (IOException e) {
            // Impossible
            throw new RuntimeException(e);
        }
    }
}
Also used : PhoenixConnection(org.apache.phoenix.jdbc.PhoenixConnection) SQLException(java.sql.SQLException) TrustedByteArrayOutputStream(org.apache.phoenix.util.TrustedByteArrayOutputStream) IOException(java.io.IOException) PhoenixStatement(org.apache.phoenix.jdbc.PhoenixStatement) StatementContext(org.apache.phoenix.compile.StatementContext) DataExceedsCapacityException(org.apache.phoenix.exception.DataExceedsCapacityException) PDataType(org.apache.phoenix.schema.types.PDataType) SQLParser(org.apache.phoenix.parse.SQLParser) SingleCellConstructorExpression(org.apache.phoenix.expression.SingleCellConstructorExpression) Expression(org.apache.phoenix.expression.Expression) LiteralExpression(org.apache.phoenix.expression.LiteralExpression) ParseNode(org.apache.phoenix.parse.ParseNode) ExpressionCompiler(org.apache.phoenix.compile.ExpressionCompiler)

Example 30 with PhoenixStatement

use of org.apache.phoenix.jdbc.PhoenixStatement in project phoenix by apache.

the class MetaDataClient method addColumn.

public MutationState addColumn(PTable table, List<ColumnDef> origColumnDefs, ListMultimap<String, Pair<String, Object>> stmtProperties, boolean ifNotExists, boolean removeTableProps, NamedTableNode namedTableNode, PTableType tableType) throws SQLException {
    connection.rollback();
    boolean wasAutoCommit = connection.getAutoCommit();
    try {
        connection.setAutoCommit(false);
        PName tenantId = connection.getTenantId();
        String schemaName = table.getSchemaName().getString();
        String tableName = table.getTableName().getString();
        Boolean isImmutableRowsProp = null;
        Boolean multiTenantProp = null;
        Boolean disableWALProp = null;
        Boolean storeNullsProp = null;
        Boolean isTransactionalProp = null;
        Long updateCacheFrequencyProp = null;
        Boolean appendOnlySchemaProp = null;
        Long guidePostWidth = -1L;
        ImmutableStorageScheme immutableStorageSchemeProp = null;
        Boolean useStatsForParallelizationProp = null;
        Map<String, List<Pair<String, Object>>> properties = new HashMap<>(stmtProperties.size());
        List<ColumnDef> columnDefs = null;
        if (table.isAppendOnlySchema()) {
            // only make the rpc if we are adding new columns
            columnDefs = Lists.newArrayList();
            for (ColumnDef columnDef : origColumnDefs) {
                String familyName = columnDef.getColumnDefName().getFamilyName();
                String columnName = columnDef.getColumnDefName().getColumnName();
                if (familyName != null) {
                    try {
                        PColumnFamily columnFamily = table.getColumnFamily(familyName);
                        columnFamily.getPColumnForColumnName(columnName);
                        if (!ifNotExists) {
                            throw new ColumnAlreadyExistsException(schemaName, tableName, columnName);
                        }
                    } catch (ColumnFamilyNotFoundException | ColumnNotFoundException e) {
                        columnDefs.add(columnDef);
                    }
                } else {
                    try {
                        table.getColumnForColumnName(columnName);
                        if (!ifNotExists) {
                            throw new ColumnAlreadyExistsException(schemaName, tableName, columnName);
                        }
                    } catch (ColumnNotFoundException e) {
                        columnDefs.add(columnDef);
                    }
                }
            }
        } else {
            columnDefs = origColumnDefs == null ? Collections.<ColumnDef>emptyList() : origColumnDefs;
        }
        for (String family : stmtProperties.keySet()) {
            List<Pair<String, Object>> origPropsList = stmtProperties.get(family);
            List<Pair<String, Object>> propsList = Lists.newArrayListWithExpectedSize(origPropsList.size());
            for (Pair<String, Object> prop : origPropsList) {
                String propName = prop.getFirst();
                if (TableProperty.isPhoenixTableProperty(propName)) {
                    TableProperty tableProp = TableProperty.valueOf(propName);
                    tableProp.validate(true, !family.equals(QueryConstants.ALL_FAMILY_PROPERTIES_KEY), table.getType());
                    Object value = tableProp.getValue(prop.getSecond());
                    if (propName.equals(PTable.IS_IMMUTABLE_ROWS_PROP_NAME)) {
                        isImmutableRowsProp = (Boolean) value;
                    } else if (propName.equals(PhoenixDatabaseMetaData.MULTI_TENANT)) {
                        multiTenantProp = (Boolean) value;
                    } else if (propName.equals(DISABLE_WAL)) {
                        disableWALProp = (Boolean) value;
                    } else if (propName.equals(STORE_NULLS)) {
                        storeNullsProp = (Boolean) value;
                    } else if (propName.equals(TRANSACTIONAL)) {
                        isTransactionalProp = (Boolean) value;
                    } else if (propName.equals(UPDATE_CACHE_FREQUENCY)) {
                        updateCacheFrequencyProp = (Long) value;
                    } else if (propName.equals(GUIDE_POSTS_WIDTH)) {
                        guidePostWidth = (Long) value;
                    } else if (propName.equals(APPEND_ONLY_SCHEMA)) {
                        appendOnlySchemaProp = (Boolean) value;
                    } else if (propName.equalsIgnoreCase(IMMUTABLE_STORAGE_SCHEME)) {
                        immutableStorageSchemeProp = (ImmutableStorageScheme) value;
                    } else if (propName.equalsIgnoreCase(USE_STATS_FOR_PARALLELIZATION)) {
                        useStatsForParallelizationProp = (Boolean) value;
                    }
                }
                // if removeTableProps is true only add the property if it is not a HTable or Phoenix Table property
                if (!removeTableProps || (!TableProperty.isPhoenixTableProperty(propName) && !MetaDataUtil.isHTableProperty(propName))) {
                    propsList.add(prop);
                }
            }
            properties.put(family, propsList);
        }
        boolean retried = false;
        boolean changingPhoenixTableProperty = false;
        boolean nonTxToTx = false;
        while (true) {
            ColumnResolver resolver = FromCompiler.getResolver(namedTableNode, connection);
            table = resolver.getTables().get(0).getTable();
            int nIndexes = table.getIndexes().size();
            int numCols = columnDefs.size();
            int nNewColumns = numCols;
            List<Mutation> tableMetaData = Lists.newArrayListWithExpectedSize((1 + nNewColumns) * (nIndexes + 1));
            List<Mutation> columnMetaData = Lists.newArrayListWithExpectedSize(nNewColumns * (nIndexes + 1));
            if (logger.isDebugEnabled()) {
                logger.debug(LogUtil.addCustomAnnotations("Resolved table to " + table.getName().getString() + " with seqNum " + table.getSequenceNumber() + " at timestamp " + table.getTimeStamp() + " with " + table.getColumns().size() + " columns: " + table.getColumns(), connection));
            }
            int position = table.getColumns().size();
            List<PColumn> currentPKs = table.getPKColumns();
            PColumn lastPK = currentPKs.get(currentPKs.size() - 1);
            // Disallow adding columns if the last column is VARBIANRY.
            if (lastPK.getDataType() == PVarbinary.INSTANCE || lastPK.getDataType().isArrayType()) {
                throw new SQLExceptionInfo.Builder(SQLExceptionCode.VARBINARY_LAST_PK).setColumnName(lastPK.getName().getString()).build().buildException();
            }
            // Disallow adding columns if last column is fixed width and nullable.
            if (lastPK.isNullable() && lastPK.getDataType().isFixedWidth()) {
                throw new SQLExceptionInfo.Builder(SQLExceptionCode.NULLABLE_FIXED_WIDTH_LAST_PK).setColumnName(lastPK.getName().getString()).build().buildException();
            }
            Boolean isImmutableRows = null;
            if (isImmutableRowsProp != null) {
                if (isImmutableRowsProp.booleanValue() != table.isImmutableRows()) {
                    if (table.getImmutableStorageScheme() != ImmutableStorageScheme.ONE_CELL_PER_COLUMN) {
                        throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_ALTER_IMMUTABLE_ROWS_PROPERTY).setSchemaName(schemaName).setTableName(tableName).build().buildException();
                    }
                    isImmutableRows = isImmutableRowsProp;
                    changingPhoenixTableProperty = true;
                }
            }
            Boolean multiTenant = null;
            if (multiTenantProp != null) {
                if (multiTenantProp.booleanValue() != table.isMultiTenant()) {
                    multiTenant = multiTenantProp;
                    changingPhoenixTableProperty = true;
                }
            }
            Boolean disableWAL = null;
            if (disableWALProp != null) {
                if (disableWALProp.booleanValue() != table.isWALDisabled()) {
                    disableWAL = disableWALProp;
                    changingPhoenixTableProperty = true;
                }
            }
            Long updateCacheFrequency = null;
            if (updateCacheFrequencyProp != null) {
                if (updateCacheFrequencyProp.longValue() != table.getUpdateCacheFrequency()) {
                    updateCacheFrequency = updateCacheFrequencyProp;
                    changingPhoenixTableProperty = true;
                }
            }
            Boolean appendOnlySchema = null;
            if (appendOnlySchemaProp != null) {
                if (appendOnlySchemaProp != table.isAppendOnlySchema()) {
                    appendOnlySchema = appendOnlySchemaProp;
                    changingPhoenixTableProperty = true;
                }
            }
            ImmutableStorageScheme immutableStorageScheme = null;
            if (immutableStorageSchemeProp != null) {
                if (table.getImmutableStorageScheme() == ONE_CELL_PER_COLUMN || immutableStorageSchemeProp == ONE_CELL_PER_COLUMN) {
                    throw new SQLExceptionInfo.Builder(SQLExceptionCode.INVALID_IMMUTABLE_STORAGE_SCHEME_CHANGE).setSchemaName(schemaName).setTableName(tableName).build().buildException();
                } else if (immutableStorageSchemeProp != table.getImmutableStorageScheme()) {
                    immutableStorageScheme = immutableStorageSchemeProp;
                    changingPhoenixTableProperty = true;
                }
            }
            if (guidePostWidth == null || guidePostWidth >= 0) {
                changingPhoenixTableProperty = true;
            }
            Boolean storeNulls = null;
            if (storeNullsProp != null) {
                if (storeNullsProp.booleanValue() != table.getStoreNulls()) {
                    storeNulls = storeNullsProp;
                    changingPhoenixTableProperty = true;
                }
            }
            Boolean useStatsForParallelization = null;
            if (useStatsForParallelizationProp != null) {
                if (useStatsForParallelizationProp.booleanValue() != table.useStatsForParallelization()) {
                    useStatsForParallelization = useStatsForParallelizationProp;
                    changingPhoenixTableProperty = true;
                }
            }
            Boolean isTransactional = null;
            if (isTransactionalProp != null) {
                if (isTransactionalProp.booleanValue() != table.isTransactional()) {
                    isTransactional = isTransactionalProp;
                    // delete markers.
                    if (!isTransactional) {
                        throw new SQLExceptionInfo.Builder(SQLExceptionCode.TX_MAY_NOT_SWITCH_TO_NON_TX).setSchemaName(schemaName).setTableName(tableName).build().buildException();
                    }
                    // cannot create a transactional table if transactions are disabled
                    boolean transactionsEnabled = connection.getQueryServices().getProps().getBoolean(QueryServices.TRANSACTIONS_ENABLED, QueryServicesOptions.DEFAULT_TRANSACTIONS_ENABLED);
                    if (!transactionsEnabled) {
                        throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_ALTER_TO_BE_TXN_IF_TXNS_DISABLED).setSchemaName(schemaName).setTableName(tableName).build().buildException();
                    }
                    // cannot make a table transactional if it has a row timestamp column
                    if (SchemaUtil.hasRowTimestampColumn(table)) {
                        throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_ALTER_TO_BE_TXN_WITH_ROW_TIMESTAMP).setSchemaName(schemaName).setTableName(tableName).build().buildException();
                    }
                    changingPhoenixTableProperty = true;
                    nonTxToTx = true;
                }
            }
            Long timeStamp = TransactionUtil.getTableTimestamp(connection, table.isTransactional() || nonTxToTx);
            int numPkColumnsAdded = 0;
            List<PColumn> columns = Lists.newArrayListWithExpectedSize(numCols);
            Set<String> colFamiliesForPColumnsToBeAdded = new LinkedHashSet<>();
            Set<String> families = new LinkedHashSet<>();
            PTable tableForCQCounters = tableType == PTableType.VIEW ? PhoenixRuntime.getTable(connection, table.getPhysicalName().getString()) : table;
            ;
            EncodedCQCounter cqCounterToUse = tableForCQCounters.getEncodedCQCounter();
            Map<String, Integer> changedCqCounters = new HashMap<>(numCols);
            if (numCols > 0) {
                StatementContext context = new StatementContext(new PhoenixStatement(connection), resolver);
                String addColumnSqlToUse = connection.isRunningUpgrade() && tableName.equals(PhoenixDatabaseMetaData.SYSTEM_CATALOG_TABLE) && schemaName.equals(PhoenixDatabaseMetaData.SYSTEM_CATALOG_SCHEMA) ? ALTER_SYSCATALOG_TABLE_UPGRADE : INSERT_COLUMN_ALTER_TABLE;
                try (PreparedStatement colUpsert = connection.prepareStatement(addColumnSqlToUse)) {
                    short nextKeySeq = SchemaUtil.getMaxKeySeq(table);
                    for (ColumnDef colDef : columnDefs) {
                        if (colDef != null && !colDef.isNull()) {
                            if (colDef.isPK()) {
                                throw new SQLExceptionInfo.Builder(SQLExceptionCode.NOT_NULLABLE_COLUMN_IN_ROW_KEY).setColumnName(colDef.getColumnDefName().getColumnName()).build().buildException();
                            } else {
                                throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_ADD_NOT_NULLABLE_COLUMN).setColumnName(colDef.getColumnDefName().getColumnName()).build().buildException();
                            }
                        }
                        if (colDef != null && colDef.isPK() && table.getType() == VIEW && table.getViewType() != MAPPED) {
                            throwIfLastPKOfParentIsFixedLength(getParentOfView(table), schemaName, tableName, colDef);
                        }
                        if (colDef != null && colDef.isRowTimestamp()) {
                            throw new SQLExceptionInfo.Builder(SQLExceptionCode.ROWTIMESTAMP_CREATE_ONLY).setColumnName(colDef.getColumnDefName().getColumnName()).build().buildException();
                        }
                        if (!colDef.validateDefault(context, null)) {
                            // Remove DEFAULT as it's not necessary
                            colDef = new ColumnDef(colDef, null);
                        }
                        Integer encodedCQ = null;
                        if (!colDef.isPK()) {
                            String colDefFamily = colDef.getColumnDefName().getFamilyName();
                            String familyName = null;
                            ImmutableStorageScheme storageScheme = table.getImmutableStorageScheme();
                            String defaultColumnFamily = tableForCQCounters.getDefaultFamilyName() != null && !Strings.isNullOrEmpty(tableForCQCounters.getDefaultFamilyName().getString()) ? tableForCQCounters.getDefaultFamilyName().getString() : DEFAULT_COLUMN_FAMILY;
                            if (table.getType() == PTableType.INDEX && table.getIndexType() == IndexType.LOCAL) {
                                defaultColumnFamily = QueryConstants.LOCAL_INDEX_COLUMN_FAMILY_PREFIX + defaultColumnFamily;
                            }
                            if (storageScheme == SINGLE_CELL_ARRAY_WITH_OFFSETS) {
                                familyName = colDefFamily != null ? colDefFamily : defaultColumnFamily;
                            } else {
                                familyName = defaultColumnFamily;
                            }
                            encodedCQ = cqCounterToUse.getNextQualifier(familyName);
                            if (cqCounterToUse.increment(familyName)) {
                                changedCqCounters.put(familyName, cqCounterToUse.getNextQualifier(familyName));
                            }
                        }
                        byte[] columnQualifierBytes = null;
                        try {
                            columnQualifierBytes = EncodedColumnsUtil.getColumnQualifierBytes(colDef.getColumnDefName().getColumnName(), encodedCQ, table, colDef.isPK());
                        } catch (QualifierOutOfRangeException e) {
                            throw new SQLExceptionInfo.Builder(SQLExceptionCode.MAX_COLUMNS_EXCEEDED).setSchemaName(schemaName).setTableName(tableName).build().buildException();
                        }
                        PColumn column = newColumn(position++, colDef, PrimaryKeyConstraint.EMPTY, table.getDefaultFamilyName() == null ? null : table.getDefaultFamilyName().getString(), true, columnQualifierBytes);
                        columns.add(column);
                        String pkName = null;
                        Short keySeq = null;
                        // TODO: support setting properties on other families?
                        if (column.getFamilyName() == null) {
                            ++numPkColumnsAdded;
                            pkName = table.getPKName() == null ? null : table.getPKName().getString();
                            keySeq = ++nextKeySeq;
                        } else {
                            families.add(column.getFamilyName().getString());
                        }
                        colFamiliesForPColumnsToBeAdded.add(column.getFamilyName() == null ? null : column.getFamilyName().getString());
                        addColumnMutation(schemaName, tableName, column, colUpsert, null, pkName, keySeq, table.getBucketNum() != null);
                    }
                    // Add any new PK columns to end of index PK
                    if (numPkColumnsAdded > 0) {
                        // create PK column list that includes the newly created columns
                        List<PColumn> pkColumns = Lists.newArrayListWithExpectedSize(table.getPKColumns().size() + numPkColumnsAdded);
                        pkColumns.addAll(table.getPKColumns());
                        for (int i = 0; i < numCols; ++i) {
                            if (columnDefs.get(i).isPK()) {
                                pkColumns.add(columns.get(i));
                            }
                        }
                        int pkSlotPosition = table.getPKColumns().size() - 1;
                        for (PTable index : table.getIndexes()) {
                            short nextIndexKeySeq = SchemaUtil.getMaxKeySeq(index);
                            int indexPosition = index.getColumns().size();
                            for (int i = 0; i < numCols; ++i) {
                                ColumnDef colDef = columnDefs.get(i);
                                if (colDef.isPK()) {
                                    PDataType indexColDataType = IndexUtil.getIndexColumnDataType(colDef.isNull(), colDef.getDataType());
                                    ColumnName indexColName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(null, colDef.getColumnDefName().getColumnName()));
                                    Expression expression = new RowKeyColumnExpression(columns.get(i), new RowKeyValueAccessor(pkColumns, ++pkSlotPosition));
                                    ColumnDef indexColDef = FACTORY.columnDef(indexColName, indexColDataType.getSqlTypeName(), colDef.isNull(), colDef.getMaxLength(), colDef.getScale(), true, colDef.getSortOrder(), expression.toString(), colDef.isRowTimestamp());
                                    PColumn indexColumn = newColumn(indexPosition++, indexColDef, PrimaryKeyConstraint.EMPTY, null, true, null);
                                    addColumnMutation(schemaName, index.getTableName().getString(), indexColumn, colUpsert, index.getParentTableName().getString(), index.getPKName() == null ? null : index.getPKName().getString(), ++nextIndexKeySeq, index.getBucketNum() != null);
                                }
                            }
                        }
                    }
                    columnMetaData.addAll(connection.getMutationState().toMutations(timeStamp).next().getSecond());
                    connection.rollback();
                }
            } else {
                // have existing indexes.
                if (Boolean.FALSE.equals(isImmutableRows) && !table.getIndexes().isEmpty()) {
                    int hbaseVersion = connection.getQueryServices().getLowestClusterHBaseVersion();
                    if (hbaseVersion < PhoenixDatabaseMetaData.MUTABLE_SI_VERSION_THRESHOLD) {
                        throw new SQLExceptionInfo.Builder(SQLExceptionCode.NO_MUTABLE_INDEXES).setSchemaName(schemaName).setTableName(tableName).build().buildException();
                    }
                    if (!connection.getQueryServices().hasIndexWALCodec() && !table.isTransactional()) {
                        throw new SQLExceptionInfo.Builder(SQLExceptionCode.INVALID_MUTABLE_INDEX_CONFIG).setSchemaName(schemaName).setTableName(tableName).build().buildException();
                    }
                }
                if (Boolean.TRUE.equals(multiTenant)) {
                    throwIfInsufficientColumns(schemaName, tableName, table.getPKColumns(), table.getBucketNum() != null, multiTenant);
                }
            }
            if (!table.getIndexes().isEmpty() && (numPkColumnsAdded > 0 || nonTxToTx)) {
                for (PTable index : table.getIndexes()) {
                    incrementTableSeqNum(index, index.getType(), numPkColumnsAdded, nonTxToTx ? Boolean.TRUE : null, updateCacheFrequency);
                }
                tableMetaData.addAll(connection.getMutationState().toMutations(timeStamp).next().getSecond());
                connection.rollback();
            }
            if (changingPhoenixTableProperty || columnDefs.size() > 0) {
                incrementTableSeqNum(table, tableType, columnDefs.size(), isTransactional, updateCacheFrequency, isImmutableRows, disableWAL, multiTenant, storeNulls, guidePostWidth, appendOnlySchema, immutableStorageScheme, useStatsForParallelization);
                tableMetaData.addAll(connection.getMutationState().toMutations(timeStamp).next().getSecond());
                connection.rollback();
            }
            // Force the table header row to be first
            Collections.reverse(tableMetaData);
            // Add column metadata afterwards, maintaining the order so columns have more predictable ordinal position
            tableMetaData.addAll(columnMetaData);
            boolean sharedIndex = tableType == PTableType.INDEX && (table.getIndexType() == IndexType.LOCAL || table.getViewIndexId() != null);
            String tenantIdToUse = connection.getTenantId() != null && sharedIndex ? connection.getTenantId().getString() : null;
            if (!changedCqCounters.isEmpty()) {
                PreparedStatement linkStatement;
                linkStatement = connection.prepareStatement(UPDATE_ENCODED_COLUMN_COUNTER);
                for (Entry<String, Integer> entry : changedCqCounters.entrySet()) {
                    linkStatement.setString(1, tenantIdToUse);
                    linkStatement.setString(2, tableForCQCounters.getSchemaName().getString());
                    linkStatement.setString(3, tableForCQCounters.getTableName().getString());
                    linkStatement.setString(4, entry.getKey());
                    linkStatement.setInt(5, entry.getValue());
                    linkStatement.execute();
                }
                // too since we want clients to get the latest PTable of the base table.
                if (tableType == VIEW) {
                    PreparedStatement incrementStatement = connection.prepareStatement(INCREMENT_SEQ_NUM);
                    incrementStatement.setString(1, null);
                    incrementStatement.setString(2, tableForCQCounters.getSchemaName().getString());
                    incrementStatement.setString(3, tableForCQCounters.getTableName().getString());
                    incrementStatement.setLong(4, tableForCQCounters.getSequenceNumber() + 1);
                    incrementStatement.execute();
                }
                tableMetaData.addAll(connection.getMutationState().toMutations(timeStamp).next().getSecond());
                connection.rollback();
            }
            byte[] family = families.size() > 0 ? families.iterator().next().getBytes() : null;
            // Figure out if the empty column family is changing as a result of adding the new column
            byte[] emptyCF = null;
            byte[] projectCF = null;
            if (table.getType() != PTableType.VIEW && family != null) {
                if (table.getColumnFamilies().isEmpty()) {
                    emptyCF = family;
                } else {
                    try {
                        table.getColumnFamily(family);
                    } catch (ColumnFamilyNotFoundException e) {
                        projectCF = family;
                        emptyCF = SchemaUtil.getEmptyColumnFamily(table);
                    }
                }
            }
            MetaDataMutationResult result = connection.getQueryServices().addColumn(tableMetaData, table, properties, colFamiliesForPColumnsToBeAdded, columns);
            try {
                MutationCode code = processMutationResult(schemaName, tableName, result);
                if (code == MutationCode.COLUMN_ALREADY_EXISTS) {
                    addTableToCache(result);
                    if (!ifNotExists) {
                        throw new ColumnAlreadyExistsException(schemaName, tableName, SchemaUtil.findExistingColumn(result.getTable(), columns));
                    }
                    return new MutationState(0, 0, connection);
                }
                // Only update client side cache if we aren't adding a PK column to a table with indexes or
                // transitioning a table from non transactional to transactional.
                // We could update the cache manually then too, it'd just be a pain.
                String fullTableName = SchemaUtil.getTableName(schemaName, tableName);
                long resolvedTimeStamp = TransactionUtil.getResolvedTime(connection, result);
                if (table.getIndexes().isEmpty() || (numPkColumnsAdded == 0 && !nonTxToTx)) {
                    connection.addTable(result.getTable(), resolvedTimeStamp);
                    table = result.getTable();
                } else if (updateCacheFrequency != null) {
                    // Force removal from cache as the update cache frequency has changed
                    // Note that clients outside this JVM won't be affected.
                    connection.removeTable(tenantId, fullTableName, null, resolvedTimeStamp);
                }
                // We only need to do this if the multiTenant transitioned to false
                if (table.getType() == PTableType.TABLE && Boolean.FALSE.equals(multiTenant) && MetaDataUtil.hasViewIndexTable(connection, table.getPhysicalName())) {
                    connection.setAutoCommit(true);
                    MetaDataUtil.deleteViewIndexSequences(connection, table.getPhysicalName(), table.isNamespaceMapped());
                    // commands are run would remove all rows already.
                    if (!connection.getQueryServices().getProps().getBoolean(DROP_METADATA_ATTRIB, DEFAULT_DROP_METADATA)) {
                        Long scn = connection.getSCN();
                        long ts = (scn == null ? result.getMutationTime() : scn);
                        byte[] viewIndexPhysicalName = MetaDataUtil.getViewIndexPhysicalName(table.getPhysicalName().getBytes());
                        PTable viewIndexTable = new PTableImpl(null, SchemaUtil.getSchemaNameFromFullName(viewIndexPhysicalName), SchemaUtil.getTableNameFromFullName(viewIndexPhysicalName), ts, table.getColumnFamilies(), table.isNamespaceMapped(), table.getImmutableStorageScheme(), table.getEncodingScheme(), table.useStatsForParallelization());
                        List<TableRef> tableRefs = Collections.singletonList(new TableRef(null, viewIndexTable, ts, false));
                        MutationPlan plan = new PostDDLCompiler(connection).compile(tableRefs, null, null, Collections.<PColumn>emptyList(), ts);
                        connection.getQueryServices().updateData(plan);
                    }
                }
                if (emptyCF != null) {
                    Long scn = connection.getSCN();
                    connection.setAutoCommit(true);
                    // Delete everything in the column. You'll still be able to do queries at earlier timestamps
                    long ts = (scn == null ? result.getMutationTime() : scn);
                    MutationPlan plan = new PostDDLCompiler(connection).compile(Collections.singletonList(new TableRef(null, table, ts, false)), emptyCF, projectCF == null ? null : Collections.singletonList(projectCF), null, ts);
                    return connection.getQueryServices().updateData(plan);
                }
                return new MutationState(0, 0, connection);
            } catch (ConcurrentTableMutationException e) {
                if (retried) {
                    throw e;
                }
                if (logger.isDebugEnabled()) {
                    logger.debug(LogUtil.addCustomAnnotations("Caught ConcurrentTableMutationException for table " + SchemaUtil.getTableName(schemaName, tableName) + ". Will try again...", connection));
                }
                retried = true;
            }
        }
    } finally {
        connection.setAutoCommit(wasAutoCommit);
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Sets.newLinkedHashSet(com.google.common.collect.Sets.newLinkedHashSet) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) PostDDLCompiler(org.apache.phoenix.compile.PostDDLCompiler) PhoenixStatement(org.apache.phoenix.jdbc.PhoenixStatement) StatementContext(org.apache.phoenix.compile.StatementContext) PDataType(org.apache.phoenix.schema.types.PDataType) ArrayList(java.util.ArrayList) List(java.util.List) SQLExceptionInfo(org.apache.phoenix.exception.SQLExceptionInfo) ColumnResolver(org.apache.phoenix.compile.ColumnResolver) ColumnDef(org.apache.phoenix.parse.ColumnDef) MutationPlan(org.apache.phoenix.compile.MutationPlan) PUnsignedLong(org.apache.phoenix.schema.types.PUnsignedLong) PLong(org.apache.phoenix.schema.types.PLong) Mutation(org.apache.hadoop.hbase.client.Mutation) QualifierOutOfRangeException(org.apache.phoenix.schema.PTable.QualifierEncodingScheme.QualifierOutOfRangeException) ImmutableStorageScheme(org.apache.phoenix.schema.PTable.ImmutableStorageScheme) MetaDataMutationResult(org.apache.phoenix.coprocessor.MetaDataProtocol.MetaDataMutationResult) Pair(org.apache.hadoop.hbase.util.Pair) PreparedStatement(java.sql.PreparedStatement) RowKeyColumnExpression(org.apache.phoenix.expression.RowKeyColumnExpression) IndexKeyConstraint(org.apache.phoenix.parse.IndexKeyConstraint) PrimaryKeyConstraint(org.apache.phoenix.parse.PrimaryKeyConstraint) ColumnDefInPkConstraint(org.apache.phoenix.parse.ColumnDefInPkConstraint) MutationCode(org.apache.phoenix.coprocessor.MetaDataProtocol.MutationCode) PInteger(org.apache.phoenix.schema.types.PInteger) ColumnName(org.apache.phoenix.parse.ColumnName) EncodedCQCounter(org.apache.phoenix.schema.PTable.EncodedCQCounter) MutationState(org.apache.phoenix.execute.MutationState) RowKeyColumnExpression(org.apache.phoenix.expression.RowKeyColumnExpression) Expression(org.apache.phoenix.expression.Expression)

Aggregations

PhoenixStatement (org.apache.phoenix.jdbc.PhoenixStatement)64 Connection (java.sql.Connection)47 Test (org.junit.Test)42 BaseConnectionlessQueryTest (org.apache.phoenix.query.BaseConnectionlessQueryTest)34 PhoenixConnection (org.apache.phoenix.jdbc.PhoenixConnection)13 ResultSet (java.sql.ResultSet)10 StatementContext (org.apache.phoenix.compile.StatementContext)10 QueryPlan (org.apache.phoenix.compile.QueryPlan)8 PTable (org.apache.phoenix.schema.PTable)8 SQLException (java.sql.SQLException)7 Statement (java.sql.Statement)7 PhoenixResultSet (org.apache.phoenix.jdbc.PhoenixResultSet)7 PColumn (org.apache.phoenix.schema.PColumn)7 ArrayList (java.util.ArrayList)6 Properties (java.util.Properties)6 MutationState (org.apache.phoenix.execute.MutationState)6 PreparedStatement (java.sql.PreparedStatement)5 List (java.util.List)5 Scan (org.apache.hadoop.hbase.client.Scan)5 ImmutableBytesWritable (org.apache.hadoop.hbase.io.ImmutableBytesWritable)5