1/// @file
2/// @brief supporting classes for the grammar
3
4#ifndef RELMODEL_HH
5#define RELMODEL_HH
6#include <cassert>
7#include <map>
8#include <memory>
9#include <string>
10#include <utility>
11#include <vector>
12
13using std::make_pair;
14using std::map;
15using std::pair;
16using std::shared_ptr;
17using std::string;
18using std::vector;
19
20struct sqltype {
21 string name;
22 static map<string, struct sqltype *> typemap;
23 static struct sqltype *get(string s);
24 sqltype(string n) : name(n) {
25 }
26
27 /** This function is used to model postgres-style pseudotypes.
28 A generic type is consistent with a more concrete type.
29 E.G., anyarray->consistent(intarray) is true
30 while int4array->consistent(anyarray) is false
31
32 There must not be cycles in the consistency graph, since the
33 grammar will use fixpoint iteration to resolve type conformance
34 situations in the direction of more concrete types */
35 virtual bool consistent(struct sqltype *rvalue);
36};
37
38struct column {
39 string name;
40 sqltype *type;
41 column(string name) : name(name) {
42 }
43 column(string name, sqltype *t) : name(name), type(t) {
44 assert(t);
45 }
46};
47
48struct relation {
49 vector<column> cols;
50 virtual ~relation() {
51 }
52 virtual vector<column> &columns() {
53 return cols;
54 }
55};
56
57struct named_relation : relation {
58 string name;
59 virtual string ident() {
60 return name;
61 }
62 virtual ~named_relation() {
63 }
64 named_relation(string n) : name(n) {
65 }
66};
67
68struct aliased_relation : named_relation {
69 relation *rel;
70 virtual ~aliased_relation() {
71 }
72 aliased_relation(string n, relation *r) : named_relation(n), rel(r) {
73 }
74 virtual vector<column> &columns() {
75 return rel->columns();
76 }
77};
78
79struct table : named_relation {
80 string schema;
81 bool is_insertable;
82 bool is_base_table;
83 vector<string> constraints;
84 table(string name, string schema, bool insertable, bool base_table)
85 : named_relation(name), schema(schema), is_insertable(insertable), is_base_table(base_table) {
86 }
87 virtual string ident() {
88 return schema + "." + name;
89 }
90 virtual ~table(){};
91};
92
93struct scope {
94 struct scope *parent;
95 /// available to table_ref productions
96 vector<named_relation *> tables;
97 /// available to column_ref productions
98 vector<named_relation *> refs;
99 struct schema *schema;
100 /// Counters for prefixed stmt-unique identifiers
101 shared_ptr<map<string, unsigned int>> stmt_seq;
102 scope(struct scope *parent = 0) : parent(parent) {
103 if (parent) {
104 schema = parent->schema;
105 tables = parent->tables;
106 refs = parent->refs;
107 stmt_seq = parent->stmt_seq;
108 }
109 }
110 vector<pair<named_relation *, column>> refs_of_type(sqltype *t) {
111 vector<pair<named_relation *, column>> result;
112 for (auto r : refs)
113 for (auto c : r->columns())
114 if (t->consistent(c.type))
115 result.push_back(make_pair(r, c));
116 return result;
117 }
118 /** Generate unique identifier with prefix. */
119 string stmt_uid(const char *prefix) {
120 string result(prefix);
121 result += "_";
122 result += std::to_string((*stmt_seq)[result]++);
123 return result;
124 }
125 /** Reset unique identifier counters. */
126 void new_stmt() {
127 stmt_seq = std::make_shared<map<string, unsigned int>>();
128 }
129};
130
131struct op {
132 string name;
133 sqltype *left;
134 sqltype *right;
135 sqltype *result;
136 op(string n, sqltype *l, sqltype *r, sqltype *res) : name(n), left(l), right(r), result(res) {
137 }
138 op() {
139 }
140};
141
142struct routine {
143 string specific_name;
144 string schema;
145 vector<sqltype *> argtypes;
146 sqltype *restype;
147 string name;
148 routine(string schema, string specific_name, sqltype *data_type, string name)
149 : specific_name(specific_name), schema(schema), restype(data_type), name(name) {
150 assert(data_type);
151 }
152 virtual ~routine() {
153 }
154 virtual string ident() {
155 if (schema.size())
156 return schema + "." + name;
157 else
158 return name;
159 }
160};
161
162#endif
163