CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-apache-phoenix--phoenix-core

Apache Phoenix Core library providing SQL-on-HBase functionality with JDBC connectivity, query compilation, and transaction support

Overview
Eval results
Files

expressions.mddocs/

Expression Framework

Phoenix's expression framework provides a powerful system for evaluating SQL expressions, functions, and operators. The framework supports literal values, column references, function calls, and complex expressions with proper type handling and optimization.

Core Imports

import org.apache.phoenix.expression.*;
import org.apache.phoenix.expression.function.*;
import org.apache.phoenix.expression.aggregator.*;
import org.apache.phoenix.schema.tuple.Tuple;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;

Core Expression Types

Expression

Base interface for all Phoenix expressions providing evaluation and metadata methods.

public interface Expression extends Writable {
    // Expression evaluation
    boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    PDataType getDataType()
    Integer getMaxLength()
    Integer getScale()
    boolean isNullable()

    // Expression properties
    SortOrder getSortOrder()
    boolean isDeterministic()
    boolean isStateless()

    // Child expressions
    List<Expression> getChildren()
    void reset()
    boolean requiresFinalEvaluation()

    // Serialization
    void write(DataOutput output) throws IOException
    void readFields(DataInput input) throws IOException
}

LiteralExpression

Expression representing constant literal values with type-safe value handling.

public class LiteralExpression implements Expression {
    // Factory methods for creating literals
    public static LiteralExpression newConstant(Object value)
    public static LiteralExpression newConstant(Object value, PDataType dataType)
    public static LiteralExpression newConstant(Object value, PDataType dataType,
                                               Integer maxLength, Integer scale)
    public static LiteralExpression newConstant(Object value, PDataType dataType,
                                               SortOrder sortOrder)

    // Expression implementation
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType()
    public Object getValue()
    public byte[] getBytes()

    // Literal-specific methods
    public boolean isNull()
    public String toString()
}

Usage:

// Create literal expressions
LiteralExpression stringLiteral = LiteralExpression.newConstant("Hello World");
LiteralExpression intLiteral = LiteralExpression.newConstant(42);
LiteralExpression decimalLiteral = LiteralExpression.newConstant(
    new BigDecimal("123.45"), PDecimal.INSTANCE, 5, 2
);

// Evaluate literals
ImmutableBytesWritable result = new ImmutableBytesWritable();
boolean success = stringLiteral.evaluate(null, result);  // Literals don't need tuple
if (success) {
    String value = (String) stringLiteral.getDataType().toObject(result);
    System.out.println("String value: " + value);
}

// Create null literal
LiteralExpression nullLiteral = LiteralExpression.newConstant(null, PVarchar.INSTANCE);
boolean isNull = nullLiteral.isNull();  // Returns true

ColumnExpression

Expression representing column references from tables.

public class ColumnExpression extends BaseTerminalExpression {
    public ColumnExpression(PColumn column, byte[] table)

    // Column information
    public PColumn getColumn()
    public byte[] getTableName()
    public String getDisplayName()

    // Expression implementation
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType()
    public boolean isNullable()
}

Usage:

// Create column expression
PTable table = connection.getTable(PNameFactory.newName("users"));
PColumn nameColumn = table.getColumn("name");
ColumnExpression nameExpr = new ColumnExpression(nameColumn, table.getName().getBytes());

// Evaluate column expression (requires tuple with row data)
Tuple rowTuple = getCurrentRowTuple();  // From query execution
ImmutableBytesWritable result = new ImmutableBytesWritable();
boolean success = nameExpr.evaluate(rowTuple, result);
if (success) {
    String name = (String) nameExpr.getDataType().toObject(result);
    System.out.println("Name: " + name);
}

// Column properties
PDataType dataType = nameExpr.getDataType();
String displayName = nameExpr.getDisplayName();
boolean nullable = nameExpr.isNullable();

Function Framework

FunctionExpression

Base class for all Phoenix function expressions providing common function behavior.

public abstract class FunctionExpression implements Expression {
    public FunctionExpression(List<Expression> children)
    public FunctionExpression(String name, List<Expression> children)

    // Function properties
    public String getName()
    public List<Expression> getChildren()
    public abstract PDataType getDataType()

