1#include "duckdb/parser/expression/case_expression.hpp"
2#include "duckdb/parser/expression/cast_expression.hpp"
3#include "duckdb/parser/expression/function_expression.hpp"
4#include "duckdb/parser/expression/operator_expression.hpp"
5#include "duckdb/parser/expression/star_expression.hpp"
6#include "duckdb/parser/expression/window_expression.hpp"
7#include "duckdb/parser/transformer.hpp"
8#include "duckdb/common/string_util.hpp"
9
10using namespace duckdb;
11using namespace std;
12
13static ExpressionType WindowToExpressionType(string &fun_name) {
14 if (fun_name == "rank") {
15 return ExpressionType::WINDOW_RANK;
16 } else if (fun_name == "rank_dense" || fun_name == "dense_rank") {
17 return ExpressionType::WINDOW_RANK_DENSE;
18 } else if (fun_name == "percent_rank") {
19 return ExpressionType::WINDOW_PERCENT_RANK;
20 } else if (fun_name == "row_number") {
21 return ExpressionType::WINDOW_ROW_NUMBER;
22 } else if (fun_name == "first_value" || fun_name == "first") {
23 return ExpressionType::WINDOW_FIRST_VALUE;
24 } else if (fun_name == "last_value" || fun_name == "last") {
25 return ExpressionType::WINDOW_LAST_VALUE;
26 } else if (fun_name == "cume_dist") {
27 return ExpressionType::WINDOW_CUME_DIST;
28 } else if (fun_name == "lead") {
29 return ExpressionType::WINDOW_LEAD;
30 } else if (fun_name == "lag") {
31 return ExpressionType::WINDOW_LAG;
32 } else if (fun_name == "ntile") {
33 return ExpressionType::WINDOW_NTILE;
34 }
35
36 return ExpressionType::WINDOW_AGGREGATE;
37}
38
39void Transformer::TransformWindowDef(PGWindowDef *window_spec, WindowExpression *expr) {
40 assert(window_spec);
41 assert(expr);
42
43 // next: partitioning/ordering expressions
44 TransformExpressionList(window_spec->partitionClause, expr->partitions);
45 TransformOrderBy(window_spec->orderClause, expr->orders);
46
47 // finally: specifics of bounds
48 expr->start_expr = TransformExpression(window_spec->startOffset);
49 expr->end_expr = TransformExpression(window_spec->endOffset);
50
51 if ((window_spec->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) ||
52 (window_spec->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)) {
53 throw Exception(
54 "Window frames starting with unbounded following or ending in unbounded preceding make no sense");
55 }
56
57 if (window_spec->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) {
58 expr->start = WindowBoundary::UNBOUNDED_PRECEDING;
59 } else if (window_spec->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) {
60 expr->start = WindowBoundary::UNBOUNDED_FOLLOWING;
61 } else if (window_spec->frameOptions & FRAMEOPTION_START_VALUE_PRECEDING) {
62 expr->start = WindowBoundary::EXPR_PRECEDING;
63 } else if (window_spec->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING) {
64 expr->start = WindowBoundary::EXPR_FOLLOWING;
65 } else if (window_spec->frameOptions & (FRAMEOPTION_START_CURRENT_ROW | FRAMEOPTION_RANGE)) {
66 expr->start = WindowBoundary::CURRENT_ROW_RANGE;
67 } else if (window_spec->frameOptions & (FRAMEOPTION_START_CURRENT_ROW | FRAMEOPTION_ROWS)) {
68 expr->start = WindowBoundary::CURRENT_ROW_ROWS;
69 }
70
71 if (window_spec->frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) {
72 expr->end = WindowBoundary::UNBOUNDED_PRECEDING;
73 } else if (window_spec->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) {
74 expr->end = WindowBoundary::UNBOUNDED_FOLLOWING;
75 } else if (window_spec->frameOptions & FRAMEOPTION_END_VALUE_PRECEDING) {
76 expr->end = WindowBoundary::EXPR_PRECEDING;
77 } else if (window_spec->frameOptions & FRAMEOPTION_END_VALUE_FOLLOWING) {
78 expr->end = WindowBoundary::EXPR_FOLLOWING;
79 } else if (window_spec->frameOptions & (FRAMEOPTION_END_CURRENT_ROW | FRAMEOPTION_RANGE)) {
80 expr->end = WindowBoundary::CURRENT_ROW_RANGE;
81 } else if (window_spec->frameOptions & (FRAMEOPTION_END_CURRENT_ROW | FRAMEOPTION_ROWS)) {
82 expr->end = WindowBoundary::CURRENT_ROW_ROWS;
83 }
84
85 assert(expr->start != WindowBoundary::INVALID && expr->end != WindowBoundary::INVALID);
86 if (((expr->start == WindowBoundary::EXPR_PRECEDING || expr->start == WindowBoundary::EXPR_PRECEDING) &&
87 !expr->start_expr) ||
88 ((expr->end == WindowBoundary::EXPR_PRECEDING || expr->end == WindowBoundary::EXPR_PRECEDING) &&
89 !expr->end_expr)) {
90 throw Exception("Failed to transform window boundary expression");
91 }
92}
93
94unique_ptr<ParsedExpression> Transformer::TransformFuncCall(PGFuncCall *root) {
95 auto name = root->funcname;
96 string schema, function_name;
97 if (name->length == 2) {
98 // schema + name
99 schema = reinterpret_cast<PGValue *>(name->head->data.ptr_value)->val.str;
100 function_name = reinterpret_cast<PGValue *>(name->head->next->data.ptr_value)->val.str;
101 } else {
102 // unqualified name
103 schema = DEFAULT_SCHEMA;
104 function_name = reinterpret_cast<PGValue *>(name->head->data.ptr_value)->val.str;
105 }
106
107 auto lowercase_name = StringUtil::Lower(function_name);
108
109 if (root->agg_filter) {
110 throw ParserException("FILTER is not implemented for aggregates");
111 }
112 if (root->agg_order) {
113 throw ParserException("ORDER BY is not implemented for aggregates");
114 }
115
116 if (root->over) {
117 if (root->agg_distinct) {
118 throw ParserException("DISTINCT is not implemented for window functions!");
119 }
120
121 auto win_fun_type = WindowToExpressionType(lowercase_name);
122 if (win_fun_type == ExpressionType::INVALID) {
123 throw Exception("Unknown/unsupported window function");
124 }
125
126 auto expr = make_unique<WindowExpression>(win_fun_type, schema, lowercase_name);
127
128 if (root->args) {
129 vector<unique_ptr<ParsedExpression>> function_list;
130 auto res = TransformExpressionList(root->args, function_list);
131 if (!res) {
132 throw Exception("Failed to transform window function children");
133 }
134 if (win_fun_type == ExpressionType::WINDOW_AGGREGATE) {
135 for (auto &child : function_list) {
136 expr->children.push_back(move(child));
137 }
138 } else {
139 if (function_list.size() > 0) {
140 expr->children.push_back(move(function_list[0]));
141 }
142 if (function_list.size() > 1) {
143 assert(win_fun_type == ExpressionType::WINDOW_LEAD || win_fun_type == ExpressionType::WINDOW_LAG);
144 expr->offset_expr = move(function_list[1]);
145 }
146 if (function_list.size() > 2) {
147 assert(win_fun_type == ExpressionType::WINDOW_LEAD || win_fun_type == ExpressionType::WINDOW_LAG);
148 expr->default_expr = move(function_list[2]);
149 }
150 assert(function_list.size() <= 3);
151 }
152 }
153 auto window_spec = reinterpret_cast<PGWindowDef *>(root->over);
154 if (window_spec->name) {
155 auto it = window_clauses.find(StringUtil::Lower(string(window_spec->name)));
156 if (it == window_clauses.end()) {
157 throw ParserException("window \"%s\" does not exist", window_spec->name);
158 }
159 window_spec = it->second;
160 assert(window_spec);
161 }
162 TransformWindowDef(window_spec, expr.get());
163
164 return move(expr);
165 }
166
167 // TransformExpressionList??
168 vector<unique_ptr<ParsedExpression>> children;
169 if (root->args != nullptr) {
170 for (auto node = root->args->head; node != nullptr; node = node->next) {
171 auto child_expr = TransformExpression((PGNode *)node->data.ptr_value);
172 children.push_back(move(child_expr));
173 }
174 }
175
176 if (lowercase_name == "if") {
177 if (children.size() != 3) {
178 throw ParserException("Wrong number of arguments to IF.");
179 }
180 auto expr = make_unique<CaseExpression>();
181 expr->check = move(children[0]);
182 expr->result_if_true = move(children[1]);
183 expr->result_if_false = move(children[2]);
184 return move(expr);
185 }
186
187 else if (lowercase_name == "ifnull") {
188 if (children.size() != 2) {
189 throw ParserException("Wrong number of arguments to IFNULL.");
190 }
191
192 // Two-argument COALESCE
193 auto expr = make_unique<CaseExpression>();
194 expr->check = make_unique<OperatorExpression>(ExpressionType::OPERATOR_IS_NOT_NULL, children[0]->Copy());
195 expr->result_if_true = move(children[0]);
196 expr->result_if_false = move(children[1]);
197 return move(expr);
198 }
199
200 return make_unique<FunctionExpression>(schema, lowercase_name.c_str(), children, root->agg_distinct);
201}
202
203static string SQLValueOpToString(PGSQLValueFunctionOp op) {
204 switch (op) {
205 case PG_SVFOP_CURRENT_DATE:
206 return "current_date";
207 case PG_SVFOP_CURRENT_TIME:
208 return "current_time";
209 case PG_SVFOP_CURRENT_TIME_N:
210 return "current_time_n";
211 case PG_SVFOP_CURRENT_TIMESTAMP:
212 return "current_timestamp";
213 case PG_SVFOP_CURRENT_TIMESTAMP_N:
214 return "current_timestamp_n";
215 case PG_SVFOP_LOCALTIME:
216 return "current_localtime";
217 case PG_SVFOP_LOCALTIME_N:
218 return "current_localtime_n";
219 case PG_SVFOP_LOCALTIMESTAMP:
220 return "current_localtimestamp";
221 case PG_SVFOP_LOCALTIMESTAMP_N:
222 return "current_localtimestamp_n";
223 case PG_SVFOP_CURRENT_ROLE:
224 return "current_role";
225 case PG_SVFOP_CURRENT_USER:
226 return "current_user";
227 case PG_SVFOP_USER:
228 return "user";
229 case PG_SVFOP_SESSION_USER:
230 return "session_user";
231 case PG_SVFOP_CURRENT_CATALOG:
232 return "current_catalog";
233 case PG_SVFOP_CURRENT_SCHEMA:
234 return "current_schema";
235 default:
236 throw Exception("Could not find named SQL value function specification " + to_string((int)op));
237 }
238}
239
240unique_ptr<ParsedExpression> Transformer::TransformSQLValueFunction(PGSQLValueFunction *node) {
241 if (!node) {
242 return nullptr;
243 }
244 vector<unique_ptr<ParsedExpression>> children;
245 auto fname = SQLValueOpToString(node->op);
246 return make_unique<FunctionExpression>(DEFAULT_SCHEMA, fname, children);
247}
248