1 /*
2 * Copyright (C) 2013 Vivien Malerba <malerba@gnome-db.org>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <libgda/libgda.h>
20 #include <sql-parser/gda-sql-parser.h>
21 #include <string.h>
22
23 #define PROV_CLASS(provider) (GDA_SERVER_PROVIDER_CLASS (G_OBJECT_GET_CLASS (provider)))
24
25 static gboolean
string_equal_to_template(const gchar * str,const gchar * tmpl)26 string_equal_to_template (const gchar *str, const gchar *tmpl)
27 {
28 const gchar *ptrs, *ptrt;
29 for (ptrs = str; *ptrs != '('; ptrs++);
30
31 for (ptrt = tmpl;
32 *ptrs && *ptrt;
33 ptrs++, ptrt++) {
34 if (*ptrt == '@')
35 continue;
36 if (*ptrs != *ptrt)
37 break;
38 }
39 if (*ptrs || *ptrt)
40 return FALSE;
41 else
42 return TRUE;
43 }
44
45 GdaTimestamp ts = {
46 .year = 2013,
47 .month = 8,
48 .day = 28,
49 .hour = 17,
50 .minute = 10,
51 .second = 23,
52 .timezone = 3600 * 2
53 };
54 GdaTime gt = {
55 .hour = 16,
56 .minute = 9,
57 .second = 22,
58 .timezone = - 3600 * 3
59 };
60
61
62 static guint
do_a_test(GdaServerProvider * prov,GdaSqlParser * parser)63 do_a_test (GdaServerProvider *prov, GdaSqlParser *parser)
64 {
65 guint nfailed = 0;
66 GdaStatement *stmt;
67 GdaSet *params;
68 gchar *sql;
69 GError *error = NULL;
70
71 /* SQL parsed as an INSERT statement */
72 sql = "INSERT INTO tstest VALUES (##ts::timestamp, ##time::time)";
73 stmt = gda_sql_parser_parse_string (parser, sql, NULL, &error);
74 if (!stmt) {
75 g_print ("Failed to parse [%s]: %s\n", sql, error && error->message ? error->message : "No detail");
76 g_clear_error (&error);
77 nfailed ++;
78 goto endtest;
79 }
80
81 g_assert (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_INSERT);
82 if (! gda_statement_get_parameters (stmt, ¶ms, &error)) {
83 g_print ("Failed to obtain parameters: %s\n", error && error->message ? error->message : "No detail");
84 g_clear_error (&error);
85 g_object_unref (stmt);
86 nfailed ++;
87 goto endtest;
88 }
89
90 if (! gda_set_set_holder_value (params, &error, "ts", &ts)) {
91 g_print ("Failed to bind 'ts' parameter: %s\n", error && error->message ? error->message : "No detail");
92 g_clear_error (&error);
93 g_object_unref (stmt);
94 g_object_unref (params);
95 nfailed ++;
96 goto endtest;
97 }
98
99 if (! gda_set_set_holder_value (params, &error, "time", >)) {
100 g_print ("Failed to bind 'time' parameter: %s\n", error && error->message ? error->message : "No detail");
101 g_clear_error (&error);
102 g_object_unref (stmt);
103 g_object_unref (params);
104 nfailed ++;
105 goto endtest;
106 }
107
108 gchar *expected;
109 expected = "('@@@@@@@@@@ 17:10:23+2', '16:09:22-3')";
110 if (prov && PROV_CLASS (prov)->statement_to_sql)
111 sql = PROV_CLASS (prov)->statement_to_sql (prov, NULL, stmt, params, 0, NULL, &error);
112 else
113 sql = gda_statement_to_sql_extended (stmt, NULL, params, 0, NULL, &error);
114 if (!sql) {
115 g_print ("Failed to render as SQL: %s\n", error && error->message ? error->message : "No detail");
116 g_clear_error (&error);
117 g_object_unref (stmt);
118 g_object_unref (params);
119 nfailed ++;
120 goto endtest;
121 }
122 if (!string_equal_to_template (sql, expected)) {
123 g_print ("Wrong rendered SQL: [%s] instead of [%s]\n", sql, expected);
124 g_object_unref (stmt);
125 g_object_unref (params);
126 g_free (sql);
127 nfailed ++;
128 goto endtest;
129 }
130 g_free (sql);
131
132 expected = "('@@@@@@@@@@ 15:10:23', '19:09:22')";
133 if (prov && PROV_CLASS (prov)->statement_to_sql)
134 sql = PROV_CLASS (prov)->statement_to_sql (prov, NULL, stmt, params, GDA_STATEMENT_SQL_TIMEZONE_TO_GMT, NULL, &error);
135 else
136 sql = gda_statement_to_sql_extended (stmt, NULL, params, GDA_STATEMENT_SQL_TIMEZONE_TO_GMT, NULL, &error);
137 if (!sql) {
138 g_print ("Failed to render as SQL: %s\n", error && error->message ? error->message : "No detail");
139 g_clear_error (&error);
140 g_object_unref (stmt);
141 g_object_unref (params);
142 nfailed ++;
143 goto endtest;
144 }
145 if (!string_equal_to_template (sql, expected)) {
146 g_print ("Wrong rendered SQL for GMT timezone: [%s] instead of [%s]\n", sql, expected);
147 g_object_unref (stmt);
148 g_object_unref (params);
149 g_free (sql);
150 nfailed ++;
151 goto endtest;
152 }
153 g_free (sql);
154
155 /* SQL not parsed as a valid statement */
156 sql = "AAAA (##ts::timestamp, ##time::time)";
157 stmt = gda_sql_parser_parse_string (parser, sql, NULL, &error);
158 if (!stmt) {
159 g_print ("Failed to parse [%s]: %s\n", sql, error && error->message ? error->message : "No detail");
160 g_clear_error (&error);
161 nfailed ++;
162 goto endtest;
163 }
164
165 g_assert (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_UNKNOWN);
166 if (! gda_statement_get_parameters (stmt, ¶ms, &error)) {
167 g_print ("Failed to obtain parameters: %s\n", error && error->message ? error->message : "No detail");
168 g_clear_error (&error);
169 g_object_unref (stmt);
170 nfailed ++;
171 goto endtest;
172 }
173
174 if (! gda_set_set_holder_value (params, &error, "ts", &ts)) {
175 g_print ("Failed to bind 'ts' parameter: %s\n", error && error->message ? error->message : "No detail");
176 g_clear_error (&error);
177 g_object_unref (stmt);
178 g_object_unref (params);
179 nfailed ++;
180 goto endtest;
181 }
182
183 if (! gda_set_set_holder_value (params, &error, "time", >)) {
184 g_print ("Failed to bind 'time' parameter: %s\n", error && error->message ? error->message : "No detail");
185 g_clear_error (&error);
186 g_object_unref (stmt);
187 g_object_unref (params);
188 nfailed ++;
189 goto endtest;
190 }
191
192 expected = "('@@@@@@@@@@ 17:10:23+2', '16:09:22-3')";
193 if (prov && PROV_CLASS (prov)->statement_to_sql)
194 sql = PROV_CLASS (prov)->statement_to_sql (prov, NULL, stmt, params, 0, NULL, &error);
195 else
196 sql = gda_statement_to_sql_extended (stmt, NULL, params, 0, NULL, &error);
197 if (!sql) {
198 g_print ("Failed to render as SQL: %s\n", error && error->message ? error->message : "No detail");
199 g_clear_error (&error);
200 g_object_unref (stmt);
201 g_object_unref (params);
202 nfailed ++;
203 goto endtest;
204 }
205 if (!string_equal_to_template (sql, expected)) {
206 g_print ("Wrong rendered SQL: [%s] instead of [%s]\n", sql, expected);
207 g_object_unref (stmt);
208 g_object_unref (params);
209 g_free (sql);
210 nfailed ++;
211 goto endtest;
212 }
213 g_free (sql);
214
215 expected = "('@@@@@@@@@@ 15:10:23', '19:09:22')";
216 if (prov && PROV_CLASS (prov)->statement_to_sql)
217 sql = PROV_CLASS (prov)->statement_to_sql (prov, NULL, stmt, params, GDA_STATEMENT_SQL_TIMEZONE_TO_GMT, NULL, &error);
218 else
219 sql = gda_statement_to_sql_extended (stmt, NULL, params, GDA_STATEMENT_SQL_TIMEZONE_TO_GMT, NULL, &error);
220 if (!sql) {
221 g_print ("Failed to render as SQL: %s\n", error && error->message ? error->message : "No detail");
222 g_clear_error (&error);
223 g_object_unref (stmt);
224 g_object_unref (params);
225 nfailed ++;
226 goto endtest;
227 }
228 if (!string_equal_to_template (sql, expected)) {
229 g_print ("Wrong rendered SQL for GMT timezone: [%s] instead of [%s]\n", sql, expected);
230 g_object_unref (stmt);
231 g_object_unref (params);
232 g_free (sql);
233 nfailed ++;
234 goto endtest;
235 }
236 g_free (sql);
237
238 endtest:
239 return nfailed;
240 }
241
242 int
main(int argc,char ** argv)243 main (int argc, char** argv)
244 {
245 gchar *file;
246 GError *error = NULL;
247 GdaDataModel *model;
248 guint i, nrows;
249 guint nfailed = 0;
250 gda_init ();
251
252 /* generic parser */
253 GdaSqlParser *parser;
254 parser = gda_sql_parser_new ();
255 nfailed += do_a_test (NULL, parser);
256 g_object_unref (parser);
257
258 /* test other parsers only if generic one is Ok */
259 if (nfailed == 0) {
260 model = gda_config_list_providers ();
261 nrows = gda_data_model_get_n_rows (model);
262 for (i = 0; i < nrows; i++) {
263 const GValue *cvalue;
264 cvalue = gda_data_model_get_value_at (model, 0, i, NULL);
265 g_assert (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_STRING));
266 if (!g_ascii_strcasecmp (g_value_get_string (cvalue), "Oracle"))
267 continue; /* ignore Oracle for now */
268 g_print ("Testing database provider '%s'\n", g_value_get_string (cvalue));
269
270 GdaServerProvider *prov;
271 prov = gda_config_get_provider (g_value_get_string (cvalue), NULL);
272 g_assert (prov);
273
274 GdaSqlParser *parser;
275 parser = gda_server_provider_create_parser (prov, NULL);
276 if (!parser)
277 parser = gda_sql_parser_new ();
278
279 nfailed += do_a_test (prov, parser);
280 g_object_unref (parser);
281 }
282 g_object_unref (model);
283 }
284
285 if (nfailed == 0) {
286 g_print ("Ok\n");
287 return EXIT_SUCCESS;
288 }
289 else {
290 g_print ("%u failed\n", nfailed);
291 return EXIT_FAILURE;
292 }
293 }
294