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, 2025 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 "sql_relation.h"
15 : #include "rel_exp.h"
16 : #include "rel_prop.h"
17 : #include "sql_string.h"
18 : #include "sql_atom.h"
19 :
20 : prop *
21 20774804 : prop_create( allocator *sa, rel_prop kind, prop *pre )
22 : {
23 20774804 : prop *p = SA_NEW(sa, prop);
24 :
25 20775105 : *p = (prop) {
26 : .kind = kind,
27 : .p = pre,
28 : };
29 20775105 : if (kind == PROP_NUNIQUES)
30 20775105 : p->value.dval = 0.0; /* floating point compatibility */
31 20775105 : return p;
32 : }
33 :
34 : prop *
35 10154187 : prop_copy( allocator *sa, prop *p )
36 : {
37 10154187 : prop *np = NULL;
38 :
39 19315529 : for(; p; p = p->p) {
40 9161337 : np = prop_create(sa, p->kind, np);
41 9161342 : np->id = p->id;
42 9161342 : switch (p->kind) {
43 4 : case PROP_COUNT:
44 4 : np->value.lval = p->value.lval;
45 4 : break;
46 3518735 : case PROP_NUNIQUES:
47 3518735 : np->value.dval = p->value.dval;
48 3518735 : break;
49 5642603 : default:
50 5642603 : np->value.pval = p->value.pval;
51 : }
52 : }
53 10154192 : return np;
54 : }
55 :
56 : prop *
57 663 : prop_remove( prop *plist, prop *p )
58 : {
59 663 : prop *op = plist;
60 :
61 663 : if (plist == p)
62 620 : return p->p;
63 43 : for(; op; op = op->p) {
64 39 : if (op->p == p) {
65 39 : op->p = p->p;
66 39 : break;
67 : }
68 : }
69 : return plist;
70 : }
71 :
72 : prop *
73 30668291 : find_prop( prop *p, rel_prop kind)
74 : {
75 53353172 : while(p) {
76 35896422 : if (p->kind == kind)
77 13211541 : return p;
78 22684881 : p = p->p;
79 : }
80 : return p;
81 : }
82 :
83 : void *
84 13543681 : find_prop_and_get(prop *p, rel_prop kind)
85 : {
86 13543681 : prop *found = find_prop(p, kind);
87 :
88 : /* this doesn't work with numbers yet */
89 13543721 : assert(kind != PROP_COUNT && kind != PROP_NUNIQUES);
90 13543721 : return found ? found->value.pval : NULL;
91 : }
92 :
93 : #ifdef MIN
94 : #undef MIN
95 : #endif
96 :
97 : #ifdef MAX
98 : #undef MAX
99 : #endif
100 :
101 : const char *
102 490 : propkind2string( prop *p)
103 : {
104 490 : switch(p->kind) {
105 : #define PT(TYPE) case PROP_##TYPE : return #TYPE
106 : PT(COUNT);
107 0 : PT(NUNIQUES);
108 63 : PT(JOINIDX);
109 1 : PT(HASHIDX);
110 414 : PT(HASHCOL);
111 12 : PT(REMOTE);
112 0 : PT(USED);
113 0 : PT(GROUPINGS);
114 0 : PT(MIN);
115 0 : PT(MAX);
116 0 : PT(NESTED);
117 0 : PT(UNNEST);
118 : }
119 0 : return "UNKNOWN";
120 : }
121 :
122 : char *
123 490 : propvalue2string(allocator *sa, prop *p)
124 : {
125 490 : char buf [BUFSIZ];
126 :
127 490 : switch(p->kind) {
128 0 : case PROP_COUNT: {
129 0 : snprintf(buf, BUFSIZ, BUNFMT, p->value.lval);
130 0 : return sa_strdup(sa, buf);
131 : }
132 0 : case PROP_NUNIQUES: {
133 0 : snprintf(buf, BUFSIZ, "%f", p->value.dval);
134 0 : return sa_strdup(sa, buf);
135 : }
136 63 : case PROP_JOINIDX: {
137 63 : sql_idx *i = p->value.pval;
138 :
139 63 : if (i) {
140 63 : snprintf(buf, BUFSIZ, "\"%s\".\"%s\".\"%s\"", sql_escape_ident(sa, i->t->s->base.name),
141 63 : sql_escape_ident(sa, i->t->base.name), sql_escape_ident(sa, i->base.name));
142 63 : return sa_strdup(sa, buf);
143 : }
144 : } break;
145 12 : case PROP_REMOTE: {
146 12 : list *tids_uris = p->value.pval;
147 12 : if (!list_empty(tids_uris)) {
148 12 : size_t offset = 0;
149 24 : for (node *n = ((list*)p->value.pval)->h; n; n = n->next) {
150 12 : tid_uri *tu = n->data;
151 12 : if (tu->uri)
152 24 : offset += snprintf(buf + offset, BUFSIZ, "%s%s",
153 : sql_escape_ident(sa, offset?" ":""),
154 : sql_escape_ident(sa, tu->uri));
155 : }
156 12 : return sa_strdup(sa, buf);
157 : }
158 : } break;
159 0 : case PROP_MIN:
160 : case PROP_MAX: {
161 0 : atom *a = p->value.pval;
162 0 : char *res = NULL;
163 :
164 0 : if (a->isnull) {
165 0 : res = sa_strdup(sa, "\"NULL\"");
166 : } else {
167 0 : char *s = ATOMformat(a->data.vtype, VALptr(&a->data));
168 0 : if (s && *s == '"') {
169 0 : res = sa_strdup(sa, s);
170 0 : } else if (s) {
171 0 : res = sa_alloc(sa, strlen(s) + 3);
172 0 : stpcpy(stpcpy(stpcpy(res, "\""), s), "\"");
173 : }
174 0 : GDKfree(s);
175 : }
176 : return res;
177 : }
178 0 : case PROP_UNNEST:
179 0 : return sa_strdup(sa, exp_name((sql_exp*)p->value.pval));
180 0 : case PROP_NESTED: {
181 0 : sql_column *c = p->value.pval;
182 0 : return sa_strdup(sa, c->storage_type);
183 : }
184 : default:
185 : break;
186 : }
187 415 : return sa_strdup(sa, "");
188 : }
|