    // Function evaluation
    public abstract boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public abstract String toString()

    // Helper methods for child evaluation
    protected boolean evaluateExpression(Expression expression, Tuple tuple,
                                        ImmutableBytesWritable ptr)
    protected Object evaluateExpression(Expression expression, Tuple tuple)
}

ScalarFunction

Base class for scalar functions that return a single value.

public abstract class ScalarFunction extends FunctionExpression {
    public ScalarFunction(List<Expression> children)
    public ScalarFunction(String name, List<Expression> children)

    // Scalar function implementation
    public abstract boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public abstract PDataType getDataType()

    // Common scalar function utilities
    protected static boolean checkNulls(Tuple tuple, Expression... expressions)
    protected static Object getObject(Expression expression, Tuple tuple)
}

AggregateFunction

Base class for aggregate functions that accumulate values across multiple rows.

public abstract class AggregateFunction extends FunctionExpression {
    public AggregateFunction(List<Expression> children, String name)

    // Aggregate function implementation
    public abstract Aggregator newAggregator()
    public abstract boolean isAggregator(Expression expression)

    // Aggregate properties
    public boolean requiresFinalEvaluation() // Returns true
    public abstract PDataType getDataType()
}

Usage:

// Create scalar function (example: UPPER function)
Expression nameColumn = new ColumnExpression(nameColumn, tableBytes);
List<Expression> upperArgs = Arrays.asList(nameColumn);
ScalarFunction upperFunc = new UpperFunction(upperArgs);

// Evaluate scalar function
Tuple rowTuple = getCurrentRowTuple();
ImmutableBytesWritable result = new ImmutableBytesWritable();
boolean success = upperFunc.evaluate(rowTuple, result);
if (success) {
    String upperName = (String) upperFunc.getDataType().toObject(result);
    System.out.println("Upper name: " + upperName);
}

// Create aggregate function (example: COUNT function)
List<Expression> countArgs = Arrays.asList(LiteralExpression.newConstant(1));
AggregateFunction countFunc = new CountAggregateFunction(countArgs);
Aggregator aggregator = countFunc.newAggregator();

Aggregation Framework

Aggregator

Interface for aggregation operations that accumulate values across multiple rows.

public interface Aggregator {
    // Aggregation operations
    void aggregate(Tuple tuple, ImmutableBytesWritable ptr)
    boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)

    // Aggregator state
    void reset()
    Aggregator newAggregator()

    // Size estimation
    int getSize()
}

ServerAggregators

Container for server-side aggregators used in distributed query execution.

public class ServerAggregators {
    public ServerAggregators(List<SingleAggregateFunction> functions,
                           int minNullableIndex)

    // Aggregator access
    public SingleAggregateFunction[] getFunctions()
    public Aggregator[] getAggregators()
    public KeyValueSchema getSchema()

    // Aggregation operations
    public void aggregate(Aggregator[] aggregators, Tuple result)
    public void reset(Aggregator[] aggregators)
    public int getEstimatedByteSize()
}

Usage:

// Create aggregators for distributed execution
List<SingleAggregateFunction> aggFunctions = Arrays.asList(
    new CountAggregateFunction(),
    new SumAggregateFunction(salaryColumn),
    new MaxAggregateFunction(salaryColumn)
);

ServerAggregators serverAggs = new ServerAggregators(aggFunctions, 0);
Aggregator[] aggregators = serverAggs.getAggregators();

// Process each row in server-side scan
while (scanner.hasNext()) {
    Tuple row = scanner.next();
    serverAggs.aggregate(aggregators, row);
}

// Get final aggregated results
ImmutableBytesWritable result = new ImmutableBytesWritable();
for (int i = 0; i < aggregators.length; i++) {
    boolean success = aggregators[i].evaluate(null, result);
    if (success) {
        Object value = aggFunctions.get(i).getDataType().toObject(result);
        System.out.println("Aggregate " + i + ": " + value);
    }
}

Common Function Types

String Functions

// String manipulation functions
public class UpperFunction extends ScalarFunction {
    public UpperFunction(List<Expression> children)
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType() // Returns PVarchar.INSTANCE
}

public class LowerFunction extends ScalarFunction {
    public LowerFunction(List<Expression> children)
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType() // Returns PVarchar.INSTANCE
}

