Search in sources :

Example 86 with PDataType

use of org.apache.phoenix.schema.types.PDataType 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 87 with PDataType

use of org.apache.phoenix.schema.types.PDataType 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)

Example 88 with PDataType

use of org.apache.phoenix.schema.types.PDataType in project phoenix by apache.

the class KeyValueSchema method toBytes.

/**
     * @return byte representation of the KeyValueSchema
     */
public byte[] toBytes(Tuple tuple, Expression[] expressions, ValueBitSet valueSet, ImmutableBytesWritable ptr) {
    int offset = 0;
    int index = 0;
    valueSet.clear();
    int minNullableIndex = getMinNullable();
    byte[] b = new byte[getEstimatedValueLength() + valueSet.getEstimatedLength()];
    List<Field> fields = getFields();
    // since repeating fields will not span the non-null/null boundary.
    for (int i = 0; i < fields.size(); i++) {
        Field field = fields.get(i);
        PDataType type = field.getDataType();
        for (int j = 0; j < field.getCount(); j++) {
            if (expressions[index].evaluate(tuple, ptr) && ptr.getLength() > 0) {
                // Skip null values
                if (index >= minNullableIndex) {
                    valueSet.set(index - minNullableIndex);
                }
                if (!type.isFixedWidth()) {
                    b = ensureSize(b, offset, offset + getVarLengthBytes(ptr.getLength()));
                    offset = writeVarLengthField(ptr, b, offset);
                } else {
                    int nBytes = ptr.getLength();
                    b = ensureSize(b, offset, offset + nBytes);
                    System.arraycopy(ptr.get(), ptr.getOffset(), b, offset, nBytes);
                    offset += nBytes;
                }
            }
            index++;
        }
    }
    // Add information about which values were set at end of value,
    // so that we can quickly access them without needing to walk
    // through the values using the schema.
    // TODO: if there aren't any non null values, don't serialize anything
    b = ensureSize(b, offset, offset + valueSet.getEstimatedLength());
    offset = valueSet.toBytes(b, offset);
    if (offset == b.length) {
        return b;
    } else {
        byte[] bExact = new byte[offset];
        System.arraycopy(b, 0, bExact, 0, offset);
        return bExact;
    }
}
Also used : PDataType(org.apache.phoenix.schema.types.PDataType)

Example 89 with PDataType

use of org.apache.phoenix.schema.types.PDataType in project phoenix by apache.

the class CeilDateExpression method evaluate.

@Override
public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    if (children.get(0).evaluate(tuple, ptr)) {
        if (ptr.getLength() == 0) {
            // child evaluated to null
            return true;
        }
        PDataType dataType = getDataType();
        long time = dataType.getCodec().decodeLong(ptr, children.get(0).getSortOrder());
        long value = roundTime(time);
        Date d = new Date(value);
        byte[] byteValue = dataType.toBytes(d);
        ptr.set(byteValue);
        return true;
    }
    return false;
}
Also used : PDataType(org.apache.phoenix.schema.types.PDataType) Date(java.sql.Date) PDate(org.apache.phoenix.schema.types.PDate)

Example 90 with PDataType

use of org.apache.phoenix.schema.types.PDataType in project phoenix by apache.

the class CeilTimestampExpression method evaluate.

@Override
public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    if (children.get(0).evaluate(tuple, ptr)) {
        if (ptr.getLength() == 0) {
            // child evaluated to null
            return true;
        }
        SortOrder sortOrder = children.get(0).getSortOrder();
        PDataType dataType = getDataType();
        int nanos = dataType.getNanos(ptr, sortOrder);
        if (nanos > 0) {
            long millis = dataType.getMillis(ptr, sortOrder);
            Timestamp roundedTs = new Timestamp(millis + 1);
            byte[] byteValue = dataType.toBytes(roundedTs);
            ptr.set(byteValue);
        }
        // for timestamp we only support rounding up the milliseconds.
        return true;
    }
    return false;
}
Also used : PDataType(org.apache.phoenix.schema.types.PDataType) SortOrder(org.apache.phoenix.schema.SortOrder) Timestamp(java.sql.Timestamp) PUnsignedTimestamp(org.apache.phoenix.schema.types.PUnsignedTimestamp) PTimestamp(org.apache.phoenix.schema.types.PTimestamp)

Aggregations

PDataType (org.apache.phoenix.schema.types.PDataType)152 Expression (org.apache.phoenix.expression.Expression)54 LiteralExpression (org.apache.phoenix.expression.LiteralExpression)31 SortOrder (org.apache.phoenix.schema.SortOrder)29 ImmutableBytesWritable (org.apache.hadoop.hbase.io.ImmutableBytesWritable)21 CoerceExpression (org.apache.phoenix.expression.CoerceExpression)18 Test (org.junit.Test)15 PDatum (org.apache.phoenix.schema.PDatum)12 BigDecimal (java.math.BigDecimal)11 SQLException (java.sql.SQLException)11 ArrayList (java.util.ArrayList)11 List (java.util.List)10 KeyValueColumnExpression (org.apache.phoenix.expression.KeyValueColumnExpression)10 RowKeyColumnExpression (org.apache.phoenix.expression.RowKeyColumnExpression)10 SingleCellConstructorExpression (org.apache.phoenix.expression.SingleCellConstructorExpression)10 IOException (java.io.IOException)9 PreparedStatement (java.sql.PreparedStatement)7 Pair (org.apache.hadoop.hbase.util.Pair)7 Date (java.sql.Date)6 AndExpression (org.apache.phoenix.expression.AndExpression)6