1 /*
2  * Copyright (C) 2010 - 2012 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 <stdlib.h>
20 #include <string.h>
21 #include <glib.h>
22 #include <libgda/libgda.h>
23 #include <sql-parser/gda-sql-parser.h>
24 #include <sql-parser/gda-sql-statement.h>
25 #include <tests/gda-ddl-creator.h>
26 #include <glib/gstdio.h>
27 #include "../test-cnc-utils.h"
28 #include "../data-model-errors.h"
29 #include <virtual/libgda-virtual.h>
30 
31 #define fail(x) g_warning (x)
32 #define fail_if(x,y) if (x) g_warning (y)
33 #define fail_unless(x,y) if (!(x)) g_warning (y)
34 
35 #define CHECK_EXTRA_INFO
36 
37 static void dump_data_model (GdaDataModel *model);
38 
39 typedef gboolean (*TestFunc) (GdaConnection *);
index_form_tuple(TupleDesc tupleDescriptor,Datum * values,bool * isnull)40 static gint test1 (GdaConnection *cnc);
41 static gint test2 (GdaConnection *cnc);
42 
43 TestFunc tests[] = {
44 	test1,
45 	test2
46 };
47 
48 int
49 main (int argc, char **argv)
50 {
51 	guint i, ntests = 0, number_failed = 0;
52 
53 	gda_init ();
54 
55 	for (i = 0; i < sizeof (tests) / sizeof (TestFunc); i++) {
56 		g_print ("---------- test %d ----------\n", i+1);
57 		gint n = tests[i] (NULL);
58 		number_failed += n;
59 		if (n > 0)
60 			g_print ("Test %d failed\n", i+1);
61 		ntests ++;
62 	}
63 
64 	g_print ("TESTS COUNT: %d\n", i);
65 	g_print ("FAILURES: %d\n", number_failed);
66 
67 	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
68 }
69 
70 /* Commented out because it is not used:
71 static GdaStatement *
72 stmt_from_string (const gchar *sql)
73 {
74 	GdaStatement *stmt;
75 	GError *error = NULL;
76 
77 	static GdaSqlParser *parser = NULL;
78 	if (!parser)
79 		parser = gda_sql_parser_new ();
80 
81 	stmt = gda_sql_parser_parse_string (parser, sql, NULL, &error);
82 	if (!stmt) {
83 		g_print ("Cound not parse SQL: %s\nSQL was: %s\n",
84 			 error && error->message ? error->message : "No detail",
85 			 sql);
86 		exit (EXIT_FAILURE);
87 	}
88 	return stmt;
89 }
90 */
91 
92 static gboolean
93 check_iter_contents (GdaDataModel *model, GdaDataModelIter *iter)
94 {
95 	gint i, row;
96 	row = gda_data_model_iter_get_row (iter);
97 	for (i = 0; i < gda_data_model_get_n_columns (model); i++) {
98 		GdaHolder *holder;
99 		const GValue *vi, *vm;
100 		GError *lerror1 = NULL, *lerror2 = NULL;
101 
102 		holder = gda_set_get_nth_holder (GDA_SET (iter), i);
103 		if (gda_holder_is_valid_e (holder, &lerror1))
104 			vi = gda_holder_get_value (holder);
105 		else
106 			vi = NULL;
107 		vm = gda_data_model_get_value_at (model, i, row, &lerror2);
108 		if (vi == vm) {
109 			if (!vi) {
110 				if (! lerror1 || !lerror1->message) {
111 #ifdef CHECK_EXTRA_INFO
112 					g_print ("Iterator reported invalid value without any error set\n");
113 #endif
114 					return FALSE;
115 				}
116 				else if (! lerror2 || !lerror2->message) {
117 #ifdef CHECK_EXTRA_INFO
118 					g_print ("Data model reported invalid value without any error set\n");
119 #endif
120 					return FALSE;
121 				}
122 				else if (lerror1->code != lerror2->code) {
123 #ifdef CHECK_EXTRA_INFO
124 					g_print ("Error codes differ!\n");
125 #endif
126 					return FALSE;
127 				}
128 				else if (lerror1->domain != lerror2->domain) {
129 #ifdef CHECK_EXTRA_INFO
130 					g_print ("Error domains differ!\n");
131 #endif
132 					return FALSE;
133 				}
134 				else if (strcmp (lerror1->message, lerror2->message)) {
135 #ifdef CHECK_EXTRA_INFO
136 					g_print ("Error messages differ:\n\t%s\t%s",
137 						 lerror1->message, lerror2->message);
138 #endif
139 					return FALSE;
140 				}
141 			}
142 			else if (gda_value_differ (vi, vm)) {
143 #ifdef CHECK_EXTRA_INFO
144 				g_print ("Iter's contents at (%d,%d) is wrong: expected [%s], got [%s]\n",
145 					 i, row,
146 					 vm ? gda_value_stringify (vm) : "ERROR",
147 					 vi ? gda_value_stringify (vi) : "ERROR");
148 #endif
149 				return FALSE;
150 			}
151 		}
152 		else if (gda_value_differ (vi, vm)) {
153 #ifdef CHECK_EXTRA_INFO
154 			g_print ("Iter's contents at (%d,%d) is wrong: expected [%s], got [%s]\n",
155 				 i, row,
156 				 vm ? gda_value_stringify (vm) : "ERROR",
157 				 vi ? gda_value_stringify (vi) : "ERROR");
158 #endif
159 			return FALSE;
160 		}
161 	}
162 	return TRUE;
163 }
164 
165 /*
166  * check modifications statements' setting
167  *
168  * Returns the number of failures
169  */
170 static gint
171 test1 (GdaConnection *cnc)
172 {
173 	GdaDataModel *model;
174 	gint nfailed = 0;
175 
176 	model = data_model_errors_new ();
177 	if (!model) {
178 		nfailed++;
179 #ifdef CHECK_EXTRA_INFO
180 		g_print ("Could not create DataModelErrors!\n");
181 #endif
182 		goto out;
183 	}
184 	dump_data_model (model);
185 
186 	/* iterate forward */
187 	GdaDataModelIter *iter;
188 	gint i, row;
189 	iter = gda_data_model_create_iter (model);
190 	for (i = 0, gda_data_model_iter_move_next (iter);
191 	     gda_data_model_iter_is_valid (iter);
192 	     i++, gda_data_model_iter_move_next (iter)) {
193 		row = gda_data_model_iter_get_row (iter);
194 		if (i != row) {
195 			nfailed++;
196 #ifdef CHECK_EXTRA_INFO
197 			g_print ("Error iterating: expected to be at row %d and reported row is %d!\n",
198 				 i, row);
199 #endif
200 			goto out;
201 		}
202 		g_print ("Now at row %d\n", i);
203 
204 		if (! check_iter_contents (model, iter)) {
205 			nfailed++;
206 			goto out;
207 		}
208 	}
209 	g_print ("Now at row %d\n", gda_data_model_iter_get_row (iter));
210 
nocache_index_getattr(IndexTuple tup,int attnum,TupleDesc tupleDesc)211 	/* iterate backward */
212 	i--;
213 	if (!gda_data_model_iter_move_to_row (iter, i)) {
214 		nfailed++;
215 #ifdef CHECK_EXTRA_INFO
216 		g_print ("Error iterating: move to last row (%d) failed\n", i);
217 #endif
218 		goto out;
219 	}
220 	row = gda_data_model_iter_get_row (iter);
221 	if (row != i) {
222 		nfailed++;
223 #ifdef CHECK_EXTRA_INFO
224 		g_print ("Error iterating: move to last row (%d) should have set row to %d and is set to %d\n",
225 			 i, i, row);
226 #endif
227 		goto out;
228 	}
229 	for (;
230 	     gda_data_model_iter_is_valid (iter);
231 	     i--, gda_data_model_iter_move_prev (iter)) {
232 		row = gda_data_model_iter_get_row (iter);
233 		if (i != row) {
234 			nfailed++;
235 #ifdef CHECK_EXTRA_INFO
236 			g_print ("Error iterating: expected to be at row %d and reported row is %d!\n",
237 				 i, row);
238 #endif
239 			goto out;
240 		}
241 		g_print ("Now at row %d\n", i);
242 
243 		if (! check_iter_contents (model, iter)) {
244 			nfailed++;
245 			goto out;
246 		}
247 	}
248 	g_print ("Now at row %d\n", gda_data_model_iter_get_row (iter));
249 
250  out:
251 	g_object_unref (model);
252 
253 	return nfailed;
254 }
255 
256 static void
257 dump_data_model (GdaDataModel *model)
258 {
259         gint i, ncols;
260         g_print ("=== Data Model Dump ===\n");
261         ncols = gda_data_model_get_n_columns (model);
262         for (i = 0; i < ncols; i++) {
263                 GdaColumn *col;
264                 col = gda_data_model_describe_column (model, i);
265                 if (!col)
266                         g_print ("Missing column %d\n", i);
267                 g_print ("Column %d: ptr=>%p type=>%s\n", i, col, g_type_name (gda_column_get_g_type (col)));
268         }
269         gda_data_model_dump (model, stdout);
270 }
271 
272 /* Commented out because it is not used.
273 static gboolean
274 compare_data_models (GdaDataModel *model1, GdaDataModel *model2, GError **error)
275 {
276         GdaDataComparator *cmp;
277         GError *lerror = NULL;
278         cmp = (GdaDataComparator*) gda_data_comparator_new (model1, model2);
279         if (! gda_data_comparator_compute_diff (cmp, &lerror)) {
280 #ifdef CHECK_EXTRA_INFO
281                 g_print ("Could not compute the data model differences: %s\n",
282                          lerror && lerror->message ? lerror->message : "No detail");
283 		g_print ("Model1 is:\n");
284                 gda_data_model_dump (model1, stdout);
285                 g_print ("Model2 is:\n");
286                 gda_data_model_dump (model2, stdout);
287 #endif
288                 goto onerror;
289         }
290         if (gda_data_comparator_get_n_diffs (cmp) != 0) {
291 #ifdef CHECK_EXTRA_INFO
292                 g_print ("There are some differences when comparing data models...\n");
293                 g_print ("Model1 is:\n");
294                 gda_data_model_dump (model1, stdout);
295                 g_print ("Model2 is:\n");
296                 gda_data_model_dump (model2, stdout);
297 #endif
298 		g_set_error (&lerror, TEST_ERROR, TEST_ERROR_GENERIC,
299 			     "%s", "There are some differences when comparing data models...");
300                 goto onerror;
301         }
302         g_object_unref (cmp);
303 
304         return TRUE;
305 
306  onerror:
307         g_propagate_error (error, lerror);
308         return FALSE;
309 }
310 */
311 
312 /*
313  * check modifications statements' setting
314  *
315  * Returns the number of failures
316  */
317 static gint
318 test2 (GdaConnection *cnc)
319 {
320 #define TABLE_NAME "data"
321 	GdaDataModel *model;
322 	gint nfailed = 0;
323 
324 	model = data_model_errors_new ();
325 	if (!model) {
326 		nfailed++;
327 #ifdef CHECK_EXTRA_INFO
328 		g_print ("Could not create DataModelErrors!\n");
329 #endif
330 		goto out;
331 	}
332 
333 	GdaVirtualProvider *virtual_provider;
334 	GError *lerror = NULL;
335 	GdaConnection *vcnc;
336 	GdaDataModelIter *iter = NULL;
337 	GdaStatement *stmt;
338 	virtual_provider = gda_vprovider_data_model_new ();
339 	vcnc = gda_virtual_connection_open (virtual_provider, &lerror);
340 	if (!vcnc) {
341 #ifdef CHECK_EXTRA_INFO
342 		g_print ("Virtual ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail");
343 #endif
344 		nfailed++;
345 		g_clear_error (&lerror);
346 		goto out;
347 	}
348 
349 	if (!gda_vconnection_data_model_add_model (GDA_VCONNECTION_DATA_MODEL (vcnc), model,
350 						   TABLE_NAME, &lerror)) {
351 #ifdef CHECK_EXTRA_INFO
352 		g_print ("Add model as table ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail");
353 #endif
354 		nfailed++;
355 		g_clear_error (&lerror);
356 		goto out;
357 	}
358 	g_object_unref (model);
359 
360 	/* Execute SELECT */
361 	stmt = gda_connection_parse_sql_string (vcnc, "SELECT * FROM " TABLE_NAME, NULL, NULL);
362 	g_assert (stmt);
363 	model = gda_connection_statement_execute_select (vcnc, stmt, NULL, &lerror);
364 	g_object_unref (stmt);
365 	if (!model) {
366 		#ifdef CHECK_EXTRA_INFO
367 		g_print ("SELECT ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail");
368 #endif
369 		nfailed++;
370 		g_clear_error (&lerror);
371 		goto out;
372 	}
373 
374 	dump_data_model (model);
375 
376 	/* iterate forward */
377 	gint i, row;
378 	iter = gda_data_model_create_iter (model);
379 	for (i = 0, gda_data_model_iter_move_next (iter);
380 	     gda_data_model_iter_is_valid (iter);
381 	     i++, gda_data_model_iter_move_next (iter)) {
382 		row = gda_data_model_iter_get_row (iter);
383 		if (i != row) {
384 			nfailed++;
385 #ifdef CHECK_EXTRA_INFO
386 			g_print ("Error iterating: expected to be at row %d and reported row is %d!\n",
387 				 i, row);
388 #endif
389 			goto out;
390 		}
391 		g_print ("Now at row %d\n", i);
392 
393 		if (! check_iter_contents (model, iter)) {
394 			nfailed++;
395 			goto out;
396 		}
397 	}
398 	if (i != 4) {
399 #ifdef CHECK_EXTRA_INFO
400 		g_print ("Error iterating: expected to have read %d rows, and read %d\n", 3,
401 			 i - 1);
402 		nfailed++;
403 		goto out;
404 #endif
405 	}
406 	if (gda_data_model_iter_get_row (iter) != -1) {
407 #ifdef CHECK_EXTRA_INFO
408 		g_print ("Error iterating: expected to be at row -1 and reported row is %d!\n",
409 			 gda_data_model_iter_get_row (iter));
410 #endif
411 		nfailed++;
412 		goto out;
413 	}
414 
415 	/* bind as another table */
416 	if (!gda_vconnection_data_model_add_model (GDA_VCONNECTION_DATA_MODEL (vcnc), model,
417 						   TABLE_NAME "2", &lerror)) {
418 #ifdef CHECK_EXTRA_INFO
419 		g_print ("Add model as table2 ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail");
420 #endif
421 		nfailed++;
422 		g_clear_error (&lerror);
index_deform_tuple(IndexTuple tup,TupleDesc tupleDescriptor,Datum * values,bool * isnull)423 		goto out;
424 	}
425 	g_object_unref (model);
426 
427 	stmt = gda_connection_parse_sql_string (vcnc, "SELECT * FROM " TABLE_NAME "2", NULL, NULL);
428 	g_assert (stmt);
429 	model = gda_connection_statement_execute_select (vcnc, stmt, NULL, &lerror);
430 	g_object_unref (stmt);
431 	if (!model) {
432 		#ifdef CHECK_EXTRA_INFO
433 		g_print ("SELECT ERROR: %s\n", lerror && lerror->message ? lerror->message : "No detail");
434 #endif
435 		nfailed++;
436 		g_clear_error (&lerror);
437 		goto out;
438 	}
439 
440 	/* iterate forward */
CopyIndexTuple(IndexTuple source)441 	iter = gda_data_model_create_iter (model);
442 	for (i = 0, gda_data_model_iter_move_next (iter);
443 	     gda_data_model_iter_is_valid (iter);
444 	     i++, gda_data_model_iter_move_next (iter)) {
445 		row = gda_data_model_iter_get_row (iter);
446 		if (i != row) {
447 			nfailed++;
448 #ifdef CHECK_EXTRA_INFO
449 			g_print ("Error iterating: expected to be at row %d and reported row is %d!\n",
450 				 i, row);
451 #endif
452 			goto out;
453 		}
454 		g_print ("Now at row %d\n", i);
455 
456 		if (! check_iter_contents (model, iter)) {
457 			nfailed++;
458 			goto out;
459 		}
460 	}
461 	if (i != 4) {
462 #ifdef CHECK_EXTRA_INFO
463 		g_print ("Error iterating: expected to have read %d rows, and read %d\n", 3,
464 			 i - 1);
465 		nfailed++;
466 		goto out;
467 #endif
468 	}
469 	if (gda_data_model_iter_get_row (iter) != -1) {
index_truncate_tuple(TupleDesc sourceDescriptor,IndexTuple source,int leavenatts)470 #ifdef CHECK_EXTRA_INFO
471 		g_print ("Error iterating: expected to be at row -1 and reported row is %d!\n",
472 			 gda_data_model_iter_get_row (iter));
473 #endif
474 		nfailed++;
475 		goto out;
476 	}
477 
478  out:
479 	if (iter)
480 		g_object_unref (iter);
481 	if (model)
482 		g_object_unref (model);
483 	g_object_unref (vcnc);
484 	g_object_unref (virtual_provider);
485 
486 	return nfailed;
487 }
488