use of org.apache.phoenix.compile.ExpressionCompiler in project phoenix by apache.
the class ColumnRef method newColumnExpression.
public Expression newColumnExpression(boolean schemaNameCaseSensitive, boolean colNameCaseSensitive) throws SQLException {
PTable table = tableRef.getTable();
PColumn column = this.getColumn();
String displayName = tableRef.getColumnDisplayName(this, schemaNameCaseSensitive, colNameCaseSensitive);
if (SchemaUtil.isPKColumn(column)) {
return new RowKeyColumnExpression(column, new RowKeyValueAccessor(table.getPKColumns(), pkSlotPosition), displayName);
}
if (table.getType() == PTableType.PROJECTED || table.getType() == PTableType.SUBQUERY) {
return new ProjectedColumnExpression(column, table, displayName);
}
Expression expression = table.getImmutableStorageScheme() == ImmutableStorageScheme.SINGLE_CELL_ARRAY_WITH_OFFSETS ? new SingleCellColumnExpression(column, displayName, table.getEncodingScheme()) : new KeyValueColumnExpression(column, displayName);
if (column.getExpressionStr() != null) {
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);
if (!ExpressionUtil.isNull(defaultExpression, new ImmutableBytesWritable())) {
return new DefaultValueExpression(Arrays.asList(expression, defaultExpression));
}
}
return expression;
}
use of org.apache.phoenix.compile.ExpressionCompiler in project phoenix by apache.
the class ColumnDef method validateDefault.
public boolean validateDefault(StatementContext context, PrimaryKeyConstraint pkConstraint) throws SQLException {
String defaultStr = this.getExpression();
if (defaultStr == null) {
return true;
}
ExpressionCompiler compiler = new ExpressionCompiler(context);
ParseNode defaultParseNode = new SQLParser(this.getExpression()).parseExpression();
Expression defaultExpression = defaultParseNode.accept(compiler);
if (!defaultParseNode.isStateless() || defaultExpression.getDeterminism() != Determinism.ALWAYS) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_CREATE_DEFAULT).setColumnName(this.getColumnDefName().getColumnName()).build().buildException();
}
if (this.isRowTimestamp() || (pkConstraint != null && pkConstraint.isColumnRowTimestamp(this.getColumnDefName()))) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_CREATE_DEFAULT_ROWTIMESTAMP).setColumnName(this.getColumnDefName().getColumnName()).build().buildException();
}
ImmutableBytesWritable ptr = new ImmutableBytesWritable();
// Evaluate the expression to confirm it's validity
LiteralExpression defaultValue = ExpressionUtil.getConstantExpression(defaultExpression, ptr);
// A DEFAULT that evaluates to null should be ignored as it adds nothing
if (defaultValue.getValue() == null) {
return false;
}
PDataType sourceType = defaultExpression.getDataType();
PDataType targetType = this.getDataType();
// Ensure that coercion works (will throw if not)
context.getTempPtr().set(ptr.get(), ptr.getOffset(), ptr.getLength());
try {
targetType.coerceBytes(context.getTempPtr(), defaultValue.getValue(), sourceType, defaultValue.getMaxLength(), defaultValue.getScale(), defaultValue.getSortOrder(), this.getMaxLength(), this.getScale(), this.getSortOrder());
} catch (ConstraintViolationException e) {
if (e.getCause() instanceof SQLException) {
SQLException sqlE = (SQLException) e.getCause();
throw new DelegateSQLException(sqlE, ". DEFAULT " + SQLExceptionInfo.COLUMN_NAME + "=" + this.getColumnDefName().getColumnName());
}
throw e;
}
if (!targetType.isSizeCompatible(ptr, defaultValue.getValue(), sourceType, sortOrder, defaultValue.getMaxLength(), defaultValue.getScale(), this.getMaxLength(), this.getScale())) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.DATA_EXCEEDS_MAX_CAPACITY).setColumnName(this.getColumnDefName().getColumnName()).setMessage("DEFAULT " + this.getExpression()).build().buildException();
}
return true;
}
use of org.apache.phoenix.compile.ExpressionCompiler 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);
}
}
}
Aggregations