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 : #include "store_dependency.h"
15 :
16 : static void
17 1135 : _free(void *dummy, void *data)
18 : {
19 1135 : (void)dummy;
20 1135 : GDKfree(data);
21 1135 : }
22 :
23 : static sqlid
24 3 : list_find_func_id(list *ids, sqlid id)
25 : {
26 3 : node *n = ids->h;
27 3 : while (n) {
28 3 : sql_func * f = n->data;
29 3 : if (f->base.id == id)
30 : return id;
31 : else
32 0 : n = n->next;
33 : }
34 : return 0;
35 : }
36 :
37 : /*Function to create a dependency*/
38 : int
39 389742 : sql_trans_create_dependency(sql_trans* tr, sqlid id, sqlid depend_id, sql_dependency depend_type)
40 : {
41 389742 : assert(id && depend_id);
42 389742 : sqlstore *store = tr->store;
43 389742 : sql_schema * s = find_sql_schema(tr, "sys");
44 389742 : sql_table *t = find_sql_table(tr, s, "dependencies");
45 389742 : sql_column *c_id = find_sql_column(t, "id");
46 389742 : sql_column *c_dep_id = find_sql_column(t, "depend_id");
47 389742 : sql_column *c_dep_type = find_sql_column(t, "depend_type");
48 389742 : sht dtype = (sht) depend_type;
49 389742 : int log_res = LOG_OK;
50 :
51 389742 : if (is_oid_nil(store->table_api.column_find_row(tr, c_id, &id, c_dep_id, &depend_id, c_dep_type, &dtype, NULL)))
52 386109 : log_res = store->table_api.table_insert(tr, t, &id, &depend_id, &dtype);
53 :
54 389742 : return log_res;
55 : }
56 :
57 : /*Function to drop the dependencies on depend_id*/
58 : int
59 40206 : sql_trans_drop_dependencies(sql_trans* tr, sqlid depend_id)
60 : {
61 40206 : sqlstore *store = tr->store;
62 40206 : oid rid;
63 40206 : sql_schema * s = find_sql_schema(tr, "sys");
64 40206 : sql_table* deps = find_sql_table(tr, s, "dependencies");
65 40206 : sql_column * dep_dep_id = find_sql_column(deps, "depend_id");
66 40206 : rids *rs;
67 40206 : int log_res = LOG_OK;
68 :
69 40206 : rs = store->table_api.rids_select(tr, dep_dep_id, &depend_id, &depend_id, NULL);
70 40206 : if (rs == NULL)
71 : return LOG_ERR;
72 66585 : for (rid = store->table_api.rids_next(rs); !is_oid_nil(rid) && log_res == LOG_OK; rid = store->table_api.rids_next(rs))
73 26379 : log_res = store->table_api.table_delete(tr, deps, rid);
74 40206 : store->table_api.rids_destroy(rs);
75 40206 : return log_res;
76 : }
77 :
78 : /*Function to drop the dependency between object and target, ie obj_id/depend_id*/
79 : int
80 424 : sql_trans_drop_dependency(sql_trans* tr, sqlid obj_id, sqlid depend_id, sql_dependency depend_type)
81 : {
82 424 : sqlstore *store = tr->store;
83 424 : oid rid;
84 424 : sql_schema * s = find_sql_schema(tr, "sys");
85 424 : sql_table* deps = find_sql_table(tr, s, "dependencies");
86 424 : sql_column *dep_obj_id = find_sql_column(deps, "id");
87 424 : sql_column *dep_dep_id = find_sql_column(deps, "depend_id");
88 424 : sql_column *dep_dep_type = find_sql_column(deps, "depend_type");
89 424 : sht dtype = (sht) depend_type;
90 424 : rids *rs;
91 424 : int log_res = LOG_OK;
92 :
93 424 : rs = store->table_api.rids_select(tr, dep_obj_id, &obj_id, &obj_id, dep_dep_id, &depend_id, &depend_id, dep_dep_type, &dtype, &dtype, NULL);
94 424 : if (rs == NULL)
95 : return LOG_ERR;
96 718 : for (rid = store->table_api.rids_next(rs); !is_oid_nil(rid) && log_res == LOG_OK; rid = store->table_api.rids_next(rs))
97 294 : log_res = store->table_api.table_delete(tr, deps, rid);
98 424 : store->table_api.rids_destroy(rs);
99 424 : return log_res;
100 : }
101 :
102 : /*It returns a list with depend_id_1, depend_type_1,
103 : depend_id_2, depend_type_2, ....*/
104 : list*
105 11571 : sql_trans_get_dependents(sql_trans* tr, sqlid id,
106 : sql_dependency dependent_type,
107 : list * ignore_ids)
108 : {
109 11571 : sqlstore *store = tr->store;
110 11571 : table_functions table_api = store->table_api;
111 11571 : sql_schema *s = find_sql_schema(tr, "sys");
112 11571 : sql_table *deps = find_sql_table(tr, s, "dependencies");
113 11571 : sql_column *dep_id, *dep_dep_id, *dep_dep_type, *tri_id, *table_id;
114 11571 : list *dep_list = list_create((fdestroy)_free),
115 11571 : *schema_tables = NULL;
116 11571 : void *v;
117 11571 : oid rid;
118 11571 : rids *rs;
119 11571 : sqlid low_id = id, high_id = -1;
120 :
121 11571 : if (!dep_list)
122 : return NULL;
123 :
124 11571 : dep_id = find_sql_column(deps, "id");
125 11571 : dep_dep_id = find_sql_column(deps, "depend_id");
126 11571 : dep_dep_type = find_sql_column(deps, "depend_type");
127 :
128 11571 : if (dependent_type == SCHEMA_DEPENDENCY) {
129 17 : sql_schema *s = find_sql_schema_id(tr, id);
130 17 : assert(s);
131 17 : schema_tables = list_create((fdestroy)_free);
132 17 : if (schema_tables == NULL) {
133 0 : list_destroy(dep_list);
134 0 : return NULL;
135 : }
136 17 : struct os_iter oi;
137 17 : os_iterator(&oi, s->tables, tr, NULL);
138 17 : bool first = true;
139 20 : for (sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
140 3 : sqlid* local_id = MNEW(sqlid);
141 3 : if (local_id == NULL) {
142 0 : list_destroy(dep_list);
143 0 : return NULL;
144 : }
145 3 : *local_id = b->id;
146 3 : if (list_append(schema_tables, local_id) == NULL) {
147 0 : list_destroy(dep_list);
148 0 : list_destroy(schema_tables);
149 0 : return NULL;
150 : }
151 3 : if (first) {
152 3 : low_id = b->id;
153 3 : first = false;
154 : }
155 3 : high_id = b->id;
156 : }
157 : }
158 :
159 11571 : rs = table_api.rids_select(tr, dep_id, &low_id,
160 11571 : high_id == -1 ? &low_id :
161 3 : low_id == high_id ? &low_id : &high_id,
162 : NULL);
163 11571 : if (rs == NULL) {
164 0 : list_destroy(dep_list);
165 0 : list_destroy(schema_tables);
166 0 : return NULL;
167 : }
168 :
169 12122 : for (rid = table_api.rids_next(rs); !is_oid_nil(rid); rid = table_api.rids_next(rs)){
170 551 : if (dependent_type == SCHEMA_DEPENDENCY) {
171 1 : if (!(v = table_api.column_find_value(tr, dep_id, rid))) {
172 0 : list_destroy(dep_list);
173 0 : list_destroy(schema_tables);
174 0 : table_api.rids_destroy(rs);
175 0 : return NULL;
176 : }
177 1 : if (list_find_id(schema_tables, *(sqlid*)v) == NULL) {
178 0 : _DELETE(v);
179 0 : continue;
180 : }
181 1 : _DELETE(v);
182 : }
183 551 : if (!(v = table_api.column_find_value(tr, dep_dep_id, rid))) {
184 0 : list_destroy(dep_list);
185 0 : list_destroy(schema_tables);
186 0 : table_api.rids_destroy(rs);
187 0 : return NULL;
188 : }
189 551 : id = *(sqlid*)v;
190 554 : if (!(ignore_ids && list_find_func_id(ignore_ids, id))) {
191 548 : if (list_append(dep_list, v) == NULL) {
192 0 : _DELETE(v);
193 0 : list_destroy(dep_list);
194 0 : list_destroy(schema_tables);
195 0 : table_api.rids_destroy(rs);
196 0 : return NULL;
197 : }
198 548 : if (!(v = table_api.column_find_value(tr, dep_dep_type, rid))) {
199 0 : list_destroy(dep_list);
200 0 : list_destroy(schema_tables);
201 0 : table_api.rids_destroy(rs);
202 0 : return NULL;
203 : }
204 548 : if (list_append(dep_list, v) == NULL) {
205 0 : _DELETE(v);
206 0 : list_destroy(dep_list);
207 0 : list_destroy(schema_tables);
208 0 : table_api.rids_destroy(rs);
209 0 : return NULL;
210 : }
211 : } else {
212 551 : _DELETE(v);
213 : }
214 : }
215 11571 : table_api.rids_destroy(rs);
216 :
217 11571 : if (dependent_type == SCHEMA_DEPENDENCY)
218 17 : list_destroy(schema_tables);
219 :
220 11571 : if (dependent_type == TABLE_DEPENDENCY) {
221 4185 : sql_table *triggers = find_sql_table(tr, s, "triggers");
222 4185 : table_id = find_sql_column(triggers, "table_id");
223 4185 : tri_id = find_sql_column(triggers, "id");
224 4185 : dependent_type = TRIGGER_DEPENDENCY;
225 :
226 4185 : rs = table_api.rids_select(tr, table_id, &id, &id, NULL);
227 4185 : if (rs == NULL) {
228 0 : list_destroy(dep_list);
229 0 : return NULL;
230 : }
231 4186 : for (rid = table_api.rids_next(rs); !is_oid_nil(rid); rid = table_api.rids_next(rs)) {
232 1 : if (!(v = table_api.column_find_value(tr, tri_id, rid))) {
233 0 : list_destroy(dep_list);
234 0 : table_api.rids_destroy(rs);
235 0 : return NULL;
236 : }
237 1 : if (list_append(dep_list, v) == NULL) {
238 0 : _DELETE(v);
239 0 : list_destroy(dep_list);
240 0 : table_api.rids_destroy(rs);
241 0 : return NULL;
242 : }
243 1 : if (!(v = MNEW(sht))) {
244 0 : list_destroy(dep_list);
245 0 : table_api.rids_destroy(rs);
246 0 : return NULL;
247 : }
248 1 : *(sht *) v = (sht) dependent_type;
249 1 : if (list_append(dep_list, v) == NULL) {
250 0 : _DELETE(v);
251 0 : list_destroy(dep_list);
252 0 : table_api.rids_destroy(rs);
253 0 : return NULL;
254 : }
255 : }
256 4185 : table_api.rids_destroy(rs);
257 : }
258 :
259 : return dep_list;
260 : }
261 :
262 : /*It checks if there are dependency between two ID's */
263 : sqlid
264 167 : sql_trans_get_dependency_type(sql_trans *tr, sqlid id, sql_dependency depend_type)
265 : {
266 167 : sqlstore *store = tr->store;
267 167 : oid rid;
268 167 : sql_schema *s;
269 167 : sql_table *dep;
270 167 : sql_column *dep_id, *dep_dep_id, *dep_dep_type;
271 167 : sht dtype = (sht) depend_type;
272 :
273 167 : s = find_sql_schema(tr, "sys");
274 167 : dep = find_sql_table(tr, s, "dependencies");
275 167 : dep_id = find_sql_column(dep, "id");
276 167 : dep_dep_id = find_sql_column(dep, "depend_id");
277 167 : dep_dep_type = find_sql_column(dep, "depend_type");
278 :
279 167 : rid = store->table_api.column_find_row(tr, dep_id, &id, dep_dep_type, &dtype, NULL);
280 167 : if (!is_oid_nil(rid)) {
281 146 : return store->table_api.column_find_sqlid(tr, dep_dep_id, rid);
282 : } else {
283 : return -1;
284 : }
285 : }
286 :
287 : /*It checks if there are dependency between two ID's */
288 : int
289 0 : sql_trans_check_dependency(sql_trans *tr, sqlid id, sqlid depend_id, sql_dependency depend_type)
290 : {
291 0 : sqlstore *store = tr->store;
292 0 : oid rid;
293 0 : sql_schema *s;
294 0 : sql_table *dep;
295 0 : sql_column *dep_id, *dep_dep_id, *dep_dep_type;
296 0 : sht dtype = (sht) depend_type;
297 :
298 0 : s = find_sql_schema(tr, "sys");
299 0 : dep = find_sql_table(tr, s, "dependencies");
300 0 : dep_id = find_sql_column(dep, "id");
301 0 : dep_dep_id = find_sql_column(dep, "depend_id");
302 0 : dep_dep_type = find_sql_column(dep, "depend_type");
303 :
304 0 : rid = store->table_api.column_find_row(tr, dep_id, &id, dep_dep_id, &depend_id, dep_dep_type, &dtype, NULL);
305 0 : if (!is_oid_nil(rid))
306 : return 1;
307 0 : else return 0;
308 : }
309 :
310 : /*Schema on users*/
311 :
312 : list *
313 17 : sql_trans_schema_user_dependencies(sql_trans *tr, sqlid schema_id)
314 : {
315 17 : sqlstore *store = tr->store;
316 17 : void *v;
317 17 : sql_schema * s = find_sql_schema(tr, "sys");
318 17 : sql_table *auths = find_sql_table(tr, s, "auths");
319 17 : sql_column *auth_id = find_sql_column(auths, "id");
320 17 : sql_dependency type = USER_DEPENDENCY;
321 17 : list *l = list_create((fdestroy) _free);
322 17 : rids *users;
323 17 : oid rid;
324 :
325 17 : if (!l || !(users = backend_schema_user_dependencies(tr, schema_id))) {
326 0 : list_destroy(l);
327 0 : return NULL;
328 : }
329 :
330 17 : for (rid = store->table_api.rids_next(users); !is_oid_nil(rid); rid = store->table_api.rids_next(users)) {
331 0 : if (!(v = store->table_api.column_find_value(tr, auth_id, rid))) {
332 0 : list_destroy(l);
333 0 : store->table_api.rids_destroy(users);
334 0 : return NULL;
335 : }
336 0 : list_append(l,v);
337 0 : if (!(v = MNEW(sht))) {
338 0 : list_destroy(l);
339 0 : store->table_api.rids_destroy(users);
340 0 : return NULL;
341 : }
342 0 : *(sht*)v = (sht) type;
343 0 : list_append(l,v);
344 : }
345 17 : store->table_api.rids_destroy(users);
346 :
347 17 : if (list_length(l) == 0) {
348 17 : list_destroy(l);
349 17 : l = NULL;
350 : }
351 :
352 : return l;
353 : }
354 :
355 : /*owner on schemas*/
356 : list *
357 107 : sql_trans_owner_schema_dependencies(sql_trans *tr, sqlid owner_id)
358 : {
359 107 : sqlstore *store = tr->store;
360 107 : void *v;
361 107 : sql_schema * s = find_sql_schema(tr, "sys");
362 107 : sql_table *schemas = find_sql_table(tr, s, "schemas");
363 107 : sql_column *schema_owner = find_sql_column(schemas, "authorization");
364 107 : sql_column *schema_id = find_sql_column(schemas, "id");
365 107 : sql_dependency type = SCHEMA_DEPENDENCY;
366 107 : list *l = list_create((fdestroy) _free);
367 107 : rids *rs;
368 107 : oid rid;
369 :
370 107 : if (!l)
371 : return NULL;
372 :
373 107 : rs = store->table_api.rids_select(tr, schema_owner, &owner_id, &owner_id, NULL);
374 107 : if (rs == NULL)
375 : return NULL;
376 :
377 124 : for (rid = store->table_api.rids_next(rs); !is_oid_nil(rid); rid = store->table_api.rids_next(rs)) {
378 17 : if (!(v = store->table_api.column_find_value(tr, schema_id, rid))) {
379 0 : list_destroy(l);
380 0 : store->table_api.rids_destroy(rs);
381 0 : return NULL;
382 : }
383 17 : list_append(l, v);
384 17 : if (!(v = MNEW(sht))) {
385 0 : list_destroy(l);
386 0 : store->table_api.rids_destroy(rs);
387 0 : return NULL;
388 : }
389 17 : *(sht*)v = (sht) type;
390 17 : list_append(l,v);
391 : }
392 107 : store->table_api.rids_destroy(rs);
393 107 : return l;
394 : }
395 :
396 : /*Function on Functions*/
|