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