1#include "duckdb/main/relation.hpp"
2#include "duckdb/common/printer.hpp"
3#include "duckdb/parser/parser.hpp"
4#include "duckdb/main/relation/aggregate_relation.hpp"
5#include "duckdb/main/relation/distinct_relation.hpp"
6#include "duckdb/main/relation/explain_relation.hpp"
7#include "duckdb/main/relation/filter_relation.hpp"
8#include "duckdb/main/relation/insert_relation.hpp"
9#include "duckdb/main/relation/limit_relation.hpp"
10#include "duckdb/main/relation/order_relation.hpp"
11#include "duckdb/main/relation/projection_relation.hpp"
12#include "duckdb/main/relation/setop_relation.hpp"
13#include "duckdb/main/relation/subquery_relation.hpp"
14#include "duckdb/main/relation/create_table_relation.hpp"
15#include "duckdb/main/relation/create_view_relation.hpp"
16#include "duckdb/main/relation/write_csv_relation.hpp"
17#include "duckdb/main/client_context.hpp"
18#include "duckdb/planner/binder.hpp"
19#include "duckdb/parser/tableref/subqueryref.hpp"
20#include "duckdb/parser/statement/select_statement.hpp"
21#include "duckdb/parser/expression/conjunction_expression.hpp"
22#include "duckdb/parser/expression/columnref_expression.hpp"
23#include "duckdb/main/relation/join_relation.hpp"
24#include "duckdb/main/relation/value_relation.hpp"
25
26namespace duckdb {
27
28shared_ptr<Relation> Relation::Project(string select_list) {
29 return Project(select_list, vector<string>());
30}
31
32shared_ptr<Relation> Relation::Project(string expression, string alias) {
33 return Project(expression, vector<string>({alias}));
34}
35
36shared_ptr<Relation> Relation::Project(string select_list, vector<string> aliases) {
37 auto expressions = Parser::ParseExpressionList(select_list);
38 return make_shared<ProjectionRelation>(shared_from_this(), move(expressions), move(aliases));
39}
40
41shared_ptr<Relation> Relation::Project(vector<string> expressions) {
42 vector<string> aliases;
43 return Project(move(expressions), aliases);
44}
45
46static vector<unique_ptr<ParsedExpression>> StringListToExpressionList(vector<string> expressions) {
47 if (expressions.size() == 0) {
48 throw ParserException("Zero expressions provided");
49 }
50 vector<unique_ptr<ParsedExpression>> result_list;
51 for (auto &expr : expressions) {
52 auto expression_list = Parser::ParseExpressionList(expr);
53 if (expression_list.size() != 1) {
54 throw ParserException("Expected a single expression in the expression list");
55 }
56 result_list.push_back(move(expression_list[0]));
57 }
58 return result_list;
59}
60
61shared_ptr<Relation> Relation::Project(vector<string> expressions, vector<string> aliases) {
62 auto result_list = StringListToExpressionList(move(expressions));
63 return make_shared<ProjectionRelation>(shared_from_this(), move(result_list), move(aliases));
64}
65
66shared_ptr<Relation> Relation::Filter(string expression) {
67 auto expression_list = Parser::ParseExpressionList(expression);
68 if (expression_list.size() != 1) {
69 throw ParserException("Expected a single expression as filter condition");
70 }
71 return make_shared<FilterRelation>(shared_from_this(), move(expression_list[0]));
72}
73
74shared_ptr<Relation> Relation::Filter(vector<string> expressions) {
75 // if there are multiple expressions, we AND them together
76 auto expression_list = StringListToExpressionList(expressions);
77 if (expression_list.size() == 0) {
78 throw ParserException("Zero filter conditions provided");
79 }
80 auto expr = move(expression_list[0]);
81 for (idx_t i = 1; i < expression_list.size(); i++) {
82 expr =
83 make_unique<ConjunctionExpression>(ExpressionType::CONJUNCTION_AND, move(expr), move(expression_list[i]));
84 }
85 return make_shared<FilterRelation>(shared_from_this(), move(expr));
86}
87
88shared_ptr<Relation> Relation::Limit(int64_t limit, int64_t offset) {
89 return make_shared<LimitRelation>(shared_from_this(), limit, offset);
90}
91
92shared_ptr<Relation> Relation::Order(string expression) {
93 auto order_list = Parser::ParseOrderList(expression);
94 return make_shared<OrderRelation>(shared_from_this(), move(order_list));
95}
96
97shared_ptr<Relation> Relation::Order(vector<string> expressions) {
98 if (expressions.size() == 0) {
99 throw ParserException("Zero ORDER BY expressions provided");
100 }
101 vector<OrderByNode> order_list;
102 for (auto &expression : expressions) {
103 auto inner_list = Parser::ParseOrderList(expression);
104 if (inner_list.size() != 1) {
105 throw ParserException("Expected a single ORDER BY expression in the expression list");
106 }
107 order_list.push_back(move(inner_list[0]));
108 }
109 return make_shared<OrderRelation>(shared_from_this(), move(order_list));
110}
111
112shared_ptr<Relation> Relation::Join(shared_ptr<Relation> other, string condition, JoinType type) {
113 auto expression_list = Parser::ParseExpressionList(condition);
114 if (expression_list.size() == 0) {
115 throw ParserException("Expected a single expression as join condition");
116 }
117 if (expression_list.size() > 1 || expression_list[0]->type == ExpressionType::COLUMN_REF) {
118 // multiple columns or single column ref: the condition is a USING list
119 vector<string> using_columns;
120 for (auto &expr : expression_list) {
121 if (expr->type != ExpressionType::COLUMN_REF) {
122 throw ParserException("Expected a single expression as join condition");
123 }
124 auto &colref = (ColumnRefExpression &)*expr;
125 if (!colref.table_name.empty()) {
126 throw ParserException("Expected empty table name for column in USING clause");
127 }
128 using_columns.push_back(colref.column_name);
129 }
130 return make_shared<JoinRelation>(shared_from_this(), other, move(using_columns), type);
131 } else {
132 // single expression that is not a column reference: use the expression as a join condition
133 return make_shared<JoinRelation>(shared_from_this(), other, move(expression_list[0]), type);
134 }
135}
136
137shared_ptr<Relation> Relation::Union(shared_ptr<Relation> other) {
138 return make_shared<SetOpRelation>(shared_from_this(), move(other), SetOperationType::UNION);
139}
140
141shared_ptr<Relation> Relation::Except(shared_ptr<Relation> other) {
142 return make_shared<SetOpRelation>(shared_from_this(), move(other), SetOperationType::EXCEPT);
143}
144
145shared_ptr<Relation> Relation::Intersect(shared_ptr<Relation> other) {
146 return make_shared<SetOpRelation>(shared_from_this(), move(other), SetOperationType::INTERSECT);
147}
148
149shared_ptr<Relation> Relation::Distinct() {
150 return make_shared<DistinctRelation>(shared_from_this());
151}
152
153shared_ptr<Relation> Relation::Alias(string alias) {
154 return make_shared<SubqueryRelation>(shared_from_this(), alias);
155}
156
157shared_ptr<Relation> Relation::Aggregate(string aggregate_list) {
158 auto expression_list = Parser::ParseExpressionList(aggregate_list);
159 return make_shared<AggregateRelation>(shared_from_this(), move(expression_list));
160}
161
162shared_ptr<Relation> Relation::Aggregate(string aggregate_list, string group_list) {
163 auto expression_list = Parser::ParseExpressionList(aggregate_list);
164 auto groups = Parser::ParseExpressionList(group_list);
165 return make_shared<AggregateRelation>(shared_from_this(), move(expression_list), move(groups));
166}
167
168shared_ptr<Relation> Relation::Aggregate(vector<string> aggregates) {
169 auto aggregate_list = StringListToExpressionList(move(aggregates));
170 return make_shared<AggregateRelation>(shared_from_this(), move(aggregate_list));
171}
172
173shared_ptr<Relation> Relation::Aggregate(vector<string> aggregates, vector<string> groups) {
174 auto aggregate_list = StringListToExpressionList(move(aggregates));
175 auto group_list = StringListToExpressionList(move(groups));
176 return make_shared<AggregateRelation>(shared_from_this(), move(aggregate_list), move(group_list));
177}
178
179string Relation::GetAlias() {
180 return "relation";
181}
182
183unique_ptr<TableRef> Relation::GetTableRef() {
184 return make_unique<SubqueryRef>(GetQueryNode(), GetAlias());
185}
186
187unique_ptr<QueryResult> Relation::Execute() {
188 return context.Execute(shared_from_this());
189}
190
191BoundStatement Relation::Bind(Binder &binder) {
192 SelectStatement stmt;
193 stmt.node = GetQueryNode();
194 return binder.Bind((SQLStatement &)stmt);
195}
196
197void Relation::Insert(string table_name) {
198 Insert(DEFAULT_SCHEMA, table_name);
199}
200
201void Relation::Insert(string schema_name, string table_name) {
202 auto insert = make_shared<InsertRelation>(shared_from_this(), schema_name, table_name);
203 insert->Execute();
204}
205
206void Relation::Insert(vector<vector<Value>> values){
207 vector<string> column_names;
208 auto rel = make_shared<ValueRelation>(context, move(values), move(column_names), "values");
209 rel->Insert(GetAlias());
210}
211
212void Relation::Create(string table_name) {
213 Create(DEFAULT_SCHEMA, table_name);
214}
215
216void Relation::Create(string schema_name, string table_name) {
217 auto create = make_shared<CreateTableRelation>(shared_from_this(), schema_name, table_name);
218 create->Execute();
219}
220
221void Relation::WriteCSV(string csv_file) {
222 auto write_csv = make_shared<WriteCSVRelation>(shared_from_this(), csv_file);
223 write_csv->Execute();
224}
225
226void Relation::Head(idx_t limit) {
227 auto limit_node = Limit(limit);
228 limit_node->Execute()->Print();
229}
230
231shared_ptr<Relation> Relation::CreateView(string name, bool replace) {
232 auto view = make_shared<CreateViewRelation>(shared_from_this(), name, replace);
233 view->Execute();
234 return shared_from_this();
235}
236
237unique_ptr<QueryResult> Relation::Query(string sql) {
238 return context.Query(sql, false);
239}
240
241unique_ptr<QueryResult> Relation::Query(string name, string sql) {
242 CreateView(name);
243 return Query(sql);
244}
245
246unique_ptr<QueryResult> Relation::Explain() {
247 auto explain = make_shared<ExplainRelation>(shared_from_this());
248 return explain->Execute();
249}
250
251void Relation::Update(string update, string condition) {
252 throw Exception("UPDATE can only be used on base tables!");
253}
254
255void Relation::Delete(string condition) {
256 throw Exception("DELETE can only be used on base tables!");
257}
258
259string Relation::ToString() {
260 string str;
261 str += "---------------------\n";
262 str += "-- Expression Tree --\n";
263 str += "---------------------\n";
264 str += ToString(0);
265 str += "\n\n";
266 str += "---------------------\n";
267 str += "-- Result Columns --\n";
268 str += "---------------------\n";
269 auto &cols = Columns();
270 for (idx_t i = 0; i < cols.size(); i++) {
271 str += "- " + cols[i].name + " (" + SQLTypeToString(cols[i].type) + ")\n";
272 }
273 return str;
274}
275
276void Relation::Print() {
277 Printer::Print(ToString());
278}
279
280string Relation::RenderWhitespace(idx_t depth) {
281 return string(depth * 2, ' ');
282}
283
284} // namespace duckdb
285