1#include "duckdb/parser/statement/insert_statement.hpp"
2#include "duckdb/parser/statement/update_statement.hpp"
3#include "duckdb/parser/tableref/expressionlistref.hpp"
4#include "duckdb/parser/transformer.hpp"
5
6namespace duckdb {
7
8OnConflictAction TransformOnConflictAction(duckdb_libpgquery::PGOnConflictClause *on_conflict) {
9 if (!on_conflict) {
10 return OnConflictAction::THROW;
11 }
12 switch (on_conflict->action) {
13 case duckdb_libpgquery::PG_ONCONFLICT_NONE:
14 return OnConflictAction::THROW;
15 case duckdb_libpgquery::PG_ONCONFLICT_NOTHING:
16 return OnConflictAction::NOTHING;
17 case duckdb_libpgquery::PG_ONCONFLICT_UPDATE:
18 return OnConflictAction::UPDATE;
19 default:
20 throw InternalException("Type not implemented for OnConflictAction");
21 }
22}
23
24vector<string> Transformer::TransformConflictTarget(duckdb_libpgquery::PGList &list) {
25 vector<string> columns;
26 for (auto cell = list.head; cell != nullptr; cell = cell->next) {
27 auto index_element = PGPointerCast<duckdb_libpgquery::PGIndexElem>(ptr: cell->data.ptr_value);
28 if (index_element->collation) {
29 throw NotImplementedException("Index with collation not supported yet!");
30 }
31 if (index_element->opclass) {
32 throw NotImplementedException("Index with opclass not supported yet!");
33 }
34 if (!index_element->name) {
35 throw NotImplementedException("Non-column index element not supported yet!");
36 }
37 if (index_element->nulls_ordering) {
38 throw NotImplementedException("Index with null_ordering not supported yet!");
39 }
40 if (index_element->ordering) {
41 throw NotImplementedException("Index with ordering not supported yet!");
42 }
43 columns.emplace_back(args&: index_element->name);
44 }
45 return columns;
46}
47
48unique_ptr<OnConflictInfo> Transformer::DummyOnConflictClause(duckdb_libpgquery::PGOnConflictActionAlias type,
49 const string &relname) {
50 switch (type) {
51 case duckdb_libpgquery::PGOnConflictActionAlias::PG_ONCONFLICT_ALIAS_REPLACE: {
52 // This can not be fully resolved yet until the bind stage
53 auto result = make_uniq<OnConflictInfo>();
54 result->action_type = OnConflictAction::REPLACE;
55 return result;
56 }
57 case duckdb_libpgquery::PGOnConflictActionAlias::PG_ONCONFLICT_ALIAS_IGNORE: {
58 // We can just fully replace this with DO NOTHING, and be done with it
59 auto result = make_uniq<OnConflictInfo>();
60 result->action_type = OnConflictAction::NOTHING;
61 return result;
62 }
63 default: {
64 throw InternalException("Type not implemented for PGOnConflictActionAlias");
65 }
66 }
67}
68
69unique_ptr<OnConflictInfo> Transformer::TransformOnConflictClause(duckdb_libpgquery::PGOnConflictClause *node,
70 const string &relname) {
71 auto stmt = reinterpret_cast<duckdb_libpgquery::PGOnConflictClause *>(node);
72 D_ASSERT(stmt);
73
74 auto result = make_uniq<OnConflictInfo>();
75 result->action_type = TransformOnConflictAction(on_conflict: stmt);
76 if (stmt->infer) {
77 // A filter for the ON CONFLICT ... is specified
78 if (stmt->infer->indexElems) {
79 // Columns are specified
80 result->indexed_columns = TransformConflictTarget(list&: *stmt->infer->indexElems);
81 if (stmt->infer->whereClause) {
82 result->condition = TransformExpression(node: stmt->infer->whereClause);
83 }
84 } else {
85 throw NotImplementedException("ON CONSTRAINT conflict target is not supported yet");
86 }
87 }
88
89 if (result->action_type == OnConflictAction::UPDATE) {
90 result->set_info = TransformUpdateSetInfo(target_list: stmt->targetList, where_clause: stmt->whereClause);
91 }
92 return result;
93}
94
95} // namespace duckdb
96