1 /*
2 * Copyright (C) Tildeslash Ltd. All rights reserved.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 * In addition, as a special exception, the copyright holders give
16 * permission to link the code of portions of this program with the
17 * OpenSSL library under certain conditions as described in each
18 * individual source file, and distribute linked combinations
19 * including the two.
20 *
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL.
23 */
24
25
26 #include "Config.h"
27
28 #include <stdio.h>
29
30 #include "ResultSet.h"
31 #include "system/Time.h"
32
33
34 /**
35 * Implementation of the ResultSet interface
36 *
37 * @file
38 */
39
40
41 /* ----------------------------------------------------------- Definitions */
42
43
44 #define T ResultSet_T
45 struct ResultSet_S {
46 Rop_T op;
47 ResultSetDelegate_T D;
48 int fetchSize;
49 };
50
51
52 /* ------------------------------------------------------- Private methods */
53
54
_getIndex(T R,const char * name)55 static inline int _getIndex(T R, const char *name) {
56 int columns = ResultSet_getColumnCount(R);
57 for (int i = 1; i <= columns; i++)
58 if (Str_isByteEqual(name, ResultSet_getColumnName(R, i)))
59 return i;
60 THROW(SQLException, "Invalid column name '%s'", name ? name : "null");
61 return -1;
62 }
63
64
65 /* ----------------------------------------------------- Protected methods */
66
67
68 #ifdef PACKAGE_PROTECTED
69 #pragma GCC visibility push(hidden)
70 #endif
71
ResultSet_new(ResultSetDelegate_T D,Rop_T op)72 T ResultSet_new(ResultSetDelegate_T D, Rop_T op) {
73 T R;
74 assert(D);
75 assert(op);
76 NEW(R);
77 R->D = D;
78 R->op = op;
79 return R;
80 }
81
82
ResultSet_free(T * R)83 void ResultSet_free(T *R) {
84 assert(R && *R);
85 (*R)->op->free(&((*R)->D));
86 FREE(*R);
87 }
88
89 #ifdef PACKAGE_PROTECTED
90 #pragma GCC visibility pop
91 #endif
92
93
94 /* ------------------------------------------------------------ Properties */
95
96
ResultSet_getColumnCount(T R)97 int ResultSet_getColumnCount(T R) {
98 assert(R);
99 return R->op->getColumnCount(R->D);
100 }
101
102
ResultSet_getColumnName(T R,int columnIndex)103 const char *ResultSet_getColumnName(T R, int columnIndex) {
104 assert(R);
105 return R->op->getColumnName(R->D, columnIndex);
106 }
107
108
ResultSet_getColumnSize(T R,int columnIndex)109 long ResultSet_getColumnSize(T R, int columnIndex) {
110 assert(R);
111 return R->op->getColumnSize(R->D, columnIndex);
112 }
113
114
ResultSet_setFetchSize(T R,int rows)115 void ResultSet_setFetchSize(T R, int rows) {
116 assert(R);
117 assert(rows > 0);
118 if (R->op->setFetchSize)
119 R->op->setFetchSize(R->D, rows);
120 }
121
122
ResultSet_getFetchSize(T R)123 int ResultSet_getFetchSize(T R) {
124 assert(R);
125 return R->op->getFetchSize ? R->op->getFetchSize(R->D) : 0;
126 }
127
128
129 /* -------------------------------------------------------- Public methods */
130
131
ResultSet_next(T R)132 bool ResultSet_next(T R) {
133 return R ? R->op->next(R->D) : false;
134 }
135
136
ResultSet_isnull(T R,int columnIndex)137 bool ResultSet_isnull(T R, int columnIndex) {
138 assert(R);
139 return R->op->isnull(R->D, columnIndex);
140 }
141
142
143 /* --------------------------------------------------------------- Columns */
144
145
ResultSet_getString(T R,int columnIndex)146 const char *ResultSet_getString(T R, int columnIndex) {
147 assert(R);
148 return R->op->getString(R->D, columnIndex);
149 }
150
151
ResultSet_getStringByName(T R,const char * columnName)152 const char *ResultSet_getStringByName(T R, const char *columnName) {
153 assert(R);
154 return ResultSet_getString(R, _getIndex(R, columnName));
155 }
156
157
ResultSet_getInt(T R,int columnIndex)158 int ResultSet_getInt(T R, int columnIndex) {
159 assert(R);
160 const char *s = R->op->getString(R->D, columnIndex);
161 return s ? Str_parseInt(s) : 0;
162 }
163
164
ResultSet_getIntByName(T R,const char * columnName)165 int ResultSet_getIntByName(T R, const char *columnName) {
166 assert(R);
167 return ResultSet_getInt(R, _getIndex(R, columnName));
168 }
169
170
ResultSet_getLLong(T R,int columnIndex)171 long long ResultSet_getLLong(T R, int columnIndex) {
172 assert(R);
173 const char *s = R->op->getString(R->D, columnIndex);
174 return s ? Str_parseLLong(s) : 0;
175 }
176
177
ResultSet_getLLongByName(T R,const char * columnName)178 long long ResultSet_getLLongByName(T R, const char *columnName) {
179 assert(R);
180 return ResultSet_getLLong(R, _getIndex(R, columnName));
181 }
182
183
ResultSet_getDouble(T R,int columnIndex)184 double ResultSet_getDouble(T R, int columnIndex) {
185 assert(R);
186 const char *s = R->op->getString(R->D, columnIndex);
187 return s ? Str_parseDouble(s) : 0.0;
188 }
189
190
ResultSet_getDoubleByName(T R,const char * columnName)191 double ResultSet_getDoubleByName(T R, const char *columnName) {
192 assert(R);
193 return ResultSet_getDouble(R, _getIndex(R, columnName));
194 }
195
196
ResultSet_getBlob(T R,int columnIndex,int * size)197 const void *ResultSet_getBlob(T R, int columnIndex, int *size) {
198 assert(R);
199 const void *b = R->op->getBlob(R->D, columnIndex, size);
200 if (! b)
201 *size = 0;
202 return b;
203 }
204
205
ResultSet_getBlobByName(T R,const char * columnName,int * size)206 const void *ResultSet_getBlobByName(T R, const char *columnName, int *size) {
207 assert(R);
208 return ResultSet_getBlob(R, _getIndex(R, columnName), size);
209 }
210
211
212 /* --------------------------------------------------------- Date and Time */
213
214
ResultSet_getTimestamp(T R,int columnIndex)215 time_t ResultSet_getTimestamp(T R, int columnIndex) {
216 assert(R);
217 time_t t = 0;
218 if (R->op->getTimestamp) {
219 t = R->op->getTimestamp(R->D, columnIndex);
220 } else {
221 const char *s = ResultSet_getString(R, columnIndex);
222 if (STR_DEF(s))
223 t = Time_toTimestamp(s);
224 }
225 return t;
226 }
227
228
ResultSet_getTimestampByName(T R,const char * columnName)229 time_t ResultSet_getTimestampByName(T R, const char *columnName) {
230 assert(R);
231 return ResultSet_getTimestamp(R, _getIndex(R, columnName));
232 }
233
234
ResultSet_getDateTime(T R,int columnIndex)235 struct tm ResultSet_getDateTime(T R, int columnIndex) {
236 assert(R);
237 struct tm t = {.tm_year = 0};
238 if (R->op->getDateTime) {
239 R->op->getDateTime(R->D, columnIndex, &t);
240 } else {
241 const char *s = ResultSet_getString(R, columnIndex);
242 if (STR_DEF(s))
243 Time_toDateTime(s, &t);
244 }
245 return t;
246 }
247
248
ResultSet_getDateTimeByName(T R,const char * columnName)249 struct tm ResultSet_getDateTimeByName(T R, const char *columnName) {
250 assert(R);
251 return ResultSet_getDateTime(R, _getIndex(R, columnName));
252 }
253
254