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 "res_table.h" |
11 | #include "sql_types.h" |
12 | |
13 | static void |
14 | bat_incref(bat bid) |
15 | { |
16 | BBPretain(bid); |
17 | } |
18 | |
19 | static void |
20 | bat_decref(bat bid) |
21 | { |
22 | BBPrelease(bid); |
23 | } |
24 | |
25 | res_table * |
26 | res_table_create(sql_trans *tr, int res_id, oid query_id, int nr_cols, sql_query_t type, res_table *next, void *O) |
27 | { |
28 | BAT *order = (BAT*)O; |
29 | res_table *t = ZNEW(res_table); |
30 | if(!t) |
31 | return NULL; |
32 | |
33 | (void) tr; |
34 | t->id = res_id; |
35 | t->query_id = query_id; |
36 | t->query_type = type; |
37 | t->nr_cols = nr_cols; |
38 | t->cur_col = 0; |
39 | t->cols = NEW_ARRAY(res_col, nr_cols); |
40 | if(!t->cols) { |
41 | _DELETE(t); |
42 | return NULL; |
43 | } |
44 | |
45 | memset((char*) t->cols, 0, nr_cols * sizeof(res_col)); |
46 | t->tsep = t->rsep = t->ssep = t->ns = NULL; |
47 | |
48 | t->order = 0; |
49 | if (order) { |
50 | t->order = order->batCacheid; |
51 | bat_incref(t->order); |
52 | } |
53 | t->next = next; |
54 | return t; |
55 | } |
56 | |
57 | res_col * |
58 | res_col_create(sql_trans *tr, res_table *t, const char *tn, const char *name, const char *typename, int digits, int scale, int mtype, void *val) |
59 | { |
60 | res_col *c = t->cols + t->cur_col; |
61 | BAT *b; |
62 | |
63 | if (!sql_find_subtype(&c->type, typename, digits, scale)) |
64 | sql_init_subtype(&c->type, sql_trans_bind_type(tr, NULL, typename), digits, scale); |
65 | c->tn = _STRDUP(tn); |
66 | c->name = _STRDUP(name); |
67 | if (c->tn == NULL || c->name == NULL) { |
68 | _DELETE(c->tn); |
69 | _DELETE(c->name); |
70 | return NULL; |
71 | } |
72 | c->b = 0; |
73 | c->p = NULL; |
74 | c->mtype = mtype; |
75 | if (mtype == TYPE_bat) { |
76 | b = (BAT*)val; |
77 | } else { // wrap scalar values in BATs for result consistency |
78 | b = COLnew(0, mtype, 1, TRANSIENT); |
79 | if (b == NULL) { |
80 | _DELETE(c->tn); |
81 | _DELETE(c->name); |
82 | return NULL; |
83 | } |
84 | if (BUNappend(b, val, false) != GDK_SUCCEED) { |
85 | BBPreclaim(b); |
86 | _DELETE(c->tn); |
87 | _DELETE(c->name); |
88 | return NULL; |
89 | } |
90 | /* we need to set the order bat otherwise mvc_export_result won't work with single-row result sets containing BATs */ |
91 | if (!t->order) { |
92 | oid zero = 0; |
93 | BAT *o = BATconstant(0, TYPE_oid, &zero, 1, TRANSIENT); |
94 | if (o == NULL) { |
95 | BBPreclaim(b); |
96 | _DELETE(c->tn); |
97 | _DELETE(c->name); |
98 | return NULL; |
99 | } |
100 | t->order = o->batCacheid; |
101 | BBPkeepref(t->order); |
102 | } |
103 | } |
104 | c->b = b->batCacheid; |
105 | bat_incref(c->b); |
106 | if (mtype != TYPE_bat) |
107 | BBPunfix(c->b); |
108 | t->cur_col++; |
109 | assert(t->cur_col <= t->nr_cols); |
110 | return c; |
111 | } |
112 | |
113 | static void |
114 | res_col_destroy(res_col *c) |
115 | { |
116 | if (c->b) { |
117 | bat_decref(c->b); |
118 | } else { |
119 | _DELETE(c->p); |
120 | } |
121 | _DELETE(c->name); |
122 | _DELETE(c->tn); |
123 | } |
124 | |
125 | void |
126 | res_table_destroy(res_table *t) |
127 | { |
128 | int i; |
129 | |
130 | for (i = 0; i < t->nr_cols; i++) { |
131 | res_col *c = t->cols + i; |
132 | |
133 | res_col_destroy(c); |
134 | } |
135 | if (t->order) |
136 | bat_decref(t->order); |
137 | _DELETE(t->cols); |
138 | _DELETE(t); |
139 | } |
140 | |
141 | res_table * |
142 | res_tables_remove(res_table *results, res_table *t) |
143 | { |
144 | res_table *r = results; |
145 | |
146 | if (r == t) { |
147 | results = t->next; |
148 | } else { |
149 | for (; r; r = r->next) { |
150 | if (r->next == t) { |
151 | r->next = t->next; |
152 | break; |
153 | } |
154 | } |
155 | } |
156 | res_table_destroy(t); |
157 | return results; |
158 | } |
159 | |
160 | void |
161 | res_tables_destroy(res_table *tab) |
162 | { |
163 | if (tab) { |
164 | res_table *r = tab, *t; |
165 | |
166 | for (t = r; t; t = r) { |
167 | r = t->next; |
168 | res_table_destroy(t); |
169 | } |
170 | } |
171 | } |
172 | |
173 | res_table * |
174 | res_tables_find(res_table *results, int res_id) |
175 | { |
176 | res_table *r = results; |
177 | |
178 | for (; r; r = r->next) { |
179 | if (r->id == res_id) |
180 | return r; |
181 | } |
182 | return NULL; |
183 | } |
184 | |