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