1#include "duckdb/common/exception.hpp"
2#include "duckdb/parser/expression/columnref_expression.hpp"
3#include "duckdb/parser/expression/function_expression.hpp"
4#include "duckdb/parser/expression/star_expression.hpp"
5#include "duckdb/parser/transformer.hpp"
6
7namespace duckdb {
8
9unique_ptr<ParsedExpression> Transformer::TransformStarExpression(duckdb_libpgquery::PGAStar &star) {
10 auto result = make_uniq<StarExpression>(args: star.relation ? star.relation : string());
11 if (star.except_list) {
12 for (auto head = star.except_list->head; head; head = head->next) {
13 auto value = PGPointerCast<duckdb_libpgquery::PGValue>(ptr: head->data.ptr_value);
14 D_ASSERT(value->type == duckdb_libpgquery::T_PGString);
15 string exclude_entry = value->val.str;
16 if (result->exclude_list.find(x: exclude_entry) != result->exclude_list.end()) {
17 throw ParserException("Duplicate entry \"%s\" in EXCLUDE list", exclude_entry);
18 }
19 result->exclude_list.insert(x: std::move(exclude_entry));
20 }
21 }
22 if (star.replace_list) {
23 for (auto head = star.replace_list->head; head; head = head->next) {
24 auto list = PGPointerCast<duckdb_libpgquery::PGList>(ptr: head->data.ptr_value);
25 D_ASSERT(list->length == 2);
26 auto replace_expression =
27 TransformExpression(node: PGPointerCast<duckdb_libpgquery::PGNode>(ptr: list->head->data.ptr_value));
28 auto value = PGPointerCast<duckdb_libpgquery::PGValue>(ptr: list->tail->data.ptr_value);
29 D_ASSERT(value->type == duckdb_libpgquery::T_PGString);
30 string exclude_entry = value->val.str;
31 if (result->replace_list.find(x: exclude_entry) != result->replace_list.end()) {
32 throw ParserException("Duplicate entry \"%s\" in REPLACE list", exclude_entry);
33 }
34 if (result->exclude_list.find(x: exclude_entry) != result->exclude_list.end()) {
35 throw ParserException("Column \"%s\" cannot occur in both EXCEPT and REPLACE list", exclude_entry);
36 }
37 result->replace_list.insert(x: make_pair(x: std::move(exclude_entry), y: std::move(replace_expression)));
38 }
39 }
40 if (star.expr) {
41 D_ASSERT(star.columns);
42 D_ASSERT(result->relation_name.empty());
43 D_ASSERT(result->exclude_list.empty());
44 D_ASSERT(result->replace_list.empty());
45 result->expr = TransformExpression(node: star.expr);
46 if (result->expr->type == ExpressionType::STAR) {
47 auto &child_star = result->expr->Cast<StarExpression>();
48 result->exclude_list = std::move(child_star.exclude_list);
49 result->replace_list = std::move(child_star.replace_list);
50 result->expr.reset();
51 } else if (result->expr->type == ExpressionType::LAMBDA) {
52 vector<unique_ptr<ParsedExpression>> children;
53 children.push_back(x: make_uniq<StarExpression>());
54 children.push_back(x: std::move(result->expr));
55 auto list_filter = make_uniq<FunctionExpression>(args: "list_filter", args: std::move(children));
56 result->expr = std::move(list_filter);
57 }
58 }
59 result->columns = star.columns;
60 result->query_location = star.location;
61 return std::move(result);
62}
63
64unique_ptr<ParsedExpression> Transformer::TransformColumnRef(duckdb_libpgquery::PGColumnRef &root) {
65 auto fields = root.fields;
66 auto head_node = PGPointerCast<duckdb_libpgquery::PGNode>(ptr: fields->head->data.ptr_value);
67 switch (head_node->type) {
68 case duckdb_libpgquery::T_PGString: {
69 if (fields->length < 1) {
70 throw InternalException("Unexpected field length");
71 }
72 vector<string> column_names;
73 for (auto node = fields->head; node; node = node->next) {
74 column_names.emplace_back(args&: PGPointerCast<duckdb_libpgquery::PGValue>(ptr: node->data.ptr_value)->val.str);
75 }
76 auto colref = make_uniq<ColumnRefExpression>(args: std::move(column_names));
77 colref->query_location = root.location;
78 return std::move(colref);
79 }
80 case duckdb_libpgquery::T_PGAStar: {
81 return TransformStarExpression(star&: PGCast<duckdb_libpgquery::PGAStar>(node&: *head_node));
82 }
83 default:
84 throw NotImplementedException("ColumnRef not implemented!");
85 }
86}
87
88} // namespace duckdb
89