1 /*
2 * Copyright (C) 2008 - 2011 Vivien Malerba <malerba@gnome-db.org>
3 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 #include <libgda/libgda.h>
20 #include <sql-parser/gda-sql-parser.h>
21 #include <string.h>
22 #include <gmodule.h>
23 #include "common.h"
24
25 static GdaSqlParser *create_parser_for_provider (const gchar *prov_name);
26
27 /*
28 * tests
29 */
30 typedef gboolean (*TestFunc) (GError **);
31 static gboolean test1 (GError **error);
32 static gboolean test2 (GError **error);
33
34 GHashTable *data;
35 TestFunc tests[] = {
36 test1,
37 test2
38 };
39
40 int
main(int argc,char ** argv)41 main (int argc, char** argv)
42 {
43 #if GLIB_CHECK_VERSION(2,36,0)
44 #else
45 g_type_init ();
46 #endif
47 gda_init ();
48
49 guint failures = 0;
50 guint i, ntests = 0;
51
52 data = tests_common_load_data ("stmt.data");
53 for (i = 0; i < sizeof (tests) / sizeof (TestFunc); i++) {
54 GError *error = NULL;
55 if (! tests[i] (&error)) {
56 g_print ("Test %d failed: %s\n", i+1,
57 error && error->message ? error->message : "No detail");
58 if (error)
59 g_error_free (error);
60 failures ++;
61 }
62 ntests ++;
63 }
64
65 g_print ("TESTS COUNT: %d\n", ntests);
66 g_print ("FAILURES: %d\n", failures);
67
68 return failures != 0 ? 1 : 0;
69 }
70
71 typedef struct {
72 gboolean result; /* TRUE if test is supposed to succeed */
73 gchar *id; /* same id as in data file */
74 gchar *sql;
75 } ATest;
76
77 static ATest test1_data[] = {
78 {FALSE, NULL, "SELECT ##p1::gint, 12.3 /* name:p2 */"},
79 {TRUE, "T1.1", "SELECT ##p1::gint, 12.3 /* name:p2 type:gfloat */"},
80 {TRUE, "T1.2", "SELECT ##p1::gint, 12.3 /* name:p1 type:gfloat */"},
81 {TRUE, "T1.3", "SELECT a, b FROM (SELECT version(##vers::date), ##aparam::string)"}
82 };
83
84 /*
85 * get_parameters()
86 */
87 static gboolean
test1(GError ** error)88 test1 (GError **error)
89 {
90 GdaSqlParser *parser;
91 guint i;
92
93 parser = gda_sql_parser_new ();
94
95 for (i = 0; i < sizeof (test1_data) / sizeof (ATest); i++) {
96 ATest *test = &(test1_data[i]);
97 GdaStatement *stmt;
98 GError *lerror = NULL;
99
100 stmt = gda_sql_parser_parse_string (parser, test->sql, NULL, &lerror);
101 if (!stmt) {
102 if (test->result) {
103 if (lerror)
104 g_propagate_error (error, lerror);
105 return FALSE;
106 }
107 }
108 else {
109 GdaSet *set;
110 if (!gda_statement_get_parameters (stmt, &set, &lerror)) {
111 if (test->result) {
112 if (lerror)
113 g_propagate_error (error, lerror);
114 return FALSE;
115 }
116 }
117 else if (set) {
118 if (!tests_common_check_set (data, test->id, set, &lerror)) {
119 if (lerror)
120 g_propagate_error (error, lerror);
121 return FALSE;
122 }
123 g_object_unref (set);
124 }
125 g_object_unref (stmt);
126 }
127
128 if (lerror)
129 g_error_free (lerror);
130 }
131
132 g_object_unref (parser);
133
134 return TRUE;
135 }
136
137 /*
138 * render SQL
139 */
140 static gboolean
test2(GError ** error)141 test2 (GError **error)
142 {
143 GdaSqlParser *parser = NULL;
144 GHashTable *parsers_hash;
145 GdaDataModel *providers_model;
146 gint i;
147
148 /* create parsers */
149 parsers_hash = g_hash_table_new (g_str_hash, g_str_equal);
150 providers_model = gda_config_list_providers ();
151 for (i = 0; i < gda_data_model_get_n_rows (providers_model); i++) {
152 const GValue *pname;
153 pname = gda_data_model_get_value_at (providers_model, 0, i, error);
154 if (!pname)
155 return FALSE;
156 parser = create_parser_for_provider (g_value_get_string (pname));
157 g_hash_table_insert (parsers_hash, g_strdup (g_value_get_string (pname)), parser);
158 g_print ("Created parser for provider %s\n", g_value_get_string (pname));
159 }
160 g_object_unref (providers_model);
161 g_hash_table_insert (parsers_hash, "", gda_sql_parser_new ());
162
163 xmlDocPtr doc;
164 xmlNodePtr root, node;
165 gchar *fname;
166
167 fname = g_build_filename (ROOT_DIR, "tests", "parser", "testdata.xml", NULL);
168 if (! g_file_test (fname, G_FILE_TEST_EXISTS)) {
169 g_set_error (error, TEST_ERROR, TEST_ERROR_GENERIC, "File '%s' does not exist\n", fname);
170 return FALSE;
171 }
172 doc = xmlParseFile (fname);
173 g_free (fname);
174 g_assert (doc);
175 root = xmlDocGetRootElement (doc);
176 g_assert (!strcmp ((gchar*) root->name, "testdata"));
177 for (node = root->children; node; node = node->next) {
178 if (strcmp ((gchar*) node->name, "test"))
179 continue;
180 xmlNodePtr snode;
181 xmlChar *sql = NULL;
182 xmlChar *id;
183 xmlChar *prov_name;
184
185 prov_name = xmlGetProp (node, BAD_CAST "provider");
186 if (prov_name) {
187 parser = g_hash_table_lookup (parsers_hash, (gchar *) prov_name);
188 xmlFree (prov_name);
189 }
190 else
191 parser = g_hash_table_lookup (parsers_hash, "");
192 if (!parser)
193 continue;
194
195 for (snode = node->children; snode && strcmp ((gchar*) snode->name, "sql"); snode = snode->next);
196 if (!snode)
197 continue;
198 sql = xmlNodeGetContent (snode);
199 if (!sql)
200 continue;
201
202 GdaStatement *stmt;
203 GError *lerror = NULL;
204
205 stmt = gda_sql_parser_parse_string (parser, sql, NULL, &lerror);
206 xmlFree (sql);
207 id = xmlGetProp (node, BAD_CAST "id");
208 g_print ("===== TEST %s\n", id);
209
210 if (!stmt) {
211 /* skip that SQL if it can't be parsed */
212 g_error_free (lerror);
213 continue;
214 }
215 else {
216 GdaStatement *stmt2;
217 gchar *rsql;
218 gchar *ser1, *ser2;
219
220 rsql = gda_statement_to_sql_extended (stmt, NULL, NULL, 0, NULL, &lerror);
221 if (!rsql) {
222 g_print ("REM: test '%s' can't be rendered: %s\n", id,
223 lerror && lerror->message ? lerror->message : "No detail");
224 xmlFree (id);
225 continue;
226 }
227
228 /*g_print ("--> rendered SQL: %s\n", rsql);*/
229 stmt2 = gda_sql_parser_parse_string (parser, rsql, NULL, error);
230 if (!stmt2)
231 return FALSE;
232
233 GdaSqlStatement *sqlst;
234
235 g_object_get (G_OBJECT (stmt), "structure", &sqlst, NULL);
236 g_free (sqlst->sql);
237 sqlst->sql = NULL;
238 ser1 = gda_sql_statement_serialize (sqlst);
239 gda_sql_statement_free (sqlst);
240
241 g_object_get (G_OBJECT (stmt2), "structure", &sqlst, NULL);
242 g_free (sqlst->sql);
243 sqlst->sql = NULL;
244 ser2 = gda_sql_statement_serialize (sqlst);
245 gda_sql_statement_free (sqlst);
246
247 if (strcmp (ser1, ser2)) {
248 g_set_error (error, TEST_ERROR, TEST_ERROR_GENERIC,
249 "Statement failed, ID: %s\nSQL: %s\nSER1: %s\nSER2 :%s",
250 id, rsql, ser1, ser2);
251 g_free (ser1);
252 g_free (ser2);
253 return FALSE;
254 }
255
256 g_free (rsql);
257 g_free (ser1);
258 g_free (ser2);
259 g_object_unref (stmt);
260 g_object_unref (stmt2);
261 }
262
263 xmlFree (id);
264
265 if (lerror)
266 g_error_free (lerror);
267 }
268
269 g_object_unref (parser);
270
271 return TRUE;
272 }
273
274 static GdaSqlParser *
create_parser_for_provider(const gchar * prov_name)275 create_parser_for_provider (const gchar *prov_name)
276 {
277 GdaServerProvider *prov;
278 GdaSqlParser *parser;
279 GError *error = NULL;
280
281 prov = gda_config_get_provider (prov_name, &error);
282 if (!prov)
283 g_error ("Could not create provider for '%s': %s\n", prov_name,
284 error && error->message ? error->message : "No detail");
285
286 parser = gda_server_provider_create_parser (prov, NULL);
287 if (!parser)
288 parser = gda_sql_parser_new ();
289
290 return parser;
291 }
292