15 using impedance::matched;
17 shared_ptr<value_expr> value_expr::factory(
prod *p,
sqltype *type_constraint)
20 if (1 == d20() && p->
level < d6() && window_function::allowed(p))
21 return make_shared<window_function>(p, type_constraint);
22 else if (1 == d42() && p->
level < d6())
23 return make_shared<coalesce>(p, type_constraint);
24 else if (1 == d42() && p->
level < d6())
25 return make_shared<nullif>(p, type_constraint);
26 else if (p->
level < d6() && d6() == 1)
27 return make_shared<funcall>(p, type_constraint);
29 return make_shared<atomic_subselect>(p, type_constraint);
30 else if (p->
level< d6() && d9()==1)
31 return make_shared<case_expr>(p, type_constraint);
32 else if (p->
scope->
refs.size() && d20() > 1)
33 return make_shared<column_reference>(p, type_constraint);
35 return make_shared<const_expr>(p, type_constraint);
36 }
catch (runtime_error &e) {
39 return factory(p, type_constraint);
42 case_expr::case_expr(
prod *p,
sqltype *type_constraint)
45 condition = bool_expr::factory(
this);
46 true_expr = value_expr::factory(
this, type_constraint);
47 false_expr = value_expr::factory(
this, true_expr->type);
49 if(false_expr->type != true_expr->type) {
52 if (true_expr->type->consistent(false_expr->type))
53 true_expr = value_expr::factory(
this, false_expr->type);
55 false_expr = value_expr::factory(
this, true_expr->type);
57 type = true_expr->type;
62 out <<
"case when " << *condition;
63 out <<
" then " << *true_expr;
64 out <<
" else " << *true_expr;
74 false_expr->accept(v);
79 if (type_constraint) {
80 auto pairs =
scope->refs_of_type(type_constraint);
81 auto picked = random_pick(pairs);
82 reference += picked.first->ident()
83 +
"." + picked.second.name;
84 type = picked.second.type;
89 reference += r->ident() +
".";
90 column &c = random_pick(r->columns());
96 shared_ptr<bool_expr> bool_expr::factory(
prod *p)
99 if (p->
level > d100())
100 return make_shared<truth_value>(p);
102 return make_shared<comparison_op>(p);
104 return make_shared<bool_term>(p);
106 return make_shared<null_predicate>(p);
108 return make_shared<truth_value>(p);
110 return make_shared<exists_predicate>(p);
112 }
catch (runtime_error &e) {
121 subquery = make_shared<query_spec>(
this,
scope);
134 out << *subquery <<
")";
139 lhs = make_shared<column_reference>(
this);
140 rhs = make_shared<column_reference>(
this, lhs->type);
145 auto &idx = p->
scope->schema->operators_returning_type;
147 auto iters = idx.equal_range(
scope->schema->booltype);
148 oper = random_pick<>(iters)->second;
150 lhs = value_expr::factory(
this, oper->left);
151 rhs = value_expr::factory(
this, oper->right);
153 if (oper->left == oper->right
154 && lhs->type != rhs->type) {
156 if (lhs->type->consistent(rhs->type))
157 lhs = value_expr::factory(
this, rhs->type);
159 rhs = value_expr::factory(
this, lhs->type);
163 coalesce::coalesce(
prod *p,
sqltype *type_constraint,
const char *abbrev)
166 auto first_expr = value_expr::factory(
this, type_constraint);
167 auto second_expr = value_expr::factory(
this, first_expr->type);
170 while(first_expr->type != second_expr->type) {
172 if (first_expr->type->consistent(second_expr->type))
173 first_expr = value_expr::factory(
this, second_expr->type);
175 second_expr = value_expr::factory(
this, first_expr->type);
177 type = second_expr->type;
179 value_exprs.push_back(first_expr);
180 value_exprs.push_back(second_expr);
185 out <<
"cast(" << abbrev_ <<
"(";
186 for (
auto expr = value_exprs.begin(); expr != value_exprs.end(); expr++) {
188 if (expr+1 != value_exprs.end())
192 out <<
" as " << type->name <<
")";
195 const_expr::const_expr(
prod *p,
sqltype *type_constraint)
198 type = type_constraint ? type_constraint :
scope->schema->inttype;
200 if (type ==
scope->schema->inttype)
201 expr = to_string(d100());
202 else if (type ==
scope->schema->booltype)
203 expr += (d6() > 3) ?
scope->schema->true_literal :
scope->schema->false_literal;
204 else if (
dynamic_cast<insert_stmt*
>(p) && (d6() > 3))
207 expr +=
"cast(null as " + type->name +
")";
210 funcall::funcall(
prod *p,
sqltype *type_constraint,
bool agg)
213 if (type_constraint ==
scope->schema->internaltype)
214 fail(
"cannot call functions involving internal type");
216 auto &idx = agg ? p->
scope->schema->aggregates_returning_type
218 p->
scope->schema->routines_returning_type
219 : p->
scope->schema->parameterless_routines_returning_type;
223 if (!type_constraint) {
224 proc = random_pick(idx.begin(), idx.end())->second;
226 auto iters = idx.equal_range(type_constraint);
227 proc = random_pick<>(iters)->second;
228 if (proc && !type_constraint->
consistent(proc->restype)) {
240 type = type_constraint;
242 type = proc->restype;
244 if (type ==
scope->schema->internaltype) {
249 for (
auto type : proc->argtypes)
250 if (type ==
scope->schema->internaltype
251 || type ==
scope->schema->arraytype) {
256 for (
auto argtype : proc->argtypes) {
258 auto expr = value_expr::factory(
this, argtype);
259 parms.push_back(expr);
265 out << proc->ident() <<
"(";
266 for (
auto expr = parms.begin(); expr != parms.end(); expr++) {
268 out <<
"cast(" << **expr <<
" as " << (*expr)->type->name <<
")";
269 if (expr+1 != parms.end())
273 if (is_aggregate && (parms.begin() == parms.end()))
278 atomic_subselect::atomic_subselect(
prod *p,
sqltype *type_constraint)
279 :
value_expr(p), offset((d6() == 6) ? d100() : d6())
283 if (type_constraint) {
284 auto idx =
scope->schema->aggregates_returning_type;
285 auto iters = idx.equal_range(type_constraint);
286 agg = random_pick<>(iters)->second;
288 agg = &random_pick<>(
scope->schema->aggregates);
290 if (agg->argtypes.size() != 1)
293 type_constraint = agg->argtypes[0];
298 if (type_constraint) {
299 auto idx =
scope->schema->tables_with_columns_of_type;
301 auto iters = idx.equal_range(type_constraint);
302 tab = random_pick<>(iters)->second;
304 for (
auto &cand : tab->columns()) {
312 tab = &random_pick<>(
scope->schema->tables);
313 col = &random_pick<>(tab->columns());
316 type = agg ? agg->restype : col->type;
324 out << agg->ident() <<
"(" << col->name <<
")";
328 out <<
" from " << tab->ident();
331 out <<
" limit 1 offset " << offset;
340 out << *aggregate <<
" over (partition by ";
342 for (
auto ref = partition_by.begin(); ref != partition_by.end(); ref++) {
344 if (ref+1 != partition_by.end())
350 for (
auto ref = order_by.begin(); ref != order_by.end(); ref++) {
352 if (ref+1 != order_by.end())
359 window_function::window_function(
prod *p,
sqltype *type_constraint)
363 aggregate = make_shared<funcall>(
this, type_constraint,
true);
364 type = aggregate->type;
365 partition_by.push_back(make_shared<column_reference>(
this));
367 partition_by.push_back(make_shared<column_reference>(
this));
369 order_by.push_back(make_shared<column_reference>(
this));
371 order_by.push_back(make_shared<column_reference>(
this));
374 bool window_function::allowed(
prod *p)
381 return allowed(p->
pprod);
grammar: Value expression productions
grammar: Top-level and unsorted grammar productions
feedback to the grammar about failed productions
supporting classes for the grammar
Base class providing schema information to grammar.
virtual void out(std::ostream &out)
Emit SQL for this production.
virtual void out(std::ostream &out)
Emit SQL for this production.
virtual void accept(prod_visitor *v)
Visitor pattern for walking the AST.
virtual void out(std::ostream &out)
Emit SQL for this production.
virtual void out(std::ostream &out)
Emit SQL for this production.
virtual void accept(prod_visitor *v)
Visitor pattern for walking the AST.
virtual void out(std::ostream &out)
Emit SQL for this production.
Base class for walking the AST.
Base class for AST nodes.
virtual void indent(std::ostream &out)
Newline and indent according to tree level.
void retry()
Increase the retry count and throw an exception when retry_limit is exceeded.
struct scope * scope
Scope object to model column/table reference visibility.
long retry_limit
Maximum number of retries allowed before reporting a failure to the Parent prod.
int level
Level of this production in the AST. 0 for root node.
struct prod * pprod
Parent production that instanciated this one.
virtual void fail(const char *reason)
Report a "failed to generate" error.
virtual void match()
Check with the impedance matching code whether this production has been blacklisted and throw an exce...
vector< named_relation * > refs
available to column_ref productions
virtual bool consistent(struct sqltype *rvalue)
This function is used to model postgres-style pseudotypes.
virtual void out(std::ostream &out)
Emit SQL for this production.