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