public class SubstrFunction extends ScalarFunction {
    public SubstrFunction(List<Expression> children)  // string, start, [length]
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType() // Returns PVarchar.INSTANCE
}

public class LengthFunction extends ScalarFunction {
    public LengthFunction(List<Expression> children)
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType() // Returns PInteger.INSTANCE
}

Usage:

// String function examples
Expression nameColumn = new ColumnExpression(nameColumn, tableBytes);

// UPPER(name)
UpperFunction upper = new UpperFunction(Arrays.asList(nameColumn));

// LENGTH(name)
LengthFunction length = new LengthFunction(Arrays.asList(nameColumn));

// SUBSTR(name, 1, 5)
SubstrFunction substr = new SubstrFunction(Arrays.asList(
    nameColumn,
    LiteralExpression.newConstant(1),
    LiteralExpression.newConstant(5)
));

// Evaluate functions
Tuple row = getCurrentRowTuple();
ImmutableBytesWritable result = new ImmutableBytesWritable();

if (upper.evaluate(row, result)) {
    String upperName = (String) upper.getDataType().toObject(result);
    System.out.println("Upper: " + upperName);
}

if (length.evaluate(row, result)) {
    Integer nameLength = (Integer) length.getDataType().toObject(result);
    System.out.println("Length: " + nameLength);
}

Numeric Functions

// Mathematical functions
public class RoundFunction extends ScalarFunction {
    public RoundFunction(List<Expression> children)  // number, [scale]
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType() // Returns number type
}

public class AbsFunction extends ScalarFunction {
    public AbsFunction(List<Expression> children)
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType() // Returns same as input
}

public class PowerFunction extends ScalarFunction {
    public PowerFunction(List<Expression> children)  // base, exponent
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType() // Returns PDouble.INSTANCE
}

Date/Time Functions

// Date/time manipulation functions
public class NowFunction extends ScalarFunction {
    public NowFunction()  // No arguments
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType() // Returns PTimestamp.INSTANCE
}

public class ToDateFunction extends ScalarFunction {
    public ToDateFunction(List<Expression> children)  // string, [format]
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType() // Returns PDate.INSTANCE
}

public class YearFunction extends ScalarFunction {
    public YearFunction(List<Expression> children)  // date
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType() // Returns PInteger.INSTANCE
}

Aggregate Functions

// Standard aggregate functions
public class CountAggregateFunction extends SingleAggregateFunction {
    public CountAggregateFunction(List<Expression> children)
    public Aggregator newAggregator()
    public PDataType getDataType() // Returns PLong.INSTANCE
}

public class SumAggregateFunction extends SingleAggregateFunction {
    public SumAggregateFunction(List<Expression> children)
    public Aggregator newAggregator()
    public PDataType getDataType() // Returns numeric type
}

public class AvgAggregateFunction extends SingleAggregateFunction {
    public AvgAggregateFunction(List<Expression> children)
    public Aggregator newAggregator()
    public PDataType getDataType() // Returns PDecimal.INSTANCE
}

public class MinAggregateFunction extends SingleAggregateFunction {
    public MinAggregateFunction(List<Expression> children)
    public Aggregator newAggregator()
    public PDataType getDataType() // Returns same as input
}

public class MaxAggregateFunction extends SingleAggregateFunction {
    public MaxAggregateFunction(List<Expression> children)
    public Aggregator newAggregator()
    public PDataType getDataType() // Returns same as input
}

Usage:

// Aggregate function examples
Expression salaryColumn = new ColumnExpression(salaryColumn, tableBytes);

// COUNT(*)
CountAggregateFunction count = new CountAggregateFunction(
    Arrays.asList(LiteralExpression.newConstant(1))
);

// SUM(salary)
SumAggregateFunction sum = new SumAggregateFunction(Arrays.asList(salaryColumn));

// AVG(salary)
AvgAggregateFunction avg = new AvgAggregateFunction(Arrays.asList(salaryColumn));

// MIN(salary)
MinAggregateFunction min = new MinAggregateFunction(Arrays.asList(salaryColumn));

// MAX(salary)
MaxAggregateFunction max = new MaxAggregateFunction(Arrays.asList(salaryColumn));

