客户端调用phoenix的jdbc接口,代码如下:
Connection conn = DriverManager.getConnection(url);
Statement statement = conn.createStatement();
ResultSet rset = statement.executeQuery("select a from test1");
while (rset.next()) {
System.out.println(rset.toString());
}
rset.close();
statement.close();
conn.close();
在PhoenixStatement类中,executeQuery(string sql)方法用来初步处理sql语句字符串
public ResultSet executeQuery(String sql) throws SQLException {
if (logger.isDebugEnabled()) {
logger.debug("Execute query: " + sql);
}
CompilableStatement stmt = parseStatement(sql);
if (stmt.getOperation().isMutation()) {
throw new ExecuteQueryNotApplicableException(sql);
}
return executeQuery(stmt);
}
其中,
parseStatement(sql)语句负责将sql字符串转换为statement对象,其代码为:
protected CompilableStatement parseStatement(String sql) throws SQLException {
PhoenixStatementParser parser = null;
try {
parser = new PhoenixStatementParser(sql, new ExecutableNodeFactory());
} catch (IOException e) {
throw ServerUtil.parseServerException(e);
}
CompilableStatement statement = parser.parseStatement();
return statement;
}
其核心的实现过程在
parser.parseStatement
中执行,这部分是由antlr实现,具体细节可以参考antlr相关文档。
在phoenix中,selectstatement类的主要成员变量如下:
private final List<TableNode> fromTable;
private final HintNode hint;
private final boolean isDistinct;
private final List<AliasedNode> select;
private final ParseNode where;
private final List<ParseNode> groupBy;
private final ParseNode having;
private final List<OrderByNode> orderBy;
private final LimitNode limit;
private final int bindCount;
private final boolean isAggregate;
private final boolean hasSequence;
通过parseStatement函数,将sql语句中的各个语句块解析成statement对象中的一个个node
解析成statement的成员后,将调用executeQuery(final CompilableStatement stmt),进行执行,这也是核心部分,其核心代码为:
//生成查询计划
QueryPlan plan = stmt.compilePlan(PhoenixStatement.this, Sequence.ValueOp.RESERVE_SEQUENCE);
//检查是否能使用索引表优化查询
plan = connection.getQueryServices().getOptimizer().optimize(
PhoenixStatement.this, plan);
// this will create its own trace internally, so we don't wrap this
// whole thing in tracing
//创建hbase的scnner
ResultIterator resultIterator = plan.iterator();
if (logger.isDebugEnabled()) {
String explainPlan = QueryUtil.getExplainPlan(resultIterator);
logger.debug("Explain plan: " + explainPlan);
}
//创建一个resultset对象
PhoenixResultSet rs = newResultSet(resultIterator, plan.getProjector());
//将rs加入reslutSets队列
resultSets.add(rs);
//保存此次的查询计划
setLastQueryPlan(plan);
//保存此次的resultset
setLastResultSet(rs);
//将update次数统计清零
setLastUpdateCount(NO_UPDATE);
//保存此次查询的操作类型
setLastUpdateOperation(stmt.getOperation());
//返回resulteset对象给客户端
return rs;
在客户端代码的rset.next()函数实际上调用的是phoenixResultSets类中的
public boolean next() throws SQLException {
checkOpen();
try {
currentRow = scanner.next();
} catch (RuntimeException e) {
// FIXME: Expression.evaluate does not throw SQLException
// so this will unwrap throws from that.
if (e.getCause() instanceof SQLException) {
throw (SQLException) e.getCause();
}
throw e;
}
return currentRow != null;
}
触发了hbase的scanner执行next,从hbase中获取数据