1#include "duckdb/common/exception.hpp"
2#include "duckdb/parser/tableref/basetableref.hpp"
3#include "duckdb/parser/tableref/joinref.hpp"
4#include "duckdb/parser/transformer.hpp"
5
6namespace duckdb {
7
8unique_ptr<TableRef> Transformer::TransformJoin(duckdb_libpgquery::PGJoinExpr &root) {
9 auto result = make_uniq<JoinRef>(args: JoinRefType::REGULAR);
10 switch (root.jointype) {
11 case duckdb_libpgquery::PG_JOIN_INNER: {
12 result->type = JoinType::INNER;
13 break;
14 }
15 case duckdb_libpgquery::PG_JOIN_LEFT: {
16 result->type = JoinType::LEFT;
17 break;
18 }
19 case duckdb_libpgquery::PG_JOIN_FULL: {
20 result->type = JoinType::OUTER;
21 break;
22 }
23 case duckdb_libpgquery::PG_JOIN_RIGHT: {
24 result->type = JoinType::RIGHT;
25 break;
26 }
27 case duckdb_libpgquery::PG_JOIN_SEMI: {
28 result->type = JoinType::SEMI;
29 break;
30 }
31 case duckdb_libpgquery::PG_JOIN_ANTI: {
32 result->type = JoinType::ANTI;
33 break;
34 }
35 case duckdb_libpgquery::PG_JOIN_POSITION: {
36 result->ref_type = JoinRefType::POSITIONAL;
37 break;
38 }
39 default: {
40 throw NotImplementedException("Join type %d not supported\n", root.jointype);
41 }
42 }
43
44 // Check the type of left arg and right arg before transform
45 result->left = TransformTableRefNode(n&: *root.larg);
46 result->right = TransformTableRefNode(n&: *root.rarg);
47 switch (root.joinreftype) {
48 case duckdb_libpgquery::PG_JOIN_NATURAL:
49 result->ref_type = JoinRefType::NATURAL;
50 break;
51 case duckdb_libpgquery::PG_JOIN_ASOF:
52 result->ref_type = JoinRefType::ASOF;
53 break;
54 default:
55 break;
56 }
57 result->query_location = root.location;
58
59 if (root.usingClause && root.usingClause->length > 0) {
60 // usingClause is a list of strings
61 for (auto node = root.usingClause->head; node != nullptr; node = node->next) {
62 auto target = reinterpret_cast<duckdb_libpgquery::PGNode *>(node->data.ptr_value);
63 D_ASSERT(target->type == duckdb_libpgquery::T_PGString);
64 auto column_name = string(reinterpret_cast<duckdb_libpgquery::PGValue *>(target)->val.str);
65 result->using_columns.push_back(x: column_name);
66 }
67 return std::move(result);
68 }
69
70 if (!root.quals && result->using_columns.empty() && result->ref_type == JoinRefType::REGULAR) { // CROSS PRODUCT
71 result->ref_type = JoinRefType::CROSS;
72 }
73 result->condition = TransformExpression(node: root.quals);
74 return std::move(result);
75}
76
77} // namespace duckdb
78