// Create aggregators
Aggregator countAgg = count.newAggregator();
Aggregator sumAgg = sum.newAggregator();
Aggregator avgAgg = avg.newAggregator();

// Process rows
while (hasMoreRows()) {
    Tuple row = getNextRow();

    // Aggregate each row
    countAgg.aggregate(row, null);
    ImmutableBytesWritable ptr = new ImmutableBytesWritable();
    if (salaryColumn.evaluate(row, ptr)) {
        sumAgg.aggregate(row, ptr);
        avgAgg.aggregate(row, ptr);
    }
}

// Get final results
ImmutableBytesWritable result = new ImmutableBytesWritable();

if (countAgg.evaluate(null, result)) {
    Long countValue = (Long) count.getDataType().toObject(result);
    System.out.println("Count: " + countValue);
}

if (sumAgg.evaluate(null, result)) {
    Object sumValue = sum.getDataType().toObject(result);
    System.out.println("Sum: " + sumValue);
}

Complex Expression Examples

Conditional Expressions

// CASE WHEN expressions
public class CaseExpression extends ScalarFunction {
    public CaseExpression(List<Expression> children)
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType()
}

// Usage: CASE WHEN age < 18 THEN 'Minor' ELSE 'Adult' END
Expression ageColumn = new ColumnExpression(ageColumn, tableBytes);
Expression condition = new ComparisonExpression(
    CompareOp.LESS,
    Arrays.asList(ageColumn, LiteralExpression.newConstant(18))
);
Expression caseExpr = new CaseExpression(Arrays.asList(
    condition,
    LiteralExpression.newConstant("Minor"),
    LiteralExpression.newConstant("Adult")
));

Arithmetic Expressions

// Arithmetic operations
public class ArithmeticExpression extends ScalarFunction {
    public ArithmeticExpression(ArithmeticOp op, List<Expression> children)
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType()
}

// Usage: salary * 1.1 (10% raise)
Expression salaryColumn = new ColumnExpression(salaryColumn, tableBytes);
Expression raiseMultiplier = LiteralExpression.newConstant(new BigDecimal("1.1"));
Expression raisedSalary = new ArithmeticExpression(
    ArithmeticOp.MULT,
    Arrays.asList(salaryColumn, raiseMultiplier)
);

Comparison Expressions

// Comparison operations
public class ComparisonExpression extends ScalarFunction {
    public ComparisonExpression(CompareOp op, List<Expression> children)
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr)
    public PDataType getDataType() // Returns PBoolean.INSTANCE
}

// Usage: age >= 21
Expression ageColumn = new ColumnExpression(ageColumn, tableBytes);
Expression legalAge = LiteralExpression.newConstant(21);
Expression isLegalAge = new ComparisonExpression(
    CompareOp.GREATER_OR_EQUAL,
    Arrays.asList(ageColumn, legalAge)
);

Practical Examples

Building Complex Expressions

public class ExpressionBuilder {
    private final PTable table;
    private final byte[] tableBytes;

    public ExpressionBuilder(PTable table) {
        this.table = table;
        this.tableBytes = table.getName().getBytes();
    }

    public Expression buildFullNameExpression() {
        // CONCAT(first_name, ' ', last_name)
        Expression firstName = new ColumnExpression(table.getColumn("first_name"), tableBytes);
        Expression lastName = new ColumnExpression(table.getColumn("last_name"), tableBytes);
        Expression space = LiteralExpression.newConstant(" ");

        return new ConcatFunction(Arrays.asList(firstName, space, lastName));
    }

    public Expression buildAgeGroupExpression() {
        // CASE
        //   WHEN age < 18 THEN 'Minor'
        //   WHEN age < 65 THEN 'Adult'
        //   ELSE 'Senior'
        // END
        Expression ageColumn = new ColumnExpression(table.getColumn("age"), tableBytes);

        Expression isMinor = new ComparisonExpression(
            CompareOp.LESS,
            Arrays.asList(ageColumn, LiteralExpression.newConstant(18))
        );

        Expression isAdult = new ComparisonExpression(
            CompareOp.LESS,
            Arrays.asList(ageColumn, LiteralExpression.newConstant(65))
        );

        return new CaseExpression(Arrays.asList(
            isMinor, LiteralExpression.newConstant("Minor"),
            isAdult, LiteralExpression.newConstant("Adult"),
            LiteralExpression.newConstant("Senior")
        ));
    }

