Create ExprTestData for a given query. Returned *test_data contains valid ExprTestData* in which eval_ is already opened. Assumes 'query' is a constant query.
| 92 | // Returned *test_data contains valid ExprTestData* in which eval_ is already opened. |
| 93 | // Assumes 'query' is a constant query. |
| 94 | Status PrepareScalarExpression(const string& query, ExprTestData** test_data) { |
| 95 | TExecRequest request; |
| 96 | TQueryCtx query_ctx; |
| 97 | query_ctx.__set_session(session_state_); |
| 98 | query_ctx.client_request.__set_stmt(query); |
| 99 | query_ctx.client_request.__set_query_options(query_options_); |
| 100 | string dummy_hostname = ""; |
| 101 | NetworkAddressPB dummy_addr; |
| 102 | ImpalaServer::PrepareQueryContext(dummy_hostname, dummy_addr, &query_ctx); |
| 103 | |
| 104 | RuntimeState* state = pool_.Add(new RuntimeState(query_ctx, &exec_env_)); |
| 105 | TPlanFragment* fragment = state->obj_pool()->Add(new TPlanFragment()); |
| 106 | PlanFragmentCtxPB* fragment_ctx = state->obj_pool()->Add(new PlanFragmentCtxPB()); |
| 107 | |
| 108 | FragmentState* fragment_state = state->obj_pool()->Add( |
| 109 | new FragmentState(state->query_state(), *fragment, *fragment_ctx)); |
| 110 | RETURN_IF_ERROR(frontend_.GetExecRequest(query_ctx, &request)); |
| 111 | |
| 112 | // For query "select 1 + 1", planner will return query plan: |
| 113 | // |
| 114 | // F00:PLAN FRAGMENT [UNPARTITIONED] hosts=1 instances=1 |
| 115 | // | Per-Host Resources: mem-estimate=4.00MB mem-reservation=4.00MB thread-reservation=1 |
| 116 | // PLAN-ROOT SINK |
| 117 | // | output exprs: 1 + 1 |
| 118 | // | mem-estimate=4.00MB mem-reservation=4.00MB spill-buffer=2.00MB thread-reservation=0 |
| 119 | // | |
| 120 | // 00:UNION |
| 121 | // constant-operands=1 |
| 122 | // mem-estimate=0B mem-reservation=0B thread-reservation=0 |
| 123 | // tuple-ids=0 row-size=2B cardinality=1 |
| 124 | // |
| 125 | // However, the TExpr for the scalar expression is not in the output_sink's |
| 126 | // output_exprs. Instead, it is in the union node's const_expr_lists. |
| 127 | const TQueryExecRequest& query_request = request.query_exec_request; |
| 128 | TUnionNode union_node = |
| 129 | query_request.plan_exec_info[0].fragments[0].plan.nodes[0].union_node; |
| 130 | vector<TExpr> texprs = union_node.const_expr_lists[0]; |
| 131 | DCHECK_EQ(texprs.size(), 1); |
| 132 | |
| 133 | ScalarExpr* expr; |
| 134 | RETURN_IF_ERROR( |
| 135 | ScalarExpr::Create(texprs[0], RowDescriptor(), fragment_state, &expr)); |
| 136 | ScalarExprEvaluator* eval; |
| 137 | RETURN_IF_ERROR(ScalarExprEvaluator::Create( |
| 138 | *expr, state, state->obj_pool(), &expr_perm_pool_, &expr_results_pool_, &eval)); |
| 139 | |
| 140 | // UDFs which cannot be interpreted need to be handled by codegen. |
| 141 | // This follow examples from fe-support.cc |
| 142 | if (fragment_state->ScalarExprNeedsCodegen()) { |
| 143 | RETURN_IF_ERROR(fragment_state->CreateCodegen()); |
| 144 | LlvmCodeGen* codegen = fragment_state->codegen(); |
| 145 | DCHECK(codegen != NULL); |
| 146 | RETURN_IF_ERROR(fragment_state->CodegenScalarExprs()); |
| 147 | codegen->EnableOptimizations(true); |
| 148 | RETURN_IF_ERROR(codegen->FinalizeModule()); |
| 149 | } |
| 150 | RETURN_IF_ERROR(eval->Open(state)); |
| 151 |
no test coverage detected