James Taylor commented on PHOENIX-476:

Thanks for chiming in, [~julianhyde]. So we can still implement DEFAULT without 
storing the default value for non PK columns, [~kliew]. This is important as 
for a multi billion row table, it will save a lot of space.

Instead of using using CoalesceFunction during the wrapping, we can create a 
new Expression and register it in ExpressionType, called 
DefaultValueExpression. The evaluate method can distinguish between the case 
where there's no value for the column (i.e. colRefChildExpression.evaluate 
returns false) versus it returning a null value (i.e. 
colRefChildExpression.evaluate returns true but ptr.getLength() is zero). We'd 
want to force STORE_NULLS=true when a table is created with default values. See 
MetaDataClient.createTableInternal() and how we force this option to true for 
transactional tables - we'd want to do something similar here if any of the 
columns for the new table define a DEFAULT. With this option in place, Phoenix 
will store an empty byte array as the column value instead of issuing an HBase 

The evaluate method of DefaultValueExpression would look something like this 
(just one very subtle change from the CoalesceFunction implementation):
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
        boolean evaluated = children.get(0).evaluate(tuple, ptr);
        if (evaluated) {
            // Will potentially evaluate to null without evaluating the second 
            return true;
        if (tuple.isImmutable()) { // This is true if it's the last time an 
evaluation is happening on the row
            Expression secondChild = children.get(1);
            if (secondChild.evaluate(tuple, ptr)) {
                // Coerce the type of the second child to the type of the first 
                getDataType().coerceBytes(ptr, secondChild.getDataType(), 
secondChild.getSortOrder(), getSortOrder());
                return true;
        return false;

> Support declaration of DEFAULT in CREATE statement
> --------------------------------------------------
>                 Key: PHOENIX-476
>                 URL: https://issues.apache.org/jira/browse/PHOENIX-476
>             Project: Phoenix
>          Issue Type: Task
>    Affects Versions: 3.0-Release
>            Reporter: James Taylor
>            Assignee: Kevin Liew
>              Labels: enhancement
>         Attachments: PHOENIX-476.2.patch, PHOENIX-476.patch
> Support the declaration of a default value in the CREATE TABLE/VIEW statement 
> like this:
>     CREATE TABLE Persons (
>         Pid int NOT NULL PRIMARY KEY,
>         LastName varchar(255) NOT NULL,
>         FirstName varchar(255),
>         Address varchar(255),
>         City varchar(255) DEFAULT 'Sandnes'
>     )
> To implement this, we'd need to:
> 1. add a new DEFAULT_VALUE key value column in SYSTEM.TABLE and pass through 
> the value when the table is created (in MetaDataClient).
> 2. always set NULLABLE to ResultSetMetaData.columnNoNulls if a default value 
> is present, since the column will never be null.
> 3. add a getDefaultValue() accessor in PColumn
> 4.  for a row key column, during UPSERT use the default value if no value was 
> specified for that column. This could be done in the PTableImpl.newKey method.
> 5.  for a key value column with a default value, we can get away without 
> incurring any storage cost. Although a little bit of extra effort than if we 
> persisted the default value on an UPSERT for key value columns, this approach 
> has the benefit of not incurring any storage cost for a default value.
>     * serialize any default value into KeyValueColumnExpression
>     * in the evaluate method of KeyValueColumnExpression, conditionally use 
> the default value if the column value is not present. If doing partial 
> evaluation, you should not yet return the default value, as we may not have 
> encountered the the KeyValue for the column yet (since a filter evaluates 
> each time it sees each KeyValue, and there may be more than one KeyValue 
> referenced in the expression). Partial evaluation is determined by calling 
> Tuple.isImmutable(), where false means it is NOT doing partial evaluation, 
> while true means it is.
>     * modify EvaluateOnCompletionVisitor by adding a visitor method for 
> RowKeyColumnExpression and KeyValueColumnExpression to set 
> evaluateOnCompletion to true if they have a default value specified. This 
> will cause filter evaluation to execute one final time after all KeyValues 
> for a row have been seen, since it's at this time we know we should use the 
> default value.

This message was sent by Atlassian JIRA

Reply via email to