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.h>
00026 #include <glib/gstdio.h>
00027 #include <libintl.h>
00028 #include <libgda/libgda.h>
00029 #include "qof.h"
00030 #include "qof-gda.h"
00031
00032 #define _(String) dgettext (GETTEXT_PACKAGE, String)
00033 #define ACCESS_METHOD "gda"
00034 #define LIBGDA_DIR ".qofgda"
00035 #define GDA_DBNAME "gda-database-name"
00036 #define GDA_USERNAME "gda-username"
00037 #define GDA_PASSWORD "gda-password"
00038 #define GDA_DATASOURCE "qof-gda-source"
00039
00045 static QofLogModule log_module = QOF_MOD_GDA;
00046
00047 typedef struct
00048 {
00049 QofBackend be;
00050 GdaClient * client_pool;
00051 GdaConnection * connection;
00052 GdaCommand * command;
00053 GdaDataModel * dm;
00054 GValue * gda_value;
00055
00056 gchar * undo_trans, * commit_trans;
00057 GError * gda_err;
00058 const GdaColumn *gda_param;
00059 GList * entities;
00060 gint dbversion;
00061 gint create_handler;
00062 gint delete_handler;
00063 const gchar *fullpath;
00064 const gchar * table_name;
00065 GSList * field_list;
00066
00067 gchar * data_source_name;
00068 gchar * provider_name;
00069 gchar * database_name;
00070 gchar * source_description;
00071 gchar * username;
00072 gchar * password;
00073
00074 gchar *err;
00075 gchar *sql_str;
00076 gboolean error;
00077 QofIdType e_type;
00078 QofBook * book;
00079 } QGdaBackend;
00080
00081 static gboolean
00082 qgda_determine_file_type (const gchar * path)
00083 {
00084 if (!path)
00085 return FALSE;
00086
00087 return TRUE;
00088 }
00089
00090 static void
00091 qgda_modify (QofBackend *be, QofInstance *inst)
00092 {
00093
00094 }
00095
00096 static GdaColumn *
00097 qoftype_to_gdafield (QofIdTypeConst qoftype)
00098 {
00099 GdaColumn *p;
00100
00101 p = gda_column_new();
00102 gda_column_set_allow_null (p, TRUE);
00103 gda_column_set_g_type (p, G_TYPE_NONE);
00104 if (0 == safe_strcasecmp (qoftype, QOF_TYPE_STRING))
00105 gda_column_set_g_type (p, G_TYPE_STRING);
00106 if (0 == safe_strcasecmp (qoftype, QOF_TYPE_GUID))
00107 {
00108 gda_column_set_g_type (p, G_TYPE_STRING);
00109 gda_column_set_allow_null (p, FALSE);
00110 gda_column_set_primary_key (p, TRUE);
00111 }
00112 if (0 == safe_strcasecmp (qoftype, QOF_TYPE_CHAR))
00113 gda_column_set_g_type (p, G_TYPE_STRING);
00114 if ((0 == safe_strcasecmp (qoftype, QOF_TYPE_DOUBLE)) ||
00115 (0 == safe_strcasecmp (qoftype, QOF_TYPE_NUMERIC)) ||
00116 (0 == safe_strcasecmp (qoftype, QOF_TYPE_DEBCRED)))
00117 gda_column_set_g_type (p, G_TYPE_DOUBLE);
00118 if (0 == safe_strcasecmp (qoftype, QOF_TYPE_TIME))
00119 gda_column_set_g_type (p, G_TYPE_DATE);
00120 if (0 == safe_strcasecmp (qoftype, QOF_TYPE_BOOLEAN))
00121 gda_column_set_g_type (p, G_TYPE_BOOLEAN);
00122 if (0 == safe_strcasecmp (qoftype, QOF_TYPE_INT32))
00123 gda_column_set_g_type (p, G_TYPE_INT);
00124 if (0 == safe_strcasecmp (qoftype, QOF_TYPE_INT64))
00125 gda_column_set_g_type (p, G_TYPE_INT64);
00126
00127
00128
00129 if (gda_column_get_g_type (p) == G_TYPE_NONE)
00130 {
00131 g_free (p);
00132 return NULL;
00133 }
00134 return p;
00135 }
00136
00137 static void
00138 convert_params (QofParam * param, gpointer user_data)
00139 {
00140 GdaColumn * p;
00141 QGdaBackend * qgda_be;
00142
00143 qgda_be = (QGdaBackend*)user_data;
00144 if (!param)
00145 return;
00146 if (0 == safe_strcasecmp (param->param_type, QOF_ID_BOOK))
00147 return;
00148 p = qoftype_to_gdafield (param->param_type);
00149 if (!p)
00150 {
00151 DEBUG (" unsupported QofParam: %s %s",
00152 param->param_name, param->param_type);
00153 return;
00154 }
00155 gda_column_set_name (p, param->param_name);
00156 gda_column_set_table (p, qgda_be->table_name);
00157 qgda_be->field_list = g_slist_append (qgda_be->field_list, p);
00158 PINFO (" name=%s table=%s type=%s", param->param_name,
00159 qgda_be->table_name, param->param_type);
00160 }
00161
00162 static void
00163 build_table (gpointer value, gpointer user_data)
00164 {
00165 QGdaBackend * qgda_be;
00166 GdaParameterList * plist;
00167 GError * qgda_err;
00168 gint c;
00169
00170 qgda_err = NULL;
00171 qgda_be = (QGdaBackend*)user_data;
00172 if (!gda_connection_is_opened (qgda_be->connection))
00173 {
00174
00175 PERR (" no connection to gda available");
00176 return;
00177 }
00178 PINFO (" length=%d", g_slist_length(qgda_be->field_list));
00179 c = g_slist_length(qgda_be->field_list);
00180 if (c > 0)
00181 {
00182 gchar * text;
00183
00184
00185
00186
00187
00188 text = g_strdup ("create table ... ");
00189 plist = NULL;
00190 qgda_be->command = gda_command_new (text, GDA_COMMAND_TYPE_SQL,
00191 GDA_COMMAND_OPTION_STOP_ON_ERRORS);
00192 gda_connection_execute_non_select_command (qgda_be->connection,
00193 qgda_be->command, plist, &qgda_err);
00194
00195 if (qgda_err)
00196 {
00197
00198 g_clear_error (&qgda_err);
00199 }
00200 gda_command_free (qgda_be->command);
00201 }
00202 }
00203
00204 static void
00205 create_tables (QofObject * obj, gpointer user_data)
00206 {
00207 QGdaBackend * qgda_be;
00208
00209 qgda_be = (QGdaBackend*)user_data;
00210 if (qgda_be->field_list)
00211 g_slist_free (qgda_be->field_list);
00212 qgda_be->field_list = NULL;
00213 qgda_be->table_name = obj->e_type;
00214 qof_class_param_foreach (obj->e_type, convert_params,
00215 qgda_be);
00216 g_slist_foreach (qgda_be->field_list, build_table, qgda_be);
00217 }
00218
00219 static gboolean
00220 create_data_source (QGdaBackend * qgda_be)
00221 {
00222 gchar * cnc_string;
00223 QofBackend * be;
00224 GdaProviderInfo * prov;
00225
00226 ENTER (" ");
00227 be = (QofBackend*)qgda_be;
00228 if (!qgda_be->data_source_name)
00229 {
00230 qof_error_set_be (be, qof_error_register
00231 (_("GDA: Missing data source name."), FALSE));
00232 LEAVE (" empty data source name");
00233 return FALSE;
00234 }
00235 prov = gda_config_get_provider_by_name (qgda_be->provider_name);
00236 if (!prov)
00237 {
00238 gchar * msg;
00239
00240 msg = g_strdup_printf (_("GDA Provider '%s' could not be found"),
00241 qgda_be->provider_name);
00242 qof_error_set_be (be, qof_error_register(msg, FALSE));
00243 g_free (msg);
00244 LEAVE (" provider '%s' not found", qgda_be->provider_name);
00245 return FALSE;
00246 }
00247
00248
00249 cnc_string = g_strdup ("URI=/home/neil/gda-test.db");
00250
00251 gda_config_save_data_source (qgda_be->data_source_name,
00252 qgda_be->provider_name, cnc_string,
00253 qgda_be->source_description, qgda_be->username,
00254 qgda_be->password, TRUE);
00255
00256 qof_object_foreach_type (create_tables, qgda_be);
00257
00258 LEAVE (" created data source for %s, %s, %s, %s",
00259 qgda_be->data_source_name,
00260 qgda_be->provider_name, cnc_string,
00261 qgda_be->username);
00262 return TRUE;
00263 }
00264
00265 static void
00266 qgda_session_begin(QofBackend *be, QofSession *session, const
00267 gchar *book_path, gboolean ignore_lock,
00268 gboolean create_if_nonexistent)
00269 {
00270 QGdaBackend *qgda_be;
00271 GError * qgda_err;
00272
00273
00274 qgda_err = NULL;
00275
00276 PINFO (" gda session start");
00277 qgda_be = (QGdaBackend*)be;
00278 be->fullpath = g_strdup (book_path);
00279 if(book_path == NULL)
00280 {
00281 qof_error_set_be (be, qof_error_register
00282 (_("GDA: No data source path specified."), FALSE));
00283 qgda_be->error = TRUE;
00284 LEAVE (" bad URL");
00285 return;
00286 }
00287
00288 {
00289 gchar * gdahome;
00290 struct stat lg;
00291 gint ret;
00292
00293 ret = g_stat (g_get_home_dir(), &lg);
00294 if (ret)
00295 {
00296 qof_error_set_be (be, qof_error_register
00297 (_("GDA: Unable to locate your home directory."),
00298 FALSE));
00299 qgda_be->error = TRUE;
00300 LEAVE (" unable to use stat on home_dir.");
00301 return;
00302 }
00303 gdahome = g_strconcat (g_get_home_dir(),
00304 "/", LIBGDA_DIR, NULL);
00305 if (!S_ISDIR (lg.st_mode) || lg.st_size == 0)
00306 ret = g_mkdir_with_parents (gdahome, 0700);
00307 if (ret)
00308 {
00309 qof_error_set_be (be, qof_error_register
00310 (_("GDA: Unable to create a .libgda directory "
00311 "within your home directory."), FALSE));
00312 qgda_be->error = TRUE;
00313 LEAVE (" unable to create '%s' 0700", gdahome);
00314 return;
00315 }
00316 g_free (gdahome);
00317 }
00318 {
00319
00320 GdaDataSourceInfo * source;
00321 gboolean created;
00322
00323 created = FALSE;
00324 source = gda_config_find_data_source
00325 (qgda_be->data_source_name);
00326 if (!source && create_if_nonexistent)
00327 {
00328 DEBUG (" no source, creating . . .");
00329 created = create_data_source (qgda_be);
00330 }
00331 if (!source && !created)
00332 {
00333 qof_error_set_be (be, qof_error_register
00334 (_("GDA: No data source found at '%s' - "
00335 "Try loading data from another file "
00336 "and write to gda: again to create the "
00337 "GDA data source."), TRUE));
00338 DEBUG (" no source but set not to create.");
00339 qgda_be->error = TRUE;
00340 return;
00341 }
00342 }
00343 PINFO (" trying for a connection");
00344
00345 qgda_be->connection = gda_client_open_connection
00346 (qgda_be->client_pool, qgda_be->data_source_name,
00347 NULL, NULL, GDA_CONNECTION_OPTIONS_DONT_SHARE, &qgda_err);
00348 if (qgda_be->connection)
00349 {
00350 PINFO (" appear to be connected.");
00351
00352 qof_object_foreach_type (create_tables, qgda_be);
00353 }
00354 else
00355 {
00356 gchar * msg;
00357
00358 msg = g_strdup_printf (
00359 _("GDA encountered an error '%s' using data source '%s'."),
00360 qgda_err->message, qgda_be->data_source_name);
00361 qof_error_set_be (be, qof_error_register (msg, FALSE));
00362 PERR (" failed to connect to GDA: '%s'", msg);
00363 qgda_be->error = TRUE;
00364 g_free (msg);
00365 }
00366 }
00367
00368 static void
00369 load_entities (gpointer value, gpointer user_data)
00370 {
00371 gint column_id, row_id;
00372 GdaDataModel * dm;
00373 QGdaBackend * qgda_be;
00374
00375 qgda_be = (QGdaBackend*)user_data;
00376 dm = (GdaDataModel*)value;
00377 if (!dm)
00378 {
00379 qgda_be->error = TRUE;
00380 DEBUG (" empty data model on load");
00381 return;
00382 }
00383 for (column_id = 0; column_id < gda_data_model_get_n_columns (dm);
00384 column_id++)
00385 g_print("%s\t", gda_data_model_get_column_title (dm, column_id));
00386 g_print("\n");
00387 for (row_id = 0; row_id < gda_data_model_get_n_rows (dm); row_id++) {
00388 for (column_id = 0; column_id < gda_data_model_get_n_columns (dm);
00389 column_id++)
00390 {
00391 gchar *str;
00392
00393 qgda_be->gda_value = (GValue*)gda_data_model_get_value_at
00394 (dm, column_id, row_id);
00395 str = gda_value_stringify (qgda_be->gda_value);
00396 g_print ("%s\t", str);
00397 g_free (str);
00398 }
00399 g_print("\n");
00400 }
00401 g_object_unref(dm);
00402 }
00403
00404 static void
00405 qgda_class_foreach (QofObject * obj, gpointer data)
00406 {
00407 QGdaBackend *qgda_be;
00408 GError * qgda_err;
00409
00410 qgda_err = NULL;
00411 qgda_be = (QGdaBackend*)data;
00412 qgda_be->sql_str = g_strdup_printf(
00413 "SELECT * FROM %s;", obj->e_type);
00414 PINFO (" sql=%s", qgda_be->sql_str);
00415 qgda_be->command = gda_command_new (qgda_be->sql_str,
00416 GDA_COMMAND_TYPE_SQL, GDA_COMMAND_OPTION_STOP_ON_ERRORS);
00417 qgda_be->entities = gda_connection_execute_command (qgda_be->connection,
00418 qgda_be->command, NULL, &qgda_err);
00419 g_list_foreach (qgda_be->entities, load_entities, qgda_be);
00420 gda_command_free (qgda_be->command);
00421 }
00422
00423 static void
00424 qgda_db_load (QofBackend *be, QofBook *book)
00425 {
00426 QGdaBackend *qgda_be;
00427
00428 qgda_be = (QGdaBackend*)be;
00429 if (qgda_be->error)
00430 return;
00431
00432 qgda_be->book = book;
00433 qof_object_foreach_type(qgda_class_foreach, qgda_be);
00434 }
00435
00436 static void
00437 qgda_write_db (QofBackend *be, QofBook *book)
00438 {
00439
00440 }
00441
00442 static void
00443 qgda_session_end (QofBackend *be)
00444 {
00445 QGdaBackend *qgda_be;
00446
00447 qgda_be = (QGdaBackend*)be;
00448 if (qgda_be->dm)
00449 g_object_unref(G_OBJECT(qgda_be->dm));
00450 gda_client_close_all_connections (qgda_be->client_pool);
00451 }
00452
00453 static void
00454 qgda_destroy_backend (QofBackend *be)
00455 {
00456 QGdaBackend *qgda_be;
00457
00458 qgda_be = (QGdaBackend*)be;
00459 if (qgda_be)
00460 g_object_unref(G_OBJECT(qgda_be->client_pool));
00461 qof_event_unregister_handler (qgda_be->create_handler);
00462 qof_event_unregister_handler (qgda_be->delete_handler);
00463 g_free (be);
00464 g_free (qgda_be);
00465 }
00466
00467 static void
00468 option_cb (QofBackendOption * option, gpointer data)
00469 {
00470 QGdaBackend * qgda_be;
00471
00472 qgda_be = (QGdaBackend *) data;
00473 g_return_if_fail (qgda_be);
00474 if (0 == safe_strcmp (GDA_DBNAME, option->option_name))
00475 {
00476 qgda_be->database_name = g_strdup (option->value);
00477 PINFO (" database name = %s", qgda_be->database_name);
00478 }
00479 if (0 == safe_strcmp (GDA_USERNAME, option->option_name))
00480 {
00481 qgda_be->username = g_strdup (option->value);
00482 PINFO (" username=%s", qgda_be->username);
00483 }
00484 if (0 == safe_strcmp (GDA_PASSWORD, option->option_name))
00485 {
00486
00487 qgda_be->password = g_strdup (option->value);
00488 }
00489 if (0 == safe_strcmp (GDA_DATASOURCE, option->option_name))
00490 {
00491 qgda_be->data_source_name = g_strdup (option->value);
00492 }
00493 }
00494
00495 static void
00496 load_config (QofBackend * be, KvpFrame * config)
00497 {
00498 QGdaBackend *qgda_be;
00499
00500 ENTER (" ");
00501 qgda_be = (QGdaBackend *) be;
00502 g_return_if_fail (qgda_be);
00503 qof_backend_option_foreach (config, option_cb, qgda_be);
00504 LEAVE (" ");
00505 }
00506
00507 static KvpFrame *
00508 get_config (QofBackend * be)
00509 {
00510 QofBackendOption *option;
00511 QGdaBackend *qgda_be;
00512
00513 if (!be)
00514 {
00515 return NULL;
00516 }
00517 ENTER (" ");
00518 qgda_be = (QGdaBackend *) be;
00519 g_return_val_if_fail (qgda_be, NULL);
00520 qof_backend_prepare_frame (be);
00521 option = g_new0 (QofBackendOption, 1);
00522 option->option_name = GDA_DBNAME;
00523 option->description =
00524 _("Name of the database to use.");
00525 option->tooltip =
00526 _("Override the default database name with "
00527 "a name of your own choice.");
00528 option->type = KVP_TYPE_STRING;
00529 option->value = (gpointer) qgda_be->database_name;
00530 qof_backend_prepare_option (be, option);
00531 g_free (option);
00532 option = g_new0 (QofBackendOption, 1);
00533 option->option_name = GDA_USERNAME;
00534 option->description =
00535 _("The username to use to access this data source.");
00536 option->tooltip =
00537 _("The username specified in the configuration of this "
00538 "data source that provides write access to the data.");
00539 option->type = KVP_TYPE_STRING;
00540 option->value = (gpointer) qgda_be->username;
00541 qof_backend_prepare_option (be, option);
00542 g_free (option);
00543 option = g_new0 (QofBackendOption, 1);
00544 option->option_name = GDA_PASSWORD;
00545 option->description =
00546 _("Password to use with the username.");
00547 option->tooltip =
00548 _("The password that is to be used with the specified "
00549 "username.");
00550 option->type = KVP_TYPE_STRING;
00551 option->value = (gpointer) qgda_be->password;
00552 qof_backend_prepare_option (be, option);
00553 g_free (option);
00554 option = g_new0 (QofBackendOption, 1);
00555 option->option_name = GDA_DATASOURCE;
00556 option->description =
00557 _("Name of this data source.");
00558 option->tooltip =
00559 _("The name of this data source as specified "
00560 "in the GDA configuration.");
00561 option->type = KVP_TYPE_STRING;
00562 option->value = (gpointer) qgda_be->password;
00563 qof_backend_prepare_option (be, option);
00564 g_free (option);
00565 LEAVE (" ");
00566 return qof_backend_complete_frame (be);
00567 }
00568
00569 static QofBackend *
00570 qgda_backend_new (void)
00571 {
00572 QGdaBackend *qgda_be;
00573 QofBackend *be;
00574
00575 ENTER (" ");
00576 qgda_be = g_new0(QGdaBackend, 1);
00577 be = (QofBackend*) qgda_be;
00578 qof_backend_init(be);
00579 gda_init (PACKAGE, "0.1", 0, NULL);
00580 qgda_be->client_pool = gda_client_new ();
00581 qgda_be->dbversion = QOF_OBJECT_VERSION;
00582 be->session_begin = qgda_session_begin;
00583
00584 be->session_end = qgda_session_end;
00585 be->destroy_backend = qgda_destroy_backend;
00586 be->load = qgda_db_load;
00587 be->save_may_clobber_data = NULL;
00588 be->begin = NULL;
00589
00590 be->commit = qgda_modify;
00591 be->rollback = NULL;
00592
00593 be->compile_query = NULL;
00594
00595 be->free_query = NULL;
00596 be->run_query = NULL;
00597 be->counter = NULL;
00598
00599 be->events_pending = NULL;
00600 be->process_events = NULL;
00601
00602 be->sync = qgda_write_db;
00603 be->load_config = load_config;
00604 be->get_config = get_config;
00605 LEAVE (" ");
00606
00607
00608 qgda_be->data_source_name = "QOF_DEBUG";
00609 qgda_be->database_name = "URI=/home/neil/test.gda";
00610 qgda_be->provider_name = "XML";
00611 qgda_be->source_description = "QOF GDA debug data";
00612
00613 return be;
00614 }
00615
00616 static void
00617 qgda_provider_free (QofBackendProvider *prov)
00618 {
00619 prov->provider_name = NULL;
00620 prov->access_method = NULL;
00621 g_free (prov);
00622 }
00623
00624 void qof_gda_provider_init(void)
00625 {
00626 QofBackendProvider *prov;
00627
00628 bindtextdomain (PACKAGE, LOCALE_DIR);
00629 prov = g_new0 (QofBackendProvider, 1);
00630 prov->provider_name = "QOF GDA Backend Version 0.1";
00631 prov->access_method = ACCESS_METHOD;
00632 prov->partial_book_supported = TRUE;
00633 prov->backend_new = qgda_backend_new;
00634 prov->check_data_type = qgda_determine_file_type;
00635 prov->provider_free = qgda_provider_free;
00636 qof_backend_register_provider (prov);
00637 }