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 : #include "sql_storage.h"
20 :
21 : static sql_column *
22 4934 : bt_find_column( sql_rel *rel, char *tname, char *name)
23 : {
24 4934 : if (!rel || list_empty(rel->exps) || !rel->l)
25 0 : return NULL;
26 4934 : sql_exp *ne = NULL;
27 4934 : sql_table *t = rel->l;
28 4934 : if ((ne = exps_bind_column2(rel->exps, tname, name, NULL)) != NULL)
29 4934 : return find_sql_column(t, ne->r);
30 : return NULL;
31 : }
32 :
33 : static sql_column *
34 4947 : exp_find_column( sql_rel *rel, sql_exp *exp)
35 : {
36 4949 : if (exp->type == e_column)
37 4934 : return bt_find_column(is_basetable(rel->op)?rel:rel->l, exp->l, exp->r);
38 15 : if (exp->type == e_convert)
39 2 : return exp_find_column( rel, exp->l);
40 : return NULL;
41 : }
42 :
43 : static sql_rel *
44 147800 : rel_find_predicates(visitor *v, sql_rel *rel)
45 : {
46 147800 : bool needall = false;
47 :
48 147800 : if (is_basetable(rel->op)) {
49 9165 : sql_table *t = rel->l;
50 :
51 9165 : if (!t || list_empty(rel->exps) || isNew(t) || !isGlobal(t) || isGlobalTemp(t))
52 2264 : return rel;
53 6901 : sql_rel *parent = v->parent;
54 :
55 : /* select with basetable */
56 6901 : if (is_select(parent->op)) {
57 : /* add predicates */
58 2627 : if (list_empty(parent->exps)) {
59 : needall = true;
60 : } else {
61 5996 : for (node *n = parent->exps->h; n && !needall; n = n->next) {
62 3369 : sql_exp *e = n->data, *r = e->r, *r2 = e->f;
63 3369 : sql_column *c = NULL;
64 :
65 3369 : 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)))
66 : needall = true;
67 : }
68 2627 : if (!needall) {
69 4192 : for (node *n = parent->exps->h; n; n = n->next) {
70 2232 : sql_exp *e = n->data, *r = e->r, *r2 = e->f;
71 2232 : sql_column *c = exp_find_column(rel, e->l);
72 :
73 2232 : if (isNew(c))
74 0 : continue;
75 2232 : atom *e1 = r && r->l ? atom_copy(NULL, r->l) : NULL, *e2 = r2 && r2->l ? atom_copy(NULL, r2->l) : NULL;
76 :
77 2232 : if ((r && r->l && !e1) || (r2 && r2->l && !e2)) {
78 0 : if (e1) {
79 0 : VALclear(&e1->data);
80 0 : _DELETE(e1);
81 : }
82 0 : if (e2) {
83 0 : VALclear(&e2->data);
84 0 : _DELETE(e2);
85 : }
86 0 : return sql_error(v->sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
87 : }
88 :
89 2232 : if (sql_trans_add_predicate(v->sql->session->tr, c, e->flag, e1, e2, is_anti(e), is_semantics(e)) != LOG_OK) {
90 0 : if (e1) {
91 0 : VALclear(&e1->data);
92 0 : _DELETE(e1);
93 : }
94 0 : if (e2) {
95 0 : VALclear(&e2->data);
96 0 : _DELETE(e2);
97 : }
98 0 : return sql_error(v->sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
99 : }
100 2232 : v->changes++;
101 : }
102 : }
103 : }
104 : }
105 :
106 6901 : if (!is_select(parent->op) || needall) {
107 : /* any other case, add all predicates */
108 4941 : sql_table *t = rel->l;
109 :
110 4941 : if (!t || list_empty(rel->exps) || isNew(t) || !isGlobal(t) || isGlobalTemp(t))
111 0 : return rel;
112 24642 : for (node *n = rel->exps->h; n; n = n->next) {
113 19701 : sql_exp *e = n->data;
114 :
115 19701 : if (!is_intern(e)) {
116 15320 : sql_column *c = find_sql_column(t, e->r);
117 :
118 15320 : assert(c);
119 15320 : if (isNew(c))
120 0 : continue;
121 15320 : if (sql_trans_add_predicate(v->sql->session->tr, c, 0, NULL, NULL, false, false) != LOG_OK)
122 0 : return sql_error(v->sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
123 15320 : v->changes++;
124 : }
125 : }
126 : }
127 : }
128 : return rel;
129 : }
130 :
131 : sql_rel *
132 109187 : rel_predicates(backend *be, sql_rel *rel)
133 : {
134 109187 : if ((be->mvc->session->level & tr_snapshot) == tr_snapshot)
135 : return rel;
136 109252 : visitor v = { .sql = be->mvc };
137 109252 : rel = rel_visitor_topdown(&v, rel, &rel_find_predicates);
138 109252 : return rel;
139 : }
|