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 4084 : bt_find_column( sql_rel *rel, char *tname, char *name)
22 : {
23 4084 : if (!rel || list_empty(rel->exps) || !rel->l)
24 0 : return NULL;
25 4084 : sql_exp *ne = NULL;
26 4084 : sql_table *t = rel->l;
27 4084 : if ((ne = exps_bind_column2(rel->exps, tname, name, NULL)) != NULL)
28 4084 : return find_sql_column(t, ne->r);
29 : return NULL;
30 : }
31 :
32 : static sql_column *
33 4097 : exp_find_column( sql_rel *rel, sql_exp *exp)
34 : {
35 4099 : if (exp->type == e_column)
36 4084 : return bt_find_column(is_basetable(rel->op)?rel:rel->l, exp->l, exp->r);
37 15 : if (exp->type == e_convert)
38 2 : return exp_find_column( rel, exp->l);
39 : return NULL;
40 : }
41 :
42 : static sql_rel *
43 135787 : rel_find_predicates(visitor *v, sql_rel *rel)
44 : {
45 135787 : bool needall = false;
46 :
47 135787 : if (is_basetable(rel->op)) {
48 8696 : sql_table *t = rel->l;
49 :
50 8696 : if (!t || list_empty(rel->exps) || isNew(t) || !isGlobal(t) || isGlobalTemp(t))
51 2264 : return rel;
52 6432 : sql_rel *parent = v->parent;
53 :
54 : /* select with basetable */
55 6432 : if (is_select(parent->op)) {
56 : /* add predicates */
57 2273 : if (list_empty(parent->exps)) {
58 : needall = true;
59 : } else {
60 5016 : for (node *n = parent->exps->h; n && !needall; n = n->next) {
61 2743 : sql_exp *e = n->data, *r = e->r, *r2 = e->f;
62 2743 : sql_column *c = NULL;
63 :
64 2743 : 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 2273 : if (!needall) {
68 3614 : for (node *n = parent->exps->h; n; n = n->next) {
69 1895 : sql_exp *e = n->data, *r = e->r, *r2 = e->f;
70 1895 : sql_column *c = exp_find_column(rel, e->l);
71 :
72 1895 : if (isNew(c))
73 0 : continue;
74 1895 : atom *e1 = r && r->l ? atom_copy(NULL, r->l) : NULL, *e2 = r2 && r2->l ? atom_copy(NULL, r2->l) : NULL;
75 :
76 1895 : 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 1895 : 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 1895 : v->changes++;
100 : }
101 : }
102 : }
103 : }
104 :
105 6432 : if (!is_select(parent->op) || needall) {
106 : /* any other case, add all predicates */
107 4713 : sql_table *t = rel->l;
108 :
109 4713 : if (!t || list_empty(rel->exps) || isNew(t) || !isGlobal(t) || isGlobalTemp(t))
110 0 : return rel;
111 22633 : for (node *n = rel->exps->h; n; n = n->next) {
112 17920 : sql_exp *e = n->data;
113 :
114 17920 : if (!is_intern(e)) {
115 13682 : sql_column *c = find_sql_column(t, e->r);
116 :
117 13682 : assert(c);
118 13682 : if (isNew(c))
119 0 : continue;
120 13682 : 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 13682 : v->changes++;
123 : }
124 : }
125 : }
126 : }
127 : return rel;
128 : }
129 :
130 : sql_rel *
131 98498 : rel_predicates(backend *be, sql_rel *rel)
132 : {
133 98498 : if ((be->mvc->session->level & tr_snapshot) == tr_snapshot)
134 : return rel;
135 98498 : visitor v = { .sql = be->mvc };
136 98498 : rel = rel_visitor_topdown(&v, rel, &rel_find_predicates);
137 98498 : return rel;
138 : }
|