1#include "duckdb/common/exception.hpp"
2#include "duckdb/parser/query_node/select_node.hpp"
3#include "duckdb/parser/query_node/set_operation_node.hpp"
4#include "duckdb/parser/statement/select_statement.hpp"
5#include "duckdb/parser/transformer.hpp"
6#include "duckdb/parser/expression/star_expression.hpp"
7#include "duckdb/common/string_util.hpp"
8
9using namespace duckdb;
10using namespace std;
11
12unique_ptr<QueryNode> Transformer::TransformSelectNode(PGSelectStmt *stmt) {
13 unique_ptr<QueryNode> node;
14
15 switch (stmt->op) {
16 case PG_SETOP_NONE: {
17 node = make_unique<SelectNode>();
18 auto result = (SelectNode *)node.get();
19
20 if (stmt->windowClause) {
21 for (auto window_ele = stmt->windowClause->head; window_ele != NULL; window_ele = window_ele->next) {
22 auto window_def = reinterpret_cast<PGWindowDef *>(window_ele->data.ptr_value);
23 assert(window_def);
24 assert(window_def->name);
25 auto window_name = StringUtil::Lower(string(window_def->name));
26
27 auto it = window_clauses.find(window_name);
28 if (it != window_clauses.end()) {
29 throw ParserException("window \"%s\" is already defined", window_name.c_str());
30 }
31 window_clauses[window_name] = window_def;
32 }
33 }
34
35 // do this early so the value lists also have a `FROM`
36 if (stmt->valuesLists) {
37 // VALUES list, create an ExpressionList
38 assert(!stmt->fromClause);
39 result->from_table = TransformValuesList(stmt->valuesLists);
40 result->select_list.push_back(make_unique<StarExpression>());
41 } else {
42 result->from_table = TransformFrom(stmt->fromClause);
43 if (!stmt->targetList) {
44 throw ParserException("SELECT clause without selection list");
45 }
46 // select list
47 if (!TransformExpressionList(stmt->targetList, result->select_list)) {
48 throw Exception("Failed to transform expression list.");
49 }
50 }
51 // checks distinct clause
52 if (stmt->distinctClause != NULL) {
53 auto modifier = make_unique<DistinctModifier>();
54 // checks distinct on clause
55 auto target = reinterpret_cast<PGNode *>(stmt->distinctClause->head->data.ptr_value);
56 if (target) {
57 // add the columns defined in the ON clause to the select list
58 if (!TransformExpressionList(stmt->distinctClause, modifier->distinct_on_targets)) {
59 throw Exception("Failed to transform expression list from DISTINCT ON.");
60 }
61 }
62 result->modifiers.push_back(move(modifier));
63 }
64 // from table
65 // group by
66 TransformGroupBy(stmt->groupClause, result->groups);
67 result->having = TransformExpression(stmt->havingClause);
68 // where
69 result->where_clause = TransformExpression(stmt->whereClause);
70 break;
71 }
72 case PG_SETOP_UNION:
73 case PG_SETOP_EXCEPT:
74 case PG_SETOP_INTERSECT: {
75 node = make_unique<SetOperationNode>();
76 auto result = (SetOperationNode *)node.get();
77 result->left = TransformSelectNode(stmt->larg);
78 result->right = TransformSelectNode(stmt->rarg);
79 if (!result->left || !result->right) {
80 throw Exception("Failed to transform setop children.");
81 }
82
83 bool select_distinct = true;
84 switch (stmt->op) {
85 case PG_SETOP_UNION:
86 select_distinct = !stmt->all;
87 result->setop_type = SetOperationType::UNION;
88 break;
89 case PG_SETOP_EXCEPT:
90 result->setop_type = SetOperationType::EXCEPT;
91 break;
92 case PG_SETOP_INTERSECT:
93 result->setop_type = SetOperationType::INTERSECT;
94 break;
95 default:
96 throw Exception("Unexpected setop type");
97 }
98 if (select_distinct) {
99 result->modifiers.push_back(make_unique<DistinctModifier>());
100 }
101 break;
102 }
103 default:
104 throw NotImplementedException("Statement type %d not implemented!", stmt->op);
105 }
106 // transform the common properties
107 // both the set operations and the regular select can have an ORDER BY/LIMIT attached to them
108 vector<OrderByNode> orders;
109 TransformOrderBy(stmt->sortClause, orders);
110 if (orders.size() > 0) {
111 auto order_modifier = make_unique<OrderModifier>();
112 order_modifier->orders = move(orders);
113 node->modifiers.push_back(move(order_modifier));
114 }
115 if (stmt->limitCount || stmt->limitOffset) {
116 auto limit_modifier = make_unique<LimitModifier>();
117 if (stmt->limitCount) {
118 limit_modifier->limit = TransformExpression(stmt->limitCount);
119 }
120 if (stmt->limitOffset) {
121 limit_modifier->offset = TransformExpression(stmt->limitOffset);
122 }
123 node->modifiers.push_back(move(limit_modifier));
124 }
125 return node;
126}
127