Apache Phoenix Core library providing SQL-on-HBase functionality with JDBC connectivity, query compilation, and transaction support
Phoenix Core provides a complete JDBC 4.0 implementation that enables standard SQL database connectivity to HBase. The JDBC API serves as the primary interface for client applications to interact with Phoenix.
import org.apache.phoenix.jdbc.*;
import java.sql.*;
import java.util.Properties;The main JDBC driver implementation for production use. Extends PhoenixEmbeddedDriver and provides connection pooling and caching.
public final class PhoenixDriver extends PhoenixEmbeddedDriver {
public static final PhoenixDriver INSTANCE;
// Standard JDBC Driver methods
public Connection connect(String url, Properties info) throws SQLException
public boolean acceptsURL(String url) throws SQLException
// Phoenix-specific methods
public QueryServices getQueryServices() throws SQLException
public void close() throws SQLException
void invalidateCache(String url, Properties properties) throws SQLException
}Usage:
// Driver is automatically registered via static initialization
String url = "jdbc:phoenix:zk1,zk2,zk3:2181";
Properties props = new Properties();
Connection connection = DriverManager.getConnection(url, props);Abstract base driver class with embedded driver functionality.
public abstract class PhoenixEmbeddedDriver implements Driver, SQLCloseable {
public abstract QueryServices getQueryServices() throws SQLException
// Standard JDBC Driver methods
public boolean acceptsURL(String url) throws SQLException
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException
public int getMajorVersion()
public int getMinorVersion()
public boolean jdbcCompliant()
public Logger getParentLogger() throws SQLFeatureNotSupportedException
}Primary connection implementation providing Phoenix-specific extensions to standard JDBC Connection.
public class PhoenixConnection implements MetaDataMutated, SQLCloseable, PhoenixMonitoredConnection {
// Constructors
public PhoenixConnection(PhoenixConnection connection) throws SQLException
public PhoenixConnection(ConnectionQueryServices services, String url, Properties info, PMetaData metaData) throws SQLException
// Standard JDBC Connection methods
public Statement createStatement() throws SQLException
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
public PreparedStatement prepareStatement(String sql) throws SQLException
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
public void commit() throws SQLException
public void rollback() throws SQLException
public void close() throws SQLException
public boolean getAutoCommit() throws SQLException
public void setAutoCommit(boolean autoCommit) throws SQLException
// Phoenix-specific extensions
public ConnectionQueryServices getQueryServices()
public PMetaData getMetaDataCache()
public MutationState getMutationState()
public PTable getTable(String name) throws SQLException
public PTable getTable(PTableKey key) throws SQLException
public PTable getTableNoCache(String name) throws SQLException
public @Nullable PName getTenantId()
public Long getSCN()
public String getURL()
public int getMutateBatchSize()
public long getMutateBatchSizeBytes()
public String getDatePattern()
public String getTimePattern()
public String getTimestampPattern()
public boolean isInternalConnection()
public int executeStatements(Reader reader, List<Object> binds, PrintStream out) throws IOException, SQLException
}Usage:
PhoenixConnection phoenixConn = connection.unwrap(PhoenixConnection.class);
// Access Phoenix-specific features
PTable table = phoenixConn.getTable("my_table");
MutationState mutations = phoenixConn.getMutationState();
PName tenantId = phoenixConn.getTenantId();
Long scn = phoenixConn.getSCN();Abstract base class containing connection configuration and connection string information.
public abstract class ConnectionInfo {
// Static factory method
public static ConnectionInfo create(String url, ReadOnlyProps props, Properties info) throws SQLException
// Instance methods
public abstract String getUrl()
public abstract ReadOnlyProps asProps()
public abstract boolean isConnectionless()
public boolean isTestUrl()
public String getPrincipal()
public String getKeytab()
public User getUser()
public String getHaGroup()
}Phoenix implementation of JDBC Statement with monitoring capabilities.
public class PhoenixStatement implements PhoenixMonitoredStatement, SQLCloseable {
// Constructor
public PhoenixStatement(PhoenixConnection connection)
// Standard JDBC Statement methods
public ResultSet executeQuery(String sql) throws SQLException
public int executeUpdate(String sql) throws SQLException
public boolean execute(String sql) throws SQLException
public void close() throws SQLException
public PhoenixConnection getConnection() throws SQLException
public int getMaxRows() throws SQLException
public void setMaxRows(int max) throws SQLException
public int getQueryTimeout() throws SQLException
public void setQueryTimeout(int seconds) throws SQLException
public void addBatch(String sql) throws SQLException
public void clearBatch() throws SQLException
public int[] executeBatch() throws SQLException
// Phoenix-specific methods
public PhoenixResultSet newResultSet(ResultIterator iterator, RowProjector projector, StatementContext context) throws SQLException
public String getTargetForAudit(CompilableStatement stmt)
}Usage:
PhoenixStatement stmt = connection.createStatement().unwrap(PhoenixStatement.class);
// Execute queries
String sql = "SELECT * FROM users WHERE age > 25";
ResultSet rs = stmt.executeQuery(sql);
// Execute updates
int rowsAffected = stmt.executeUpdate("DELETE FROM users WHERE status = 'INACTIVE'");Phoenix implementation of JDBC PreparedStatement.
public class PhoenixPreparedStatement extends PhoenixStatement implements PhoenixMonitoredPreparedStatement, SQLCloseable {
// Constructors
public PhoenixPreparedStatement(PhoenixConnection connection, String query) throws SQLException
public PhoenixPreparedStatement(PhoenixConnection connection, PhoenixStatementParser parser) throws SQLException, IOException
// Standard JDBC PreparedStatement methods
public ResultSet executeQuery() throws SQLException
public int executeUpdate() throws SQLException
public boolean execute() throws SQLException
public void addBatch() throws SQLException
public void clearParameters() throws SQLException
// Parameter setting methods
public void setString(int parameterIndex, String x) throws SQLException
public void setInt(int parameterIndex, int x) throws SQLException
public void setLong(int parameterIndex, long x) throws SQLException
public void setDouble(int parameterIndex, double x) throws SQLException
public void setFloat(int parameterIndex, float x) throws SQLException
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
public void setBoolean(int parameterIndex, boolean x) throws SQLException
public void setByte(int parameterIndex, byte x) throws SQLException
public void setShort(int parameterIndex, short x) throws SQLException
public void setBytes(int parameterIndex, byte[] x) throws SQLException
public void setDate(int parameterIndex, Date x) throws SQLException
public void setTime(int parameterIndex, Time x) throws SQLException
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
public void setNull(int parameterIndex, int sqlType) throws SQLException
public void setObject(int parameterIndex, Object x) throws SQLException
// Metadata methods
public ResultSetMetaData getMetaData() throws SQLException
public ParameterMetaData getParameterMetaData() throws SQLException
// Phoenix-specific methods
public List<Object> getParameters()
public QueryPlan compileQuery() throws SQLException
public MutationPlan compileMutation() throws SQLException
public QueryPlan optimizeQuery() throws SQLException
}Usage:
String sql = "SELECT * FROM users WHERE id = ? AND status = ?";
PhoenixPreparedStatement pstmt = connection.prepareStatement(sql)
.unwrap(PhoenixPreparedStatement.class);
pstmt.setLong(1, userId);
pstmt.setString(2, "ACTIVE");
ResultSet rs = pstmt.executeQuery();Phoenix implementation of JDBC ResultSet with monitoring capabilities.
public class PhoenixResultSet implements PhoenixMonitoredResultSet, SQLCloseable {
// Constructor
public PhoenixResultSet(ResultIterator resultIterator, RowProjector rowProjector, StatementContext context) throws SQLException
// Standard JDBC ResultSet methods
public boolean next() throws SQLException
public boolean first() throws SQLException
public boolean last() throws SQLException
public void close() throws SQLException
public boolean isClosed() throws SQLException
// Data retrieval methods
public String getString(int columnIndex) throws SQLException
public String getString(String columnLabel) throws SQLException
public int getInt(int columnIndex) throws SQLException
public int getInt(String columnLabel) throws SQLException
public long getLong(int columnIndex) throws SQLException
public long getLong(String columnLabel) throws SQLException
public double getDouble(int columnIndex) throws SQLException
public double getDouble(String columnLabel) throws SQLException
public BigDecimal getBigDecimal(int columnIndex) throws SQLException
public BigDecimal getBigDecimal(String columnLabel) throws SQLException
public Date getDate(int columnIndex) throws SQLException
public Date getDate(String columnLabel) throws SQLException
public Time getTime(int columnIndex) throws SQLException
public Time getTime(String columnLabel) throws SQLException
public Timestamp getTimestamp(int columnIndex) throws SQLException
public Timestamp getTimestamp(String columnLabel) throws SQLException
public boolean getBoolean(int columnIndex) throws SQLException
public boolean getBoolean(String columnLabel) throws SQLException
public byte getByte(int columnIndex) throws SQLException
public byte getByte(String columnLabel) throws SQLException
public byte[] getBytes(int columnIndex) throws SQLException
public byte[] getBytes(String columnLabel) throws SQLException
public Object getObject(int columnIndex) throws SQLException
public Object getObject(String columnLabel) throws SQLException
public Array getArray(int columnIndex) throws SQLException
public Array getArray(String columnLabel) throws SQLException
// Metadata methods
public ResultSetMetaData getMetaData() throws SQLException
public int findColumn(String columnLabel) throws SQLException
// Navigation methods
public boolean wasNull() throws SQLException
public void clearWarnings() throws SQLException
public SQLWarning getWarnings() throws SQLException
}Usage:
ResultSet rs = stmt.executeQuery("SELECT id, name, created_date FROM users");
PhoenixResultSet phoenixRs = rs.unwrap(PhoenixResultSet.class);
while (rs.next()) {
long id = rs.getLong("id");
String name = rs.getString("name");
Date created = rs.getDate("created_date");
// Check for null values
if (rs.wasNull()) {
System.out.println("Last column was null");
}
}Metadata for Phoenix result sets.
public class PhoenixResultSetMetaData implements ResultSetMetaData {
public PhoenixResultSetMetaData(PhoenixConnection connection, RowProjector projector)
public int getColumnCount() throws SQLException
public String getColumnName(int column) throws SQLException
public String getColumnLabel(int column) throws SQLException
public int getColumnType(int column) throws SQLException
public String getColumnTypeName(int column) throws SQLException
public String getColumnClassName(int column) throws SQLException
public int getPrecision(int column) throws SQLException
public int getScale(int column) throws SQLException
public int getColumnDisplaySize(int column) throws SQLException
public int isNullable(int column) throws SQLException
public boolean isAutoIncrement(int column) throws SQLException
public boolean isCaseSensitive(int column) throws SQLException
public boolean isSearchable(int column) throws SQLException
public boolean isCurrency(int column) throws SQLException
public boolean isSigned(int column) throws SQLException
}Phoenix implementation of JDBC DatabaseMetaData.
public class PhoenixDatabaseMetaData implements DatabaseMetaData {
public PhoenixDatabaseMetaData(PhoenixConnection connection) throws SQLException
public ResultSet getTables(String catalog, String schemaPattern,
String tableNamePattern, String[] types) throws SQLException
public ResultSet getColumns(String catalog, String schemaPattern,
String tableNamePattern, String columnNamePattern) throws SQLException
public ResultSet getIndexInfo(String catalog, String schema, String table,
boolean unique, boolean approximate) throws SQLException
public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException
public ResultSet getSchemas() throws SQLException
public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException
public ResultSet getCatalogs() throws SQLException
public ResultSet getTableTypes() throws SQLException
public String getDatabaseProductName() throws SQLException
public String getDatabaseProductVersion() throws SQLException
public String getDriverName() throws SQLException
public String getDriverVersion() throws SQLException
public int getDriverMajorVersion()
public int getDriverMinorVersion()
}Parameter metadata for Phoenix prepared statements.
public class PhoenixParameterMetaData implements ParameterMetaData {
public PhoenixParameterMetaData(PhoenixConnection connection, PDatum[] params)
public int getParameterCount() throws SQLException
public int getParameterType(int param) throws SQLException
public String getParameterTypeName(int param) throws SQLException
public String getParameterClassName(int param) throws SQLException
public int getPrecision(int param) throws SQLException
public int getScale(int param) throws SQLException
public int isNullable(int param) throws SQLException
public boolean isSigned(int param) throws SQLException
}Usage:
// Database metadata
DatabaseMetaData metaData = connection.getMetaData();
ResultSet tables = metaData.getTables(null, "MYSCHEMA", "%", new String[]{"TABLE"});
// Parameter metadata for prepared statements
PreparedStatement pstmt = connection.prepareStatement("SELECT * FROM users WHERE id = ? AND age > ?");
ParameterMetaData paramMeta = pstmt.getParameterMetaData();
int paramCount = paramMeta.getParameterCount();
// Result set metadata
ResultSet rs = pstmt.executeQuery();
ResultSetMetaData rsMeta = rs.getMetaData();
int columnCount = rsMeta.getColumnCount();Connection implementation with failover capabilities that wraps a regular PhoenixConnection and provides automatic failover between HBase clusters.
public class FailoverPhoenixConnection implements PhoenixMonitoredConnection {
// Constants
public static final String FAILOVER_TIMEOUT_MS_ATTR = "phoenix.ha.failover.timeout.ms"
public static final long FAILOVER_TIMEOUT_MS_DEFAULT = 10_000
// Constructor
public FailoverPhoenixConnection(HighAvailabilityGroup haGroup, Properties properties, FailoverPolicy policy) throws SQLException
// Standard JDBC Connection methods (delegated)
public Statement createStatement() throws SQLException
public PreparedStatement prepareStatement(String sql) throws SQLException
public void close() throws SQLException
public boolean isClosed() throws SQLException
public void commit() throws SQLException
public void rollback() throws SQLException
public boolean getAutoCommit() throws SQLException
public void setAutoCommit(boolean autoCommit) throws SQLException
public DatabaseMetaData getMetaData() throws SQLException
// High availability methods
public HighAvailabilityGroup getHighAvailabilityGroup()
public FailoverPolicy getFailoverPolicy()
public PhoenixConnection getWrappedConnection()
public boolean isFailoverNeeded() throws SQLException
}Manages high availability groups for Phoenix connections with cluster role monitoring.
public class HighAvailabilityGroup {
// Constants
public static final String PHOENIX_HA_ATTR_PREFIX = "phoenix.ha."
public static final String PHOENIX_HA_GROUP_ATTR = PHOENIX_HA_ATTR_PREFIX + "group.name"
public static final String PHOENIX_HA_ZOOKEEPER_ZNODE_NAMESPACE = "phoenix/ha"
// Static factory method
public static HighAvailabilityGroup create(String name, Properties props) throws SQLException
// Instance methods
public String getGroupName()
public ClusterRoleRecord getClusterRoleRecord(String cluster) throws SQLException
public Optional<String> getActiveClusterUrl() throws SQLException
public boolean isActive(String clusterUrl) throws SQLException
public void close() throws SQLException
public boolean isClosed()
}Functional interface defining failover behavior policies.
@FunctionalInterface
public interface FailoverPolicy {
// Constants
String PHOENIX_HA_FAILOVER_POLICY_ATTR = "phoenix.ha.failover.policy"
String PHOENIX_HA_FAILOVER_COUNT_ATTR = "phoenix.ha.failover.count"
// Main method
boolean shouldFailover(FailoverSQLException exception, int failoverCount)
// Predefined policies
FailoverPolicy NEVER = (exception, count) -> false
FailoverPolicy IMMEDIATE = (exception, count) -> true
FailoverPolicy MAX_RETRIES = (exception, count) -> count < 3
}Usage:
// Set up connection properties for HA
Properties props = new Properties();
props.setProperty(HighAvailabilityGroup.PHOENIX_HA_GROUP_ATTR, "production-group");
props.setProperty(FailoverPolicy.PHOENIX_HA_FAILOVER_POLICY_ATTR, "immediate");
// Connect using HA-enabled URL
String url = "jdbc:phoenix+zk://cluster1-zk1:2181,cluster1-zk2:2181/hbase;" +
"phoenix.ha.group.name=production-group";
Connection connection = DriverManager.getConnection(url, props);
FailoverPhoenixConnection haConnection = connection.unwrap(FailoverPhoenixConnection.class);
// Check if failover is needed
if (haConnection.isFailoverNeeded()) {
LOG.info("Cluster failover detected, connection will handle automatically");
}Connection implementation supporting parallel query execution across multiple connections.
public class ParallelPhoenixConnection implements PhoenixMonitoredConnection {
// Constructor
public ParallelPhoenixConnection(List<String> urls, Properties properties) throws SQLException
// Standard JDBC Connection methods (delegated to primary connection)
public Statement createStatement() throws SQLException
public PreparedStatement prepareStatement(String sql) throws SQLException
public void close() throws SQLException
public boolean isClosed() throws SQLException
public void commit() throws SQLException
public void rollback() throws SQLException
// Parallel-specific methods
public List<PhoenixConnection> getAllConnections()
public PhoenixConnection getPrimaryConnection()
public int getConnectionCount()
public boolean isAllConnectionsClosed()
}Prepared statement implementation for parallel query execution.
public class ParallelPhoenixPreparedStatement extends PhoenixPreparedStatement {
// Constructor
public ParallelPhoenixPreparedStatement(ParallelPhoenixConnection connection, String sql) throws SQLException
// All standard PreparedStatement methods are inherited
// Execution is automatically parallelized across multiple connections
}Usage:
// Create parallel connection with multiple cluster URLs
List<String> clusterUrls = Arrays.asList(
"jdbc:phoenix:zk1:2181",
"jdbc:phoenix:zk2:2181",
"jdbc:phoenix:zk3:2181"
);
Properties props = new Properties();
ParallelPhoenixConnection parallelConn = new ParallelPhoenixConnection(clusterUrls, props);
// Execute queries in parallel across clusters
PreparedStatement pstmt = parallelConn.prepareStatement("SELECT * FROM large_table WHERE id > ?");
pstmt.setLong(1, 1000000);
ResultSet rs = pstmt.executeQuery(); // Automatically parallelizedInterface for monitored Phoenix connections that provides metrics collection.
public interface PhoenixMonitoredConnection extends Connection {
/**
* @return map of Table Name String to a Map of Metric Type to current value for mutations
*/
Map<String, Map<MetricType, Long>> getMutationMetrics()
/**
* @return map of Table Name String to a Map of Metric Type to current value for reads
*/
Map<String, Map<MetricType, Long>> getReadMetrics()
/**
* @return true if request metrics are enabled false otherwise
*/
boolean isRequestLevelMetricsEnabled()
/**
* Clears the local metrics values by setting them back to 0
*/
void clearMetrics()
}Interface for monitored Phoenix statements.
public interface PhoenixMonitoredStatement extends Statement {
// Inherits all Statement methods
// Implementations provide monitoring capabilities
}Interface for monitored Phoenix prepared statements.
public interface PhoenixMonitoredPreparedStatement extends PreparedStatement, PhoenixMonitoredStatement {
// Inherits all PreparedStatement and PhoenixMonitoredStatement methods
// Implementations provide monitoring capabilities for prepared statements
}Interface for monitored Phoenix result sets.
public interface PhoenixMonitoredResultSet extends ResultSet {
// Inherits all ResultSet methods
// Implementations provide monitoring capabilities for result set operations
}// Establish connection
Connection connection = DriverManager.getConnection("jdbc:phoenix:localhost:2181");
try {
// Create and execute statement
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT id, name FROM users WHERE status = 'ACTIVE'");
// Process results
while (rs.next()) {
long id = rs.getLong("id");
String name = rs.getString("name");
System.out.println("User: " + id + " - " + name);
}
} finally {
connection.close();
}String sql = "INSERT INTO users (id, name, email, created_date) VALUES (?, ?, ?, ?)";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setLong(1, 1001L);
pstmt.setString(2, "John Doe");
pstmt.setString(3, "john@example.com");
pstmt.setDate(4, new Date(System.currentTimeMillis()));
int rowsAffected = pstmt.executeUpdate();
System.out.println("Inserted " + rowsAffected + " rows");String sql = "INSERT INTO metrics (timestamp, metric_name, value) VALUES (?, ?, ?)";
PreparedStatement pstmt = connection.prepareStatement(sql);
// Add multiple rows to batch
for (int i = 0; i < 1000; i++) {
pstmt.setLong(1, System.currentTimeMillis() + i);
pstmt.setString(2, "cpu_usage");
pstmt.setDouble(3, Math.random() * 100);
pstmt.addBatch();
}
// Execute batch
int[] results = pstmt.executeBatch();
System.out.println("Batch inserted " + results.length + " rows");connection.setAutoCommit(false);
try {
Statement stmt = connection.createStatement();
// Multiple operations in transaction
stmt.executeUpdate("INSERT INTO accounts (id, balance) VALUES (1, 1000)");
stmt.executeUpdate("INSERT INTO accounts (id, balance) VALUES (2, 2000)");
stmt.executeUpdate("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
stmt.executeUpdate("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
// Commit transaction
connection.commit();
} catch (SQLException e) {
// Rollback on error
connection.rollback();
throw e;
} finally {
connection.setAutoCommit(true);
}Install with Tessl CLI
npx tessl i tessl/maven-org-apache-phoenix--phoenix-core