    public Expression buildSalaryBonusExpression() {
        // salary + (salary * bonus_percentage / 100)
        Expression salary = new ColumnExpression(table.getColumn("salary"), tableBytes);
        Expression bonusPercent = new ColumnExpression(table.getColumn("bonus_percentage"), tableBytes);
        Expression hundred = LiteralExpression.newConstant(100);

        Expression bonusAmount = new ArithmeticExpression(
            ArithmeticOp.MULT,
            Arrays.asList(salary, bonusPercent)
        );

        Expression bonusDivided = new ArithmeticExpression(
            ArithmeticOp.DIV,
            Arrays.asList(bonusAmount, hundred)
        );

        return new ArithmeticExpression(
            ArithmeticOp.ADD,
            Arrays.asList(salary, bonusDivided)
        );
    }
}

// Usage
PTable employeeTable = connection.getTable(PNameFactory.newName("employees"));
ExpressionBuilder builder = new ExpressionBuilder(employeeTable);

Expression fullName = builder.buildFullNameExpression();
Expression ageGroup = builder.buildAgeGroupExpression();
Expression totalSalary = builder.buildSalaryBonusExpression();

// Evaluate expressions for a row
Tuple employeeRow = getCurrentEmployeeRow();
ImmutableBytesWritable result = new ImmutableBytesWritable();

if (fullName.evaluate(employeeRow, result)) {
    String name = (String) fullName.getDataType().toObject(result);
    System.out.println("Full Name: " + name);
}

if (ageGroup.evaluate(employeeRow, result)) {
    String group = (String) ageGroup.getDataType().toObject(result);
    System.out.println("Age Group: " + group);
}

if (totalSalary.evaluate(employeeRow, result)) {
    BigDecimal total = (BigDecimal) totalSalary.getDataType().toObject(result);
    System.out.println("Total Salary: $" + total);
}

Custom Function Implementation

// Custom scalar function example
public class AgeFromBirthdateFunction extends ScalarFunction {
    public AgeFromBirthdateFunction(List<Expression> children) {
        super("AGE_FROM_BIRTHDATE", children);
        if (children.size() != 1) {
            throw new IllegalArgumentException("AGE_FROM_BIRTHDATE expects 1 argument");
        }
    }

    @Override
    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
        Expression birthdateExpr = getChildren().get(0);

        if (!birthdateExpr.evaluate(tuple, ptr)) {
            return false;
        }

        if (ptr.getLength() == 0) {
            return true; // NULL input -> NULL output
        }

        // Get birthdate value
        Date birthdate = (Date) birthdateExpr.getDataType().toObject(ptr);

        // Calculate age
        Calendar birth = Calendar.getInstance();
        birth.setTime(birthdate);

        Calendar now = Calendar.getInstance();

        int age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
        if (now.get(Calendar.DAY_OF_YEAR) < birth.get(Calendar.DAY_OF_YEAR)) {
            age--;
        }

        // Convert result to bytes
        return PInteger.INSTANCE.toBytes(age, ptr.get(), ptr.getOffset());
    }

    @Override
    public PDataType getDataType() {
        return PInteger.INSTANCE;
    }
}

// Usage
Expression birthdateColumn = new ColumnExpression(table.getColumn("birthdate"), tableBytes);
AgeFromBirthdateFunction ageFunc = new AgeFromBirthdateFunction(Arrays.asList(birthdateColumn));

// Evaluate custom function
Tuple row = getCurrentRow();
ImmutableBytesWritable result = new ImmutableBytesWritable();
if (ageFunc.evaluate(row, result)) {
    Integer age = (Integer) ageFunc.getDataType().toObject(result);
    System.out.println("Calculated age: " + age);
}

Install with Tessl CLI

npx tessl i tessl/maven-org-apache-phoenix--phoenix-core

docs

configuration.md

exceptions.md

execution.md

expressions.md

index.md

jdbc.md

mapreduce.md

monitoring.md

query-compilation.md

schema-metadata.md

server.md

transactions.md

types.md

tile.json