1#include "duckdb/parser/expression/case_expression.hpp"
2#include "duckdb/parser/expression/operator_expression.hpp"
3#include "duckdb/parser/transformer.hpp"
4
5using namespace duckdb;
6using namespace std;
7
8// COALESCE(a,b,c) returns the first argument that is NOT NULL, so
9// rewrite into CASE(a IS NOT NULL, a, CASE(b IS NOT NULL, b, c))
10unique_ptr<ParsedExpression> Transformer::TransformCoalesce(PGAExpr *root) {
11 if (!root) {
12 return nullptr;
13 }
14 auto coalesce_args = reinterpret_cast<PGList *>(root->lexpr);
15
16 auto exp_root = make_unique<CaseExpression>();
17 auto cur_root = exp_root.get();
18 for (auto cell = coalesce_args->head; cell && cell->next; cell = cell->next) {
19 // get the value of the COALESCE
20 auto value_expr = TransformExpression(reinterpret_cast<PGNode *>(cell->data.ptr_value));
21 // perform an IS NOT NULL comparison with the value here
22 cur_root->check = make_unique<OperatorExpression>(ExpressionType::OPERATOR_IS_NOT_NULL, value_expr->Copy());
23 // if IS NOT NULL, we output the value
24 cur_root->result_if_true = move(value_expr);
25 if (cell->next->next == nullptr) {
26 // if there is no next in the chain, the COALESCE ends there
27 cur_root->result_if_false = TransformExpression(reinterpret_cast<PGNode *>(cell->next->data.ptr_value));
28 } else {
29 // more COALESCE parameters remain, create a nested CASE statement
30 auto next_case = make_unique<CaseExpression>();
31 auto case_ptr = next_case.get();
32 cur_root->result_if_false = move(next_case);
33 cur_root = case_ptr;
34 }
35 }
36 return move(exp_root);
37}
38