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 (®istering);
134 if (type == 0)
135 type = g_type_register_static (GDA_TYPE_VIRTUAL_PROVIDER, "GdaVproviderDataModel", &info, 0);
136 g_mutex_unlock (®istering);
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 (©, G_VALUE_TYPE (cvalue));
876 g_value_copy (cvalue, ©);
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, ¶ms, 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