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
13static void
14bat_incref(bat bid)
15{
16 BBPretain(bid);
17}
18
19static void
20bat_decref(bat bid)
21{
22 BBPrelease(bid);
23}
24
25res_table *
26res_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
57res_col *
58res_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
113static void
114res_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
125void
126res_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
141res_table *
142res_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
160void
161res_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
173res_table *
174res_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