感谢回复。
补充如下:
我举得的这个例子可能有点特殊。
翻阅resolver层的解析流程后发现ob对于以上的insert语句中values子句的表达式会调用以下成员函数进行处理。
//insert into test values(1, c1 + 2);
//本函数用来解决c1的取值过程。先查找到C1对应的expr 1,然后将expr 1 变成column_conv(1) ;
//将 c1+2==> column_conv(1) + 2;
int ObInsertResolver::replace_column_ref(ObArray<ObRawExpr*> *value_row,
ObRawExpr *&expr,
bool in_generated_column /*default false*/)
相当于在resolver层就将c1,c2 的值作为常量填充到了表达式之中。所以之后也就不会走列引用的处理逻辑了。
再回过来探讨列引用的值是在什么时候获取的呢?
重新举一个例子:
create table t1 (c1 datetime, c2 int, c3 varchar(10));
insert into t1 values(current_date, 1, 'day1'),(current_date, 2, 'day2'),(current_date, 3, 'day3');
select str_to_date(c1, %Y%m%d) from t1;
通过explain可以看到最后执行的算子为TABLE FULL SCAN
,对应源码中就是ObTableScanOp
算子:
obclient [test]> explain select date_format(c1, '%Y-%m-%d %h:%i:%s') from t1;
+---------------------------------------------------------------------------------+
| Query Plan |
+---------------------------------------------------------------------------------+
| =============================================== |
| |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| |
| ----------------------------------------------- |
| |0 |TABLE FULL SCAN|t1 |3 |3 | |
| =============================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([date_format(t1.c1, '%Y-%m-%d %h:%i:%s')]), filter(nil), rowset=16 |
| access([t1.c1]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([t1.__pk_increment]), range(MIN ; MAX)always true |
+---------------------------------------------------------------------------------+
11 rows in set (0.054 sec)
对于这条select语句查看执行引擎中它的部分调用栈:
#0 oceanbase::sql::ObExprDateFormat::calc_date_format(oceanbase::sql::ObExpr const&, oceanbase::sql::ObEvalCtx&, oceanbase::common::ObDatum&) (expr=...,
ctx=..., expr_datum=...) at ./src/sql/engine/expr/ob_expr_date_format.cpp:72
#1 0x000055b0490664e3 in oceanbase::sql::expr_default_eval_batch_func(oceanbase::sql::ObExpr const&, oceanbase::sql::ObEvalCtx&, oceanbase::sql::ObBitVectorImpl<unsigned long> const&, oceanbase::sql::EvalBound const&) (expr=..., ctx=..., skip=..., bound=...) at ./src/sql/engine/expr/ob_expr.cpp:1211
#2 0x000055b049066850 in oceanbase::sql::expr_default_eval_batch_func(oceanbase::sql::ObExpr const&, oceanbase::sql::ObEvalCtx&, oceanbase::sql::ObBitVectorImpl<unsigned long> const&, long) (expr=..., ctx=..., skip=..., size=3) at ./src/sql/engine/expr/ob_expr.cpp:1231
#3 0x000055b049066007 in oceanbase::sql::expr_default_eval_vector_func(oceanbase::sql::ObExpr const&, oceanbase::sql::ObEvalCtx&, oceanbase::sql::ObBitVectorImpl<unsigned long> const&, oceanbase::sql::EvalBound const&) (expr=..., ctx=..., skip=..., bound=...) at ./src/sql/engine/expr/ob_expr.cpp:1244
#4 0x000055b03dc9c9ca in oceanbase::sql::ObExpr::eval_vector(oceanbase::sql::ObEvalCtx&, oceanbase::sql::ObBitVectorImpl<unsigned long> const&, oceanbase::sql::EvalBound const&) const (this=0x7fcac188e138, ctx=..., skip=..., bound=...) at ./src/sql/engine/expr/ob_expr.cpp:1169
#5 0x000055b03dc6004e in eval_vector (this=0x7fcac188e138, ctx=..., skip=..., size=3, all_rows_active=true) at ./src/sql/engine/expr/ob_expr.h:1337
#6 eval_vector (this=0x7fcac188e138, ctx=..., brs=...) at ./src/sql/engine/expr/ob_expr.h:1329
#7 oceanbase::sql::ObOperator::get_next_batch(long, oceanbase::sql::ObBatchRows const*&) (this=0x7fcaa5e98bf0, max_row_cnt=9223372036854775807,
batch_rows=@0x7fcac67c5d98: 0x7fcaa5e98de8) at ./src/sql/engine/ob_operator.cpp:1328
#8 0x000055b03dc5ea32 in oceanbase::sql::ObBatchRowIter::get_next_row() (this=0x7fcac67c5d90) at ./src/sql/engine/ob_operator.cpp:1709
#9 0x000055b03dc5ca02 in oceanbase::sql::ObExecuteResult::get_next_row(oceanbase::sql::ObExecContext&, oceanbase::common::ObNewRow const*&) (
this=0x7fcac67c5d58, ctx=..., row=@0x7fcac67c51d8: 0x7fcac67c5d70) at ./src/sql/executor/ob_execute_result.cpp:70
#10 0x000055b03dc5bd86 in inner_get_next_row (this=0x7fcac67c58b0, row=@0x7fcac67c51d8: 0x7fcac67c5d70) at ./src/sql/ob_result_set.cpp:408
#11 oceanbase::sql::ObResultSet::get_next_row(oceanbase::common::ObNewRow const*&) (this=0x7fcac67c58b0, row=@0x7fcac67c51d8: 0x7fcac67c5d70)
at ./src/sql/ob_result_set.cpp:396
而在ObOperator::get_next_batch
的中首先会执行Operator对应的实际算子类型为ObTableScanOp
的inner_get_next_batch
。
int ObOperator::get_next_batch(const int64_t max_row_cnt, const ObBatchRows *&batch_rows)
{
......
while (OB_SUCC(ret) && !brs_.end_) {
if (OB_FAIL(inner_get_next_batch(max_row_cnt))) {
LOG_WARN("get next batch failed", K(ret), K_(eval_ctx), "id", spec_.get_id(), "op_name", op_name());
} else {
LOG_DEBUG("inner get next batch", "id", spec_.get_id(), "op_name", op_name(), K(brs_));
}
......
}
在ObTableScanOp::inner_get_next_batch(const int64_t max_row_cnt)
它的调用逻辑为:
ObTableScanOp::inner_get_next_batch(const int64_t max_row_cnt) ->
ObTableScanOp::inner_get_next_batch_for_tsc(const int64_t max_row_cnt) ->
ObTableScanOp::get_next_batch_with_das(int64_t &count, int64_t capacity)
而在算子的open阶段可能已经拿到了数据,之后会填充到Operator的EvalCtx中。
int ObDASScanOp::open_op()
{
......
int ret = OB_SUCCESS;
ObITabletScan &tsc_service = get_tsc_service();
//Retry may be called many times.
//Only for DASScanOp now, we add a retry alloc to avoid
//memory expansion.
if (in_part_retry_) {
init_retry_alloc();
}
reset_access_datums_ptr();
if (OB_FAIL(init_scan_param())) {
LOG_WARN("init scan param failed", K(ret));
} else if (OB_FAIL(tsc_service.table_scan(scan_param_, result_))) {
......
}
最后回到表达式的执行date_format的时候对于列引用直接获取就行。目前推测大概是这么一个流程。
但是对于(1) ObDASScanOp如何拿取数据,(2) 如何填充到EvalCtx中还没有看到。期待补充。