1 /*
2  * Copyright (C) 2007 - 2013 Vivien Malerba <malerba@gnome-db.org>
3  * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com>
4  * Copyright (C) 2012 Daniel Espinosa <despinosa@src.gnome.org>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 #include <stdlib.h>
21 #include <string.h>
22 #include "prov-test-common.h"
23 #include "prov-test-util.h"
24 #include <sql-parser/gda-sql-parser.h>
25 #include <sql-parser/gda-sql-statement.h>
26 #include "../test-cnc-utils.h"
27 #include "../test-errors.h"
28 
29 
30 #define CHECK_EXTRA_INFO
31 /*#undef CHECK_EXTRA_INFO*/
32 
33 GdaProviderInfo *pinfo;
34 GdaConnection   *cnc;
35 gboolean         params_provided;
36 gboolean         fork_tests = TRUE;
37 
38 /*
39  *
40  * SETUP
41  *
42  */
43 
44 int
prov_test_common_setup(void)45 prov_test_common_setup (void)
46 {
47 	int number_failed = 0;
48 	GError *error = NULL;
49 
50 #ifdef CHECK_EXTRA_INFO
51 	g_print ("\n============= %s() =============\n", __FUNCTION__);
52 #endif
53 
54 	cnc = test_cnc_setup_connection (pinfo->id, "testcheckdb", &error);
55 	if (!cnc) {
56 		if (error) {
57 			if (error->domain != TEST_ERROR) {
58 				gchar *str = g_strdup_printf ("Could not setup connection: %s",
59 							      error->message ? error->message : "No detail");
60 				g_warning ("%s", str);
61 				g_free (str);
62 				number_failed++;
63 			}
64 			else
65 				g_print ("==> %s\n", error->message ? error->message : "No detail");
66 			g_error_free (error);
67 		}
68 	}
69 	else {
70 		gchar *file;
71 		file = g_build_filename (CHECK_SQL_FILES, "tests", "providers", "prov_dbstruct.xml", NULL);
72 		if (!test_cnc_setup_db_structure (cnc, file, &error)) {
73 			gchar *str = g_strdup_printf ("Could not setup database structure: %s",
74 						      error && error->message ? error->message : "No detail");
75 			g_warning ("%s", str);
76 			g_free (str);
77 			if (error)
78 				g_error_free (error);
79 			number_failed++;
80 		}
81 		g_free (file);
82 	}
83 	return number_failed;
84 }
85 
86 GdaConnection *
prov_test_common_create_extra_connection(void)87 prov_test_common_create_extra_connection (void)
88 {
89 	GdaConnection *cnc;
90 	GError *lerror = NULL;
91 	cnc = test_cnc_open_connection (pinfo->id, "testcheckdb", &lerror);
92 	if (!cnc) {
93 		g_print ("Error setting up connection: %s\n", lerror && lerror->message ? lerror->message : "No detail");
94 		g_clear_error (&lerror);
95 	}
96 	return cnc;
97 }
98 
99 
100 /*
101  *
102  * CLEAN
103  *
104  */
105 int
prov_test_common_clean(void)106 prov_test_common_clean (void)
107 {
108 	int number_failed = 0;
109 
110 #ifdef CHECK_EXTRA_INFO
111 	g_print ("\n============= %s() =============\n", __FUNCTION__);
112 #endif
113 
114 	if (!test_cnc_clean_connection (cnc, NULL))
115 		number_failed++;
116 
117 	return number_failed;
118 }
119 
120 /*
121  *
122  * CHECK_META
123  *
124  */
125 
126 int
prov_test_common_check_meta(void)127 prov_test_common_check_meta (void)
128 {
129 	int number_failed = 0;
130 	GSList *tables = NULL, *list;
131 	gboolean dump_ok = TRUE;
132 	GdaMetaStore *store;
133 	gchar **dump1 = NULL;
134 	GError *gerror = NULL;
135 	gint ntables, i;
136 
137 #ifdef CHECK_EXTRA_INFO
138 	g_print ("\n============= %s() =============\n", __FUNCTION__);
139 #endif
140 
141 	/* update meta store */
142 #ifdef CHECK_EXTRA_INFO
143 	g_print ("Updating the complete meta store...\n");
144 #endif
145 	if (! gda_connection_update_meta_store (cnc, NULL, &gerror)) {
146 #ifdef CHECK_EXTRA_INFO
147 		g_warning ("Can't update meta store (1): %s\n",
148 			   gerror && gerror->message ? gerror->message : "???");
149 #endif
150 		g_error_free (gerror);
151 		number_failed++;
152 		goto theend;
153 	}
154 
155 	/* dump all tables */
156 	store = gda_connection_get_meta_store (cnc);
157 	tables = gda_meta_store_schema_get_all_tables (store);
158 	ntables = g_slist_length (tables);
159 	dump1 = g_new0 (gchar *, ntables + 1);
160 
161 	for (i = 0, list = tables; list; i++, list = list->next) {
162 		GdaDataModel *model;
163 		gchar *tmp;
164 
165 		tmp = g_strdup_printf ("SELECT * FROM %s", (gchar*) list->data);
166 		model = gda_meta_store_extract (store, tmp, &gerror, NULL);
167 		g_free (tmp);
168 		if (!model) {
169 #ifdef CHECK_EXTRA_INFO
170 			g_warning ("Can't execute SELECT statement: %s\n",
171 				   gerror && gerror->message ? gerror->message : "???");
172 #endif
173 			g_error_free (gerror);
174 			dump_ok = FALSE;
175 			break;
176 		}
177 
178 		dump1 [i] = gda_data_model_export_to_string (model, GDA_DATA_MODEL_IO_DATA_ARRAY_XML,
179 							     NULL, 0, NULL, 0, NULL);
180 		g_object_unref (model);
181 		if (!dump1 [i]) {
182 #ifdef CHECK_EXTRA_INFO
183 			g_warning ("Can't export data model\n");
184 #endif
185 			dump_ok = FALSE;
186 			break;
187 		}
188 	}
189 
190 	if (!dump_ok) {
191 		number_failed++;
192 		goto theend;
193 	}
194 
195 	/* update meta store */
196 #ifdef CHECK_EXTRA_INFO
197 	g_print ("Updating the complete meta store...\n");
198 #endif
199 	if (! gda_connection_update_meta_store (cnc, NULL, &gerror)) {
200 #ifdef CHECK_EXTRA_INFO
201 		g_warning ("Can't update meta store (2): %s\n",
202 			   gerror && gerror->message ? gerror->message : "???");
203 #endif
204 		g_error_free (gerror);
205 		number_failed++;
206 		goto theend;
207 	}
208 	/* Update meta store by context */
209 	GdaMetaContext *ctx;
210 	ctx = gda_meta_context_new ();
211 	gchar *meta_tables[] = {"_tables", "_attributes", "_information_schema_catalog_name",
212 						"_schemata", "_builtin_data_types", "_udt", "_udt_columns",
213 						"_enums", "_element_types", "_domains", "_views", "_collations",
214 						"_character_sets", "_routines", "_triggers", "_columns",
215 						"_table_constraints", "_referential_constraints",
216 						"_key_column_usage", "__declared_fk", "_check_column_usage",
217 						"_view_column_usage", "_domain_constraints", "_parameters",
218 						"_routine_columns", "_table_indexes", "_index_column_usage",
219 						NULL};
220 	for (i = 0; meta_tables[i]; i++) {
221 		gda_meta_context_set_table (ctx, meta_tables[i]);
222 #ifdef CHECK_EXTRA_INFO
223 		g_print ("Updating the meta store for table '%s'\n", meta_tables[i]);
224 #endif
225 		if (! gda_connection_update_meta_store (cnc, ctx, &gerror)) {
226 #ifdef CHECK_EXTRA_INFO
227 			g_warning ("Can't update meta store (on table %s): %s\n",
228 				   meta_tables[i], gerror && gerror->message ? gerror->message : "???");
229 #endif
230 			g_error_free (gerror);
231 			number_failed++;
232 			goto theend;
233 		}
234 	}
235 	gda_meta_context_free (ctx);
236 
237 	for (i = 0, list = tables; list; i++, list = list->next) {
238 		GdaDataModel *model;
239 		gchar *tmp;
240 		GError *gerror = NULL;
241 
242 		tmp = g_strdup_printf ("SELECT * FROM %s", (gchar*) list->data);
243 		model = gda_meta_store_extract (store, tmp, &gerror, NULL);
244 		g_free (tmp);
245 		if (!model) {
246 #ifdef CHECK_EXTRA_INFO
247 			g_warning ("Can't execute SELECT statement: %s\n",
248 				   gerror && gerror->message ? gerror->message : "???");
249 #endif
250 			g_error_free (gerror);
251 			number_failed++;
252 			continue;
253 		}
254 
255 		tmp = gda_data_model_export_to_string (model, GDA_DATA_MODEL_IO_DATA_ARRAY_XML,
256 						       NULL, 0, NULL, 0, NULL);
257 		g_object_unref (model);
258 		if (!tmp) {
259 #ifdef CHECK_EXTRA_INFO
260 			g_warning ("Can't export data model\n");
261 #endif
262 			number_failed++;
263 			continue;
264 		}
265 		if (strcmp (tmp, dump1[i])) {
266 #ifdef CHECK_EXTRA_INFO
267 			g_warning ("Meta data has changed after update for table %s\n", (gchar*) list->data);
268 			g_print ("===\n%s\n===\n%s\n===\n", tmp, dump1[i]);
269 #endif
270 			number_failed++;
271 			g_free (tmp);
272 			continue;
273 		}
274 #ifdef CHECK_EXTRA_INFO
275 		else
276 			g_print ("Meta for table '%s' Ok\n", (gchar*) list->data);
277 #endif
278 		g_free (tmp);
279 	}
280 
281  theend:
282 	/* remove tmp files */
283 	if (dump1)
284 		g_strfreev (dump1);
285 	g_slist_free (tables);
286 
287 	return number_failed;
288 }
289 
290 /*
291  *
292  * CHECK_META_IDENTIFIERS
293  *
294  */
295 
296 int
prov_test_common_check_meta_identifiers(gboolean case_sensitive,gboolean update_all)297 prov_test_common_check_meta_identifiers (gboolean case_sensitive, gboolean update_all)
298 {
299 	GdaMetaStore *store;
300 	GError *error = NULL;
301 	gchar *table_name = "CapitalTest";
302 	gchar *field_name = "AName";
303 	GdaServerProvider* provider = gda_connection_get_provider (cnc);
304 	GdaServerOperation* operation;
305 	GdaDataModel* data;
306 	GValue *value, *value2;
307 	const GValue *cvalue;
308 	GdaMetaContext mcontext = {"_tables", 1, NULL, NULL};
309 	GdaConnectionOptions options;
310 
311 #ifdef CHECK_EXTRA_INFO
312 	g_print ("\n============= %s(%s, %s) =============\n", __FUNCTION__,
313 		 case_sensitive ? "case sensitive" : "case NOT sensitive",
314 		 update_all ? "complete meta data update" : "partial meta data update");
315 #endif
316 
317 	g_object_get (G_OBJECT (cnc), "options", &options, NULL);
318 	if (case_sensitive)
319 		g_object_set (G_OBJECT (cnc), "options",
320 			      options | GDA_CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE, NULL);
321 
322 
323 
324 	/* DROP table */
325         operation = gda_server_provider_create_operation (provider, cnc,
326 							  GDA_SERVER_OPERATION_DROP_TABLE, NULL, &error);
327         g_assert (operation);
328         gda_server_operation_set_value_at_path (operation, table_name, "/TABLE_DESC_P/TABLE_NAME", NULL);
329         gda_server_provider_perform_operation (provider, cnc, operation, NULL);
330 	g_object_unref (operation);
331 
332 	/* CREATE table */
333 	operation = gda_server_provider_create_operation (provider, cnc,
334 							  GDA_SERVER_OPERATION_CREATE_TABLE, NULL, &error);
335         g_assert (operation);
336         gda_server_operation_set_value_at (operation, table_name, NULL, "/TABLE_DEF_P/TABLE_NAME");
337         gda_server_operation_set_value_at (operation, "id", NULL, "/FIELDS_A/@COLUMN_NAME/0");
338         gda_server_operation_set_value_at (operation, "int", NULL, "/FIELDS_A/@COLUMN_TYPE/0");
339         gda_server_operation_set_value_at (operation, "TRUE", NULL, "/FIELDS_A/@COLUMN_PKEY/0");
340         if (! gda_server_provider_perform_operation (provider, cnc, operation, &error)) {
341 #ifdef CHECK_EXTRA_INFO
342                 g_warning ("perform_operation(CREATE_TABLE) failed: %s\n", error && error->message ?
343 			   error->message : "???");
344 #endif
345                 g_clear_error (&error);
346 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
347                 return 1;
348         }
349 
350 
351 	/* update meta store */
352 #ifdef CHECK_EXTRA_INFO
353 	g_print ("Updating the complete meta store...\n");
354 #endif
355 	if (!update_all) {
356 		g_value_take_string ((value = gda_value_new (G_TYPE_STRING)),
357 				     gda_meta_store_sql_identifier_quote (table_name, cnc));
358 		mcontext.column_names = g_new (gchar *, 1);
359 		mcontext.column_names [0] = "table_name";
360 		mcontext.column_values = g_new (GValue *, 1);
361 		mcontext.column_values [0] = value;
362 	}
363 	store = gda_meta_store_new (NULL); /* create an in memory meta store */
364 	g_object_set (G_OBJECT (cnc), "meta-store", store, NULL);
365 	g_object_unref (store);
366 	if (! gda_connection_update_meta_store (cnc, update_all ? NULL : &mcontext, &error)) {
367 #ifdef CHECK_EXTRA_INFO
368 		g_warning ("Can't FULL update meta store: %s\n",
369 			   error && error->message ? error->message : "???");
370 #endif
371 		g_clear_error (&error);
372 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
373 		return 1;
374 	}
375 
376 	/* check table */
377 #ifdef CHECK_EXTRA_INFO
378 	g_print ("Checking fetched meta data...\n");
379 #endif
380 	g_value_take_string ((value = gda_value_new (G_TYPE_STRING)),
381 			     gda_meta_store_sql_identifier_quote (table_name, cnc));
382 	data = gda_connection_get_meta_store_data (cnc, GDA_CONNECTION_META_TABLES, &error, 1,
383 						   "name", value);
384 	g_assert (data);
385 	if (gda_data_model_get_n_rows (data) != 1) {
386 #ifdef CHECK_EXTRA_INFO
387                 g_warning ("gda_connection_get_meta_store_data(): wrong number of rows : %d\n",
388 			   gda_data_model_get_n_rows (data));
389 #endif
390 		gda_value_free (value);
391 		g_object_unref (data);
392 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
393 		return 1;
394 	}
395 	cvalue = gda_data_model_get_value_at (data, 0, 0, &error);
396 	g_assert (cvalue);
397 	if (gda_value_compare (value, cvalue)) {
398 #ifdef CHECK_EXTRA_INFO
399                 g_warning ("gda_connection_get_meta_store_data(): expected %s and got %s\n",
400 			   gda_value_stringify (cvalue), gda_value_stringify (value));
401 #endif
402 		gda_value_free (value);
403 		g_object_unref (data);
404 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
405 		return 1;
406 	}
407 	g_object_unref (data);
408 
409 	/* check fields of table */
410 	data = gda_connection_get_meta_store_data (cnc, GDA_CONNECTION_META_FIELDS, &error, 1,
411 						   "name", value);
412 	g_assert (data);
413 	if (gda_data_model_get_n_rows (data) != 1) {
414 #ifdef CHECK_EXTRA_INFO
415                 g_warning ("gda_connection_get_meta_store_data(): wrong number of rows : %d\n",
416 			   gda_data_model_get_n_rows (data));
417 #endif
418 		gda_value_free (value);
419 		g_object_unref (data);
420 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
421 		return 1;
422 	}
423 	cvalue = gda_data_model_get_value_at (data, 0, 0, &error);
424 	g_assert (cvalue);
425 	g_value_set_string ((value2 = gda_value_new (G_TYPE_STRING)), "id");
426 	if (gda_value_compare (value2, cvalue)) {
427 #ifdef CHECK_EXTRA_INFO
428                 g_warning ("gda_connection_get_meta_store_data(): expected %s and got %s\n",
429 			   gda_value_stringify (cvalue), gda_value_stringify (value));
430 #endif
431 		gda_value_free (value);
432 		g_object_unref (data);
433 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
434 		return 1;
435 	}
436 	gda_value_free (value);
437 	gda_value_free (value2);
438 	g_object_unref (data);
439 
440 	/* ALTER table to add a column */
441 	operation = gda_server_provider_create_operation (provider, cnc,
442 							  GDA_SERVER_OPERATION_ADD_COLUMN, NULL, &error);
443         g_assert (operation);
444         gda_server_operation_set_value_at_path (operation, table_name, "/COLUMN_DEF_P/TABLE_NAME", NULL);
445         gda_server_operation_set_value_at (operation, field_name, NULL, "/COLUMN_DEF_P/COLUMN_NAME", NULL);
446         gda_server_operation_set_value_at (operation, "int", NULL, "/COLUMN_DEF_P/COLUMN_TYPE", NULL);
447         if (! gda_server_provider_perform_operation (provider, cnc, operation, &error)) {
448 #ifdef CHECK_EXTRA_INFO
449                 g_warning ("perform_operation(ADD_COLUMN) failed: %s\n", error && error->message ?
450 			   error->message : "???");
451 #endif
452                 g_clear_error (&error);
453 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
454                 return 1;
455         }
456 
457 	/* update meta store */
458 #ifdef CHECK_EXTRA_INFO
459 	g_print ("Updating the complete meta store...\n");
460 #endif
461 	if (! gda_connection_update_meta_store (cnc, update_all ? NULL : &mcontext, &error)) {
462 #ifdef CHECK_EXTRA_INFO
463 		g_warning ("Can't FULL update meta store: %s\n",
464 			   error && error->message ? error->message : "???");
465 #endif
466 		g_clear_error (&error);
467 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
468 		return 1;
469 	}
470 
471 	/* check table */
472 #ifdef CHECK_EXTRA_INFO
473 	g_print ("Checking fetched meta data...\n");
474 #endif
475 	g_value_take_string ((value = gda_value_new (G_TYPE_STRING)),
476 			     gda_meta_store_sql_identifier_quote (table_name, cnc));
477 	data = gda_connection_get_meta_store_data (cnc, GDA_CONNECTION_META_TABLES, &error, 1,
478 						   "name", value);
479 	g_assert (data);
480 	if (gda_data_model_get_n_rows (data) != 1) {
481 #ifdef CHECK_EXTRA_INFO
482                 g_warning ("gda_connection_get_meta_store_data(): wrong number of rows : %d\n",
483 			   gda_data_model_get_n_rows (data));
484 #endif
485 		gda_value_free (value);
486 		g_object_unref (data);
487 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
488 		return 1;
489 	}
490 	cvalue = gda_data_model_get_value_at (data, 0, 0, &error);
491 	g_assert (cvalue);
492 	if (gda_value_compare (value, cvalue)) {
493 #ifdef CHECK_EXTRA_INFO
494                 g_warning ("gda_connection_get_meta_store_data(): expected %s and got %s\n",
495 			   gda_value_stringify (cvalue), gda_value_stringify (value));
496 #endif
497 		gda_value_free (value);
498 		g_object_unref (data);
499 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
500 		return 1;
501 	}
502 	g_object_unref (data);
503 
504 	/* check fields of table */
505 	g_value_take_string ((value2 = gda_value_new (G_TYPE_STRING)),
506 			     gda_meta_store_sql_identifier_quote (field_name, cnc));
507 	data = gda_connection_get_meta_store_data (cnc, GDA_CONNECTION_META_FIELDS, &error, 2,
508 						   "name", value, "field_name", value2);
509 	g_assert (data);
510 	if (gda_data_model_get_n_rows (data) != 1) {
511 #ifdef CHECK_EXTRA_INFO
512                 g_warning ("gda_connection_get_meta_store_data(): wrong number of rows : %d\n",
513 			   gda_data_model_get_n_rows (data));
514 #endif
515 		gda_value_free (value);
516 		g_object_unref (data);
517 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
518 		return 1;
519 	}
520 	cvalue = gda_data_model_get_value_at (data, 0, 0, &error);
521 	g_assert (cvalue);
522 	if (gda_value_compare (value2, cvalue)) {
523 #ifdef CHECK_EXTRA_INFO
524                 g_warning ("gda_connection_get_meta_store_data(): expected %s and got %s\n",
525 			   gda_value_stringify (cvalue), gda_value_stringify (value));
526 #endif
527 		gda_value_free (value);
528 		g_object_unref (data);
529 		g_object_set (G_OBJECT (cnc), "options", options, NULL);
530 		return 1;
531 	}
532 	gda_value_free (value);
533 	g_object_unref (data);
534 
535 	g_object_set (G_OBJECT (cnc), "options", options, NULL);
536 	return 0;
537 }
538 
539 /*
540  *
541  * LOAD_DATA
542  *
543  */
544 int
prov_test_common_load_data(void)545 prov_test_common_load_data (void)
546 {
547 	int number_failed = 0;
548 
549 #ifdef CHECK_EXTRA_INFO
550 	g_print ("\n============= %s() =============\n", __FUNCTION__);
551 #endif
552 
553 	if (!prov_test_load_data (cnc, "actor"))
554 		number_failed++;
555 	if (!prov_test_load_data (cnc, "language"))
556 		number_failed++;
557 	if (!prov_test_load_data (cnc, "film"))
558 		number_failed++;
559 	if (!prov_test_load_data (cnc, "film_actor"))
560 		number_failed++;
561 
562 	return number_failed;
563 }
564 
565 /*
566  *
567  * CHECK_CURSOR_MODELS
568  *
569  */
570 int
prov_test_common_check_cursor_models(void)571 prov_test_common_check_cursor_models (void)
572 {
573 	int number_failed = 0;
574 
575 #ifdef CHECK_EXTRA_INFO
576 	g_print ("\n============= %s() =============\n", __FUNCTION__);
577 #endif
578 
579 	if (!prov_test_check_table_cursor_model (cnc, "actor"))
580 		number_failed++;
581 	if (!prov_test_check_table_cursor_model (cnc, "language"))
582 		number_failed++;
583 	if (!prov_test_check_table_cursor_model (cnc, "film"))
584 		number_failed++;
585 	if (!prov_test_check_table_cursor_model (cnc, "film_actor"))
586 		number_failed++;
587 	if (!prov_test_check_types_schema (cnc))
588 		number_failed++;
589 
590 	return number_failed;
591 }
592 
593 /*
594  *
595  * Check for the GdaDataModel returned from a SELECT combined with the GDA_STATEMENT_MODEL_ALLOW_NOPARAM
596  * flag
597  *
598  */
599 int
prov_test_common_check_data_select(void)600 prov_test_common_check_data_select (void)
601 {
602 	GdaSqlParser *parser = NULL;
603 	GdaStatement *stmt = NULL;
604 	GdaSet *params = NULL;
605 	GError *error = NULL;
606 	int number_failed = 0;
607 	GdaDataModel *model = NULL;
608 	const gchar *remain;
609 	GSList *columns;
610 	gint i, ncols;
611 
612 #ifdef CHECK_EXTRA_INFO
613 	g_print ("\n============= %s() =============\n", __FUNCTION__);
614 #endif
615 
616 	parser = gda_connection_create_parser (cnc);
617 	if (!parser)
618 		parser = gda_sql_parser_new ();
619 
620 	/* create statement */
621 	stmt = gda_sql_parser_parse_string (parser, "SELECT * FROM actor WHERE actor_id <= ##theid::gint",
622 					    &remain, &error);
623 	if (!stmt) {
624 		number_failed ++;
625 		goto out;
626 	}
627 	if (remain) {
628 		g_set_error (&error, TEST_ERROR, TEST_ERROR_PARSING,
629 			     "Parsing error, remains: %s", remain);
630 		number_failed ++;
631 		goto out;
632 	}
633 
634 	/* get model */
635 	if (! (gda_statement_get_parameters (stmt, &params, &error))) {
636 		number_failed ++;
637 		goto out;
638 	}
639 
640 	model = gda_connection_statement_execute_select_full (cnc, stmt, params, GDA_STATEMENT_MODEL_ALLOW_NOPARAM,
641                                                               NULL, &error);
642 	if (!model) {
643 		number_failed ++;
644 		goto out;
645 	}
646 
647 	if (gda_data_model_get_n_rows (model) != 0) {
648 		g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
649 			     "Data model reports %d rows when 0 expected", gda_data_model_get_n_rows (model));
650 		number_failed ++;
651 		goto out;
652 	}
653 
654 	ncols = gda_data_model_get_n_columns (model);
655 	for (columns = NULL, i = 0;
656 	     i < ncols; i++)
657 		columns = g_slist_append (columns, gda_data_model_describe_column (model, i));
658 
659 	/* change param */
660 	g_object_set (model, "auto-reset", TRUE, NULL);
661 	if (! gda_set_set_holder_value (params, &error, "theid", 9)) {
662                 number_failed++;
663                 goto out;
664         }
665 
666 	if (gda_data_model_get_n_rows (model) != 9) {
667 		g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
668 			     "Data model reports %d rows when 9 expected", gda_data_model_get_n_rows (model));
669 		number_failed ++;
670 		goto out;
671 	}
672 
673 	/* check the columns haven't changed */
674 	ncols = gda_data_model_get_n_columns (model);
675 	if (i != ncols) {
676 		g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
677 			     "Number of columns has changed from %d to %d\n", i, ncols);
678 		number_failed ++;
679 		goto out;
680 	}
681 
682 	for (i = 0; i < ncols; i++) {
683 		if (gda_data_model_describe_column (model, i) != g_slist_nth_data (columns, i)) {
684 			g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
685 				     "GdaColumn %d has changed from %p to %p\n", i,
686 				     g_slist_nth_data (columns, i),
687 				     gda_data_model_describe_column (model, i));
688 			number_failed ++;
689 			goto out;
690 		}
691 	}
692 
693  out:
694 	if (stmt)
695 		g_object_unref (stmt);
696 	if (params)
697 		g_object_unref (params);
698 	if (model)
699 		g_object_unref (model);
700 	g_object_unref (parser);
701 
702 #ifdef CHECK_EXTRA_INFO
703 	g_print ("GdaDataSelect test resulted in %d error(s)\n", number_failed);
704 	if (number_failed != 0)
705 		g_print ("error: %s\n", error && error->message ? error->message : "No detail");
706 	if (error)
707 		g_error_free (error);
708 #endif
709 
710 	return number_failed;
711 }
712 
713 
714 /*
715  * Check that timezones are handled correctly when storing and retreiving timestamps
716  */
717 static gboolean
timestamp_equal(const GValue * cv1,const GValue * cv2)718 timestamp_equal (const GValue *cv1, const GValue *cv2)
719 {
720 	g_assert (G_VALUE_TYPE (cv1) == GDA_TYPE_TIMESTAMP);
721 	g_assert (G_VALUE_TYPE (cv2) == GDA_TYPE_TIMESTAMP);
722 	const GdaTimestamp *ts1, *ts2;
723 	ts1 = gda_value_get_timestamp (cv1);
724 	ts2 = gda_value_get_timestamp (cv2);
725 	if (ts1->timezone == ts2->timezone)
726 		return gda_value_differ (cv1, cv2) ? FALSE : TRUE;
727 
728 	GdaTimestamp *ts;
729 	ts = gda_timestamp_copy ((GdaTimestamp*) ts1);
730 	gda_timestamp_change_timezone (ts, ts2->timezone);
731 	gboolean res;
732 	res = memcmp (ts2, ts, sizeof (GdaTimestamp)) ? FALSE : TRUE;
733 	gda_timestamp_free (ts);
734 	return res;
735 }
736 
737 int
prov_test_common_check_timestamp(void)738 prov_test_common_check_timestamp (void)
739 {
740 	GdaSqlParser *parser = NULL;
741 	GdaStatement *stmt = NULL;
742 	GdaSet *params = NULL;
743 	GError *error = NULL;
744 	int number_failed = 0;
745 	GdaDataModel *model = NULL;
746 
747 #ifdef CHECK_EXTRA_INFO
748 	g_print ("\n============= %s() =============\n", __FUNCTION__);
749 #endif
750 
751 	parser = gda_connection_create_parser (cnc);
752 	if (!parser)
753 		parser = gda_sql_parser_new ();
754 
755 	GValue *tso;
756 	tso = gda_value_new_timestamp_from_timet (time (NULL));
757 
758 	/* insert timestamp */
759 	stmt = gda_sql_parser_parse_string (parser, "INSERT INTO tstest (ts) VALUES (##ts::timestamp)", NULL, &error);
760 	if (!stmt ||
761 	    ! gda_statement_get_parameters (stmt, &params, &error) ||
762 	    ! gda_set_set_holder_value (params, &error, "ts", gda_value_get_timestamp (tso)) ||
763 	    (gda_connection_statement_execute_non_select (cnc, stmt, params, NULL, &error) == -1)) {
764 		number_failed ++;
765 		goto out;
766 	}
767 
768 	g_print ("Inserted TS %s\n", gda_value_stringify (tso));
769 
770 	/* retreive timestamp */
771 	stmt = gda_sql_parser_parse_string (parser, "SELECT ts FROM tstest", NULL, &error);
772 	if (!stmt) {
773 		number_failed ++;
774 		goto out;
775 	}
776 
777 	model = gda_connection_statement_execute_select (cnc, stmt, NULL, &error);
778 	if (!model) {
779 		number_failed ++;
780 		goto out;
781 	}
782 	gda_data_model_dump (model, NULL);
783 	if (gda_data_model_get_n_rows (model) != 1) {
784 		g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
785 			     "Data model should have exactly 1 row");
786 		number_failed ++;
787 		goto out;
788 	}
789 
790 	const GValue *cvalue;
791 	cvalue = gda_data_model_get_typed_value_at (model, 0, 0, GDA_TYPE_TIMESTAMP, FALSE, &error);
792 	if (!cvalue) {
793 		number_failed ++;
794 		goto out;
795 	}
796 	if (! timestamp_equal (tso, cvalue)) {
797 		gchar *tmpg, *tmpe;
798 		tmpg = gda_value_stringify (cvalue);
799 		tmpe = gda_value_stringify (tso);
800 		g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
801 			     "Retreived time stamp differs from expected: got '%s' and expected '%s'", tmpg, tmpe);
802 		g_free (tmpg);
803 		g_free (tmpe);
804 		number_failed ++;
805 		goto out;
806 	}
807 
808 	/* check that data handler is correctly configured: compare the same timestamp rendered by a data handler for
809 	 * timestamps with the date rendered as a string by the server (by appending a string to the timestamp field) */
810 	GdaDataHandler *dh;
811 	dh = gda_server_provider_get_data_handler_g_type (gda_connection_get_provider (cnc), cnc, GDA_TYPE_TIMESTAMP);
812 	gchar *str;
813 	str = gda_data_handler_get_str_from_value (dh, cvalue);
814 	g_object_unref (model);
815 
816 	stmt = gda_sql_parser_parse_string (parser, "SELECT ts || 'asstring' FROM tstest", NULL, &error); /* retreive timestamp as string */
817 	if (!stmt) {
818 		g_free (str);
819 		number_failed ++;
820 		goto out;
821 	}
822 
823 	model = gda_connection_statement_execute_select (cnc, stmt, NULL, &error);
824 	if (!model) {
825 		g_free (str);
826 		number_failed ++;
827 		goto out;
828 	}
829 	gda_data_model_dump (model, NULL);
830 	if (gda_data_model_get_n_rows (model) != 1) {
831 		g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
832 			     "Data model should have exactly 1 row");
833 		g_free (str);
834 		number_failed ++;
835 		goto out;
836 	}
837 	cvalue = gda_data_model_get_typed_value_at (model, 0, 0, G_TYPE_STRING, FALSE, &error);
838 	if (!cvalue) {
839 		g_free (str);
840 		number_failed ++;
841 		goto out;
842 	}
843 	if (strncmp (str, g_value_get_string (cvalue), 10)) { /* only compare date parts */
844 		g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
845 			     "Returned GdaDataHandler returned wrong result: '%s' and expected '%s'", str, g_value_get_string (cvalue));
846 		g_free (str);
847 		number_failed ++;
848 		goto out;
849 	}
850 
851 out:
852 	if (stmt)
853 		g_object_unref (stmt);
854 	if (params)
855 		g_object_unref (params);
856 	if (model)
857 		g_object_unref (model);
858 	g_object_unref (parser);
859 
860 #ifdef CHECK_EXTRA_INFO
861 	g_print ("Timestamp test resulted in %d error(s)\n", number_failed);
862 	if (number_failed != 0)
863 		g_print ("error: %s\n", error && error->message ? error->message : "No detail");
864 	if (error)
865 		g_error_free (error);
866 #endif
867 
868 	return number_failed;
869 }
870 
871 static GValue *
value_new_date_from_timet(time_t val)872 value_new_date_from_timet (time_t val)
873 {
874 	GValue *value;
875 	GDate *date;
876 	date = g_date_new ();
877 	g_date_set_time_t (date, val);
878 
879 	value = gda_value_new (G_TYPE_DATE);
880 	g_value_set_boxed (value, date);
881 	g_date_free (date);
882 
883         return value;
884 }
885 
886 static gboolean
date_equal(const GValue * cv1,const GValue * cv2)887 date_equal (const GValue *cv1, const GValue *cv2)
888 {
889 	g_assert (G_VALUE_TYPE (cv1) == G_TYPE_DATE);
890 	g_assert (G_VALUE_TYPE (cv2) == G_TYPE_DATE);
891 	const GDate *ts1, *ts2;
892 	ts1 = (GDate*) g_value_get_boxed (cv1);
893 	ts2 = (GDate*) g_value_get_boxed (cv2);
894 	return g_date_compare (ts1, ts2) ? FALSE : TRUE;
895 }
896 
897 int
prov_test_common_check_date(void)898 prov_test_common_check_date (void)
899 {
900 	GdaSqlParser *parser = NULL;
901 	GdaStatement *stmt = NULL;
902 	GdaSet *params = NULL;
903 	GError *error = NULL;
904 	int number_failed = 0;
905 	GdaDataModel *model = NULL;
906 
907 #ifdef CHECK_EXTRA_INFO
908 	g_print ("\n============= %s() =============\n", __FUNCTION__);
909 #endif
910 
911 	parser = gda_connection_create_parser (cnc);
912 	if (!parser)
913 		parser = gda_sql_parser_new ();
914 
915 	GValue *tso;
916 	tso = value_new_date_from_timet (time (NULL));
917 
918 	/* insert date */
919 	stmt = gda_sql_parser_parse_string (parser, "INSERT INTO datetest (thedate) VALUES (##thedate::date)", NULL, &error);
920 	if (!stmt ||
921 	    ! gda_statement_get_parameters (stmt, &params, &error) ||
922 	    ! gda_set_set_holder_value (params, &error, "thedate", (GDate*) g_value_get_boxed (tso)) ||
923 	    (gda_connection_statement_execute_non_select (cnc, stmt, params, NULL, &error) == -1)) {
924 		number_failed ++;
925 		goto out;
926 	}
927 
928 	g_print ("Inserted date %s\n", gda_value_stringify (tso));
929 
930 	/* retreive date */
931 	stmt = gda_sql_parser_parse_string (parser, "SELECT thedate FROM datetest", NULL, &error);
932 	if (!stmt) {
933 		number_failed ++;
934 		goto out;
935 	}
936 
937 	model = gda_connection_statement_execute_select (cnc, stmt, NULL, &error);
938 	if (!model) {
939 		number_failed ++;
940 		goto out;
941 	}
942 	gda_data_model_dump (model, NULL);
943 	if (gda_data_model_get_n_rows (model) != 1) {
944 		g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
945 			     "Data model should have exactly 1 row");
946 		number_failed ++;
947 		goto out;
948 	}
949 
950 	const GValue *cvalue;
951 	cvalue = gda_data_model_get_typed_value_at (model, 0, 0, G_TYPE_DATE, FALSE, &error);
952 	if (!cvalue) {
953 		number_failed ++;
954 		goto out;
955 	}
956 	if (! date_equal (tso, cvalue)) {
957 		gchar *tmpg, *tmpe;
958 		tmpg = gda_value_stringify (cvalue);
959 		tmpe = gda_value_stringify (tso);
960 		g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
961 			     "Retreived date differs from expected: got '%s' and expected '%s'", tmpg, tmpe);
962 		g_free (tmpg);
963 		g_free (tmpe);
964 		number_failed ++;
965 		goto out;
966 	}
967 
968 	/* check that data handler is correctly configured: compare the same timestamp rendered by a data handler for
969 	 * timestamps with the date rendered as a string by the server (by appending a string to the timestamp field) */
970 	GdaDataHandler *dh;
971 	dh = gda_server_provider_get_data_handler_g_type (gda_connection_get_provider (cnc), cnc, G_TYPE_DATE);
972 	gchar *str;
973 	str = gda_data_handler_get_str_from_value (dh, cvalue);
974 	g_object_unref (model);
975 
976 	stmt = gda_sql_parser_parse_string (parser, "SELECT thedate || 'asstring' FROM datetest", NULL, &error); /* retreive date as string */
977 	if (!stmt) {
978 		g_free (str);
979 		number_failed ++;
980 		goto out;
981 	}
982 
983 	model = gda_connection_statement_execute_select (cnc, stmt, NULL, &error);
984 	if (!model) {
985 		g_free (str);
986 		number_failed ++;
987 		goto out;
988 	}
989 	gda_data_model_dump (model, NULL);
990 	if (gda_data_model_get_n_rows (model) != 1) {
991 		g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
992 			     "Data model should have exactly 1 row");
993 		g_free (str);
994 		number_failed ++;
995 		goto out;
996 	}
997 	cvalue = gda_data_model_get_typed_value_at (model, 0, 0, G_TYPE_STRING, FALSE, &error);
998 	if (!cvalue) {
999 		g_free (str);
1000 		number_failed ++;
1001 		goto out;
1002 	}
1003 	if (strncmp (str, g_value_get_string (cvalue), 10)) { /* only compare date parts */
1004 		g_set_error (&error, TEST_ERROR, TEST_ERROR_GENERIC,
1005 			     "Returned GdaDataHandler returned wrong result: '%s' and expected '%s'", str, g_value_get_string (cvalue));
1006 		g_free (str);
1007 		number_failed ++;
1008 		goto out;
1009 	}
1010 
1011 out:
1012 	if (stmt)
1013 		g_object_unref (stmt);
1014 	if (params)
1015 		g_object_unref (params);
1016 	if (model)
1017 		g_object_unref (model);
1018 	g_object_unref (parser);
1019 
1020 #ifdef CHECK_EXTRA_INFO
1021 	g_print ("Date test resulted in %d error(s)\n", number_failed);
1022 	if (number_failed != 0)
1023 		g_print ("error: %s\n", error && error->message ? error->message : "No detail");
1024 	if (error)
1025 		g_error_free (error);
1026 #endif
1027 
1028 	return number_failed;
1029 }
1030