Line data Source code
1 :
2 : #include "monetdb_config.h"
3 : #include "rel_multiset.h"
4 : #include "rel_exp.h"
5 : #include "rel_rel.h"
6 : #include "rel_basetable.h"
7 : #include "rel_updates.h"
8 : #include "rel_rewriter.h"
9 :
10 : /* TODO move into unnest code */
11 : static bool
12 183 : has_multiset(list *exps)
13 : {
14 183 : bool needed = false;
15 183 : if (list_empty(exps))
16 : return needed;
17 731 : for(node *n = exps->h; n && !needed; n = n->next) {
18 548 : sql_exp *e = n->data;
19 548 : sql_subtype *t = exp_subtype(e);
20 :
21 548 : needed = (t && t->multiset);
22 548 : if (!needed && t && t->type->composite && is_nested(e))
23 23 : needed = has_multiset(e->f);
24 : }
25 : return needed;
26 : }
27 :
28 : static sql_rel *
29 156 : ms_add_join_exps(visitor *v, sql_rel *rel, list *exps)
30 : {
31 156 : if (list_empty(exps))
32 : return rel;
33 156 : sql_rel *r = rel->r;
34 156 : prop *p = r->p;
35 156 : if (!p || p->kind != PROP_UNNEST)
36 : return NULL;
37 156 : sql_exp *re = p->value.pval;
38 :
39 496 : for(node *n = exps->h; n; n = n->next) {
40 407 : sql_exp *e = n->data;
41 407 : sql_subtype *t = exp_subtype(e);
42 407 : if (exp_match(e, re) && t->multiset) {
43 38 : v->changes++;
44 38 : sql_exp *le = exp_ref(v->sql, e);
45 38 : list *rexps = rel_projections(v->sql, rel->r, NULL, 0, 1);
46 38 : sql_exp *re = exps_bind_column(rexps, MSID_NAME, NULL, NULL, 0);
47 38 : if (le && re) {
48 38 : re = exp_ref(v->sql, re);
49 38 : e = exp_compare(v->sql->sa, le, re, cmp_equal);
50 38 : rel->exps = sa_list_append(v->sql->sa, rel->exps, e);
51 : }
52 38 : return rel;
53 369 : } else if (t->type->composite) {
54 : /* sofar only handles one level */
55 118 : sql_rel *res = ms_add_join_exps(v, rel, e->f);
56 118 : if (res)
57 29 : return res;
58 : }
59 : }
60 : return NULL;
61 : }
62 :
63 : /* TODO handle composite/multset (ie deep nested cases) too */
64 : static sql_rel *
65 122207 : fm_join(visitor *v, sql_rel *rel)
66 : {
67 122207 : if (is_dependent(rel) && list_length(rel->exps) <= 1) {
68 2954 : if (list_length(rel->exps) == 1) {
69 2802 : sql_exp *e = rel->exps->h->data;
70 2802 : if (!exp_is_true(e))
71 : return rel;
72 : }
73 160 : list *exps = rel_projections(v->sql, rel->l, NULL, 0, 1);
74 160 : bool needed = has_multiset(exps);
75 :
76 160 : if (needed)
77 38 : return ms_add_join_exps(v, rel, exps);
78 : }
79 : return rel;
80 : }
81 :
82 : static sql_rel *
83 2059424 : flatten_multiset(visitor *v, sql_rel *rel)
84 : {
85 2059424 : (void)v;
86 2059424 : switch(rel->op) {
87 122207 : case op_join:
88 : case op_left:
89 122207 : return fm_join(v, rel);
90 : default:
91 : return rel;
92 : }
93 : return rel;
94 : }
95 :
96 : sql_rel *
97 770673 : rel_multiset(mvc *sql, sql_rel *rel)
98 : {
99 770673 : visitor v = { .sql = sql };
100 :
101 770673 : rel = rel_visitor_bottomup(&v, rel, &flatten_multiset);
102 771548 : return rel;
103 : }
|