Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 :
15 : #include "rel_predicates.h"
16 : #include "rel_rel.h"
17 : #include "rel_exp.h"
18 : #include "mal_backend.h"
19 :
20 : static sql_column *
21 4502 : bt_find_column( sql_rel *rel, char *tname, char *name)
22 : {
23 4502 : if (!rel || list_empty(rel->exps) || !rel->l)
24 0 : return NULL;
25 4502 : sql_exp *ne = NULL;
26 4502 : sql_table *t = rel->l;
27 4502 : if ((ne = exps_bind_column2(rel->exps, tname, name, NULL)) != NULL)
28 4502 : return find_sql_column(t, ne->r);
29 : return NULL;
30 : }
31 :
32 : static sql_column *
33 4514 : exp_find_column( sql_rel *rel, sql_exp *exp)
34 : {
35 4515 : if (exp->type == e_column)
36 4502 : return bt_find_column(is_basetable(rel->op)?rel:rel->l, exp->l, exp->r);
37 13 : if (exp->type == e_convert)
38 1 : return exp_find_column( rel, exp->l);
39 : return NULL;
40 : }
41 :
42 : static sql_rel *
43 144392 : rel_find_predicates(visitor *v, sql_rel *rel)
44 : {
45 144392 : bool needall = false;
46 :
47 144392 : if (is_basetable(rel->op)) {
48 9011 : sql_table *t = rel->l;
49 :
50 9011 : if (!t || list_empty(rel->exps) || isNew(t) || !isGlobal(t) || isGlobalTemp(t))
51 2206 : return rel;
52 6805 : sql_rel *parent = v->parent;
53 :
54 : /* select with basetable */
55 6805 : if (is_select(parent->op)) {
56 : /* add predicates */
57 2121 : if (list_empty(parent->exps)) {
58 : needall = true;
59 : } else {
60 5348 : for (node *n = parent->exps->h; n && !needall; n = n->next) {
61 3229 : sql_exp *e = n->data, *r = e->r, *r2 = e->f;
62 3229 : sql_column *c = NULL;
63 :
64 3229 : if (!is_compare(e->type) || !is_theta_exp(e->flag) || r->type != e_atom || !r->l || (r2 && (r2->type != e_atom || !r2->l)) || is_symmetric(e) || !(c = exp_find_column(rel, e->l)))
65 : needall = true;
66 : }
67 2119 : if (!needall) {
68 3392 : for (node *n = parent->exps->h; n; n = n->next) {
69 1877 : sql_exp *e = n->data, *r = e->r, *r2 = e->f;
70 1877 : sql_column *c = exp_find_column(rel, e->l);
71 :
72 1877 : if (isNew(c))
73 0 : continue;
74 1877 : atom *e1 = r && r->l ? atom_copy(NULL, r->l) : NULL, *e2 = r2 && r2->l ? atom_copy(NULL, r2->l) : NULL;
75 :
76 1877 : if ((r && r->l && !e1) || (r2 && r2->l && !e2)) {
77 0 : if (e1) {
78 0 : VALclear(&e1->data);
79 0 : _DELETE(e1);
80 : }
81 0 : if (e2) {
82 0 : VALclear(&e2->data);
83 0 : _DELETE(e2);
84 : }
85 0 : return sql_error(v->sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
86 : }
87 :
88 1877 : if (sql_trans_add_predicate(v->sql->session->tr, c, e->flag, e1, e2, is_anti(e), is_semantics(e)) != LOG_OK) {
89 0 : if (e1) {
90 0 : VALclear(&e1->data);
91 0 : _DELETE(e1);
92 : }
93 0 : if (e2) {
94 0 : VALclear(&e2->data);
95 0 : _DELETE(e2);
96 : }
97 0 : return sql_error(v->sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
98 : }
99 1877 : v->changes++;
100 : }
101 : }
102 : }
103 : }
104 :
105 6805 : if (!is_select(parent->op) || needall) {
106 : /* any other case, add all predicates */
107 5290 : sql_table *t = rel->l;
108 :
109 5290 : if (!t || list_empty(rel->exps) || isNew(t) || !isGlobal(t) || isGlobalTemp(t))
110 0 : return rel;
111 16783 : for (node *n = rel->exps->h; n; n = n->next) {
112 11493 : sql_exp *e = n->data;
113 :
114 11493 : if (!is_intern(e)) {
115 7034 : sql_column *c = find_sql_column(t, e->r);
116 :
117 7034 : assert(c);
118 7034 : if (isNew(c))
119 0 : continue;
120 7034 : if (sql_trans_add_predicate(v->sql->session->tr, c, 0, NULL, NULL, false, false) != LOG_OK)
121 0 : return sql_error(v->sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
122 7034 : v->changes++;
123 : }
124 : }
125 : }
126 : }
127 : return rel;
128 : }
129 :
130 : sql_rel *
131 107937 : rel_predicates(backend *be, sql_rel *rel)
132 : {
133 107937 : if ((be->mvc->session->level & tr_snapshot) == tr_snapshot)
134 : return rel;
135 107971 : visitor v = { .sql = be->mvc };
136 107971 : rel = rel_visitor_topdown(&v, rel, &rel_find_predicates);
137 107971 : return rel;
138 : }
|