1#include "duckdb/parser/statement/create_statement.hpp"
2#include "duckdb/parser/parsed_data/create_sequence_info.hpp"
3#include "duckdb/parser/tableref/basetableref.hpp"
4#include "duckdb/parser/transformer.hpp"
5
6using namespace duckdb;
7using namespace std;
8
9unique_ptr<CreateStatement> Transformer::TransformCreateSequence(PGNode *node) {
10 auto stmt = reinterpret_cast<PGCreateSeqStmt *>(node);
11
12 auto result = make_unique<CreateStatement>();
13 auto info = make_unique<CreateSequenceInfo>();
14
15 auto sequence_name = TransformRangeVar(stmt->sequence);
16 auto &sequence_ref = (BaseTableRef &)*sequence_name;
17 info->schema = sequence_ref.schema_name;
18 info->name = sequence_ref.table_name;
19
20 if (stmt->options) {
21 PGListCell *cell = nullptr;
22 for_each_cell(cell, stmt->options->head) {
23 auto *def_elem = reinterpret_cast<PGDefElem *>(cell->data.ptr_value);
24 string opt_name = string(def_elem->defname);
25
26 auto val = (PGValue *)def_elem->arg;
27 if (def_elem->defaction == PG_DEFELEM_UNSPEC && !val) { // e.g. NO MINVALUE
28 continue;
29 }
30 assert(val);
31
32 if (opt_name == "increment") {
33 assert(val->type == T_PGInteger);
34 info->increment = val->val.ival;
35 if (info->increment == 0) {
36 throw ParserException("Increment must not be zero");
37 }
38 if (info->increment < 0) {
39 info->start_value = info->max_value = -1;
40 info->min_value = numeric_limits<int64_t>::min();
41 } else {
42 info->start_value = info->min_value = 1;
43 info->max_value = numeric_limits<int64_t>::max();
44 }
45 } else if (opt_name == "minvalue") {
46 assert(val->type == T_PGInteger);
47 info->min_value = val->val.ival;
48 if (info->increment > 0) {
49 info->start_value = info->min_value;
50 }
51 } else if (opt_name == "maxvalue") {
52 assert(val->type == T_PGInteger);
53 info->max_value = val->val.ival;
54 if (info->increment < 0) {
55 info->start_value = info->max_value;
56 }
57 } else if (opt_name == "start") {
58 assert(val->type == T_PGInteger);
59 info->start_value = val->val.ival;
60 } else if (opt_name == "cycle") {
61 assert(val->type == T_PGInteger);
62 info->cycle = val->val.ival > 0;
63 } else {
64 throw ParserException("Unrecognized option \"%s\" for CREATE SEQUENCE", opt_name.c_str());
65 }
66 }
67 }
68 info->temporary = !stmt->sequence->relpersistence;
69 info->on_conflict = stmt->if_not_exists ? OnCreateConflict::IGNORE : OnCreateConflict::ERROR;
70 if (info->max_value <= info->min_value) {
71 throw ParserException("MINVALUE (%lld) must be less than MAXVALUE (%lld)", info->min_value, info->max_value);
72 }
73 if (info->start_value < info->min_value) {
74 throw ParserException("START value (%lld) cannot be less than MINVALUE (%lld)", info->start_value,
75 info->min_value);
76 }
77 if (info->start_value > info->max_value) {
78 throw ParserException("START value (%lld) cannot be greater than MAXVALUE (%lld)", info->start_value,
79 info->max_value);
80 }
81 result->info = move(info);
82 return result;
83}
84