00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include <glib/gstdio.h>
00026 #include <sqlite.h>
00027 #include <glib.h>
00028 #include <libintl.h>
00029 #include "qof.h"
00030
00031 #define _(String) dgettext (GETTEXT_PACKAGE, String)
00032 #define QOF_MOD_SQLITE "qof-sqlite-module"
00033 #define ACCESS_METHOD "sqlite"
00034
00035
00036 #define PRIORITY_HIGH 9
00037
00038 #define PRIORITY_STANDARD 5
00039
00040 #define PRIORITY_LOW 0
00041
00042 #define QSQL_ERROR -1
00043
00044 #define END_DB_VERSION " dbversion int );"
00045
00046 static QofLogModule log_module = QOF_MOD_SQLITE;
00047
00048 typedef enum
00049 {
00050
00051 SQL_NONE = 0,
00052
00053 SQL_CREATE,
00054
00055 SQL_LOAD,
00056
00057 SQL_WRITE,
00058
00059 SQL_INSERT,
00060
00061 SQL_DELETE,
00062
00063 SQL_UPDATE
00064 }QsqlStatementType;
00065
00066 typedef struct
00067 {
00068 QofBackend be;
00069 sqlite *sqliteh;
00070 QsqlStatementType stm_type;
00071 gint dbversion;
00072 gint create_handler;
00073 gint delete_handler;
00074 const gchar *fullpath;
00075 gchar *err;
00076 gchar *sql_str;
00077 gboolean error;
00078 QofIdType e_type;
00079 QofBook * book;
00080 QofErrorId err_delete, err_insert, err_update, err_create;
00081 } QSQLiteBackend;
00082
00083 static gchar*
00084 qsql_param_to_sql(QofParam *param)
00085 {
00086 if(0 == safe_strcmp(param->param_type, QOF_TYPE_STRING))
00087 return g_strdup_printf(" %s mediumtext", param->param_name);
00088 if(0 == safe_strcmp(param->param_type, QOF_TYPE_BOOLEAN))
00089 return g_strdup_printf(" %s int", param->param_name);
00090 if(0 == safe_strcmp(param->param_type, QOF_TYPE_GUID))
00091 return g_strdup_printf(" %s char(32) PRIMARY KEY NOT NULL",
00092 param->param_name);
00093 if((0 == safe_strcmp(param->param_type, QOF_TYPE_NUMERIC))
00094 || (0 == safe_strcmp(param->param_type, QOF_TYPE_DOUBLE))
00095 || (0 == safe_strcmp(param->param_type, QOF_TYPE_DEBCRED)))
00096 {
00097 return g_strdup_printf(" %s double", param->param_name);
00098 }
00099 if(0 == safe_strcmp(param->param_type, QOF_TYPE_INT32))
00100 return g_strdup_printf(" %s int", param->param_name);
00101 #ifndef QOF_DISABLE_DEPRECATED
00102 if((0 == safe_strcmp(param->param_type, QOF_TYPE_DATE)) ||
00103 (0 == safe_strcmp(param->param_type, QOF_TYPE_TIME)))
00104 #else
00105 if(0 == safe_strcmp(param->param_type, QOF_TYPE_TIME))
00106 #endif
00107 return g_strdup_printf(" %s datetime", param->param_name);
00108 if(0 == safe_strcmp(param->param_type, QOF_TYPE_CHAR))
00109 return g_strdup_printf(" %s char(1)", param->param_name);
00110 if(0 == safe_strcmp(param->param_type, QOF_TYPE_KVP))
00111 return g_strdup_printf(" %s mediumtext", param->param_name);
00112 if(0 == safe_strcmp(param->param_type, QOF_TYPE_COLLECT))
00113 return g_strdup_printf(" %s char(32)", param->param_name);
00114 return g_strdup_printf(" %s char(32)", param->param_name);
00115 }
00116
00122 struct QsqlBuilder
00123 {
00125 QSQLiteBackend *qsql_be;
00127 QofEntity *ent;
00129 gchar *sql_str;
00131 GList *dirty_list;
00133 gboolean exists;
00135 const QofParam * dirty;
00136 };
00137
00138 static void
00139 create_param_list (QofParam *param, gpointer user_data)
00140 {
00141 struct QsqlBuilder *qb;
00142 qb = (struct QsqlBuilder *)user_data;
00143
00144 if (!g_str_has_suffix (qb->sql_str, "("))
00145 qb->sql_str = g_strconcat (qb->sql_str, ", ",
00146 param->param_name, NULL);
00147 else
00148 qb->sql_str = g_strconcat (qb->sql_str,
00149 param->param_name, NULL);
00150 }
00151
00152 static void
00153 create_each_param (QofParam *param, gpointer user_data)
00154 {
00155 gchar *value;
00156 struct QsqlBuilder *qb;
00157 qb = (struct QsqlBuilder *)user_data;
00158
00160 value = qof_util_param_to_string (qb->ent, param);
00161 if (value)
00162 g_strescape (value, NULL);
00163 if (!value)
00164 value = g_strdup ("");
00165 if (!g_str_has_suffix (qb->sql_str, "("))
00166 qb->sql_str = g_strconcat (qb->sql_str, ", \"",
00167 value, "\"", NULL);
00168 else
00169 qb->sql_str = g_strconcat (qb->sql_str, "\"",
00170 value, "\"", NULL);
00171 }
00172
00173
00174
00175
00176
00177 static void
00178 delete_event (QofEntity *ent, QofEventId event_type,
00179 gpointer handler_data, gpointer event_data)
00180 {
00181 QofBackend *be;
00182 QSQLiteBackend *qsql_be;
00183 gchar gstr[GUID_ENCODING_LENGTH+1];
00184 gchar * sql_str;
00185
00186 qsql_be = (QSQLiteBackend*)handler_data;
00187 be = (QofBackend*)qsql_be;
00188 if (!ent)
00189 return;
00190 if (0 == safe_strcmp (ent->e_type, QOF_ID_BOOK))
00191 return;
00192 ENTER (" %s", ent->e_type);
00193 switch (event_type)
00194 {
00195 case QOF_EVENT_DESTROY :
00196 {
00197 guid_to_string_buff (qof_entity_get_guid (ent), gstr);
00198 sql_str = g_strdup_printf ("DELETE from %s ",
00199 ent->e_type);
00200 sql_str = g_strconcat (sql_str,
00201 "WHERE ", QOF_TYPE_GUID, "='", gstr,
00202 "';", NULL);
00203 DEBUG (" sql_str=%s", sql_str);
00204 if(sqlite_exec (qsql_be->sqliteh, sql_str,
00205 NULL, qsql_be, &qsql_be->err) !=
00206 SQLITE_OK)
00207 {
00208 qof_error_set_be (be, qsql_be->err_delete);
00209 qsql_be->error = TRUE;
00210 PERR (" %s", qsql_be->err);
00211 }
00212 break;
00213 }
00214 default : break;
00215 }
00216 LEAVE (" ");
00217 }
00218
00219 static void
00220 create_event (QofEntity *ent, QofEventId event_type,
00221 gpointer handler_data, gpointer event_data)
00222 {
00223 QofBackend *be;
00224 struct QsqlBuilder qb;
00225 QSQLiteBackend *qsql_be;
00226
00227 qsql_be = (QSQLiteBackend*)handler_data;
00228 be = (QofBackend*)qsql_be;
00229 if (!ent)
00230 return;
00231 if (0 == safe_strcmp (ent->e_type, QOF_ID_BOOK))
00232 return;
00233 ENTER (" %s", ent->e_type);
00234 switch (event_type)
00235 {
00236 case QOF_EVENT_CREATE :
00237 {
00238 qb.ent = ent;
00239 qb.sql_str = g_strdup_printf ("INSERT into %s (",
00240 ent->e_type);
00241 qof_class_param_foreach (ent->e_type, create_param_list,
00242 &qb);
00243 qb.sql_str = g_strconcat (qb.sql_str, ") VALUES (", NULL);
00244 qof_class_param_foreach (ent->e_type,
00245 create_each_param, &qb);
00246 qb.sql_str = g_strconcat (qb.sql_str, ");", NULL);
00247 DEBUG (" sql_str=%s", qb.sql_str);
00248 if(sqlite_exec (qsql_be->sqliteh, qb.sql_str,
00249 NULL, qsql_be, &qsql_be->err) !=
00250 SQLITE_OK)
00251 {
00252 qof_error_set_be (be, qsql_be->err_insert);
00253 qsql_be->error = TRUE;
00254 PERR (" %s", qsql_be->err);
00255 }
00256 else
00257 ((QofInstance*)ent)->dirty = FALSE;
00258 break;
00259 }
00260 default : break;
00261 }
00262 LEAVE (" ");
00263 }
00264
00265 static void
00266 qsql_modify (QofBackend *be, QofInstance *inst)
00267 {
00268 struct QsqlBuilder qb;
00269 QSQLiteBackend *qsql_be;
00270 gchar gstr[GUID_ENCODING_LENGTH+1];
00271 gchar * param_str;
00272
00273 qsql_be = (QSQLiteBackend*)be;
00274 if (!inst)
00275 return;
00276 if (!inst->param)
00277 return;
00278 ENTER (" ");
00279
00280 guid_to_string_buff (qof_instance_get_guid (inst), gstr);
00281 qb.ent = (QofEntity*)inst;
00282 param_str = qof_util_param_to_string (qb.ent, inst->param);
00283 if (param_str)
00284 g_strescape (param_str, NULL);
00285 qb.sql_str = g_strdup_printf ("UPDATE %s SET %s=\"",
00286 qb.ent->e_type, inst->param->param_name);
00287 qb.sql_str = g_strconcat (qb.sql_str, param_str,
00288 "\" WHERE ", QOF_TYPE_GUID, "='", gstr,
00289 "';", NULL);
00290 DEBUG (" sql_str=%s param_Str=%s", qb.sql_str, param_str);
00291 if(sqlite_exec (qsql_be->sqliteh, qb.sql_str,
00292 NULL, qsql_be, &qsql_be->err) !=
00293 SQLITE_OK)
00294 {
00295 qof_error_set_be (be, qsql_be->err_update);
00296 qsql_be->error = TRUE;
00297 PERR (" %s", qsql_be->err);
00298 }
00299 else
00300 inst->dirty = FALSE;
00301 LEAVE (" ");
00302 }
00303
00304 static gint
00305 qsql_record_foreach(gpointer data, gint col_num, gchar **strings,
00306 gchar **columnNames)
00307 {
00308 QSQLiteBackend *qsql_be;
00309 const QofParam * param;
00310 QofInstance * inst;
00311 gint i;
00312
00313 g_return_val_if_fail(data, QSQL_ERROR);
00314 qsql_be = (QSQLiteBackend*)data;
00315 qof_event_suspend ();
00316 inst = (QofInstance*)qof_object_new_instance (qsql_be->e_type,
00317 qsql_be->book);
00318 for(i = 0;i < col_num; i++)
00319 {
00320
00321 param = qof_class_get_parameter (qsql_be->e_type,
00322 columnNames[i]);
00323 if (!param)
00324 continue;
00325 if (0 == safe_strcmp (columnNames[i], QOF_TYPE_GUID))
00326 {
00327 GUID * guid;
00328 guid = guid_malloc();
00329 if (!string_to_guid(strings[i], guid))
00330 {
00331 DEBUG (" set guid failed:%s", strings[i]);
00332 return QSQL_ERROR;
00333 }
00334 qof_entity_set_guid (&inst->entity, guid);
00335 }
00336 if (strings[1])
00337 qof_util_param_set_string (&inst->entity, param, strings[i]);
00338 }
00339 qof_event_resume ();
00340 return SQLITE_OK;
00341 }
00342
00343
00344 static void
00345 qsql_param_foreach(QofParam *param, gpointer data)
00346 {
00347 QSQLiteBackend *qsql_be;
00348 gchar *p_str;
00349
00350 qsql_be = (QSQLiteBackend*)data;
00351 p_str = qsql_param_to_sql(param);
00352 qsql_be->sql_str = g_strconcat(qsql_be->sql_str,
00353 p_str, ",", NULL);
00354 g_free(p_str);
00355 }
00356
00357 static void
00358 update_param_foreach(QofParam *param, gpointer user_data)
00359 {
00360 struct QsqlBuilder * qb;
00361 gchar * value;
00362
00363 qb = (struct QsqlBuilder*) user_data;
00364 if (param != qb->dirty)
00365 return;
00366
00367 value = qof_util_param_to_string (qb->ent, param);
00368 if (value)
00369 g_strescape (value, NULL);
00370 if (!value)
00371 value = g_strdup ("");
00372 if (g_str_has_suffix (qb->sql_str, " "))
00373 qb->sql_str = g_strconcat (qb->sql_str,
00374 param->param_name, "=\"", value, "\"", NULL);
00375 else
00376 qb->sql_str = g_strconcat (qb->sql_str, ",",
00377 param->param_name, "=\"", value, "\"", NULL);
00378 }
00379
00380 static void
00381 update_dirty (gpointer value, gpointer user_data)
00382 {
00383 QofInstance * inst;
00384 QofEntity * ent;
00385 struct QsqlBuilder * qb;
00386 QSQLiteBackend *qsql_be;
00387 QofBackend * be;
00388 gchar gstr[GUID_ENCODING_LENGTH+1];
00389 gchar * param_str;
00390
00391 qb = (struct QsqlBuilder*) user_data;
00392 qsql_be = qb->qsql_be;
00393 be = (QofBackend*)qsql_be;
00394 ent = (QofEntity*) value;
00395 inst = (QofInstance*) ent;
00396 if (!inst->dirty)
00397 return;
00398 ENTER (" ");
00399 guid_to_string_buff (qof_entity_get_guid (ent), gstr);
00400
00401 qb->sql_str = g_strdup_printf ("UPDATE %s SET ",
00402 ent->e_type);
00403 qof_class_param_foreach (ent->e_type, update_param_foreach, qb);
00404 param_str = g_strdup_printf ("WHERE %s=\"%s\";",
00405 QOF_TYPE_GUID, gstr);
00406 qb->sql_str = g_strconcat (qb->sql_str, param_str, NULL);
00407 g_free (param_str);
00408 DEBUG (" update=%s", qb->sql_str);
00409 if(sqlite_exec (qsql_be->sqliteh, qb->sql_str,
00410 NULL, qsql_be, &qsql_be->err) != SQLITE_OK)
00411 {
00412 qof_error_set_be (be, qsql_be->err_update);
00413 qsql_be->error = TRUE;
00414 PERR (" %s", qsql_be->err);
00415 }
00416 else
00417 inst->dirty = FALSE;
00418 LEAVE (" ");
00419 return;
00420 }
00421
00422 static gint
00423 create_dirty_list (gpointer data, gint col_num, gchar **strings,
00424 gchar **columnNames)
00425 {
00426 struct QsqlBuilder * qb;
00427 QofInstance * inst;
00428 const QofParam * param;
00429 gchar * value, *columnName, *tmp;
00430
00431 qb = (struct QsqlBuilder*) data;
00432
00433 inst = (QofInstance*) qb->ent;
00434 qb->exists = TRUE;
00435 if (!inst->dirty)
00436 return SQLITE_OK;
00437 columnName = columnNames[col_num];
00438 tmp = strings[col_num];
00439 param = qof_class_get_parameter (qb->ent->e_type, columnName);
00440 value = qof_util_param_to_string (qb->ent, param);
00441 PINFO (" tmp=%s value=%s columnName=%s", tmp, value, columnName);
00442 qb->dirty = param;
00443 qb->dirty_list = g_list_prepend (qb->dirty_list, qb->ent);
00444 DEBUG (" dirty_list=%d", g_list_length (qb->dirty_list));
00445 return SQLITE_OK;
00446 }
00447
00448 static gint
00449 mark_entity (gpointer data, gint col_num, gchar **strings,
00450 gchar **columnNames)
00451 {
00452 struct QsqlBuilder * qb;
00453
00454 qb = (struct QsqlBuilder*) data;
00455 qb->exists = TRUE;
00456 DEBUG (" already exists");
00457 return SQLITE_OK;
00458 }
00459
00460 static void
00461 qsql_create (QofBackend *be, QofInstance *inst)
00462 {
00463 gchar gstr[GUID_ENCODING_LENGTH+1];
00464 QSQLiteBackend *qsql_be;
00465 struct QsqlBuilder qb;
00466 QofEntity * ent;
00467
00468 qsql_be = (QSQLiteBackend*)be;
00469 if (!inst)
00470 return;
00471 ent = (QofEntity*) inst;
00472 guid_to_string_buff (qof_entity_get_guid (ent), gstr);
00473 qb.sql_str = g_strdup_printf(
00474 "SELECT * FROM %s where guid = \"%s\";", ent->e_type, gstr);
00475 PINFO (" write: %s", qb.sql_str);
00476 qb.ent = ent;
00477 qb.dirty_list = NULL;
00478 qb.exists = FALSE;
00479 if(sqlite_exec (qsql_be->sqliteh, qb.sql_str,
00480 mark_entity, &qb, &qsql_be->err) !=
00481 SQLITE_OK)
00482 {
00483 qof_error_set_be (be, qsql_be->err_update);
00484 qsql_be->error = TRUE;
00485 PERR (" %s", qsql_be->err);
00486 }
00487 if (!qb.exists)
00488 {
00489
00490 PINFO (" insert");
00491 qb.sql_str = g_strdup_printf ("INSERT into %s (",
00492 ent->e_type);
00493 qof_class_param_foreach (ent->e_type,
00494 create_param_list, &qb);
00495 qb.sql_str = g_strconcat (qb.sql_str, ") VALUES (", NULL);
00496 qof_class_param_foreach (ent->e_type,
00497 create_each_param, &qb);
00498 qb.sql_str = g_strconcat (qb.sql_str, ");", NULL);
00499 DEBUG (" sql_str= %s", qb.sql_str);
00500 if(sqlite_exec (qsql_be->sqliteh, qb.sql_str,
00501 NULL, qsql_be, &qsql_be->err) != SQLITE_OK)
00502 {
00503 qof_error_set_be (be, qsql_be->err_insert);
00504 qsql_be->error = TRUE;
00505 PERR (" %s", qsql_be->err);
00506 }
00507 }
00508 g_free (qb.sql_str);
00509 }
00510
00511 static void
00512 check_state (QofEntity * ent, gpointer user_data)
00513 {
00514 gchar gstr[GUID_ENCODING_LENGTH+1];
00515 QSQLiteBackend *qsql_be;
00516 struct QsqlBuilder qb;
00517 QofBackend *be;
00518 QofInstance * inst;
00519
00520 qsql_be = (QSQLiteBackend*) user_data;
00521 be = (QofBackend*)qsql_be;
00522 inst = (QofInstance*)ent;
00523 if (!inst->dirty)
00524 return;
00525
00526 guid_to_string_buff (qof_entity_get_guid (ent), gstr);
00527 qb.sql_str = g_strdup_printf(
00528 "SELECT * FROM %s where guid = \"%s\";", ent->e_type, gstr);
00529 PINFO (" write: %s", qb.sql_str);
00530 qb.ent = ent;
00531 qb.dirty_list = NULL;
00532
00533
00534 qb.exists = FALSE;
00535 qb.qsql_be = qsql_be;
00536
00537
00538
00539
00540 if(sqlite_exec (qsql_be->sqliteh, qb.sql_str,
00541 create_dirty_list, &qb, &qsql_be->err) !=
00542 SQLITE_OK)
00543 {
00544 qof_error_set_be (be, qsql_be->err_update);
00545 qsql_be->error = TRUE;
00546 PERR (" %s", qsql_be->err);
00547 }
00548 if (!qb.exists)
00549 {
00550
00551 PINFO (" insert");
00552 qb.sql_str = g_strdup_printf ("INSERT into %s (",
00553 ent->e_type);
00554 qof_class_param_foreach (ent->e_type,
00555 create_param_list, &qb);
00556 qb.sql_str = g_strconcat (qb.sql_str, ") VALUES (", NULL);
00557 qof_class_param_foreach (ent->e_type,
00558 create_each_param, &qb);
00559 qb.sql_str = g_strconcat (qb.sql_str, ");", NULL);
00560 DEBUG (" sql_str= %s", qb.sql_str);
00561 if(sqlite_exec (qsql_be->sqliteh, qb.sql_str,
00562 NULL, qsql_be, &qsql_be->err) != SQLITE_OK)
00563 {
00564 qof_error_set_be (be, qsql_be->err_insert);
00565 qsql_be->error = TRUE;
00566 PERR (" %s", qsql_be->err);
00567 }
00568 }
00569
00570 g_list_foreach (qb.dirty_list, update_dirty, &qb);
00571 g_free (qb.sql_str);
00572 }
00573
00574 static void
00575 qsql_class_foreach(QofObject *obj, gpointer data)
00576 {
00577 QSQLiteBackend *qsql_be;
00578 QofBackend *be;
00579
00580 qsql_be = (QSQLiteBackend*)data;
00581 be = (QofBackend*)qsql_be;
00582 qsql_be->e_type = obj->e_type;
00583 ENTER (" obj_type=%s", qsql_be->e_type);
00584 switch (qsql_be->stm_type)
00585 {
00586 case SQL_NONE :
00587 case SQL_INSERT :
00588 case SQL_DELETE :
00589 case SQL_UPDATE :
00590 {
00591 break;
00592 }
00593 case SQL_CREATE :
00594 {
00595 qsql_be->sql_str = g_strdup_printf(
00596 "CREATE TABLE %s (", obj->e_type);
00597 qof_class_param_foreach(obj->e_type,
00598 qsql_param_foreach, data);
00599 qsql_be->sql_str = g_strconcat(qsql_be->sql_str,
00600 END_DB_VERSION, NULL);
00601 if(sqlite_exec (qsql_be->sqliteh, qsql_be->sql_str,
00602 NULL, NULL, &qsql_be->err) != SQLITE_OK)
00603 {
00604 qof_error_set_be (be, qsql_be->err_create);
00605 qsql_be->error = TRUE;
00606 PERR (" %s", qsql_be->err);
00607 }
00608 PINFO(" %s", qsql_be->sql_str);
00609 g_free(qsql_be->sql_str);
00610 break;
00611 }
00612 case SQL_LOAD :
00613 {
00614 qsql_be->sql_str = g_strdup_printf(
00615 "SELECT * FROM %s;", obj->e_type);
00616 PINFO (" sql=%s", qsql_be->sql_str);
00617 if(sqlite_exec(qsql_be->sqliteh, qsql_be->sql_str,
00618 qsql_record_foreach, qsql_be, &qsql_be->err) !=
00619 SQLITE_OK)
00620 {
00621 qsql_be->error = TRUE;
00622 PERR (" %s", qsql_be->err);
00623 }
00624 break;
00625 }
00626 case SQL_WRITE :
00627 {
00628 if (!qof_book_not_saved (qsql_be->book))
00629 break;
00630 qof_object_foreach (obj->e_type, qsql_be->book,
00631 check_state, qsql_be);
00632 break;
00633 }
00634 }
00635 LEAVE (" ");
00636 }
00637
00638 static void
00639 qsql_backend_createdb(QofBackend *be, QofSession *session)
00640 {
00641 FILE * f;
00642 QSQLiteBackend *qsql_be;
00643
00644 g_return_if_fail(be || session);
00645 ENTER (" ");
00646 qsql_be = (QSQLiteBackend*)be;
00647 qsql_be->stm_type = SQL_CREATE;
00648 qsql_be->book = qof_session_get_book (session);
00649 DEBUG (" create_file %s", qsql_be->fullpath);
00650 f = fopen (qsql_be->fullpath, "a+");
00651 if (f)
00652 fclose (f);
00653 else
00654 {
00655 qof_error_set (session, qof_error_register
00656 (_("Unable to open the output file '%s' - do you have "
00657 "permission to create this file?"), TRUE));
00658 qsql_be->error = TRUE;
00659 LEAVE (" unable to create new file '%s'",
00660 qsql_be->fullpath);
00661 return;
00662 }
00663 qsql_be->sqliteh = sqlite_open (qsql_be->fullpath, 0644,
00664 &qsql_be->err);
00665 if(!qsql_be->sqliteh)
00666 {
00667 qof_error_set_be (be, qsql_be->err_create);
00668 qsql_be->error = TRUE;
00669 LEAVE (" %s", qsql_be->err);
00670 return;
00671 }
00672 qof_object_foreach_type(qsql_class_foreach, qsql_be);
00673 LEAVE (" ");
00674 }
00675
00676 static void
00677 qsql_backend_opendb (QofBackend *be, QofSession *session)
00678 {
00679 QSQLiteBackend *qsql_be;
00680
00681 g_return_if_fail(be || session);
00682 ENTER (" ");
00683 qsql_be = (QSQLiteBackend*)be;
00684 qsql_be->sqliteh = sqlite_open (qsql_be->fullpath, 0666,
00685 &qsql_be->err);
00686 if(!qsql_be->sqliteh)
00687 {
00688 qof_error_set_be (be, qof_error_register
00689 (_("Unable to open the sqlite database '%s'."), TRUE));
00690 qsql_be->error = TRUE;
00691 PERR (" %s", qsql_be->err);
00692 }
00693 LEAVE (" %s", qsql_be->fullpath);
00694 }
00695
00696 static void
00697 qsqlite_session_begin(QofBackend *be, QofSession *session, const
00698 gchar *book_path, gboolean ignore_lock,
00699 gboolean create_if_nonexistent)
00700 {
00701 QSQLiteBackend *qsql_be;
00702 gchar** pp;
00703 struct stat statinfo;
00704 gint stat_val;
00705
00706 g_return_if_fail(be);
00707 ENTER (" book_path=%s", book_path);
00708 qsql_be = (QSQLiteBackend*)be;
00709 qsql_be->fullpath = NULL;
00710 if(book_path == NULL)
00711 {
00712 qof_error_set_be (be, qof_error_register
00713 (_("Please provide a filename for sqlite."), FALSE));
00714 qsql_be->error = TRUE;
00715 LEAVE (" bad URL");
00716 return;
00717 }
00718
00719 pp = g_strsplit(book_path, ":", 2);
00720 if(0 == safe_strcmp(pp[0], ACCESS_METHOD))
00721 {
00722 qsql_be->fullpath = g_strdup(pp[1]);
00723 g_strfreev (pp);
00724 }
00725 else
00726 qsql_be->fullpath = g_strdup (book_path);
00727 be->fullpath = g_strdup (qsql_be->fullpath);
00728 PINFO (" final path = %s", qsql_be->fullpath);
00729 stat_val = g_stat (qsql_be->fullpath, &statinfo);
00730 if (!S_ISREG (statinfo.st_mode) || statinfo.st_size == 0)
00731 qsql_backend_createdb (be, session);
00732 if (!qsql_be->error)
00733 qsql_backend_opendb (be, session);
00734 if(qof_error_check_be (be) || qsql_be->error)
00735 {
00736 LEAVE(" open failed");
00737 return;
00738 }
00739 qsql_be->create_handler =
00740 qof_event_register_handler (create_event, qsql_be);
00741 qsql_be->delete_handler =
00742 qof_event_register_handler (delete_event, qsql_be);
00743 LEAVE (" db=%s", qsql_be->fullpath);
00744 }
00745
00746 static void
00747 qsqlite_db_load (QofBackend *be, QofBook *book)
00748 {
00749 QSQLiteBackend *qsql_be;
00750
00751 g_return_if_fail(be);
00752 ENTER (" ");
00753 qsql_be = (QSQLiteBackend*)be;
00754 qsql_be->stm_type = SQL_LOAD;
00755 qsql_be->book = book;
00756
00757 qof_object_foreach_type(qsql_class_foreach, qsql_be);
00758 LEAVE (" ");
00759 }
00760
00761 static void
00762 qsqlite_write_db (QofBackend *be, QofBook *book)
00763 {
00764 QSQLiteBackend *qsql_be;
00765
00766 g_return_if_fail(be);
00767 qsql_be = (QSQLiteBackend*)be;
00768 qsql_be->stm_type = SQL_WRITE;
00769 qsql_be->book = book;
00770
00771 qof_object_foreach_type(qsql_class_foreach, qsql_be);
00772 }
00773
00774 static gboolean
00775 qsql_determine_file_type (const gchar *path)
00776 {
00777 if (!path)
00778 return FALSE;
00779 return TRUE;
00780 }
00781
00782 static void
00783 qsqlite_session_end (QofBackend *be)
00784 {
00785 QSQLiteBackend *qsql_be;
00786
00787 g_return_if_fail(be);
00788 qsql_be = (QSQLiteBackend*)be;
00789 if (qsql_be->sqliteh)
00790 sqlite_close (qsql_be->sqliteh);
00791 }
00792
00793 static void
00794 qsqlite_destroy_backend (QofBackend *be)
00795 {
00796 QSQLiteBackend *qsql_be;
00797
00798 g_return_if_fail(be);
00799 qsql_be = (QSQLiteBackend*)be;
00800 qof_event_unregister_handler (qsql_be->create_handler);
00801 qof_event_unregister_handler (qsql_be->delete_handler);
00802 g_free (be);
00803 g_free (qsql_be);
00804 }
00805
00806 static void
00807 qsql_provider_free (QofBackendProvider *prov)
00808 {
00809 prov->provider_name = NULL;
00810 prov->access_method = NULL;
00811 g_free (prov);
00812 }
00813
00814 static QofBackend*
00815 qsql_backend_new(void)
00816 {
00817 QSQLiteBackend *qsql_be;
00818 QofBackend *be;
00819
00820 ENTER (" ");
00821 qsql_be = g_new0(QSQLiteBackend, 1);
00822 be = (QofBackend*) qsql_be;
00823 qof_backend_init(be);
00824 qsql_be->dbversion = QOF_OBJECT_VERSION;
00825 qsql_be->stm_type = SQL_NONE;
00826 qsql_be->err_delete = qof_error_register
00827 (_("Unable to delete record."), FALSE);
00828 qsql_be->err_create = qof_error_register
00829 (_("Unable to create record."), FALSE);
00830 qsql_be->err_insert = qof_error_register
00831 (_("Unable to insert a new record."), FALSE);
00832 qsql_be->err_update = qof_error_register
00833 (_("Unable to update existing record."), FALSE);
00834
00835 be->session_begin = qsqlite_session_begin;
00836
00837 be->session_end = qsqlite_session_end;
00838 be->destroy_backend = qsqlite_destroy_backend;
00839 be->load = qsqlite_db_load;
00840 be->save_may_clobber_data = NULL;
00841
00842
00843 be->begin = qsql_create;
00844
00845 be->commit = qsql_modify;
00846 be->rollback = NULL;
00847
00848 be->compile_query = NULL;
00849
00850 be->free_query = NULL;
00851 be->run_query = NULL;
00852 be->counter = NULL;
00853
00854 be->events_pending = NULL;
00855 be->process_events = NULL;
00856
00857 be->sync = qsqlite_write_db;
00858 be->load_config = NULL;
00859 be->get_config = NULL;
00860 LEAVE (" ");
00861 return be;
00862 }
00863
00864 void qof_sqlite_provider_init(void)
00865 {
00866 QofBackendProvider *prov;
00867
00868 ENTER (" ");
00869 prov = g_new0 (QofBackendProvider, 1);
00870 prov->provider_name = "QOF SQLite Backend Version 0.2";
00871 prov->access_method = ACCESS_METHOD;
00872 prov->partial_book_supported = TRUE;
00873 prov->backend_new = qsql_backend_new;
00874 prov->check_data_type = qsql_determine_file_type;
00875 prov->provider_free = qsql_provider_free;
00876 qof_backend_register_provider (prov);
00877 LEAVE (" ");
00878 }
00879
00880