1 /*
2  * Copyright (C) 2007 - 2012 Vivien Malerba <malerba@gnome-db.org>
3  * Copyright (C) 2009 Bas Driessen <bas.driessen@xobas.com>
4  * Copyright (C) 2010 David King <davidk@openismus.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA  02110-1301, USA.
20  */
21 
22 #include <glib/gi18n-lib.h>
23 #include <string.h>
24 #include "gda-vprovider-data-model.h"
25 #include "gda-vconnection-data-model.h"
26 #include "gda-vconnection-data-model-private.h"
27 #include <sqlite3.h>
28 #include <libgda/gda-connection-private.h>
29 #include <libgda/gda-connection-internal.h>
30 #include <libgda/gda-data-model-iter.h>
31 #include <libgda/gda-blob-op.h>
32 #include "../gda-sqlite.h"
33 #include <sql-parser/gda-statement-struct-util.h>
34 #include <libgda/gda-debug-macros.h>
35 
36 #define GDA_DEBUG_VIRTUAL
37 #undef GDA_DEBUG_VIRTUAL
38 
39 struct _GdaVproviderDataModelPrivate {
40 	int foo;
41 };
42 
43 static void gda_vprovider_data_model_class_init (GdaVproviderDataModelClass *klass);
44 static void gda_vprovider_data_model_init       (GdaVproviderDataModel *prov, GdaVproviderDataModelClass *klass);
45 static void gda_vprovider_data_model_finalize   (GObject *object);
46 static GObjectClass  *parent_class = NULL;
47 
48 static GdaConnection *gda_vprovider_data_model_create_connection (GdaServerProvider *provider);
49 static gboolean       gda_vprovider_data_model_open_connection (GdaServerProvider *provider, GdaConnection *cnc,
50 								GdaQuarkList *params, GdaQuarkList *auth,
51 								guint *task_id, GdaServerProviderAsyncCallback async_cb,
52 								gpointer cb_data);
53 static gboolean       gda_vprovider_data_model_close_connection (GdaServerProvider *provider,
54 								 GdaConnection *cnc);
55 static GObject        *gda_vprovider_data_model_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
56 								   GdaStatement *stmt, GdaSet *params,
57 								   GdaStatementModelUsage model_usage,
58 								   GType *col_types, GdaSet **last_inserted_row,
59 								   guint *task_id, GdaServerProviderExecCallback async_cb,
60 								   gpointer cb_data, GError **error);
61 static const gchar   *gda_vprovider_data_model_get_name (GdaServerProvider *provider);
62 
63 static GValue **create_gvalues_array_from_sqlite3_array (int argc, sqlite3_value **argv);
64 
65 
66 /*
67  * GdaVproviderDataModel class implementation
68  */
69 static void
gda_vprovider_data_model_class_init(GdaVproviderDataModelClass * klass)70 gda_vprovider_data_model_class_init (GdaVproviderDataModelClass *klass)
71 {
72 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
73 	GdaServerProviderClass *server_class = GDA_SERVER_PROVIDER_CLASS (klass);
74 
75 	parent_class = g_type_class_peek_parent (klass);
76 
77 	object_class->finalize = gda_vprovider_data_model_finalize;
78 	server_class->create_connection = gda_vprovider_data_model_create_connection;
79 	server_class->open_connection = gda_vprovider_data_model_open_connection;
80 	server_class->close_connection = gda_vprovider_data_model_close_connection;
81 	server_class->statement_execute = gda_vprovider_data_model_statement_execute;
82 
83 	server_class->get_name = gda_vprovider_data_model_get_name;
84 
85 	/* explicitly unimplement the DDL queries */
86 	server_class->supports_operation = NULL;
87         server_class->create_operation = NULL;
88         server_class->render_operation = NULL;
89         server_class->perform_operation = NULL;
90 }
91 
92 static void
gda_vprovider_data_model_init(GdaVproviderDataModel * prov,G_GNUC_UNUSED GdaVproviderDataModelClass * klass)93 gda_vprovider_data_model_init (GdaVproviderDataModel *prov, G_GNUC_UNUSED GdaVproviderDataModelClass *klass)
94 {
95 	prov->priv = g_new (GdaVproviderDataModelPrivate, 1);
96 }
97 
98 static void
gda_vprovider_data_model_finalize(GObject * object)99 gda_vprovider_data_model_finalize (GObject *object)
100 {
101 	GdaVproviderDataModel *prov = (GdaVproviderDataModel *) object;
102 
103 	g_return_if_fail (GDA_IS_VPROVIDER_DATA_MODEL (prov));
104 
105 	/* free memory */
106 	g_free (prov->priv);
107 	prov->priv = NULL;
108 
109 	/* chain to parent class */
110 	parent_class->finalize (object);
111 }
112 
113 GType
gda_vprovider_data_model_get_type(void)114 gda_vprovider_data_model_get_type (void)
115 {
116 	static GType type = 0;
117 
118 	if (G_UNLIKELY (type == 0)) {
119 		static GMutex registering;
120 		if (type == 0) {
121 			static GTypeInfo info = {
122 				sizeof (GdaVproviderDataModelClass),
123 				(GBaseInitFunc) NULL,
124 				(GBaseFinalizeFunc) NULL,
125 				(GClassInitFunc) gda_vprovider_data_model_class_init,
126 				NULL, NULL,
127 				sizeof (GdaVproviderDataModel),
128 				0,
129 				(GInstanceInitFunc) gda_vprovider_data_model_init,
130 				0
131 			};
132 
133 		g_mutex_lock (&registering);
134 		if (type == 0)
135 			type = g_type_register_static (GDA_TYPE_VIRTUAL_PROVIDER, "GdaVproviderDataModel", &info, 0);
136 		g_mutex_unlock (&registering);
137 		}
138 	}
139 
140 	return type;
141 }
142 
143 /**
144  * gda_vprovider_data_model_new
145  *
146  * Creates a new GdaVirtualProvider object which allows one to
147  * add and remove GdaDataModel objects as tables within a connection
148  *
149  * Returns: a new #GdaVirtualProvider object.
150  */
151 GdaVirtualProvider *
gda_vprovider_data_model_new(void)152 gda_vprovider_data_model_new (void)
153 {
154 	GdaVirtualProvider *provider;
155 
156         provider = g_object_new (gda_vprovider_data_model_get_type (), NULL);
157         return provider;
158 }
159 
160 /*
161  * Note about RowIDs and how SQLite uses them:
162  *
163  * SQLite considers that each virtual table has unique row IDs, absolute value available all the time.
164  * When an UPDATE or DELETE statement is executed, SQLite does the following:
165  *  - xBegin (table): request a transaction start
166  *  - xOpen (table): create a new cursor
167  *  - xFilter (cursor): initialize the cursor
168  *  - moves the cursor one step at a time up to the end (xEof, xColumn and xNext). If it finds a
169  *    row needing to be updated or deleted, it calls xRowid (cursor) to get the RowID
170  *  - xClose (cursor): free the now useless cursor
171  *  - calls xUpdate (table) as many times as needed (one time for each row where xRowid was called)
172  *  - xSync (table)
173  *  - xCommit (table)
174  *
175  * This does not work well with Libgda because RowID are not pre-defined. To circumvent this problem,
176  * for each data model, the RowID as returned for each cursor is the row number in the data model, plus
177  * an offset defined uniquely for each table:
178  *   RowID (guint 64) = ID (guint32) << 32 + row (guint 31)
179  */
180 
181 #ifdef GDA_DEBUG_VIRTUAL
182 #define TRACE(table,cursor) g_print ("== %s (table=>%p cursor=>%p)\n", __FUNCTION__, (table), (cursor))
183 #else
184 #define TRACE(table,cursor)
185 #endif
186 
187 typedef struct VirtualTable VirtualTable;
188 typedef struct VirtualCursor VirtualCursor;
189 
190 struct VirtualTable {
191 	sqlite3_vtab                 base;
192 	GdaVconnectionDataModel     *cnc;
193 	GdaVConnectionTableData     *td;
194 	gboolean                     locked;
195 
196 	guint32                      rows_offset;
197 };
198 
199 #define MAX_VDATA_NUMBER 30
200 
201 struct VirtualCursor {
202 	sqlite3_vtab_cursor      base; /* base.pVtab is a pointer to the sqlite3_vtab virtual table */
203 	VirtualFilteredData     *data; /* a ref is held here */
204 	gint                     row; /* starts at 0 */
205 };
206 
207 
208 
209 static VirtualFilteredData *
virtual_filtered_data_new(VirtualTable * vtable,GdaDataModel * model,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)210 virtual_filtered_data_new (VirtualTable *vtable, GdaDataModel *model,
211 			   int idxNum, const char *idxStr, int argc, sqlite3_value **argv)
212 {
213 	VirtualFilteredData *data;
214 
215 	g_assert (model);
216 	data = g_new0 (VirtualFilteredData, 1);
217 	data->refcount = 1;
218 	data->reuseable = TRUE;
219 	data->idxNum = idxNum;
220 	data->idxStr = idxStr ? g_strdup (idxStr) : NULL;
221 	data->argc = argc;
222 	data->argv = create_gvalues_array_from_sqlite3_array (argc, argv);
223 	data->model = g_object_ref (model);
224 	if (GDA_IS_DATA_PROXY (model))
225 		data->iter = g_object_new (GDA_TYPE_DATA_MODEL_ITER,
226 					   "data-model", model, NULL);
227 	else
228 		data->iter = gda_data_model_create_iter (model);
229 	g_object_set (data->iter, "validate-changes", FALSE, NULL);
230 
231 	gint n;
232 	n = gda_data_model_get_n_columns (model);
233 	n = (n >= 0) ? n : 1;
234 	data->values_array = g_array_new (FALSE, FALSE, sizeof (GValue));
235 	data->ncols = gda_data_model_get_n_columns (model);
236 	data->nrows = -1;
237 	data->rowid_offset = vtable->rows_offset;
238 	vtable->rows_offset ++;
239 
240 #ifdef DEBUG_VCONTEXT
241 	g_print ("New VData %p for table [%s] idxNum=%d, idxStr=[%s], argc=%d\n", data, vtable->td->table_name,
242 		 idxNum, idxStr, argc);
243 	for (n= 0; n < data->argc; n++)
244 		g_print ("    [%s]\n", gda_value_stringify (data->argv [n]));
245 #endif
246 	return data;
247 }
248 
249 static void
virtual_filtered_data_free(VirtualFilteredData * data)250 virtual_filtered_data_free (VirtualFilteredData *data)
251 {
252 	g_return_if_fail (data != NULL);
253 	if (data->argv) {
254 		int i;
255 		for (i = 0; i < data->argc; i++)
256 			gda_value_free (data->argv [i]);
257 		g_free (data->argv);
258 	}
259 	g_free (data->idxStr);
260 	g_object_unref (data->model);
261 	if (data->iter)
262 		g_object_unref (data->iter);
263 
264 	if (data->values_array) {
265 		guint i;
266 		for (i = 0; i < data->values_array->len; i++) {
267 			GValue *value;
268 			value = & g_array_index (data->values_array, GValue, i);
269 			g_value_reset (value);
270 		}
271 		g_array_free (data->values_array, TRUE);
272 	}
273 	g_free (data);
274 
275 #ifdef DEBUG_VCONTEXT
276 	g_print ("Freed VData %p\n", data);
277 #endif
278 }
279 
280 static VirtualFilteredData *
virtual_filtered_data_ref(VirtualFilteredData * data)281 virtual_filtered_data_ref (VirtualFilteredData *data)
282 {
283 	g_return_val_if_fail (data != NULL, NULL);
284 	data->refcount ++;
285 	return data;
286 }
287 
288 void
_gda_vconnection_virtual_filtered_data_unref(VirtualFilteredData * data)289 _gda_vconnection_virtual_filtered_data_unref (VirtualFilteredData *data)
290 {
291 	g_return_if_fail (data != NULL);
292 	data->refcount --;
293 	if (data->refcount == 0)
294 		virtual_filtered_data_free (data);
295 }
296 
297 static void
virtual_cursor_free(VirtualCursor * cursor)298 virtual_cursor_free (VirtualCursor *cursor)
299 {
300 	if (!cursor)
301 		return;
302 
303 	_gda_vconnection_virtual_filtered_data_unref (cursor->data);
304 	cursor->data = NULL;
305 	g_free (cursor);
306 }
307 
308 /* module creation */
309 static int virtualCreate (sqlite3 *db, void *pAux, int argc, const char *const *argv, sqlite3_vtab **ppVtab, char **pzErr);
310 static int virtualConnect (sqlite3 *db, void *pAux, int argc, const char *const *argv, sqlite3_vtab **ppVtab, char **pzErr);
311 static int virtualDisconnect (sqlite3_vtab *pVtab);
312 static int virtualDestroy (sqlite3_vtab *pVtab);
313 static int virtualOpen (sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
314 static int virtualClose (sqlite3_vtab_cursor *cur);
315 static int virtualEof (sqlite3_vtab_cursor *cur);
316 static int virtualNext (sqlite3_vtab_cursor *cur);
317 static int virtualColumn (sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i);
318 static int virtualRowid (sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid);
319 static int virtualFilter (sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv);
320 static int virtualBestIndex (sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo);
321 static int virtualUpdate (sqlite3_vtab *tab, int nData, sqlite3_value **apData, sqlite_int64 *pRowid);
322 static int virtualBegin (sqlite3_vtab *tab);
323 static int virtualSync (sqlite3_vtab *tab);
324 static int virtualCommit (sqlite3_vtab *tab);
325 static int virtualRollback (sqlite3_vtab *tab);
326 static int virtualRename (sqlite3_vtab *pVtab, const char *zNew);
327 
328 static sqlite3_module Module = {
329 	1,                         /* iVersion */
330 	virtualCreate,
331 	virtualConnect,
332 	virtualBestIndex,
333 	virtualDisconnect,
334 	virtualDestroy,
335 	virtualOpen,                  /* xOpen - open a cursor */
336 	virtualClose,                 /* xClose - close a cursor */
337 	virtualFilter,                /* xFilter - configure scan constraints */
338 	virtualNext,                  /* xNext - advance a cursor */
339 	virtualEof,                   /* xEof */
340 	virtualColumn,                /* xColumn - read data */
341 	virtualRowid,                 /* xRowid - read data */
342 	virtualUpdate,                /* xUpdate - write data */
343 	virtualBegin,                 /* xBegin - begin transaction */
344 	virtualSync,                  /* xSync - sync transaction */
345 	virtualCommit,                /* xCommit - commit transaction */
346 	virtualRollback,              /* xRollback - rollback transaction */
347 	NULL,                         /* xFindFunction - function overloading */
348 	virtualRename,                /* Rename - Notification that the table will be given a new name */
349 #if SQLITE_VERSION_NUMBER >= 3007007
350 	NULL,                         /* xSavepoint */
351 	NULL,                         /* xRelease */
352 	NULL                          /* xRollbackTo */
353 #endif
354 };
355 
356 static GdaConnection *
gda_vprovider_data_model_create_connection(GdaServerProvider * provider)357 gda_vprovider_data_model_create_connection (GdaServerProvider *provider)
358 {
359 	GdaConnection *cnc;
360 	g_return_val_if_fail (GDA_IS_VPROVIDER_DATA_MODEL (provider), NULL);
361 
362 	cnc = g_object_new (GDA_TYPE_VCONNECTION_DATA_MODEL, "provider", provider, NULL);
363 
364 	return cnc;
365 }
366 
367 static gboolean
gda_vprovider_data_model_open_connection(GdaServerProvider * provider,GdaConnection * cnc,GdaQuarkList * params,GdaQuarkList * auth,G_GNUC_UNUSED guint * task_id,GdaServerProviderAsyncCallback async_cb,G_GNUC_UNUSED gpointer cb_data)368 gda_vprovider_data_model_open_connection (GdaServerProvider *provider, GdaConnection *cnc,
369 					  GdaQuarkList *params, GdaQuarkList *auth,
370 					  G_GNUC_UNUSED guint *task_id, GdaServerProviderAsyncCallback async_cb, G_GNUC_UNUSED gpointer cb_data)
371 {
372 	GdaQuarkList *m_params;
373 
374 	g_return_val_if_fail (GDA_IS_VPROVIDER_DATA_MODEL (provider), FALSE);
375 	g_return_val_if_fail (GDA_IS_VCONNECTION_DATA_MODEL (cnc), FALSE);
376 
377 	if (async_cb) {
378 		gda_connection_add_event_string (cnc, _("Provider does not support asynchronous connection open"));
379                 return FALSE;
380 	}
381 
382 	if (params) {
383 		m_params = gda_quark_list_copy (params);
384 		gda_quark_list_add_from_string (m_params, "_IS_VIRTUAL=TRUE;EXTRA_FUNCTIONS=TRUE", TRUE);
385 	}
386 	else
387 		m_params = gda_quark_list_new_from_string ("_IS_VIRTUAL=TRUE;EXTRA_FUNCTIONS=TRUE");
388 
389 	if (! GDA_SERVER_PROVIDER_CLASS (parent_class)->open_connection (GDA_SERVER_PROVIDER (provider), cnc, m_params,
390 									 auth, NULL, NULL, NULL)) {
391 		if (auth)
392 			gda_quark_list_protect_values (auth);
393 		gda_quark_list_free (m_params);
394 		return FALSE;
395 	}
396 	if (auth)
397 		gda_quark_list_protect_values (auth);
398 	gda_quark_list_free (m_params);
399 
400 	SqliteConnectionData *scnc;
401 	scnc = (SqliteConnectionData*) gda_connection_internal_get_provider_data ((GdaConnection *) cnc);
402 	if (!scnc) {
403 		gda_connection_close_no_warning (cnc);
404 		gda_connection_add_event_string (cnc,
405 						 _("Connection is closed"));
406 		return FALSE;
407 	}
408 
409 	/* Module to declare wirtual tables */
410 	if (SQLITE3_CALL (sqlite3_create_module) (scnc->connection, G_OBJECT_TYPE_NAME (provider), &Module, cnc) != SQLITE_OK)
411 		return FALSE;
412 	/*g_print ("==== Declared module for DB %p\n", scnc->connection);*/
413 
414 	return TRUE;
415 }
416 
417 static void
cnc_close_foreach_func(G_GNUC_UNUSED GdaDataModel * model,const gchar * table_name,GdaVconnectionDataModel * cnc)418 cnc_close_foreach_func (G_GNUC_UNUSED GdaDataModel *model, const gchar *table_name, GdaVconnectionDataModel *cnc)
419 {
420 	/*g_print ("---- FOREACH: Removing virtual table '%s'\n", table_name);*/
421 	GError *lerror = NULL;
422 	if (! gda_vconnection_data_model_remove (cnc, table_name, &lerror)) {
423 		g_warning ("Internal GdaVproviderDataModel error: %s",
424 			   lerror && lerror->message ? lerror->message : _("No detail"));
425 		g_clear_error (&lerror);
426 	}
427 }
428 
429 static gboolean
gda_vprovider_data_model_close_connection(GdaServerProvider * provider,GdaConnection * cnc)430 gda_vprovider_data_model_close_connection (GdaServerProvider *provider, GdaConnection *cnc)
431 {
432 	g_return_val_if_fail (GDA_IS_VPROVIDER_DATA_MODEL (provider), FALSE);
433 	g_return_val_if_fail (GDA_IS_VCONNECTION_DATA_MODEL (cnc), FALSE);
434 
435 	gda_vconnection_data_model_foreach (GDA_VCONNECTION_DATA_MODEL (cnc),
436 					    (GdaVconnectionDataModelFunc) cnc_close_foreach_func, cnc);
437 
438 	return GDA_SERVER_PROVIDER_CLASS (parent_class)->close_connection (GDA_SERVER_PROVIDER (provider), cnc);
439 }
440 
441 static GObject *
gda_vprovider_data_model_statement_execute(GdaServerProvider * provider,GdaConnection * cnc,GdaStatement * stmt,GdaSet * params,GdaStatementModelUsage model_usage,GType * col_types,GdaSet ** last_inserted_row,guint * task_id,GdaServerProviderExecCallback async_cb,gpointer cb_data,GError ** error)442 gda_vprovider_data_model_statement_execute (GdaServerProvider *provider, GdaConnection *cnc,
443 					    GdaStatement *stmt, GdaSet *params,
444 					    GdaStatementModelUsage model_usage,
445 					    GType *col_types, GdaSet **last_inserted_row,
446 					    guint *task_id, GdaServerProviderExecCallback async_cb,
447 					    gpointer cb_data, GError **error)
448 {
449 	GObject *retval;
450 	if (async_cb) {
451                 g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR,
452                              "%s", _("Provider does not support asynchronous statement execution"));
453                 return NULL;
454         }
455 
456 	_gda_vconnection_set_working_obj ((GdaVconnectionDataModel*) cnc, (GObject*) stmt);
457 	retval = GDA_SERVER_PROVIDER_CLASS (parent_class)->statement_execute (provider, cnc, stmt, params,
458 									      model_usage, col_types,
459 									      last_inserted_row, task_id,
460 									      async_cb, cb_data, error);
461 
462 	if (retval) {
463 		if (! GDA_IS_DATA_MODEL (retval))
464 			_gda_vconnection_set_working_obj ((GdaVconnectionDataModel*) cnc, NULL);
465 
466 		gchar *sql;
467 		sql = gda_statement_to_sql (stmt, params, NULL);
468 		if (sql) {
469 			gchar *ptr = NULL;
470 			/* look for DROP TABLE to signal table removal */
471 			if (! g_ascii_strncasecmp (sql, "DROP", 4))
472 				ptr = sql + 4;
473 			else if (! g_ascii_strncasecmp (sql, "CREATE", 6))
474 				ptr = sql + 6;
475 			if (ptr) {
476 				/* skip spaces */
477 				for (; *ptr && (g_ascii_isspace (*ptr) || (*ptr == '\n')); ptr++);
478 
479 				if (! g_ascii_strncasecmp (ptr, "TABLE", 5)) {
480 					/* skip spaces */
481 					gchar delim = 0;
482 					gchar *table_name, *quoted;
483 					for (ptr = ptr+5;
484 					     *ptr && (g_ascii_isspace (*ptr) || (*ptr == '\n'));
485 					     ptr++);
486 					if (*ptr == '\'') {
487 						delim = '\'';
488 						ptr++;
489 					}
490 					else if (*ptr == '"') {
491 						delim = '"';
492 						ptr++;
493 					}
494 					table_name = ptr;
495 					if (delim)
496 						for (; *ptr && (*ptr != delim) ; ptr++);
497 					else
498 						for (; *ptr && g_ascii_isalnum (*ptr); ptr++);
499 					*ptr = 0;
500 					quoted = _gda_connection_compute_table_virtual_name (GDA_CONNECTION (cnc), table_name);
501 					/*g_print ("%s() emits the 'vtable-dropped' signal for table [%s]\n",
502 					  __FUNCTION__, quoted);*/
503 					g_signal_emit_by_name (cnc, "vtable-dropped", quoted);
504 					g_free (quoted);
505 				}
506 			}
507 			g_free (sql);
508 		}
509 	}
510 	else
511 		_gda_vconnection_set_working_obj ((GdaVconnectionDataModel*) cnc, NULL);
512 	return retval;
513 }
514 
515 static const gchar *
gda_vprovider_data_model_get_name(G_GNUC_UNUSED GdaServerProvider * provider)516 gda_vprovider_data_model_get_name (G_GNUC_UNUSED GdaServerProvider *provider)
517 {
518 	return "Virtual";
519 }
520 
521 static int
virtualCreate(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)522 virtualCreate (sqlite3 *db, void *pAux, int argc, const char *const *argv, sqlite3_vtab **ppVtab, char **pzErr)
523 {
524 	GdaVconnectionDataModel *cnc = GDA_VCONNECTION_DATA_MODEL (pAux);
525 	GString *sql;
526 	gint i, ncols;
527 	gchar *spec_name, *tmp;
528 	GdaVConnectionTableData *td;
529 	GHashTable *hash;
530 
531 	TRACE (NULL, NULL);
532 
533 	/* find Spec */
534 	g_assert (argc == 4);
535 	spec_name = g_strdup (argv[3]);
536 	i = strlen (spec_name);
537 	if (spec_name [i-1] == '\'')
538 		spec_name [i-1] = 0;
539 	if (*spec_name == '\'')
540 		memmove (spec_name, spec_name+1, i);
541 
542 	td = _gda_vconnection_get_table_data_by_unique_name (cnc, spec_name);
543 	g_free (spec_name);
544 	if (!td) {
545 		/* wrong usage! */
546 		*pzErr = SQLITE3_CALL (sqlite3_mprintf) (_("Wrong usage of Libgda's virtual tables"));
547 		return SQLITE_ERROR;
548 	}
549 
550 	/* preparations */
551 	if (td->spec->data_model) {
552 		ncols = gda_data_model_get_n_columns (td->spec->data_model);
553 		if (ncols <= 0) {
554 			*pzErr = SQLITE3_CALL (sqlite3_mprintf) (_("Data model must have at least one column"));
555 			return SQLITE_ERROR;
556 		}
557 		td->real_model = td->spec->data_model;
558 		g_object_ref (td->real_model);
559 	}
560 
561 	GError *error = NULL;
562 	if (!td->columns && td->spec->create_columns_func)
563 		td->columns = td->spec->create_columns_func (td->spec, &error);
564 	if (!td->columns) {
565 		if (error && error->message) {
566 			int len = strlen (error->message) + 1;
567 			*pzErr = SQLITE3_CALL (sqlite3_malloc) (sizeof (gchar) * len);
568 			memcpy (*pzErr, error->message, len); /* Flawfinder: ignore */
569 		}
570 		else
571 			*pzErr = SQLITE3_CALL (sqlite3_mprintf) (_("Could not compute virtual table's columns"));
572 		return SQLITE_ERROR;
573 	}
574 	ncols = g_list_length (td->columns);
575 	td->n_columns = ncols;
576 
577 	/* create the CREATE TABLE statement */
578 	sql = g_string_new ("CREATE TABLE ");
579 	tmp = gda_connection_quote_sql_identifier (GDA_CONNECTION (cnc), argv[2]);
580 	g_string_append (sql, tmp);
581 	g_free (tmp);
582 	g_string_append (sql, " (");
583 	hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
584 	for (i = 0; i < ncols; i++) {
585 		GdaColumn *column;
586 		const gchar *name, *type;
587 		GType gtype;
588 		gchar *newcolname, *tmp;
589 
590 		if (i != 0)
591 			g_string_append (sql, ", ");
592 		column = g_list_nth_data (td->columns, i);
593 		if (!column) {
594 			*pzErr = SQLITE3_CALL (sqlite3_mprintf) (_("Can't get data model description for column %d"), i);
595 			g_string_free (sql, TRUE);
596 			return SQLITE_ERROR;
597 		}
598 
599 		name = gda_column_get_name (column);
600 		if (!name || !(*name))
601 			newcolname = g_strdup_printf ("_%d", i + 1);
602 		else {
603 			GString *string;
604 			gchar *ptr;
605 			string = g_string_new ("");
606 			newcolname = gda_sql_identifier_quote (name, GDA_CONNECTION (cnc), NULL, FALSE, FALSE);
607 			for (ptr = newcolname; *ptr; ptr++) {
608 				if ((*ptr == '_') ||
609 				    ((*ptr >= 'a') && (*ptr <= 'z')) ||
610 				    ((*ptr >= 'A') && (*ptr <= 'Z')))
611 					g_string_append_c (string, *ptr);
612 				else if ((*ptr >= '0') && (*ptr <= '9')) {
613 					if (ptr == name)
614 						g_string_append_c (string, '_');
615 					else
616 						g_string_append_c (string, *ptr);
617 				}
618 				else
619 					g_string_append_c (string, '_');
620 			}
621 			g_free (newcolname);
622 			newcolname = g_string_free (string, FALSE);
623 		}
624 
625 		tmp = g_ascii_strdown (newcolname, -1);
626 		if (g_hash_table_lookup (hash, tmp)) {
627 			gint i;
628 			g_free (tmp);
629 			for (i = 0; ; i++) {
630 				gchar *nc2;
631 				nc2 = g_strdup_printf ("%s%d", newcolname, i);
632 				tmp = g_ascii_strdown (nc2, -1);
633 				if (! g_hash_table_lookup (hash, tmp)) {
634 					g_free (newcolname);
635 					newcolname = nc2;
636 					break;
637 				}
638 				g_free (tmp);
639 				g_free (nc2);
640 			}
641 		}
642 
643 		gtype = gda_column_get_g_type (column);
644 		type = g_type_name (gtype);
645 		if (!type) {
646 			*pzErr = SQLITE3_CALL (sqlite3_mprintf) (_("Can't get data model's column type for column %d"), i);
647 			g_string_free (sql, TRUE);
648 			return SQLITE_ERROR;
649 		}
650 		else if (gtype == GDA_TYPE_BLOB)
651 			type = "blob";
652 		else if (gtype == GDA_TYPE_BINARY)
653 			type = "binary";
654 		else if (gtype == G_TYPE_STRING)
655 			type = "string";
656 		else if (gtype == G_TYPE_INT)
657 			type = "integer";
658 		else if (gtype == G_TYPE_UINT)
659 			type = "unsigned integer";
660 		else if ((gtype == G_TYPE_INT64) || (gtype == G_TYPE_LONG))
661 			type = "int64";
662 		else if ((gtype == G_TYPE_UINT64) || (gtype == G_TYPE_ULONG))
663 			type = "uint64";
664 		else if ((gtype == G_TYPE_DOUBLE) || (gtype == G_TYPE_FLOAT))
665 			type = "real";
666 		else if (gtype == G_TYPE_DATE)
667 			type = "date";
668 		else if (gtype == GDA_TYPE_TIME)
669 			type = "time";
670 		else if (gtype == GDA_TYPE_TIMESTAMP)
671 			type = "timestamp";
672 		else if (gtype == GDA_TYPE_SHORT)
673 			type = "short";
674 		else if (gtype == GDA_TYPE_USHORT)
675 			type = "unsigned short";
676 		else
677 			type = "text";
678 
679 		g_string_append (sql, newcolname);
680 		g_hash_table_insert (hash, tmp, (gpointer) 0x01);
681 		g_free (newcolname);
682 		g_string_append_c (sql, ' ');
683 		g_string_append (sql, type);
684 		if (! gda_column_get_allow_null (column))
685 			g_string_append (sql, " NOT NULL");
686 		if (gtype == G_TYPE_STRING)
687 			g_string_append (sql, " COLLATE LOCALE");
688 	}
689 	g_hash_table_destroy (hash);
690 
691 	/* add a hidden column which contains the row number of the data model */
692 	if (ncols != 0)
693 		g_string_append (sql, ", ");
694 	g_string_append (sql, "__gda_row_nb hidden integer");
695 
696 	g_string_append_c (sql, ')');
697 
698 	/* VirtualTable structure */
699 	VirtualTable *vtable;
700 	vtable = g_new0 (VirtualTable, 1);
701 	vtable->cnc = cnc;
702 	vtable->td = td;
703 	vtable->rows_offset = 0;
704 	*ppVtab = &(vtable->base);
705 
706 	if (SQLITE3_CALL (sqlite3_declare_vtab) (db, sql->str) != SQLITE_OK) {
707 		*pzErr = SQLITE3_CALL (sqlite3_mprintf) (_("Can't declare virtual table (%s)"), sql->str);
708 		g_string_free (sql, TRUE);
709 		g_free (vtable);
710 		*ppVtab = NULL;
711 		return SQLITE_ERROR;
712 	}
713 
714 	/*g_print ("VIRTUAL TABLE [%p]: %s\n", vtable, sql->str);*/
715 	g_string_free (sql, TRUE);
716 
717 	return SQLITE_OK;
718 }
719 
720 static int
virtualConnect(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)721 virtualConnect (sqlite3 *db, void *pAux, int argc, const char *const *argv, sqlite3_vtab **ppVtab, char **pzErr)
722 {
723 	TRACE (NULL, NULL);
724 
725 	return virtualCreate (db, pAux, argc, argv, ppVtab, pzErr);
726 }
727 
728 static int
virtualDisconnect(sqlite3_vtab * pVtab)729 virtualDisconnect (sqlite3_vtab *pVtab)
730 {
731 	/*VirtualTable *vtable = (VirtualTable *) pVtab;*/
732 
733 	TRACE (pVtab, NULL);
734 	g_free (pVtab);
735 
736 	return SQLITE_OK;
737 }
738 
739 static int
virtualDestroy(sqlite3_vtab * pVtab)740 virtualDestroy (sqlite3_vtab *pVtab)
741 {
742 	TRACE (pVtab, NULL);
743 
744 	return virtualDisconnect (pVtab);
745 }
746 
747 static int
virtualOpen(G_GNUC_UNUSED sqlite3_vtab * pVTab,sqlite3_vtab_cursor ** ppCursor)748 virtualOpen (G_GNUC_UNUSED sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor)
749 {
750 	VirtualCursor *cursor;
751 
752 	/* create empty cursor */
753 	cursor = g_new0 (VirtualCursor, 1);
754 	*ppCursor = (sqlite3_vtab_cursor*) cursor;
755 	TRACE (pVTab, cursor);
756 
757 	return SQLITE_OK;
758 }
759 
760 static int
virtualClose(sqlite3_vtab_cursor * cur)761 virtualClose (sqlite3_vtab_cursor *cur)
762 {
763 	VirtualCursor *cursor = (VirtualCursor*) cur;
764 	/*VirtualTable *vtable = (VirtualTable*) cur->pVtab;*/
765 
766 	TRACE (cur->pVtab, cur);
767 
768 	virtual_cursor_free (cursor);
769 
770 	return SQLITE_OK;
771 }
772 
773 static int
virtualEof(sqlite3_vtab_cursor * cur)774 virtualEof (sqlite3_vtab_cursor *cur)
775 {
776 	VirtualCursor *cursor = (VirtualCursor*) cur;
777 
778 	TRACE (cur->pVtab, cur);
779 
780 	if (cursor->data->iter)
781 		return FALSE;
782 	else {
783 		if (cursor->row >= cursor->data->nrows)
784 			return TRUE;
785 		else
786 			return FALSE;
787 	}
788 }
789 
790 /*
791  * handle data model exceptions and return appropriate code
792  */
793 static int
handle_data_model_exception(sqlite3_vtab * pVtab,GdaDataModel * model)794 handle_data_model_exception (sqlite3_vtab *pVtab, GdaDataModel *model)
795 {
796 	GError **exceptions;
797 	gint i;
798 	exceptions = gda_data_model_get_exceptions (model);
799 	if (!exceptions)
800 		return SQLITE_OK;
801 
802 	GError *trunc_error = NULL;
803 	GError *fatal_error = NULL;
804 	for (i = 0; exceptions [i]; i++) {
805 		GError *e;
806 		e = exceptions [i];
807 		if ((e->domain == GDA_DATA_MODEL_ERROR) &&
808 		    (e->code == GDA_DATA_MODEL_TRUNCATED_ERROR))
809 			trunc_error = e;
810 		else {
811 			fatal_error = e;
812 			break;
813 		}
814 	}
815 	if (fatal_error || trunc_error) {
816 		GError *e;
817 		e = fatal_error;
818 		if (!e)
819 			e = trunc_error;
820 		if (pVtab->zErrMsg)
821 			SQLITE3_CALL (sqlite3_free) (pVtab->zErrMsg);
822 		pVtab->zErrMsg = SQLITE3_CALL (sqlite3_mprintf)
823 			("%s", e->message ? e->message : _("No detail"));
824 		if (fatal_error)
825 			return SQLITE_ERROR;
826 		else
827 			return SQLITE_IOERR_TRUNCATE;
828 	}
829 	return SQLITE_OK;
830 }
831 
832 static int
virtualNext(sqlite3_vtab_cursor * cur)833 virtualNext (sqlite3_vtab_cursor *cur)
834 {
835 	VirtualCursor *cursor = (VirtualCursor*) cur;
836 	VirtualFilteredData *data;
837 	/*VirtualTable *vtable = (VirtualTable*) cur->pVtab;*/
838 
839 	TRACE (cur->pVtab, cur);
840 
841 	data = cursor->data;
842 	if (!data) {
843 		cur->pVtab->zErrMsg = SQLITE3_CALL (sqlite3_mprintf)
844 			(_("Internal SQLite error: no data to iterate on"));
845 		return SQLITE_MISUSE;
846 	}
847 
848 	cursor->row ++;
849 	if (data->iter && (gda_data_model_iter_get_row (data->iter) < cursor->row)) {
850 		/* move to next row */
851 		if (gda_data_model_iter_move_next (data->iter)) {
852 			int exc_res;
853 			exc_res = handle_data_model_exception (cur->pVtab, data->model);
854 			if (exc_res != SQLITE_OK)
855 				goto onerror;
856 
857 			/* load data for row */
858 			GSList *list;
859 			gint count;
860 			for (count = 0, list = ((GdaSet*) data->iter)->holders; list;
861 			     count++, list = list->next) {
862 				GdaHolder *h = (GdaHolder*) list->data;
863 				GError *lerror = NULL;
864 				if (! gda_holder_is_valid_e (h, &lerror)) {
865 					GValue value = {0};
866 					g_value_init (&value, G_TYPE_ERROR);
867 					g_value_take_boxed (&value, lerror);
868 					g_array_append_val (data->values_array, value);
869 				}
870 				else {
871 					const GValue *cvalue;
872 					cvalue = gda_holder_get_value (h);
873 					if (cvalue && (G_VALUE_TYPE (cvalue) != 0)) {
874 						GValue copy = {0};
875 						g_value_init (&copy, G_VALUE_TYPE (cvalue));
876 						g_value_copy (cvalue, &copy);
877 						g_array_append_val (data->values_array, copy);
878 					}
879 					else {
880 						GValue value = {0};
881 						g_value_init (&value, G_TYPE_ERROR);
882 						g_value_take_boxed (&value, lerror);
883 						g_array_append_val (data->values_array, value);
884 					}
885 				}
886 			}
887 			g_assert (count == data->ncols);
888 		}
889 		else {
890 			int exc_res;
891 			exc_res = handle_data_model_exception (cur->pVtab, data->model);
892 			if (exc_res != SQLITE_OK)
893 				goto onerror;
894 			else {
895 				/* end of data */
896 				g_object_unref (data->iter);
897 				data->iter = NULL;
898 				data->nrows = cursor->row;
899 			}
900 		}
901 	}
902 	return SQLITE_OK;
903 
904  onerror:
905 	cursor->row--;
906 	g_object_unref (data->iter);
907 	data->iter = NULL;
908 	data->nrows = cursor->row;
909 	return SQLITE_ERROR;
910 }
911 
912 /*
913  * @cursor may be %NULL
914  */
915 static const GValue *
get_data_value(VirtualTable * vtable,VirtualCursor * cursor,gint row,gint64 rowid,gint col,GError ** error)916 get_data_value (VirtualTable *vtable, VirtualCursor *cursor, gint row, gint64 rowid, gint col, GError **error)
917 {
918 	VirtualFilteredData *data = NULL;
919 	const GValue *value = NULL;
920 
921 	if ((col < 0) || (col >= vtable->td->n_columns)) {
922 		g_set_error (error, 0, 0, _("Column %d out of range (0-%d)"), col, vtable->td->n_columns - 1);
923 		return NULL;
924 	}
925 	if (cursor) {
926 		data = cursor->data;
927 		g_assert (data);
928 	}
929 	else {
930 		g_assert (row < 0);
931 		row = (gint) (rowid & 0xFFFFFFFF);
932 
933 		g_assert (vtable->td->context.current_vcontext);
934 		guint i;
935 		GArray *values_array = vtable->td->context.current_vcontext->context_data;
936 		for (i = 0; i < values_array->len; i++) {
937 			VirtualFilteredData *vd;
938 			vd = g_array_index (values_array, VirtualFilteredData*, i);
939 			if (vd->rowid_offset == (guint32) (rowid >> 32)) {
940 				data = vd;
941 				break;
942 			}
943 		}
944 	}
945 
946 	if (data)
947 		value = & g_array_index (data->values_array, GValue, row * data->ncols + col);
948 
949 	if (!value)
950 		g_set_error (error, 0, 0,
951 			     _("Could not find requested value at row %d and col %d"),
952 			     row, col);
953 #ifdef DEBUG_VCONTEXT
954 	g_print ("Read from [%s] [%s] %d x %d x %lld\n", vtable->td->table_name, gda_value_stringify (value), col, row, rowid);
955 #endif
956 	return value;
957 }
958 
959 static int
virtualColumn(sqlite3_vtab_cursor * cur,sqlite3_context * ctx,int i)960 virtualColumn (sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i)
961 {
962 	VirtualCursor *cursor = (VirtualCursor*) cur;
963 
964 	TRACE (cur->pVtab, cur);
965 
966 	if (i == ((VirtualTable*) cur->pVtab)->td->n_columns) {
967 		/* private hidden column, which returns the row number */
968 		SQLITE3_CALL (sqlite3_result_int) (ctx, cursor->row);
969 		return SQLITE_OK;
970 	}
971 
972 	if (i >= cursor->data->ncols) {
973 		SQLITE3_CALL (sqlite3_result_text) (ctx, _("Column not found"), -1, SQLITE_TRANSIENT);
974 		return SQLITE_MISUSE;
975 	}
976 
977 	const GValue *value;
978 	GError *lerror = NULL;
979 	value = get_data_value ((VirtualTable*) cur->pVtab, cursor, cursor->row, 0, i, &lerror);
980 	if (! value) {
981 		g_hash_table_insert (error_blobs_hash, lerror, GINT_TO_POINTER (1));
982 		SQLITE3_CALL (sqlite3_result_blob) (ctx, lerror, sizeof (GError), NULL);
983 	}
984 	else if (G_VALUE_TYPE (value) == G_TYPE_ERROR) {
985 		GError *lerror;
986 		lerror = g_value_get_boxed (value);
987 		//SQLITE3_CALL (sqlite3_result_error) (ctx, lerror && lerror->message ? lerror->message : _("No detail"), -1);
988 		if (lerror)
989 			lerror = g_error_copy (lerror);
990 		g_hash_table_insert (error_blobs_hash, lerror, GINT_TO_POINTER (1));
991 		SQLITE3_CALL (sqlite3_result_blob) (ctx, lerror, sizeof (GError), NULL);
992 	}
993 	else if (!value || gda_value_is_null (value))
994 		SQLITE3_CALL (sqlite3_result_null) (ctx);
995 	else  if (G_VALUE_TYPE (value) == G_TYPE_INT)
996 		SQLITE3_CALL (sqlite3_result_int) (ctx, g_value_get_int (value));
997 	else if (G_VALUE_TYPE (value) == G_TYPE_INT64)
998 		SQLITE3_CALL (sqlite3_result_int64) (ctx, g_value_get_int64 (value));
999 	else if (G_VALUE_TYPE (value) == G_TYPE_DOUBLE)
1000 		SQLITE3_CALL (sqlite3_result_double) (ctx, g_value_get_double (value));
1001 	else if (G_VALUE_TYPE (value) == GDA_TYPE_BLOB) {
1002 		GdaBlob *blob;
1003 		GdaBinary *bin;
1004 		blob = (GdaBlob *) gda_value_get_blob (value);
1005 		bin = (GdaBinary *) blob;
1006 		if (blob->op &&
1007 		    (bin->binary_length != gda_blob_op_get_length (blob->op)))
1008 			gda_blob_op_read_all (blob->op, blob);
1009 		SQLITE3_CALL (sqlite3_result_blob) (ctx, blob->data.data, blob->data.binary_length, SQLITE_TRANSIENT);
1010 	}
1011 	else if (G_VALUE_TYPE (value) == GDA_TYPE_BINARY) {
1012 		const GdaBinary *bin;
1013 		bin = gda_value_get_binary (value);
1014 		SQLITE3_CALL (sqlite3_result_blob) (ctx, bin->data, bin->binary_length, SQLITE_TRANSIENT);
1015 	}
1016 	else {
1017 		gchar *str = gda_value_stringify (value);
1018 		SQLITE3_CALL (sqlite3_result_text) (ctx, str, -1, SQLITE_TRANSIENT);
1019 		g_free (str);
1020 	}
1021 
1022 	return SQLITE_OK;
1023 }
1024 
1025 static int
virtualRowid(sqlite3_vtab_cursor * cur,sqlite_int64 * pRowid)1026 virtualRowid (sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid)
1027 {
1028 	VirtualCursor *cursor = (VirtualCursor*) cur;
1029 
1030 	TRACE ((VirtualTable*) cur->pVtab, cur);
1031 
1032 	*pRowid = ((sqlite_int64) cursor->row) + (((sqlite_int64) cursor->data->rowid_offset) << 32);
1033 	return SQLITE_OK;
1034 }
1035 
1036 /* NEVER returns %NULL */
1037 static GValue *
create_value_from_sqlite3_value_notype(sqlite3_value * svalue)1038 create_value_from_sqlite3_value_notype (sqlite3_value *svalue)
1039 {
1040 	GValue *value;
1041 	value = g_new0 (GValue, 1);
1042 
1043 	switch (SQLITE3_CALL (sqlite3_value_type) (svalue)) {
1044 	case SQLITE_INTEGER:
1045 		g_value_init (value, G_TYPE_INT64);
1046 		g_value_set_int64 (value, SQLITE3_CALL (sqlite3_value_int64) (svalue));
1047 		break;
1048 	case SQLITE_FLOAT:
1049 		g_value_init (value, G_TYPE_DOUBLE);
1050 		g_value_set_double (value, SQLITE3_CALL (sqlite3_value_double) (svalue));
1051 		break;
1052 	case SQLITE_BLOB: {
1053 		GdaBinary *bin;
1054 		g_value_init (value, GDA_TYPE_BINARY);
1055 		bin = g_new0 (GdaBinary, 1);
1056 		bin->binary_length = SQLITE3_CALL (sqlite3_value_bytes) (svalue);
1057 		if (bin->binary_length > 0) {
1058 			bin->data = g_new (guchar, bin->binary_length);
1059 			memcpy (bin->data, SQLITE3_CALL (sqlite3_value_blob) (svalue),
1060 				bin->binary_length);
1061 		}
1062 		else
1063 			bin->binary_length = 0;
1064 		gda_value_take_binary (value, bin);
1065 		break;
1066 	}
1067 	case SQLITE_NULL:
1068 		gda_value_set_null (value);
1069 		break;
1070 	case SQLITE3_TEXT:
1071 	default:
1072 		g_value_init (value, G_TYPE_STRING);
1073 		g_value_set_string (value, (gchar *) SQLITE3_CALL (sqlite3_value_text) (svalue));
1074 		break;
1075 	}
1076 	return value;
1077 }
1078 
1079 /*
1080  * Returns: a new array of @argc values, and %NULL if @argc = 0
1081  */
1082 static GValue **
create_gvalues_array_from_sqlite3_array(int argc,sqlite3_value ** argv)1083 create_gvalues_array_from_sqlite3_array (int argc, sqlite3_value **argv)
1084 {
1085 	GValue **array;
1086 	gint i;
1087 	if (argc == 0)
1088 		return NULL;
1089 	array = g_new (GValue *, argc);
1090 	for (i = 0; i < argc; i++)
1091 		array[i] = create_value_from_sqlite3_value_notype (argv[i]);
1092 	return array;
1093 }
1094 
1095 static void
virtual_table_manage_real_data_model(VirtualTable * vtable,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)1096 virtual_table_manage_real_data_model (VirtualTable *vtable, int idxNum, const char *idxStr,
1097 				      int argc, sqlite3_value **argv)
1098 {
1099 	/*g_print ("================== %s (VTable=> %p, %s)\n", __FUNCTION__,
1100 	  vtable, vtable->td->table_name);*/
1101 	if (!vtable->td->spec->create_filtered_model_func && !vtable->td->spec->create_model_func)
1102 		return;
1103 
1104 	if (vtable->td->real_model) {
1105 		g_object_unref (vtable->td->real_model);
1106 		vtable->td->real_model = NULL;
1107 	}
1108 
1109 	/* actual data model creation */
1110 	if (vtable->td->spec->create_filtered_model_func) {
1111 		GValue **gargv;
1112 		gargv = create_gvalues_array_from_sqlite3_array (argc, argv);
1113 		vtable->td->real_model = vtable->td->spec->create_filtered_model_func (vtable->td->spec,
1114 										       idxNum, idxStr,
1115 										       argc, gargv);
1116 		if (gargv) {
1117 			gint i;
1118 			for (i = 0; i < argc; i++)
1119 				gda_value_free (gargv[i]);
1120 			g_free (gargv);
1121 		}
1122 	}
1123 	else if (vtable->td->spec->create_model_func)
1124 		vtable->td->real_model = vtable->td->spec->create_model_func (vtable->td->spec);
1125 	if (! vtable->td->real_model)
1126 		return;
1127 
1128 	/* columns if not yet created */
1129 	if (! vtable->td->columns && vtable->td->spec->create_columns_func)
1130 		vtable->td->columns = vtable->td->spec->create_columns_func (vtable->td->spec, NULL);
1131 
1132 	if (vtable->td->columns) {
1133 		/* columns */
1134 		GList *list;
1135 		guint i, ncols;
1136 		ncols = gda_data_model_get_n_columns (vtable->td->real_model);
1137 		g_assert (ncols == g_list_length (vtable->td->columns));
1138 		for (i = 0, list = vtable->td->columns;
1139 		     i < ncols;
1140 		     i++, list = list->next) {
1141 			GdaColumn *mcol = gda_data_model_describe_column (vtable->td->real_model, i);
1142 			GdaColumn *ccol = (GdaColumn*) list->data;
1143 			if (gda_column_get_g_type (mcol) == GDA_TYPE_NULL)
1144 				gda_column_set_g_type (mcol, gda_column_get_g_type (ccol));
1145 		}
1146 	}
1147 
1148 #ifdef GDA_DEBUG_VIRTUAL
1149 	g_print ("Created real model %p for table %s\n", vtable->td->real_model, vtable->td->table_name);
1150 #endif
1151 }
1152 
1153 static int
virtualFilter(sqlite3_vtab_cursor * pVtabCursor,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)1154 virtualFilter (sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv)
1155 {
1156 	VirtualCursor *cursor = (VirtualCursor*) pVtabCursor;
1157 	VirtualTable *vtable = (VirtualTable*) pVtabCursor->pVtab;
1158 
1159 	TRACE (pVtabCursor->pVtab, pVtabCursor);
1160 #ifdef GDA_DEBUG_VIRTUAL
1161 	g_print ("\tidxStr=[%s], idxNum=[%d]\n", idxStr, idxNum);
1162 #endif
1163 
1164 	/* find a VirtualFilteredData corresponding to this filter */
1165 	VirtualFilteredData *data = NULL;
1166 	g_assert (vtable->td->context.current_vcontext);
1167 	GArray *values_array = vtable->td->context.current_vcontext->context_data;
1168 
1169 	if (values_array->len > 0) {
1170 		guint i;
1171 		for (i = 0; i < values_array->len; i++) {
1172 			VirtualFilteredData *vd;
1173 			vd = g_array_index (values_array, VirtualFilteredData*, i);
1174 			if (vd->reuseable &&
1175 			    (vd->idxNum == idxNum) &&
1176 			    (vd->argc == argc) &&
1177 			    ((!idxStr && !vd->idxStr) || (idxStr && vd->idxStr && !strcmp (idxStr, vd->idxStr)))) {
1178 				GValue **avalues;
1179 				gint i;
1180 				gboolean equal = TRUE;
1181 				avalues = create_gvalues_array_from_sqlite3_array (argc, argv);
1182 				for (i = 0; i < argc; i++) {
1183 					GValue *v1, *v2;
1184 					v1 = vd->argv [i];
1185 					v2 = avalues [i];
1186 
1187 					if (! ((!v1 && !v2) ||
1188 					       (v1 && v2 && (G_VALUE_TYPE (v1) == G_VALUE_TYPE (v2)) &&
1189 						!gda_value_differ (v1, v2)))) {
1190 						equal = FALSE;
1191 						break;
1192 					}
1193 				}
1194 				for (i = 0; i < argc; i++) {
1195 					GValue *v2;
1196 					v2 = avalues [i];
1197 					if (v2)
1198 						gda_value_free (v2);
1199 				}
1200 				g_free (avalues);
1201 
1202 				if (equal) {
1203 					data = vd;
1204 					break;
1205 				}
1206 			}
1207 		}
1208 	}
1209 #ifdef DEBUG_VCONTEXT
1210 	if (data)
1211 		g_print ("REUSE VData %p\n", data);
1212 #endif
1213 
1214 	if (!data) {
1215 		virtual_table_manage_real_data_model (vtable, idxNum, idxStr, argc, argv);
1216 		if (! vtable->td->real_model)
1217 			return SQLITE_ERROR;
1218 		data = virtual_filtered_data_new (vtable, vtable->td->real_model, idxNum, idxStr, argc, argv);
1219 		g_array_prepend_val (values_array, data);
1220 #ifdef DEBUG_VCONTEXT
1221 		g_print ("VData %p prepended to array %p wt %d\n", data, values_array,
1222 			 values_array->len);
1223 #endif
1224 		if (values_array->len > MAX_VDATA_NUMBER) {
1225 			VirtualFilteredData *ldata;
1226 			gint index;
1227 			index = values_array->len - 1;
1228 			ldata = g_array_index (values_array, VirtualFilteredData*, index);
1229 			_gda_vconnection_virtual_filtered_data_unref (ldata);
1230 			g_array_remove_index (values_array, index);
1231 		}
1232 	}
1233 
1234 	if (cursor->data != data) {
1235 		if (cursor->data)
1236 			_gda_vconnection_virtual_filtered_data_unref (cursor->data);
1237 		cursor->data = virtual_filtered_data_ref (data);
1238 	}
1239 
1240 	/* initialize cursor */
1241 	cursor->row = -1;
1242 
1243 	return virtualNext (pVtabCursor);
1244 }
1245 
1246 #ifdef GDA_DEBUG_VIRTUAL
1247 
1248 static void
index_info_dump(sqlite3_index_info * pIdxInfo,gboolean dump_out)1249 index_info_dump (sqlite3_index_info *pIdxInfo, gboolean dump_out)
1250 {
1251 	int nc;
1252 	if (dump_out) {
1253 		g_print ("Dump of OUT sqlite3_index_info [%p]\n", pIdxInfo);
1254 		for (nc = 0; nc < pIdxInfo->nConstraint; nc++) {
1255 			struct sqlite3_index_constraint_usage *cons;
1256 			cons = &(pIdxInfo->aConstraintUsage[nc]);
1257 			g_print ("sqlite3_index_constraint_usage[%d]\n", nc);
1258 			g_print ("   argvIndex=%d\n", cons->argvIndex);
1259 			g_print ("   omit=%d\n", cons->omit);
1260 		}
1261 		g_print ("idxNum=%d\n", pIdxInfo->idxNum);
1262 		g_print ("orderByConsumed=%d\n", pIdxInfo->orderByConsumed);
1263 	}
1264 	else {
1265 		g_print ("Dump of IN sqlite3_index_info [%p]\n", pIdxInfo);
1266 		for (nc = 0; nc < pIdxInfo->nConstraint; nc++) {
1267 			struct sqlite3_index_constraint *cons;
1268 			cons = &(pIdxInfo->aConstraint[nc]);
1269 			g_print ("sqlite3_index_constraint[%d]\n", nc);
1270 			g_print ("   iColumn=%d\n", cons->iColumn);
1271 			g_print ("   op=%d\n", cons->op);
1272 			g_print ("   usable=%d\n", cons->usable);
1273 			g_print ("   iTermOffset=%d\n", cons->iTermOffset);
1274 		}
1275 
1276 		for (nc = 0; nc < pIdxInfo->nOrderBy; nc++) {
1277 			struct sqlite3_index_orderby *cons;
1278 			cons = &(pIdxInfo->aOrderBy[nc]);
1279 			g_print ("sqlite3_index_orderby[%d]\n", nc);
1280 			g_print ("   iColumn=%d\n", cons->iColumn);
1281 			g_print ("   desc=%d\n", cons->desc);
1282 		}
1283 	}
1284 }
1285 #endif
1286 
1287 static void
map_sqlite3_info_to_gda_filter(sqlite3_index_info * info,GdaVconnectionDataModelFilter * filter)1288 map_sqlite3_info_to_gda_filter (sqlite3_index_info *info, GdaVconnectionDataModelFilter *filter)
1289 {
1290 	memset (filter, 0, sizeof (GdaVconnectionDataModelFilter));
1291 	if (info->nConstraint > 0) {
1292 		gint i, j;
1293 		filter->aConstraint = g_new (struct GdaVirtualConstraint, info->nConstraint);
1294 		filter->aConstraintUsage = g_new (struct GdaVirtualConstraintUsage, info->nConstraint);
1295 		for (i = 0, j = 0; i < info->nConstraint; i++) {
1296 			if (! info->aConstraint[i].usable)
1297 				continue;
1298 
1299 			switch (info->aConstraint[i].op) {
1300 			case SQLITE_INDEX_CONSTRAINT_EQ:
1301 				filter->aConstraint[j].op = GDA_SQL_OPERATOR_TYPE_EQ;
1302 				break;
1303 			case SQLITE_INDEX_CONSTRAINT_GT:
1304 				filter->aConstraint[j].op = GDA_SQL_OPERATOR_TYPE_GT;
1305 				break;
1306 			case SQLITE_INDEX_CONSTRAINT_LE:
1307 				filter->aConstraint[j].op = GDA_SQL_OPERATOR_TYPE_LEQ;
1308 				break;
1309 			case SQLITE_INDEX_CONSTRAINT_LT:
1310 				filter->aConstraint[j].op = GDA_SQL_OPERATOR_TYPE_LT;
1311 				break;
1312 			case SQLITE_INDEX_CONSTRAINT_GE:
1313 				filter->aConstraint[j].op = GDA_SQL_OPERATOR_TYPE_GEQ;
1314 				break;
1315 			case SQLITE_INDEX_CONSTRAINT_MATCH:
1316 				filter->aConstraint[j].op = GDA_SQL_OPERATOR_TYPE_REGEXP;
1317 				break;
1318 #if HAVE_SQLITE
1319 			case SQLITE_INDEX_CONSTRAINT_LIKE:
1320 				filter->aConstraint[j].op = GDA_SQL_OPERATOR_TYPE_LIKE;
1321 				break;
1322 			case SQLITE_INDEX_CONSTRAINT_GLOB:
1323 				filter->aConstraint[j].op = GDA_SQL_OPERATOR_TYPE_GLOB;
1324 				break;
1325 #endif
1326 			default:
1327 				g_assert_not_reached ();
1328 			}
1329 			filter->aConstraint[j].iColumn = info->aConstraint[i].iColumn;
1330 
1331 			filter->aConstraintUsage[j].argvIndex = 0;
1332 			filter->aConstraintUsage[j].omit = FALSE;
1333 			j++;
1334 		}
1335 		filter->nConstraint = j;
1336 	}
1337 	filter->nOrderBy = info->nOrderBy;
1338 	if (filter->nOrderBy > 0) {
1339 		gint i;
1340 		filter->aOrderBy = g_new (struct GdaVirtualOrderby, filter->nOrderBy);
1341 		for (i = 0; i < info->nOrderBy; i++) {
1342 			filter->aOrderBy[i].iColumn = info->aOrderBy[i].iColumn;
1343 			filter->aOrderBy[i].desc = info->aOrderBy[i].desc ? TRUE : FALSE;
1344 		}
1345 	}
1346 	filter->idxNum = 0;
1347 	filter->idxPointer = NULL;
1348 	filter->orderByConsumed = FALSE;
1349 	filter->estimatedCost = info->estimatedCost;
1350 }
1351 
1352 /*
1353  * Also frees @filter's dynamically allocated parts
1354  */
1355 static void
map_consume_gda_filter_to_sqlite3_info(GdaVconnectionDataModelFilter * filter,sqlite3_index_info * info)1356 map_consume_gda_filter_to_sqlite3_info (GdaVconnectionDataModelFilter *filter, sqlite3_index_info *info)
1357 {
1358 	g_assert (filter->nConstraint == info->nConstraint);
1359 	if (info->nConstraint > 0) {
1360 		gint i, j;
1361 		for (i = 0, j = 0; i < info->nConstraint; i++) {
1362 			if (! info->aConstraint[i].usable)
1363 				continue;
1364 			info->aConstraintUsage[i].argvIndex = filter->aConstraintUsage[j].argvIndex;
1365 			info->aConstraintUsage[i].omit = filter->aConstraintUsage[j].omit ? 1 : 0;
1366 			j++;
1367 		}
1368 		g_free (filter->aConstraint);
1369 		g_free (filter->aConstraintUsage);
1370 
1371 	}
1372 	if (filter->nOrderBy > 0)
1373 		g_free (filter->aOrderBy);
1374 	info->idxNum = filter->idxNum;
1375 	info->idxStr = (char*) filter->idxPointer;
1376 	info->needToFreeIdxStr = 0;
1377 	info->orderByConsumed = filter->orderByConsumed ? 1 : 0;
1378 	info->estimatedCost = filter->estimatedCost;
1379 }
1380 
1381 static int
virtualBestIndex(sqlite3_vtab * tab,sqlite3_index_info * pIdxInfo)1382 virtualBestIndex (sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo)
1383 {
1384 	VirtualTable *vtable = (VirtualTable *) tab;
1385 
1386 	TRACE (tab, NULL);
1387 #ifdef GDA_DEBUG_VIRTUAL
1388 	index_info_dump (pIdxInfo, FALSE);
1389 #endif
1390 
1391 	if (vtable->td->spec->create_filter_func) {
1392 		GdaVconnectionDataModelFilter filter;
1393 		map_sqlite3_info_to_gda_filter (pIdxInfo, &filter);
1394 		vtable->td->spec->create_filter_func (vtable->td->spec, &filter);
1395 		map_consume_gda_filter_to_sqlite3_info (&filter, pIdxInfo);
1396 #ifdef GDA_DEBUG_VIRTUAL
1397 		index_info_dump (pIdxInfo, TRUE);
1398 #endif
1399 	}
1400 
1401 	return SQLITE_OK;
1402 }
1403 
1404 /*
1405  *
1406  * Returns: >= 0 if Ok, -1 on error
1407  */
1408 static gint
param_name_to_number(gint maxrows,const gchar * str)1409 param_name_to_number (gint maxrows, const gchar *str)
1410 {
1411 	gchar *endptr [1];
1412 	long int i;
1413 	i = strtol (str, endptr, 10);
1414 	if ((**endptr == '\0') && (i < maxrows) && (i >= 0))
1415 		return i;
1416 	else
1417 		return -1;
1418 }
1419 
1420 /*
1421  * optype value: see virtualUpdate()
1422  */
1423 static int
update_data_select_model(sqlite3_vtab * tab,gint optype,int nData,sqlite3_value ** apData)1424 update_data_select_model (sqlite3_vtab *tab, gint optype, int nData, sqlite3_value **apData)
1425 {
1426 	VirtualTable *vtable = (VirtualTable *) tab;
1427 
1428 	/* determine parameters required to execute MOD statement */
1429 	GdaStatement *stmt = NULL;
1430 	ParamType ptype;
1431 	switch (optype) {
1432 	case 1:
1433 		ptype = PARAMS_DELETE;
1434 		if (! vtable->td->modif_stmt [ptype])
1435 			g_object_get (vtable->td->real_model, "delete-stmt", &stmt, NULL);
1436 		break;
1437 	case 2:
1438 		ptype = PARAMS_INSERT;
1439 		if (! vtable->td->modif_stmt [ptype])
1440 			g_object_get (vtable->td->real_model, "insert-stmt", &stmt, NULL);
1441 		break;
1442 	case 3:
1443 		ptype = PARAMS_UPDATE;
1444 		if (! vtable->td->modif_stmt [ptype])
1445 			g_object_get (vtable->td->real_model, "update-stmt", &stmt, NULL);
1446 		break;
1447 	default:
1448 		g_assert_not_reached ();
1449 	}
1450 
1451 	if (! vtable->td->modif_stmt [ptype]) {
1452 		if (! stmt) {
1453 			tab->zErrMsg = SQLITE3_CALL (sqlite3_mprintf)
1454 				(_("No statement specified to modify the data"));
1455 			return SQLITE_READONLY;
1456 		}
1457 
1458 		GdaSet *params;
1459 		if (! gda_statement_get_parameters (stmt, &params, NULL) || !params) {
1460 			tab->zErrMsg = SQLITE3_CALL (sqlite3_mprintf)
1461 				(_("Invalid statement specified to modify the data"));
1462 			g_object_unref (stmt);
1463 			return SQLITE_READONLY;
1464 		}
1465 		vtable->td->modif_stmt [ptype] = stmt;
1466 		vtable->td->modif_params [ptype] = params;
1467 	}
1468 	stmt = vtable->td->modif_stmt [ptype];
1469 
1470 	/* bind parameters */
1471 	GSList *list;
1472 
1473 	for (list = vtable->td->modif_params [ptype]->holders; list; list = list->next) {
1474 		const gchar *id;
1475 		GdaHolder *holder = GDA_HOLDER (list->data);
1476 		gboolean holder_value_set = FALSE;
1477 
1478 		id = gda_holder_get_id (holder);
1479 		if (!id) {
1480 			tab->zErrMsg = SQLITE3_CALL (sqlite3_mprintf)
1481 				(_("Invalid parameter in statement to modify the data"));
1482 			return SQLITE_READONLY;
1483 		}
1484 		if (*id == '+' && id[1]) {
1485 			long int i;
1486 			i = param_name_to_number (vtable->td->n_columns, id+1);
1487 			if (i >= 0) {
1488 				GType type;
1489 				GValue *value;
1490 				type = gda_column_get_g_type (gda_data_model_describe_column (vtable->td->real_model, i));
1491 				if ((type != GDA_TYPE_NULL) && SQLITE3_CALL (sqlite3_value_text) (apData [i+2]))
1492 					value = gda_value_new_from_string ((const gchar*) SQLITE3_CALL (sqlite3_value_text) (apData [i+2]), type);
1493 				else
1494 					value = gda_value_new_null ();
1495 				if (gda_holder_take_value (holder, value, NULL))
1496 					holder_value_set = TRUE;
1497 			}
1498 		}
1499 		else if (*id == '-') {
1500 			gint64 rowid = SQLITE3_CALL (sqlite3_value_int64) (apData [0]);
1501 			long int i;
1502 			const GValue *value;
1503 
1504 			i = param_name_to_number (vtable->td->n_columns, id+1);
1505 			value = get_data_value (vtable, NULL, -1, rowid, i, NULL);
1506 			if (value && gda_holder_set_value (holder, value, NULL))
1507 				holder_value_set = TRUE;
1508 		}
1509 
1510 		if (! holder_value_set) {
1511 			GdaSet *exec_set;
1512 			GdaHolder *eh;
1513 			g_object_get (vtable->td->real_model, "exec-params",
1514 				      &exec_set, NULL);
1515 			if (! exec_set) {
1516 				/* can't give value to param named @id */
1517 				tab->zErrMsg = SQLITE3_CALL (sqlite3_mprintf)
1518 					(_("Invalid parameter in statement to modify the data"));
1519 				return SQLITE_READONLY;
1520 			}
1521 			eh = gda_set_get_holder (exec_set, id);
1522 			if (! eh ||
1523 			    ! gda_holder_set_bind (holder, eh, NULL)) {
1524 				/* can't give value to param named @id */
1525 				tab->zErrMsg = SQLITE3_CALL (sqlite3_mprintf)
1526 					(_("Invalid parameter in statement to modify the data"));
1527 				return SQLITE_READONLY;
1528 			}
1529 		}
1530 	}
1531 
1532 	GdaConnection *cnc;
1533 	cnc = gda_data_select_get_connection (GDA_DATA_SELECT (vtable->td->real_model));
1534 
1535 	GError *lerror = NULL;
1536 #ifdef GDA_DEBUG_NO
1537 	gchar *sql;
1538 	sql = gda_statement_to_sql (stmt, NULL, NULL);
1539 	g_print ("SQL: [%s] ", sql);
1540 	g_free (sql);
1541 	sql = gda_statement_to_sql_extended (stmt, cnc, vtable->td->modif_params [ptype], GDA_STATEMENT_SQL_PRETTY, NULL, &lerror);
1542 	if (sql) {
1543 		g_print ("With params: [%s]\n", sql);
1544 		g_free (sql);
1545 	}
1546 	else {
1547 		g_print ("params ERROR [%s]\n", lerror && lerror->message ? lerror->message : "No detail");
1548 	}
1549 	g_clear_error (&lerror);
1550 #endif
1551 
1552 	if (!cnc ||
1553 	    (gda_connection_statement_execute_non_select (cnc, stmt,
1554 							  vtable->td->modif_params [ptype],
1555 							  NULL, &lerror) == -1)) {
1556 		/* failed to execute */
1557 		tab->zErrMsg = SQLITE3_CALL (sqlite3_mprintf)
1558 			(_("Failed to modify data: %s"),
1559 			 lerror && lerror->message ? lerror->message : _("No detail"));
1560 		g_clear_error (&lerror);
1561 		return SQLITE_READONLY;
1562 	}
1563 	return SQLITE_OK;
1564 }
1565 
1566 /*
1567  *    apData[0]  apData[1]  apData[2..]
1568  *
1569  *    INTEGER                              DELETE
1570  *
1571  *    INTEGER    NULL       (nCol args)    UPDATE (do not set rowid)
1572  *    INTEGER    INTEGER    (nCol args)    UPDATE (with SET rowid = <arg1>)
1573  *
1574  *    NULL       NULL       (nCol args)    INSERT INTO (automatic rowid value)
1575  *    NULL       INTEGER    (nCol args)    INSERT (incl. rowid value)
1576  */
1577 static int
virtualUpdate(sqlite3_vtab * tab,int nData,sqlite3_value ** apData,sqlite_int64 * pRowid)1578 virtualUpdate (sqlite3_vtab *tab, int nData, sqlite3_value **apData, sqlite_int64 *pRowid)
1579 {
1580 	VirtualTable *vtable = (VirtualTable *) tab;
1581 	const gchar *api_misuse_error = NULL;
1582 	gint optype; /* 1 => DELETE
1583 		      * 2 => INSERT
1584 		      * 3 => UPDATE
1585 		      */
1586 
1587 	TRACE (tab, NULL);
1588 
1589 	g_assert (vtable->td->context.current_vcontext);
1590 	GArray *values_array = vtable->td->context.current_vcontext->context_data;
1591 	if (values_array) {
1592 		guint i;
1593 		for (i = 0; i < values_array->len; i++) {
1594 			VirtualFilteredData *data;
1595 			data = g_array_index (values_array, VirtualFilteredData*, i);
1596 			data->reuseable = FALSE;
1597 		}
1598 	}
1599 
1600 	/* determine operation type */
1601 	if (nData == 1)
1602 		optype = 1;
1603 	else if ((nData > 1) && (SQLITE3_CALL (sqlite3_value_type) (apData[0]) == SQLITE_NULL)) {
1604 		optype = 2;
1605 		if (SQLITE3_CALL (sqlite3_value_type) (apData[1]) != SQLITE_NULL) {
1606 			/* argc>1 and argv[0] is not NULL: rowid is imposed by SQLite
1607 			 * which is not supported */
1608 			return SQLITE_READONLY;
1609 		}	}
1610 	else if ((nData > 1) && (SQLITE3_CALL (sqlite3_value_type) (apData[0]) == SQLITE_INTEGER)) {
1611 		optype = 3;
1612 		if (SQLITE3_CALL (sqlite3_value_int) (apData[0]) !=
1613 		    SQLITE3_CALL (sqlite3_value_int) (apData[1])) {
1614 			/* argc>1 and argv[0]==argv[1]: rowid is imposed by SQLite
1615 			 * which is not supported */
1616 			return SQLITE_READONLY;
1617 		}
1618 	}
1619 	else
1620 		return SQLITE_MISUSE;
1621 
1622 	/* handle data model */
1623 	if (! vtable->td->real_model) {
1624 		virtual_table_manage_real_data_model (vtable, -1, NULL, 0, NULL);
1625 		if (! vtable->td->real_model)
1626 			return SQLITE_ERROR;
1627 	}
1628 
1629 	GdaDataModelAccessFlags access_flags;
1630 	access_flags = gda_data_model_get_access_flags (vtable->td->real_model);
1631 	if (((optype == 1) && ! (access_flags & GDA_DATA_MODEL_ACCESS_DELETE)) ||
1632 	    ((optype == 2) && ! (access_flags & GDA_DATA_MODEL_ACCESS_INSERT)) ||
1633 	    ((optype == 3) && ! (access_flags & GDA_DATA_MODEL_ACCESS_UPDATE))) {
1634 		/* we can't use vtable->td->real_model because it can't be accessed correctly */
1635 		if (GDA_IS_DATA_SELECT (vtable->td->real_model))
1636 			return update_data_select_model (tab, optype, nData, apData);
1637 		else {
1638 			TO_IMPLEMENT;
1639 			tab->zErrMsg = SQLITE3_CALL (sqlite3_mprintf)
1640 				(_("Data model representing the table is read only"));
1641 			return SQLITE_READONLY;
1642 		}
1643 	}
1644 
1645 	/* REM: when using the values of apData[], the limit is
1646 	 * (nData -1 ) and not nData because the last column of the corresponding CREATE TABLE ...
1647 	 * is an internal hidden field which does not correspond to any column of the real data model
1648 	 */
1649 
1650 	if (optype == 1) {
1651 		/* DELETE */
1652 		if (SQLITE3_CALL (sqlite3_value_type) (apData[0]) == SQLITE_INTEGER) {
1653 			gint rowid = SQLITE3_CALL (sqlite3_value_int) (apData [0]);
1654 			return gda_data_model_remove_row (vtable->td->real_model, rowid, NULL) ?
1655 				SQLITE_OK : SQLITE_READONLY;
1656 		}
1657 		else {
1658 			api_misuse_error = "argc==1 and argv[0] is not an integer";
1659 			goto api_misuse;
1660 		}
1661 	}
1662 	else if (optype == 2) {
1663 		/* INSERT */
1664 		gint newrow, i;
1665 		GList *values = NULL;
1666 
1667 		for (i = 2; i < (nData - 1); i++) {
1668 			GType type;
1669 			GValue *value;
1670 			type = gda_column_get_g_type (gda_data_model_describe_column (vtable->td->real_model, i - 2));
1671 			if ((type != GDA_TYPE_NULL) && SQLITE3_CALL (sqlite3_value_text) (apData [i]))
1672 				value = gda_value_new_from_string ((const gchar*) SQLITE3_CALL (sqlite3_value_text) (apData [i]), type);
1673 			else
1674 				value = gda_value_new_null ();
1675 			/*g_print ("TXT #%s# => value %p (type=%s) apData[]=%p\n",
1676 			  SQLITE3_CALL (sqlite3_value_text) (apData [i]), value,
1677 			  g_type_name (type), apData[i]);*/
1678 			values = g_list_prepend (values, value);
1679 		}
1680 		values = g_list_reverse (values);
1681 
1682 		newrow = gda_data_model_append_values (vtable->td->real_model, values, NULL);
1683 		g_list_foreach (values, (GFunc) gda_value_free, NULL);
1684 		g_list_free (values);
1685 		if (newrow < 0)
1686 			return SQLITE_READONLY;
1687 
1688 		*pRowid = newrow;
1689 	}
1690 	else if (optype == 3) {
1691 		/* UPDATE */
1692 		gint i;
1693 
1694 
1695 		for (i = 2; i < (nData - 1); i++) {
1696 			GValue *value;
1697 			GType type;
1698 			gint rowid = SQLITE3_CALL (sqlite3_value_int) (apData [0]);
1699 			gboolean res;
1700 			GError *error = NULL;
1701 
1702 			/*g_print ("%d => %s\n", i, SQLITE3_CALL (sqlite3_value_text) (apData [i]));*/
1703 			type = gda_column_get_g_type (gda_data_model_describe_column (vtable->td->real_model, i - 2));
1704 			value = gda_value_new_from_string ((const gchar*) SQLITE3_CALL (sqlite3_value_text) (apData [i]), type);
1705 			res = gda_data_model_set_value_at (vtable->td->real_model, i - 2, rowid,
1706 							   value, &error);
1707 			gda_value_free (value);
1708 			if (!res) {
1709 				/*g_print ("Error: %s\n", error && error->message ? error->message : "???");*/
1710 				g_clear_error (&error);
1711 				return SQLITE_READONLY;
1712 			}
1713 		}
1714 		return SQLITE_OK;
1715 	}
1716 	else {
1717 		api_misuse_error = "argc>1 and argv[0] is not NULL and not an integer";
1718 		goto api_misuse;
1719 	}
1720 
1721 	return SQLITE_OK;
1722 
1723  api_misuse:
1724 	g_warning ("Error in the xUpdate SQLite's virtual method: %s\n"
1725 		   "this is an SQLite error, please report it", api_misuse_error);
1726 	return SQLITE_ERROR;
1727 }
1728 
1729 static int
virtualBegin(G_GNUC_UNUSED sqlite3_vtab * tab)1730 virtualBegin (G_GNUC_UNUSED sqlite3_vtab *tab)
1731 {
1732 	VirtualTable *vtable = (VirtualTable *) tab;
1733 	TRACE (tab, NULL);
1734 
1735 	if (vtable->locked)
1736 		return SQLITE_ERROR;
1737 	else {
1738 		vtable->locked = TRUE;
1739 		return SQLITE_OK;
1740 	}
1741 }
1742 
1743 static int
virtualSync(G_GNUC_UNUSED sqlite3_vtab * tab)1744 virtualSync (G_GNUC_UNUSED sqlite3_vtab *tab)
1745 {
1746 	TRACE (tab, NULL);
1747 	/* no documentation currently available, don't do anything */
1748 	return SQLITE_OK;
1749 }
1750 
1751 static int
virtualCommit(G_GNUC_UNUSED sqlite3_vtab * tab)1752 virtualCommit (G_GNUC_UNUSED sqlite3_vtab *tab)
1753 {
1754 	VirtualTable *vtable = (VirtualTable *) tab;
1755 	TRACE (tab, NULL);
1756 
1757 	vtable->locked = FALSE;
1758 	return SQLITE_OK;
1759 }
1760 
1761 static int
virtualRollback(G_GNUC_UNUSED sqlite3_vtab * tab)1762 virtualRollback (G_GNUC_UNUSED sqlite3_vtab *tab)
1763 {
1764 	VirtualTable *vtable = (VirtualTable *) tab;
1765 	TRACE (tab, NULL);
1766 
1767 	vtable->locked = FALSE;
1768 	return SQLITE_OK;
1769 }
1770 
1771 static int
virtualRename(G_GNUC_UNUSED sqlite3_vtab * pVtab,G_GNUC_UNUSED const char * zNew)1772 virtualRename (G_GNUC_UNUSED sqlite3_vtab *pVtab, G_GNUC_UNUSED const char *zNew)
1773 {
1774 	TRACE (pVtab, NULL);
1775 	/* not yet analysed and implemented */
1776 	return SQLITE_OK;
1777 }
1778