1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V.
7 */
8
9#include "monetdb_config.h"
10#include "sql_catalog.h"
11
12const char *TID = "%TID%";
13
14int
15base_key( sql_base *b )
16{
17 return hash_key(b->name);
18}
19
20static void *
21_list_find_name(list *l, const char *name)
22{
23 node *n;
24
25 if (l) {
26 MT_lock_set(&l->ht_lock);
27 if ((!l->ht || l->ht->size*16 < list_length(l)) && list_length(l) > HASH_MIN_SIZE && l->sa) {
28 l->ht = hash_new(l->sa, list_length(l), (fkeyvalue)&base_key);
29 if (l->ht == NULL) {
30 MT_lock_unset(&l->ht_lock);
31 return NULL;
32 }
33
34 for (n = l->h; n; n = n->next ) {
35 sql_base *b = n->data;
36 int key = base_key(b);
37
38 if (hash_add(l->ht, key, b) == NULL) {
39 MT_lock_unset(&l->ht_lock);
40 return NULL;
41 }
42 }
43 }
44 if (l->ht) {
45 int key = hash_key(name);
46 sql_hash_e *he = l->ht->buckets[key&(l->ht->size-1)];
47
48 for (; he; he = he->chain) {
49 sql_base *b = he->value;
50
51 if (b->name && strcmp(b->name, name) == 0) {
52 MT_lock_unset(&l->ht_lock);
53 return b;
54 }
55 }
56 MT_lock_unset(&l->ht_lock);
57 return NULL;
58 }
59 MT_lock_unset(&l->ht_lock);
60 for (n = l->h; n; n = n->next) {
61 sql_base *b = n->data;
62
63 /* check if names match */
64 if (name[0] == b->name[0] && strcmp(name, b->name) == 0) {
65 return b;
66 }
67 }
68 }
69 return NULL;
70}
71
72static void *
73_cs_find_name(changeset * cs, const char *name)
74{
75 return _list_find_name(cs->set, name);
76}
77
78node *
79cs_find_name(changeset * cs, const char *name)
80{
81 return list_find_name(cs->set, name);
82}
83
84node *
85list_find_name(list *l, const char *name)
86{
87 node *n;
88
89 if (l)
90 for (n = l->h; n; n = n->next) {
91 sql_base *b = n->data;
92
93 /* check if names match */
94 if (name[0] == b->name[0] && strcmp(name, b->name) == 0) {
95 return n;
96 }
97 }
98 return NULL;
99}
100
101node *
102cs_find_id(changeset * cs, sqlid id)
103{
104 node *n;
105 list *l = cs->set;
106
107 if (l)
108 for (n = l->h; n; n = n->next) {
109 sql_base *b = n->data;
110
111 /* check if names match */
112 if (b->id == id) {
113 return n;
114 }
115 }
116 if (cs->dset) {
117 l = cs->dset;
118 for (n = l->h; n; n = n->next) {
119 sql_base *b = n->data;
120
121 /* check if names match */
122 if (b->id == id) {
123 return n;
124 }
125 }
126 }
127 return NULL;
128}
129
130node *
131list_find_id(list *l, sqlid id)
132{
133 if (l) {
134 node *n;
135 for (n = l->h; n; n = n->next) {
136
137 /* check if ids match */
138 if (id == *(sqlid *) n->data) {
139 return n;
140 }
141 }
142 }
143 return NULL;
144}
145
146node *
147list_find_base_id(list *l, sqlid id)
148{
149 if (l) {
150 node *n;
151 for (n = l->h; n; n = n->next) {
152 sql_base *b = n->data;
153
154 if (id == b->id)
155 return n;
156 }
157 }
158 return NULL;
159}
160
161sql_key *
162find_sql_key(sql_table *t, const char *kname)
163{
164 return _cs_find_name(&t->keys, kname);
165}
166
167sql_idx *
168find_sql_idx(sql_table *t, const char *iname)
169{
170 return _cs_find_name(&t->idxs, iname);
171}
172
173sql_column *
174find_sql_column(sql_table *t, const char *cname)
175{
176 return _cs_find_name(&t->columns, cname);
177}
178
179sql_part *
180find_sql_part(sql_table *t, const char *tname)
181{
182 return _cs_find_name(&t->members, tname);
183}
184
185sql_table *
186find_sql_table(sql_schema *s, const char *tname)
187{
188 return _cs_find_name(&s->tables, tname);
189}
190
191sql_table *
192find_sql_table_id(sql_schema *s, sqlid id)
193{
194 node *n = cs_find_id(&s->tables, id);
195
196 if (n)
197 return n->data;
198 return NULL;
199}
200
201node *
202find_sql_table_node(sql_schema *s, sqlid id)
203{
204 return cs_find_id(&s->tables, id);
205}
206
207sql_sequence *
208find_sql_sequence(sql_schema *s, const char *sname)
209{
210 return _cs_find_name(&s->seqs, sname);
211}
212
213sql_schema *
214find_sql_schema(sql_trans *t, const char *sname)
215{
216 return _cs_find_name(&t->schemas, sname);
217}
218
219sql_schema *
220find_sql_schema_id(sql_trans *t, sqlid id)
221{
222 node *n = cs_find_id(&t->schemas, id);
223
224 if (n)
225 return n->data;
226 return NULL;
227}
228
229node *
230find_sql_schema_node(sql_trans *t, sqlid id)
231{
232 return cs_find_id(&t->schemas, id);
233}
234
235static sql_type *
236find_sqlname(list *l, const char *name)
237{
238 if (l) {
239 node *n;
240
241 for (n = l->h; n; n = n->next) {
242 sql_type *t = n->data;
243
244 if (strcmp(t->sqlname, name) == 0)
245 return t;
246 }
247 }
248 return NULL;
249}
250
251node *
252find_sql_type_node(sql_schema * s, sqlid id)
253{
254 return cs_find_id(&s->types, id);
255}
256
257sql_type *
258find_sql_type(sql_schema * s, const char *tname)
259{
260 return find_sqlname(s->types.set, tname);
261}
262
263sql_type *
264sql_trans_bind_type(sql_trans *tr, sql_schema *c, const char *name)
265{
266 node *n;
267 sql_type *t = NULL;
268
269 if (tr->schemas.set)
270 for (n = tr->schemas.set->h; n && !t; n = n->next) {
271 sql_schema *s = n->data;
272
273 t = find_sql_type(s, name);
274 }
275
276 if (!t && c)
277 t = find_sql_type(c, name);
278 return t;
279}
280
281node *
282find_sql_func_node(sql_schema * s, sqlid id)
283{
284 return cs_find_id(&s->funcs, id);
285}
286
287sql_func *
288find_sql_func(sql_schema * s, const char *tname)
289{
290 return _cs_find_name(&s->funcs, tname);
291}
292
293list *
294find_all_sql_func(sql_schema * s, const char *name, sql_ftype type)
295{
296 list *l = s->funcs.set, *res = NULL;
297 node *n = NULL;
298
299 if (l) {
300 for (n = l->h; n; n = n->next) {
301 sql_base *b = n->data;
302 sql_func *f = n->data;
303
304 /* check if names match */
305 if (f->type == type && name[0] == b->name[0] && strcmp(name, b->name) == 0) {
306 if (!res)
307 res = list_create((fdestroy)NULL);
308 if (!res) {
309 return NULL;
310 }
311 list_append(res, f);
312 }
313 }
314 }
315 return res;
316}
317
318sql_func *
319sql_trans_bind_func(sql_trans *tr, const char *name)
320{
321 node *n;
322 sql_func *t = NULL;
323
324 if (tr->schemas.set)
325 for (n = tr->schemas.set->h; n && !t; n = n->next) {
326 sql_schema *s = n->data;
327
328 t = find_sql_func(s, name);
329 }
330 if (!t)
331 return NULL;
332 return t;
333}
334
335sql_func *
336sql_trans_find_func(sql_trans *tr, sqlid id)
337{
338 node *n, *m;
339 sql_func *t = NULL;
340
341 if (tr->schemas.set) {
342 for (n = tr->schemas.set->h; n && !t; n = n->next) {
343 m = find_sql_func_node(n->data, id);
344 if (m)
345 t = m->data;
346 }
347 }
348 return t;
349}
350
351void*
352sql_values_list_element_validate_and_insert(void *v1, void *v2, int* res)
353{
354 sql_part_value* pt = (sql_part_value*) v1, *newp = (sql_part_value*) v2;
355
356 assert(pt->tpe.type->localtype == newp->tpe.type->localtype);
357 *res = ATOMcmp(pt->tpe.type->localtype, newp->value, pt->value);
358 return *res == 0 ? pt : NULL;
359}
360
361void*
362sql_range_part_validate_and_insert(void *v1, void *v2)
363{
364 sql_part* pt = (sql_part*) v1, *newp = (sql_part*) v2;
365 int res1, res2;
366
367 if (pt == newp) /* same pointer, skip (used in updates) */
368 return NULL;
369
370 assert(pt->tpe.type->localtype == newp->tpe.type->localtype);
371 if (newp->with_nills && pt->with_nills) //only one partition at most has null values
372 return pt;
373
374 res1 = ATOMcmp(pt->tpe.type->localtype, pt->part.range.minvalue, newp->part.range.maxvalue);
375 res2 = ATOMcmp(pt->tpe.type->localtype, newp->part.range.minvalue, pt->part.range.maxvalue);
376 if (res1 < 0 && res2 < 0) //overlap: x1 < y2 && y1 < x2
377 return pt;
378 return NULL;
379}
380
381void*
382sql_values_part_validate_and_insert(void *v1, void *v2)
383{
384 sql_part* pt = (sql_part*) v1, *newp = (sql_part*) v2;
385 list* b1 = pt->part.values, *b2 = newp->part.values;
386 node *n1 = b1->h, *n2 = b2->h;
387 int res;
388
389 if (pt == newp) /* same pointer, skip (used in updates) */
390 return NULL;
391
392 assert(pt->tpe.type->localtype == newp->tpe.type->localtype);
393 if (newp->with_nills && pt->with_nills)
394 return pt; //check for nulls first
395
396 while (n1 && n2) {
397 sql_part_value *p1 = (sql_part_value *) n1->data, *p2 = (sql_part_value *) n2->data;
398 res = ATOMcmp(pt->tpe.type->localtype, p1->value, p2->value);
399 if (!res) { //overlap -> same value in both partitions
400 return pt;
401 } else if(res < 0) {
402 n1 = n1->next;
403 } else {
404 n2 = n2->next;
405 }
406 }
407 return NULL;
408}
409