33 #include <glib/gstdio.h>
38 #include "gnc-backend-dbi-priv.h"
41 #include "qofquery-p.h"
42 #include "qofquerycore-p.h"
47 #include "Recurrence.h"
51 #include "gnc-locale-utils.h"
58 #include "splint-defs.h"
63 #define GETPID() GetCurrentProcessId()
67 #define GETPID() getpid()
70 #if LIBDBI_VERSION >= 900
71 #define HAVE_LIBDBI_R 1
72 static dbi_inst dbi_instance = NULL;
74 #define HAVE_LIBDBI_R 0
78 #include <dbi/dbi-dev.h>
80 #define GNC_HOST_NAME_MAX 255
81 #define TRANSACTION_NAME "trans"
85 static gchar lock_table[] =
"gnclock";
87 #define FILE_URI_TYPE "file"
88 #define FILE_URI_PREFIX (FILE_URI_TYPE "://")
89 #define SQLITE3_URI_TYPE "sqlite3"
90 #define SQLITE3_URI_PREFIX (SQLITE3_URI_TYPE "://")
91 #define PGSQL_DEFAULT_PORT 5432
94 const gchar* table_name,
95 const GList* col_info_list );
96 static GSList* conn_get_table_list( dbi_conn conn,
const gchar* dbname );
97 static GSList* conn_get_table_list_sqlite3( dbi_conn conn,
const gchar* dbname );
99 static GSList *conn_get_index_list_sqlite3( dbi_conn conn );
100 static void conn_drop_index_sqlite3 (dbi_conn conn,
const gchar *index );
103 conn_create_table_ddl_sqlite3,
104 conn_get_table_list_sqlite3,
105 append_sqlite3_col_def,
106 conn_get_index_list_sqlite3,
107 conn_drop_index_sqlite3
109 #define SQLITE3_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
112 const gchar* table_name,
113 const GList* col_info_list );
115 static GSList *conn_get_index_list_mysql( dbi_conn conn );
116 static void conn_drop_index_mysql (dbi_conn conn,
const gchar *index );
119 conn_create_table_ddl_mysql,
121 append_mysql_col_def,
122 conn_get_index_list_mysql,
123 conn_drop_index_mysql
125 #define MYSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d%02d%02d%02d"
128 const gchar* table_name,
129 const GList* col_info_list );
130 static GSList* conn_get_table_list_pgsql( dbi_conn conn,
const gchar* dbname );
132 static GSList *conn_get_index_list_pgsql( dbi_conn conn );
133 static void conn_drop_index_pgsql (dbi_conn conn,
const gchar *index );
137 conn_create_table_ddl_pgsql,
138 conn_get_table_list_pgsql,
139 append_pgsql_col_def,
140 conn_get_index_list_pgsql,
141 conn_drop_index_pgsql
143 #define PGSQL_TIMESPEC_STR_FORMAT "%04d%02d%02d %02d%02d%02d"
145 static gboolean gnc_dbi_lock_database(
QofBackend *qbe, gboolean ignore_lock );
146 static void gnc_dbi_unlock(
QofBackend *qbe );
147 static gboolean save_may_clobber_data(
QofBackend* qbe );
150 const gchar* index_name,
151 const gchar* table_name,
154 const gchar* table_name,
155 GList* col_info_list );
157 static GncDbiTestResult conn_test_dbi_library( dbi_conn conn );
158 #define GNC_DBI_PROVIDER_SQLITE (&provider_sqlite3)
159 #define GNC_DBI_PROVIDER_MYSQL (&provider_mysql)
160 #define GNC_DBI_PROVIDER_PGSQL (&provider_pgsql)
163 #define DBI_MAX_CONN_ATTEMPTS 5
170 gnc_table_slist_free( GSList *table_list )
173 for ( list = table_list; list != NULL; list = g_slist_next( list ))
175 g_free( list->data );
177 g_slist_free( table_list );
182 gint error_repeat, gboolean retry )
184 g_return_if_fail( dbi_conn != NULL );
186 dbi_conn->last_error = last_error;
187 if ( error_repeat > 0 )
188 dbi_conn->error_repeat = dbi_conn->error_repeat + error_repeat;
190 dbi_conn->error_repeat = 0;
191 dbi_conn->retry = retry;
197 gnc_dbi_set_error( dbi_conn, ERR_BACKEND_NO_ERR, 0, FALSE );
206 if ( dbi_conn->conn_ok )
214 gnc_dbi_init_error( dbi_conn );
215 dbi_conn->conn_ok = TRUE;
216 (void)dbi_conn_connect( dbi_conn->conn );
218 return dbi_conn->conn_ok;
224 create_tables_cb(
const gchar* type, gpointer data_p, gpointer be_p )
229 g_return_if_fail( type != NULL && data_p != NULL && be_p != NULL );
230 g_return_if_fail( pData->
version == GNC_SQL_BACKEND_VERSION );
239 sqlite3_error_fn( dbi_conn conn,
void* user_data )
243 (void)dbi_conn_error( conn, &msg );
244 PERR(
"DBI error: %s\n", msg );
250 const gchar *book_id, gboolean ignore_lock,
251 gboolean create, gboolean force )
255 gchar* dirname = NULL;
256 gchar* basename = NULL;
257 gchar *filepath = NULL;
259 gboolean file_exists;
260 GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
262 g_return_if_fail( qbe != NULL );
263 g_return_if_fail( session != NULL );
264 g_return_if_fail( book_id != NULL );
270 file_exists = g_file_test( filepath,
271 G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS );
272 if ( !create && !file_exists )
276 PWARN (
"Sqlite3 file %s not found", filepath);
280 if ( create && !force && file_exists )
283 msg =
"Might clobber, no force";
289 if ( be->conn != NULL )
291 dbi_conn_close( be->conn );
296 be->conn = dbi_conn_new_r(
"sqlite3", dbi_instance );
298 PERR (
"Attempt to connect with an uninitialized dbi_instance");
300 be->conn = dbi_conn_new(
"sqlite3" );
303 if ( be->conn == NULL )
305 PERR(
"Unable to create sqlite3 dbi connection\n" );
310 dirname = g_path_get_dirname( filepath );
311 basename = g_path_get_basename( filepath );
312 dbi_conn_error_handler( be->conn, sqlite3_error_fn, be );
314 result = dbi_conn_set_option( be->conn,
"host",
"localhost" );
317 PERR(
"Error setting 'host' option\n" );
321 result = dbi_conn_set_option( be->conn,
"dbname", basename );
324 PERR(
"Error setting 'dbname' option\n" );
328 result = dbi_conn_set_option( be->conn,
"sqlite3_dbdir", dirname );
331 PERR(
"Error setting 'sqlite3_dbdir' option\n" );
335 result = dbi_conn_connect( be->conn );
339 PERR(
"Unable to connect to %s: %d\n", book_id, result );
344 dbi_test_result = conn_test_dbi_library( be->conn );
345 switch ( dbi_test_result )
350 case GNC_DBI_FAIL_SETUP:
353 "SQLite3: Failed to setup for large number test" );
356 case GNC_DBI_FAIL_TEST:
359 "SQLite3 DBI library fails large number test" );
362 if ( dbi_test_result != GNC_DBI_PASS )
364 if ( create && !file_exists )
367 dbi_conn_close( be->conn );
369 g_unlink( filepath );
371 msg =
"Bad DBI Library";
374 if ( !gnc_dbi_lock_database( qbe, ignore_lock ) )
381 if ( be->sql_be.
conn != NULL )
383 gnc_sql_connection_dispose( be->sql_be.
conn );
385 be->sql_be.
conn = create_dbi_connection( GNC_DBI_PROVIDER_SQLITE, qbe, be->conn );
391 PINFO (
"logpath=%s", filepath ? filepath :
"(null)");
394 if ( filepath != NULL ) g_free ( filepath );
395 if ( basename != NULL ) g_free( basename );
396 if ( dirname != NULL ) g_free( dirname );
401 conn_get_index_list_sqlite3( dbi_conn conn )
405 dbi_result result = dbi_conn_query( conn,
"SELECT name FROM sqlite_master WHERE type = 'index' AND name NOT LIKE 'sqlite_autoindex%'" );
406 if ( dbi_conn_error( conn, &errmsg ) != DBI_ERROR_NONE )
408 g_print(
"Index Table Retrieval Error: %s\n", errmsg );
411 while ( dbi_result_next_row( result ) != 0 )
413 const gchar* index_name;
415 index_name = dbi_result_get_string_idx( result, 1 );
416 list = g_slist_prepend( list, strdup( index_name ) );
418 dbi_result_free( result );
423 conn_drop_index_sqlite3 (dbi_conn conn,
const gchar *index )
425 dbi_result result = dbi_conn_queryf (conn,
"DROP INDEX %s", index);
427 dbi_result_free( result );
431 mysql_error_fn( dbi_conn conn,
void* user_data )
438 const guint backoff_msecs = 1;
440 const guint backoff_usecs = 1000;
443 err_num = dbi_conn_error( conn, &msg );
452 if ( err_num == 1049 )
454 PINFO(
"DBI error: %s\n", msg );
465 PINFO(
"DBI error: %s\n", msg );
466 PINFO(
"Note: GbcDbiSqlConnection not yet initialized. Skipping further error processing." );
471 if ( err_num == 2006 )
473 PINFO(
"DBI error: %s - Reconnecting...\n", msg );
476 dbi_conn->conn_ok = TRUE;
477 (void)dbi_conn_connect( conn );
479 else if ( err_num == 2003 )
481 if (dbi_conn->error_repeat >= DBI_MAX_CONN_ATTEMPTS )
483 PERR(
"DBI error: %s - Giving up after %d consecutive attempts.\n", msg, DBI_MAX_CONN_ATTEMPTS );
486 dbi_conn->conn_ok = FALSE;
491 Sleep (backoff_msecs * 2 << dbi_conn->error_repeat);
493 usleep (backoff_usecs * 2 << dbi_conn->error_repeat);
495 PINFO(
"DBI error: %s - Reconnecting...\n", msg );
498 dbi_conn->conn_ok = TRUE;
499 (void)dbi_conn_connect( conn );
504 PERR(
"DBI error: %s\n", msg );
523 set_standard_connection_options(
QofBackend* qbe, dbi_conn conn,
const gchar* host,
int port,
524 const gchar* dbname,
const gchar* username,
const gchar* password )
528 result = dbi_conn_set_option( conn,
"host", host );
531 PERR(
"Error setting 'host' option\n" );
535 result = dbi_conn_set_option_numeric( conn,
"port", port );
538 PERR(
"Error setting 'port' option\n" );
542 result = dbi_conn_set_option( conn,
"dbname", dbname );
545 PERR(
"Error setting 'dbname' option\n" );
549 result = dbi_conn_set_option( conn,
"username", username );
552 PERR(
"Error setting 'username' option\n" );
556 result = dbi_conn_set_option( conn,
"password", password );
559 PERR(
"Error setting 'password' option\n" );
564 result = dbi_conn_set_option( conn,
"encoding",
"UTF-8" );
567 PERR(
"Error setting 'encoding' option\n" );
577 gnc_dbi_lock_database (
QofBackend* qbe, gboolean ignore_lock )
581 dbi_conn dcon = qe->conn;
583 const gchar *dbname = dbi_conn_get_option( dcon,
"dbname" );
585 result = dbi_conn_get_table_list( dcon, dbname, lock_table);
586 if (!( result && dbi_result_get_numrows( result ) ))
590 dbi_result_free( result );
593 result = dbi_conn_queryf( dcon,
"CREATE TABLE %s ( Hostname varchar(%d), PID int )", lock_table, GNC_HOST_NAME_MAX );
594 if ( dbi_conn_error( dcon, NULL ) )
597 dbi_conn_error( dcon, &errstr );
598 PERR(
"Error %s creating lock table", errstr );
602 dbi_result_free( result );
609 dbi_result_free( result );
615 dbi_result_free( result );
620 if ( (result = dbi_conn_query( dcon,
"BEGIN" )) )
623 gchar hostname[ GNC_HOST_NAME_MAX + 1 ];
626 dbi_result_free( result );
629 result = dbi_conn_queryf( dcon,
"SELECT * FROM %s", lock_table );
630 if ( result && dbi_result_get_numrows( result ) )
632 dbi_result_free( result );
638 dbi_conn_query( dcon,
"ROLLBACK" );
641 result = dbi_conn_queryf( dcon,
"DELETE FROM %s", lock_table );
646 result = dbi_conn_query( dcon,
"ROLLBACK" );
649 dbi_result_free( result );
656 dbi_result_free( result );
661 memset( hostname, 0,
sizeof(hostname) );
662 gethostname( hostname, GNC_HOST_NAME_MAX );
663 result = dbi_conn_queryf( dcon,
664 "INSERT INTO %s VALUES ('%s', '%d')",
665 lock_table, hostname, (
int)GETPID() );
670 result = dbi_conn_query( dcon,
"ROLLBACK" );
673 dbi_result_free( result );
680 dbi_result_free( result );
683 result = dbi_conn_query( dcon,
"COMMIT" );
686 dbi_result_free( result );
696 dbi_result_free( result );
705 dbi_conn dcon = qe->conn;
707 const gchar *dbname = NULL;
709 g_return_if_fail( dcon != NULL );
710 g_return_if_fail( dbi_conn_error( dcon, NULL ) == 0 );
712 dbname = dbi_conn_get_option( dcon,
"dbname" );
714 g_return_if_fail( dbname != NULL );
715 result = dbi_conn_get_table_list( dcon, dbname, lock_table);
716 if (!( result && dbi_result_get_numrows( result ) ))
720 dbi_result_free( result );
723 PWARN(
"No lock table in database, so not unlocking it.");
726 dbi_result_free( result );
728 result = dbi_conn_query( dcon,
"BEGIN" );
732 gchar hostname[ GNC_HOST_NAME_MAX + 1 ];
734 dbi_result_free( result );
736 memset( hostname, 0,
sizeof(hostname) );
737 gethostname( hostname, GNC_HOST_NAME_MAX );
738 result = dbi_conn_queryf( dcon,
"SELECT * FROM %s WHERE Hostname = '%s' AND PID = '%d'", lock_table, hostname, (
int)GETPID() );
739 if ( result && dbi_result_get_numrows( result ) )
743 dbi_result_free( result );
746 result = dbi_conn_queryf( dcon,
"DELETE FROM %s", lock_table );
749 PERR(
"Failed to delete the lock entry");
751 result = dbi_conn_query( dcon,
"ROLLBACK" );
754 dbi_result_free( result );
761 dbi_result_free( result );
764 result = dbi_conn_query( dcon,
"COMMIT" );
767 dbi_result_free( result );
772 result = dbi_conn_query( dcon,
"ROLLBACK" );
775 dbi_result_free( result );
778 PWARN(
"There was no lock entry in the Lock table");
783 dbi_result_free( result );
786 PWARN(
"Unable to get a lock on LOCK, so failed to clear the lock entry.");
792 const gchar *book_id, gboolean ignore_lock,
793 gboolean create, gboolean force )
796 gchar* protocol = NULL;
798 gchar* dbname = NULL;
799 gchar* username = NULL;
800 gchar* password = NULL;
801 gchar* basename = NULL;
802 gchar* translog_path = NULL;
805 gboolean success = FALSE;
806 GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
808 g_return_if_fail( qbe != NULL );
809 g_return_if_fail( session != NULL );
810 g_return_if_fail( book_id != NULL );
818 &username, &password, &dbname );
823 if ( be->conn != NULL )
825 dbi_conn_close( be->conn );
829 be->conn = dbi_conn_new_r(
"mysql", dbi_instance );
831 PERR (
"Attempt to connect with an uninitialized dbi_instance");
833 be->conn = dbi_conn_new(
"mysql" );
835 if ( be->conn == NULL )
837 PERR(
"Unable to create mysql dbi connection\n" );
841 dbi_conn_error_handler( be->conn, mysql_error_fn, be );
842 if ( !set_standard_connection_options( qbe, be->conn, host, portnum, dbname, username, password ) )
847 result = dbi_conn_connect( be->conn );
850 dbi_test_result = conn_test_dbi_library( be->conn );
851 switch ( dbi_test_result )
856 case GNC_DBI_FAIL_SETUP:
859 "DBI library large number test incomplete" );
862 case GNC_DBI_FAIL_TEST:
865 "DBI library fails large number test" );
868 if ( GNC_DBI_PASS != dbi_test_result )
872 if (create && !force && save_may_clobber_data( qbe ) )
875 PWARN(
"Databse already exists, Might clobber it.");
879 success = gnc_dbi_lock_database ( qbe, ignore_lock );
886 PERR(
"Unable to connect to database '%s'\n", dbname );
895 result = dbi_conn_set_option( be->conn,
"dbname",
"mysql" );
898 PERR(
"Error setting 'dbname' option\n" );
902 result = dbi_conn_connect( be->conn );
905 PERR(
"Unable to connect to 'mysql' database\n" );
909 dresult = dbi_conn_queryf( be->conn,
"CREATE DATABASE %s CHARACTER SET utf8", dbname );
910 if ( dresult == NULL )
912 PERR(
"Unable to create database '%s'\n", dbname );
916 dbi_conn_close( be->conn );
921 be->conn = dbi_conn_new_r(
"mysql", dbi_instance );
923 PERR (
"Attempt to connect with an uninitialized dbi_instance");
925 be->conn = dbi_conn_new(
"mysql" );
928 if ( be->conn == NULL )
930 PERR(
"Unable to create mysql dbi connection\n" );
934 dbi_conn_error_handler( be->conn, mysql_error_fn, be );
935 if ( !set_standard_connection_options( qbe, be->conn, host, 0, dbname, username, password ) )
939 result = dbi_conn_connect( be->conn );
942 PERR(
"Unable to create database '%s'\n", dbname );
946 dbi_test_result = conn_test_dbi_library( be->conn );
947 switch ( dbi_test_result )
952 case GNC_DBI_FAIL_SETUP:
955 "MySql: Failed to setup for large number test" );
958 case GNC_DBI_FAIL_TEST:
961 "MySql DBI library fails large number test" );
964 if ( dbi_test_result != GNC_DBI_PASS )
966 dbi_conn_queryf( be->conn,
"DROP DATABASE %s", dbname );
969 success = gnc_dbi_lock_database ( qbe, ignore_lock );
982 if ( be->sql_be.
conn != NULL )
984 gnc_sql_connection_dispose( be->sql_be.
conn );
986 be->sql_be.
conn = create_dbi_connection( GNC_DBI_PROVIDER_MYSQL, qbe, be->conn );
992 basename = g_strjoin(
"_", protocol, host, username, dbname, NULL);
995 PINFO (
"logpath=%s", translog_path ? translog_path :
"(null)");
1003 g_free( translog_path );
1010 conn_get_index_list_mysql( dbi_conn conn )
1012 GSList *index_list = NULL;
1013 dbi_result table_list;
1015 const gchar *dbname = dbi_conn_get_option( conn,
"dbname" );
1016 g_return_val_if_fail( conn != NULL, NULL );
1017 table_list = dbi_conn_get_table_list( conn, dbname, NULL );
1018 if ( dbi_conn_error( conn, &errmsg ) != DBI_ERROR_NONE )
1020 g_print(
"Table Retrieval Error: %s\n", errmsg );
1023 while ( dbi_result_next_row( table_list ) != 0 )
1026 const gchar *table_name = dbi_result_get_string_idx( table_list, 1 );
1027 result = dbi_conn_queryf( conn,
1028 "SHOW INDEXES IN %s WHERE Key_name != 'PRIMARY'",
1030 if ( dbi_conn_error( conn, &errmsg ) != DBI_ERROR_NONE )
1032 g_print(
"Index Table Retrieval Error: %s\n", errmsg );
1036 while ( dbi_result_next_row( result ) != 0 )
1038 const gchar* index_name = dbi_result_get_string_idx( result, 3 );
1039 index_list = g_slist_prepend( index_list, g_strjoin(
" ", index_name, table_name, NULL ) );
1041 dbi_result_free( result );
1048 conn_drop_index_mysql (dbi_conn conn,
const gchar *index )
1051 gchar **index_table_split = g_strsplit (index,
" ", 2);
1055 while (index_table_split[++splitlen] != NULL)
1060 g_print (
"Drop index error: invalid MySQL index format (<index> <table>): %s", index);
1064 result = dbi_conn_queryf (conn,
"DROP INDEX %s ON %s",
1065 index_table_split[0], index_table_split[1]);
1067 dbi_result_free( result );
1069 g_strfreev (index_table_split);
1073 pgsql_error_fn( dbi_conn conn,
void* user_data )
1079 const guint backoff_msecs = 1;
1081 const guint backoff_usecs = 1000;
1084 (
void)dbi_conn_error( conn, &msg );
1085 if ( g_str_has_prefix( msg,
"FATAL: database" ) &&
1086 g_str_has_suffix( msg,
"does not exist\n" ) )
1088 PINFO(
"DBI error: %s\n", msg );
1092 else if ( g_strrstr( msg,
"server closed the connection unexpectedly" ) )
1094 if ( dbi_conn == NULL )
1096 PWARN(
"DBI Error: Connection lost, connection pointer invalid");
1099 PINFO(
"DBI error: %s - Reconnecting...\n", msg );
1101 dbi_conn->conn_ok = TRUE;
1102 (void)dbi_conn_connect( conn );
1104 else if ( dbi_conn &&
1105 ( g_str_has_prefix( msg,
"connection pointer is NULL" ) ||
1106 g_str_has_prefix(msg,
"could not connect to server" ) ) )
1108 if (dbi_conn->error_repeat >= DBI_MAX_CONN_ATTEMPTS )
1110 PERR(
"DBI error: %s - Giving up after %d consecutive attempts.\n", msg, DBI_MAX_CONN_ATTEMPTS );
1112 dbi_conn->conn_ok = FALSE;
1117 Sleep (backoff_msecs * 2 << dbi_conn->error_repeat);
1119 usleep (backoff_usecs * 2 << dbi_conn->error_repeat);
1121 PINFO(
"DBI error: %s - Reconnecting...\n", msg );
1123 dbi_conn->conn_ok = TRUE;
1124 (void)dbi_conn_connect( conn );
1129 PERR(
"DBI error: %s\n", msg );
1136 const gchar *book_id, gboolean ignore_lock,
1137 gboolean create, gboolean force )
1141 gchar* protocol = NULL;
1143 gchar *dbname = NULL, *dbnamelc = NULL;
1144 gchar* username = NULL;
1145 gchar* password = NULL;
1146 gchar* basename = NULL;
1147 gchar* translog_path = NULL;
1148 gboolean success = FALSE;
1150 GncDbiTestResult dbi_test_result = GNC_DBI_PASS;
1152 g_return_if_fail( qbe != NULL );
1153 g_return_if_fail( session != NULL );
1154 g_return_if_fail( book_id != NULL );
1162 &username, &password, &dbname );
1164 portnum = PGSQL_DEFAULT_PORT;
1169 dbnamelc = g_utf8_strdown( dbname, -1 );
1174 if ( be->conn != NULL )
1176 dbi_conn_close( be->conn );
1181 be->conn = dbi_conn_new_r(
"pgsql", dbi_instance );
1183 PERR (
"Attempt to connect with an uninitialized dbi_instance");
1185 be->conn = dbi_conn_new(
"pgsql" );
1188 if ( be->conn == NULL )
1190 PERR(
"Unable to create pgsql dbi connection\n" );
1194 dbi_conn_error_handler( be->conn, pgsql_error_fn, be );
1195 if ( !set_standard_connection_options( qbe, be->conn, host, portnum, dbnamelc, username, password ) )
1200 result = dbi_conn_connect( be->conn );
1203 dbi_test_result = conn_test_dbi_library( be->conn );
1204 switch ( dbi_test_result )
1209 case GNC_DBI_FAIL_SETUP:
1212 "Postgresql: Failed to setup for large number test" );
1215 case GNC_DBI_FAIL_TEST:
1218 "Postgresql DBI library fails large number test" );
1221 if ( dbi_test_result != GNC_DBI_PASS )
1225 if (create && !force && save_may_clobber_data( qbe ) )
1228 PWARN(
"Databse already exists, Might clobber it.");
1232 success = gnc_dbi_lock_database ( qbe, ignore_lock );
1239 PERR(
"Unable to connect to database '%s'\n", dbname );
1248 result = dbi_conn_set_option( be->conn,
"dbname",
"postgres" );
1251 PERR(
"Error setting 'dbname' option\n" );
1255 result = dbi_conn_connect( be->conn );
1258 PERR(
"Unable to connect to 'postgres' database\n" );
1262 dresult = dbi_conn_queryf( be->conn,
"CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'", dbnamelc );
1263 if ( dresult == NULL )
1265 PERR(
"Unable to create database '%s'\n", dbname );
1269 dbi_conn_queryf( be->conn,
"ALTER DATABASE %s SET standard_conforming_strings TO on", dbnamelc );
1270 dbi_conn_close( be->conn );
1275 be->conn = dbi_conn_new_r(
"pgsql", dbi_instance );
1277 PERR (
"Attempt to connect with an uninitialized dbi_instance");
1279 be->conn = dbi_conn_new(
"pgsql" );
1282 if ( be->conn == NULL )
1284 PERR(
"Unable to create pgsql dbi connection\n" );
1288 dbi_conn_error_handler( be->conn, pgsql_error_fn, be );
1289 if ( !set_standard_connection_options( qbe, be->conn, host, PGSQL_DEFAULT_PORT, dbnamelc, username, password ) )
1293 result = dbi_conn_connect( be->conn );
1296 PERR(
"Unable to create database '%s'\n", dbname );
1300 dbi_test_result = conn_test_dbi_library( be->conn );
1301 switch ( dbi_test_result )
1306 case GNC_DBI_FAIL_SETUP:
1309 "DBI library large number test incomplete" );
1312 case GNC_DBI_FAIL_TEST:
1315 "DBI library fails large number test" );
1318 if ( GNC_DBI_PASS != dbi_test_result )
1320 dbi_conn_select_db( be->conn,
"template1" );
1321 dbi_conn_queryf( be->conn,
"DROP DATABASE %s", dbnamelc );
1324 success = gnc_dbi_lock_database ( qbe, ignore_lock );
1334 if ( be->sql_be.
conn != NULL )
1336 gnc_sql_connection_dispose( be->sql_be.
conn );
1338 be->sql_be.
conn = create_dbi_connection( GNC_DBI_PROVIDER_PGSQL, qbe, be->conn );
1344 basename = g_strjoin(
"_", protocol, host, username, dbname, NULL);
1347 PINFO (
"logpath=%s", translog_path ? translog_path :
"(null)");
1355 g_free( translog_path );
1363 conn_get_index_list_pgsql( dbi_conn conn )
1365 GSList *list = NULL;
1366 const gchar *errmsg;
1368 PINFO (
"Retrieving postgres index list\n");
1369 result = dbi_conn_query( conn,
"SELECT relname FROM pg_class AS a INNER JOIN pg_index AS b ON (b.indexrelid = a.oid) INNER JOIN pg_namespace AS c ON (a.relnamespace = c.oid) WHERE reltype = '0' AND indisprimary = 'f' AND nspname = 'public'" );
1370 if ( dbi_conn_error( conn, &errmsg ) != DBI_ERROR_NONE )
1372 g_print(
"Index Table Retrieval Error: %s\n", errmsg );
1375 while ( dbi_result_next_row( result ) != 0 )
1377 const gchar* index_name;
1379 index_name = dbi_result_get_string_idx( result, 1 );
1380 list = g_slist_prepend( list, strdup( index_name ) );
1382 dbi_result_free( result );
1387 conn_drop_index_pgsql (dbi_conn conn,
const gchar *index )
1389 dbi_result result = dbi_conn_queryf (conn,
"DROP INDEX %s", index);
1391 dbi_result_free( result );
1402 g_return_if_fail( be_start != NULL );
1406 if ( be->conn != NULL )
1408 gnc_dbi_unlock( be_start );
1409 dbi_conn_close( be->conn );
1412 if ( be->sql_be.
conn != NULL )
1414 gnc_sql_connection_dispose( be->sql_be.
conn );
1415 be->sql_be.
conn = NULL;
1425 g_return_if_fail( be != NULL );
1430 qof_backend_destroy( be );
1451 g_return_if_fail( qbe != NULL );
1452 g_return_if_fail( book != NULL );
1454 ENTER(
"be=%p, book=%p", be, book );
1456 if ( loadType == LOAD_TYPE_INITIAL_LOAD )
1458 g_assert( be->primary_book == NULL );
1459 be->primary_book = book;
1465 qof_object_foreach_backend( GNC_SQL_BACKEND, create_tables_cb, be );
1497 const gchar* dbname;
1499 gboolean retval = FALSE;
1502 dbname = dbi_conn_get_option( be->conn,
"dbname" );
1503 result = dbi_conn_get_table_list( be->conn, dbname, NULL );
1506 retval = dbi_result_get_numrows( result ) > 0;
1507 dbi_result_free( result );
1514 gchar *table_name, TableOpType op )
1516 gchar *new_name = g_strdup_printf(
"%s_%s", table_name,
"back" );
1517 dbi_result result = NULL;
1521 result = dbi_conn_queryf( conn->conn,
"ALTER TABLE %s RENAME TO %s",
1522 table_name, new_name );
1525 result = dbi_conn_queryf( conn->conn,
1526 "ALTER TABLE %s RENAME TO %s",
1527 new_name, table_name );
1530 result = dbi_conn_queryf( conn->conn,
"DROP TABLE %s",
1570 gboolean result = TRUE;
1572 GSList *full_table_name_list = NULL;
1573 const gchar *dbname = dbi_conn_get_option( conn->conn,
"dbname" );
1575 g_return_val_if_fail( table_name_list != NULL, FALSE );
1576 if ( op == rollback )
1577 full_table_name_list =
1578 conn->provider->get_table_list( conn->conn, dbname );
1580 for ( node = table_name_list; node != NULL && result; node = node->next )
1582 gchar* table_name = (gchar*)node->data;
1585 if ( g_strcmp0(table_name, lock_table) == 0)
1591 gnc_dbi_init_error( conn );
1595 if (g_slist_find(full_table_name_list, table_name))
1597 result = dbi_conn_queryf( conn->conn,
"DROP TABLE %s",
1605 result = conn_table_manage_backup( conn, table_name, op );
1608 result = dbi_conn_queryf( conn->conn,
"DELETE FROM TABLE %s",
1613 result = dbi_conn_queryf( conn->conn,
"DROP TABLE %s",
1618 while ( conn->retry );
1619 if ( result != NULL )
1621 if ( dbi_result_free( result ) < 0 )
1623 PERR(
"Error in dbi_result_free() result\n" );
1628 gnc_table_slist_free( full_table_name_list );
1646 GSList *table_list, *index_list, *iter;
1647 const gchar* dbname = NULL;
1649 g_return_if_fail( be != NULL );
1650 g_return_if_fail( book != NULL );
1652 ENTER(
"book=%p, primary=%p", book, be->primary_book );
1653 dbname = dbi_conn_get_option( be->conn,
"dbname" );
1654 table_list = conn->provider->get_table_list( conn->conn, dbname );
1661 LEAVE(
"Failed to rename tables" );
1662 gnc_table_slist_free( table_list );
1665 index_list = conn->provider->get_index_list( conn->conn );
1666 for ( iter = index_list; iter != NULL; iter = g_slist_next( iter) )
1669 conn->provider->drop_index (conn->conn, iter->data);
1670 if ( DBI_ERROR_NONE != dbi_conn_error( conn->conn, &errmsg ) )
1673 gnc_table_slist_free( index_list );
1676 gnc_table_slist_free( table_list );
1677 LEAVE(
"Failed to drop indexes %s", errmsg );
1681 gnc_table_slist_free( index_list );
1683 be->is_pristine_db = TRUE;
1684 be->primary_book = book;
1691 LEAVE(
"Failed to create new database tables" );
1696 gnc_table_slist_free( table_list );
1697 LEAVE(
"book=%p", book);
1705 g_return_if_fail( be != NULL );
1706 g_return_if_fail( inst != NULL );
1716 g_return_if_fail( be != NULL );
1717 g_return_if_fail( inst != NULL );
1727 g_return_if_fail( be != NULL );
1728 g_return_if_fail( inst != NULL );
1742 be->session_end = gnc_dbi_session_end;
1743 be->destroy_backend = gnc_dbi_destroy_backend;
1745 be->load = gnc_dbi_load;
1748 be->begin = gnc_dbi_begin_edit;
1749 be->commit = gnc_dbi_commit_edit;
1750 be->rollback = gnc_dbi_rollback_edit;
1753 be->events_pending = NULL;
1754 be->process_events = NULL;
1758 be->sync = gnc_dbi_safe_sync_all;
1759 be->safe_sync = gnc_dbi_safe_sync_all;
1760 be->load_config = NULL;
1761 be->get_config = NULL;
1763 be->compile_query = gnc_sql_compile_query;
1764 be->run_query = gnc_sql_run_query;
1765 be->free_query = gnc_sql_free_query;
1771 dbi_be->sql_be.
conn = NULL;
1772 dbi_be->sql_be.
book = NULL;
1785 g_assert( dbi_be != NULL );
1788 qof_backend_init( be );
1790 be->session_begin = session_begin;
1791 init_sql_backend( dbi_be );
1797 gnc_dbi_backend_sqlite3_new(
void )
1799 return new_backend( gnc_dbi_sqlite3_session_begin );
1803 gnc_dbi_backend_mysql_new(
void )
1805 return new_backend( gnc_dbi_mysql_session_begin );
1809 gnc_dbi_backend_postgres_new(
void )
1811 return new_backend( gnc_dbi_postgres_session_begin );
1817 g_return_if_fail( prov != NULL );
1827 gnc_dbi_check_sqlite3_file(
const gchar *uri )
1831 G_GNUC_UNUSED
size_t chars_read;
1836 g_return_val_if_fail( uri != NULL, FALSE );
1839 f = g_fopen( filename,
"r" );
1840 g_free ( filename );
1845 PINFO(
"doesn't exist (errno=%d) -> DBI", errno );
1850 chars_read = fread( buf,
sizeof(buf), 1, f );
1851 status = fclose( f );
1854 PERR(
"Error in fclose(): %d\n", errno );
1856 if ( g_str_has_prefix( buf,
"SQLite format 3" ) )
1858 PINFO(
"has SQLite format string -> DBI" );
1861 PINFO(
"exists, does not have SQLite format string -> not DBI" );
1871 const gchar* driver_dir;
1873 gboolean have_sqlite3_driver = FALSE;
1874 gboolean have_mysql_driver = FALSE;
1875 gboolean have_pgsql_driver = FALSE;
1879 driver_dir = g_getenv(
"GNC_DBD_DIR" );
1880 if ( driver_dir == NULL )
1882 PINFO(
"GNC_DBD_DIR not set: using libdbi built-in default\n");
1889 num_drivers = dbi_initialize_r( driver_dir, &dbi_instance );
1891 num_drivers = dbi_initialize( driver_dir );
1893 if ( num_drivers <= 0 )
1895 PWARN(
"No DBD drivers found\n" );
1899 dbi_driver driver = NULL;
1900 PINFO(
"%d DBD drivers found\n", num_drivers );
1905 driver = dbi_driver_list_r( driver, dbi_instance );
1907 driver = dbi_driver_list( driver );
1910 if ( driver != NULL )
1912 const gchar* name = dbi_driver_get_name( driver );
1914 PINFO(
"Driver: %s\n", name );
1915 if ( strcmp( name,
"sqlite3" ) == 0 )
1917 have_sqlite3_driver = TRUE;
1919 else if ( strcmp( name,
"mysql" ) == 0 )
1921 have_mysql_driver = TRUE;
1923 else if ( strcmp( name,
"pgsql" ) == 0 )
1925 have_pgsql_driver = TRUE;
1929 while ( driver != NULL );
1932 if ( have_sqlite3_driver )
1935 g_assert( prov != NULL );
1945 g_assert( prov != NULL );
1955 if ( have_mysql_driver )
1958 g_assert( prov != NULL );
1968 if ( have_pgsql_driver )
1971 g_assert( prov != NULL );
1973 prov->
provider_name =
"GnuCash Libdbi (POSTGRESQL) Backend";
1986 #ifndef GNC_NO_LOADABLE_MODULES
1987 G_MODULE_EXPORT
void
1993 G_MODULE_EXPORT
void
1994 qof_backend_module_finalize(
void )
2006 dbi_shutdown_r(dbi_instance);
2007 dbi_instance = NULL;
2030 if ( dbi_row->gvalue_list != NULL )
2032 for ( node = dbi_row->gvalue_list; node != NULL; node = node->next )
2035 if ( !G_IS_VALUE(node->data) )
2037 value = (GValue*)node->data;
2038 if ( G_VALUE_HOLDS_STRING(value) )
2040 g_free( (gpointer)g_value_get_string( value ) );
2044 g_list_free( dbi_row->gvalue_list );
2049 static const GValue*
2050 row_get_value_at_col_name(
GncSqlRow* row,
const gchar* col_name )
2057 type = dbi_result_get_field_type( dbi_row->result, col_name );
2058 attrs = dbi_result_get_field_attribs( dbi_row->result, col_name );
2059 value = g_new0( GValue, 1 );
2060 g_assert( value != NULL );
2064 case DBI_TYPE_INTEGER:
2065 (void)g_value_init( value, G_TYPE_INT64 );
2066 g_value_set_int64( value, dbi_result_get_longlong( dbi_row->result, col_name ) );
2068 case DBI_TYPE_DECIMAL:
2069 gnc_push_locale( LC_NUMERIC,
"C" );
2070 if ( (attrs & DBI_DECIMAL_SIZEMASK) == DBI_DECIMAL_SIZE4 )
2072 (void)g_value_init( value, G_TYPE_FLOAT );
2073 g_value_set_float( value, dbi_result_get_float( dbi_row->result, col_name ) );
2075 else if ( (attrs & DBI_DECIMAL_SIZEMASK) == DBI_DECIMAL_SIZE8 )
2077 (void)g_value_init( value, G_TYPE_DOUBLE );
2078 g_value_set_double( value, dbi_result_get_double( dbi_row->result, col_name ) );
2082 PERR(
"Field %s: strange decimal length attrs=%d\n", col_name, attrs );
2084 gnc_pop_locale( LC_NUMERIC );
2086 case DBI_TYPE_STRING:
2087 (void)g_value_init( value, G_TYPE_STRING );
2088 g_value_take_string( value, dbi_result_get_string_copy( dbi_row->result, col_name ) );
2090 case DBI_TYPE_DATETIME:
2091 if ( dbi_result_field_is_null( dbi_row->result, col_name ) )
2102 dbi_result_t *result = (dbi_result_t*)(dbi_row->result);
2103 guint64 row = dbi_result_get_currow (result);
2104 guint idx = dbi_result_get_field_idx (result, col_name) - 1;
2105 time64 time = result->rows[row]->field_values[idx].d_datetime;
2106 (void)g_value_init( value, G_TYPE_INT64 );
2107 g_value_set_int64 (value, time);
2111 PERR(
"Field %s: unknown DBI_TYPE: %d\n", col_name, type );
2116 dbi_row->gvalue_list = g_list_prepend( dbi_row->gvalue_list, value );
2121 create_dbi_row( dbi_result result )
2126 g_assert( row != NULL );
2128 row->base.getValueAtColName = row_get_value_at_col_name;
2129 row->base.dispose = row_dispose;
2130 row->result = result;
2153 if ( dbi_result->row != NULL )
2155 gnc_sql_row_dispose( dbi_result->row );
2157 if ( dbi_result->result != NULL )
2161 status = dbi_result_free( dbi_result->result );
2164 PERR(
"Error in dbi_result_free() result\n" );
2176 return dbi_result->num_rows;
2184 if ( dbi_result->row != NULL )
2186 gnc_sql_row_dispose( dbi_result->row );
2187 dbi_result->row = NULL;
2189 if ( dbi_result->num_rows > 0 )
2191 gint status = dbi_result_first_row( dbi_result->result );
2194 PERR(
"Error in dbi_result_first_row()\n" );
2197 dbi_result->cur_row = 1;
2198 dbi_result->row = create_dbi_row( dbi_result->result );
2199 return dbi_result->row;
2212 if ( dbi_result->row != NULL )
2214 gnc_sql_row_dispose( dbi_result->row );
2215 dbi_result->row = NULL;
2217 if ( dbi_result->cur_row < dbi_result->num_rows )
2219 gint status = dbi_result_next_row( dbi_result->result );
2222 PERR(
"Error in dbi_result_first_row()\n" );
2225 dbi_result->cur_row++;
2226 dbi_result->row = create_dbi_row( dbi_result->result );
2227 return dbi_result->row;
2241 g_assert( dbi_result != NULL );
2243 dbi_result->base.dispose = result_dispose;
2244 dbi_result->base.getNumRows = result_get_num_rows;
2245 dbi_result->base.getFirstRow = result_get_first_row;
2246 dbi_result->base.getNextRow = result_get_next_row;
2247 dbi_result->result = result;
2248 dbi_result->num_rows = (guint)dbi_result_get_numrows( result );
2249 dbi_result->cur_row = 0;
2250 dbi_result->dbi_conn = dbi_conn;
2269 if ( dbi_stmt->sql != NULL )
2271 (void)g_string_free( dbi_stmt->sql, TRUE );
2281 return dbi_stmt->sql->str;
2293 buf = g_strdup_printf(
" WHERE %s = %s", table_row->
col_name,
2295 g_free( value_str );
2296 (void)g_string_append( dbi_stmt->sql, buf );
2306 g_assert( stmt != NULL );
2308 stmt->base.dispose = stmt_dispose;
2309 stmt->base.toSql = stmt_to_sql;
2310 stmt->base.addWhereCond = stmt_add_where_cond;
2311 stmt->sql = g_string_new( sql );
2332 DEBUG(
"SQL: %s\n", dbi_stmt->sql->str );
2333 gnc_push_locale( LC_NUMERIC,
"C" );
2336 gnc_dbi_init_error( dbi_conn );
2337 result = dbi_conn_query( dbi_conn->conn, dbi_stmt->sql->str );
2339 while ( dbi_conn->retry );
2340 if ( result == NULL )
2342 PERR(
"Error executing SQL %s\n", dbi_stmt->sql->str );
2345 gnc_pop_locale( LC_NUMERIC );
2346 return create_dbi_result( dbi_conn, result );
2358 DEBUG(
"SQL: %s\n", dbi_stmt->sql->str );
2361 gnc_dbi_init_error( dbi_conn );
2362 result = dbi_conn_query( dbi_conn->conn, dbi_stmt->sql->str );
2364 while ( dbi_conn->retry );
2365 if ( result == NULL )
2367 PERR(
"Error executing SQL %s\n", dbi_stmt->sql->str );
2370 num_rows = (gint)dbi_result_get_numrows_affected( result );
2371 status = dbi_result_free( result );
2374 PERR(
"Error in dbi_result_free() result\n" );
2385 return create_dbi_statement( conn, sql );
2394 const gchar* dbname;
2397 g_return_val_if_fail( conn != NULL, FALSE );
2398 g_return_val_if_fail( table_name != NULL, FALSE );
2400 dbname = dbi_conn_get_option( dbi_conn->conn,
"dbname" );
2401 tables = dbi_conn_get_table_list( dbi_conn->conn, dbname, table_name );
2402 nTables = (gint)dbi_result_get_numrows( tables );
2403 status = dbi_result_free( tables );
2406 PERR(
"Error in dbi_result_free() result\n" );
2426 gboolean success = FALSE;
2430 if ( !gnc_dbi_verify_conn (dbi_conn) )
2432 PERR(
"gnc_dbi_verify_conn() failed\n" );
2439 gnc_dbi_init_error( dbi_conn );
2440 result = dbi_conn_queryf( dbi_conn->conn,
"BEGIN" );
2442 while ( dbi_conn->retry );
2444 success = ( result != NULL );
2445 status = dbi_result_free( result );
2448 PERR(
"Error in dbi_result_free() result\n" );
2453 PERR(
"BEGIN transaction failed()\n" );
2466 gboolean success = FALSE;
2468 DEBUG(
"ROLLBACK\n" );
2469 result = dbi_conn_queryf( dbi_conn->conn,
"ROLLBACK" );
2470 success = ( result != NULL );
2472 status = dbi_result_free( result );
2475 PERR(
"Error in dbi_result_free() result\n" );
2480 PERR(
"Error in conn_rollback_transaction()\n" );
2493 gboolean success = FALSE;
2495 DEBUG(
"COMMIT\n" );
2496 result = dbi_conn_queryf( dbi_conn->conn,
"COMMIT" );
2497 success = ( result != NULL );
2499 status = dbi_result_free( result );
2502 PERR(
"Error in dbi_result_free() result\n" );
2507 PERR(
"Error in conn_commit_transaction()\n" );
2516 const gchar* index_name,
2517 const gchar* table_name,
2523 g_return_val_if_fail( conn != NULL, NULL );
2524 g_return_val_if_fail( index_name != NULL, NULL );
2525 g_return_val_if_fail( table_name != NULL, NULL );
2526 g_return_val_if_fail( col_table != NULL, NULL );
2528 ddl = g_string_new(
"" );
2529 g_string_printf( ddl,
"CREATE INDEX %s ON %s (", index_name, table_name );
2530 for ( table_row = col_table; table_row->
col_name != NULL; ++table_row )
2532 if ( table_row != col_table )
2534 (void)g_string_append( ddl,
", " );
2536 g_string_append_printf( ddl,
"%s", table_row->
col_name );
2538 (void)g_string_append( ddl,
")" );
2540 return g_string_free( ddl, FALSE );
2545 const gchar* table_name,
2546 GList* col_info_list )
2549 const GList* list_node;
2553 g_return_val_if_fail( conn != NULL, NULL );
2554 g_return_val_if_fail( table_name != NULL, NULL );
2555 g_return_val_if_fail( col_info_list != NULL, NULL );
2557 ddl = g_string_new(
"" );
2558 g_string_printf( ddl,
"ALTER TABLE %s ", table_name );
2559 for ( list_node = col_info_list, col_num = 0; list_node != NULL;
2560 list_node = list_node->next, col_num++ )
2566 (void)g_string_append( ddl,
", " );
2568 g_string_append( ddl,
"ADD COLUMN " );
2569 dbi_conn->provider->append_col_def( ddl, info );
2570 g_free( info->
name );
2574 return g_string_free( ddl, FALSE );
2582 if ( info->
type == BCT_INT )
2584 type_name =
"integer";
2586 else if ( info->
type == BCT_INT64 )
2588 type_name =
"bigint";
2590 else if ( info->
type == BCT_DOUBLE )
2592 type_name =
"float8";
2594 else if ( info->
type == BCT_STRING || info->
type == BCT_DATE
2595 || info->
type == BCT_DATETIME )
2601 PERR(
"Unknown column type: %d\n", info->
type );
2604 g_string_append_printf( ddl,
"%s %s", info->
name, type_name );
2605 if ( info->
size != 0 )
2607 (void)g_string_append_printf( ddl,
"(%d)", info->
size );
2611 (void)g_string_append( ddl,
" PRIMARY KEY" );
2615 (void)g_string_append( ddl,
" AUTOINCREMENT" );
2619 (void)g_string_append( ddl,
" NOT NULL" );
2625 const gchar* table_name,
2626 const GList* col_info_list )
2629 const GList* list_node;
2632 g_return_val_if_fail( conn != NULL, NULL );
2633 g_return_val_if_fail( table_name != NULL, NULL );
2634 g_return_val_if_fail( col_info_list != NULL, NULL );
2636 ddl = g_string_new(
"" );
2637 g_string_printf( ddl,
"CREATE TABLE %s (", table_name );
2638 for ( list_node = col_info_list, col_num = 0; list_node != NULL;
2639 list_node = list_node->next, col_num++ )
2645 (void)g_string_append( ddl,
", " );
2647 append_sqlite3_col_def( ddl, info );
2648 g_free( info->
name );
2651 (void)g_string_append( ddl,
")" );
2653 return g_string_free( ddl, FALSE );
2661 if ( info->
type == BCT_INT )
2663 type_name =
"integer";
2665 else if ( info->
type == BCT_INT64 )
2667 type_name =
"bigint";
2669 else if ( info->
type == BCT_DOUBLE )
2671 type_name =
"double";
2673 else if ( info->
type == BCT_STRING )
2675 type_name =
"varchar";
2677 else if ( info->
type == BCT_DATE )
2682 else if ( info->
type == BCT_DATETIME )
2685 type_name =
"TIMESTAMP NULL DEFAULT 0";
2689 PERR(
"Unknown column type: %d\n", info->
type );
2692 g_string_append_printf( ddl,
"%s %s", info->
name, type_name );
2693 if ( info->
size != 0 )
2695 g_string_append_printf( ddl,
"(%d)", info->
size );
2699 (void)g_string_append( ddl,
" CHARACTER SET utf8" );
2703 (void)g_string_append( ddl,
" PRIMARY KEY" );
2707 (void)g_string_append( ddl,
" AUTO_INCREMENT" );
2711 (void)g_string_append( ddl,
" NOT NULL" );
2716 conn_create_table_ddl_mysql(
GncSqlConnection* conn,
const gchar* table_name,
2717 const GList* col_info_list )
2720 const GList* list_node;
2723 g_return_val_if_fail( conn != NULL, NULL );
2724 g_return_val_if_fail( table_name != NULL, NULL );
2725 g_return_val_if_fail( col_info_list != NULL, NULL );
2727 ddl = g_string_new(
"" );
2728 g_string_printf( ddl,
"CREATE TABLE %s (", table_name );
2729 for ( list_node = col_info_list, col_num = 0; list_node != NULL;
2730 list_node = list_node->next, col_num++ )
2736 (void)g_string_append( ddl,
", " );
2738 append_mysql_col_def( ddl, info );
2739 g_free( info->
name );
2742 (void)g_string_append( ddl,
")" );
2744 return g_string_free( ddl, FALSE );
2752 if ( info->
type == BCT_INT )
2756 type_name =
"serial";
2760 type_name =
"integer";
2763 else if ( info->
type == BCT_INT64 )
2767 else if ( info->
type == BCT_DOUBLE )
2769 type_name =
"double precision";
2771 else if ( info->
type == BCT_STRING )
2773 type_name =
"varchar";
2775 else if ( info->
type == BCT_DATE )
2780 else if ( info->
type == BCT_DATETIME )
2783 type_name =
"timestamp without time zone";
2787 PERR(
"Unknown column type: %d\n", info->
type );
2790 g_string_append_printf( ddl,
"%s %s", info->
name, type_name );
2791 if ( info->
size != 0 )
2793 g_string_append_printf( ddl,
"(%d)", info->
size );
2797 (void)g_string_append( ddl,
" PRIMARY KEY" );
2801 (void)g_string_append( ddl,
" NOT NULL" );
2806 conn_create_table_ddl_pgsql(
GncSqlConnection* conn,
const gchar* table_name,
2807 const GList* col_info_list )
2810 const GList* list_node;
2812 gboolean is_unicode = FALSE;
2814 g_return_val_if_fail( conn != NULL, NULL );
2815 g_return_val_if_fail( table_name != NULL, NULL );
2816 g_return_val_if_fail( col_info_list != NULL, NULL );
2818 ddl = g_string_new(
"" );
2819 g_string_printf( ddl,
"CREATE TABLE %s (", table_name );
2820 for ( list_node = col_info_list, col_num = 0; list_node != NULL;
2821 list_node = list_node->next, col_num++ )
2827 (void)g_string_append( ddl,
", " );
2829 append_pgsql_col_def( ddl, info );
2831 g_free( info->
name );
2834 (void)g_string_append( ddl,
")" );
2839 return g_string_free( ddl, FALSE );
2844 GList* col_info_list )
2850 g_return_val_if_fail( conn != NULL, FALSE );
2851 g_return_val_if_fail( table_name != NULL, FALSE );
2852 g_return_val_if_fail( col_info_list != NULL, FALSE );
2855 ddl = dbi_conn->provider->create_table_ddl( conn, table_name,
2857 g_list_free( col_info_list );
2862 DEBUG(
"SQL: %s\n", ddl );
2863 result = dbi_conn_query( dbi_conn->conn, ddl );
2865 status = dbi_result_free( result );
2868 PERR(
"Error in dbi_result_free() result\n" );
2888 g_return_val_if_fail( conn != NULL, FALSE );
2889 g_return_val_if_fail( index_name != NULL, FALSE );
2890 g_return_val_if_fail( table_name != NULL, FALSE );
2891 g_return_val_if_fail( col_table != NULL, FALSE );
2893 ddl = create_index_ddl( conn, index_name, table_name, col_table );
2898 DEBUG(
"SQL: %s\n", ddl );
2899 result = dbi_conn_query( dbi_conn->conn, ddl );
2901 status = dbi_result_free( result );
2904 PERR(
"Error in dbi_result_free() result\n" );
2917 conn_add_columns_to_table(
GncSqlConnection* conn,
const gchar* table_name,
2918 GList* col_info_list )
2924 g_return_val_if_fail( conn != NULL, FALSE );
2925 g_return_val_if_fail( table_name != NULL, FALSE );
2926 g_return_val_if_fail( col_info_list != NULL, FALSE );
2928 ddl = add_columns_ddl( conn, table_name, col_info_list );
2933 DEBUG(
"SQL: %s\n", ddl );
2934 result = dbi_conn_query( dbi_conn->conn, ddl );
2936 status = dbi_result_free( result );
2939 PERR(
"Error in dbi_result_free() result\n" );
2958 size = dbi_conn_quote_string_copy( dbi_conn->conn, unquoted_str,
2971 conn_get_table_list( dbi_conn conn,
const gchar* dbname )
2974 GSList* list = NULL;
2976 tables = dbi_conn_get_table_list( conn, dbname, NULL );
2977 while ( dbi_result_next_row( tables ) != 0 )
2979 const gchar* table_name;
2981 table_name = dbi_result_get_string_idx( tables, 1 );
2982 list = g_slist_prepend( list, strdup( table_name ) );
2984 dbi_result_free( tables );
2989 conn_get_table_list_sqlite3( dbi_conn conn,
const gchar* dbname )
2991 gboolean change_made;
2995 GSList* list = conn_get_table_list( conn, dbname );
2997 while ( list != NULL && change_made )
3001 change_made = FALSE;
3002 for ( node = list; node != NULL; node = node->next )
3004 const gchar* table_name = (
const gchar*)node->data;
3006 if ( strcmp( table_name,
"sqlite_sequence" ) == 0 )
3008 g_free( node->data );
3009 list = g_slist_delete_link( list, node );
3019 conn_get_table_list_pgsql( dbi_conn conn,
const gchar* dbname )
3021 gboolean change_made;
3024 GSList* list = conn_get_table_list( conn, dbname );
3026 while ( list != NULL && change_made )
3030 change_made = FALSE;
3031 for ( node = list; node != NULL; node = node->next )
3033 const gchar* table_name = (
const gchar*)node->data;
3035 if ( strcmp( table_name,
"sql_features" ) == 0 ||
3036 strcmp( table_name,
"sql_implementation_info" ) == 0 ||
3037 strcmp( table_name,
"sql_languages" ) == 0 ||
3038 strcmp( table_name,
"sql_packages" ) == 0 ||
3039 strcmp( table_name,
"sql_parts" ) == 0 ||
3040 strcmp( table_name,
"sql_sizing" ) == 0 ||
3041 strcmp( table_name,
"sql_sizing_profiles" ) == 0 )
3043 g_free( node->data );
3044 list = g_slist_delete_link( list, node );
3062 static GncDbiTestResult
3063 conn_test_dbi_library( dbi_conn conn )
3065 gint64 testlonglong = -9223372036854775807LL, resultlonglong = 0;
3066 guint64 testulonglong = 9223372036854775807LLU, resultulonglong = 0;
3067 gdouble testdouble = 1.7976921348623157E+307, resultdouble = 0.0;
3069 gchar doublestr[G_ASCII_DTOSTR_BUF_SIZE], *querystr;
3070 GncDbiTestResult retval = GNC_DBI_PASS;
3071 memset( doublestr, 0,
sizeof(doublestr));
3073 result = dbi_conn_query( conn,
"CREATE TEMPORARY TABLE numtest "
3074 "( test_int BIGINT, test_unsigned BIGINT,"
3075 " test_double FLOAT8 )" );
3076 if ( result == NULL )
3078 PWARN(
"Test_DBI_Library: Create table failed");
3079 return GNC_DBI_FAIL_SETUP;
3081 dbi_result_free( result );
3082 g_ascii_dtostr( doublestr,
sizeof(doublestr), testdouble );
3083 querystr = g_strdup_printf(
"INSERT INTO numtest VALUES (%" G_GINT64_FORMAT
3084 ", %" G_GUINT64_FORMAT
", %s)",
3085 testlonglong, testulonglong, doublestr );
3086 result = dbi_conn_query( conn, querystr );
3088 if ( result == NULL )
3090 PWARN(
"Test_DBI_Library: Failed to insert test row into table" );
3091 return GNC_DBI_FAIL_SETUP;
3093 dbi_result_free( result );
3094 gnc_push_locale( LC_NUMERIC,
"C");
3095 result = dbi_conn_query( conn,
"SELECT * FROM numtest" );
3096 if ( result == NULL )
3099 dbi_conn_error( conn, &errmsg );
3100 PWARN(
"Test_DBI_Library: Failed to retrieve test row into table: %s",
3102 result = dbi_conn_query( conn,
"DROP TABLE numtest" );
3103 gnc_pop_locale( LC_NUMERIC );
3104 return GNC_DBI_FAIL_SETUP;
3106 while ( dbi_result_next_row( result ))
3108 resultlonglong = dbi_result_get_longlong( result,
"test_int" );
3109 resultulonglong = dbi_result_get_ulonglong( result,
"test_unsigned" );
3110 resultdouble = dbi_result_get_double( result,
"test_double" );
3112 gnc_pop_locale( LC_NUMERIC );
3113 if ( testlonglong != resultlonglong )
3115 PWARN(
"Test_DBI_Library: LongLong Failed %" G_GINT64_FORMAT
" != % " G_GINT64_FORMAT,
3116 testlonglong, resultlonglong );
3117 retval = GNC_DBI_FAIL_TEST;
3119 if ( testulonglong != resultulonglong )
3121 PWARN(
"Test_DBI_Library: Unsigned longlong Failed %" G_GUINT64_FORMAT
" != %" G_GUINT64_FORMAT,
3122 testulonglong, resultulonglong );
3123 retval = GNC_DBI_FAIL_TEST;
3126 if ( testdouble >= resultdouble + 0.000001e307 ||
3127 testdouble <= resultdouble - 0.000001e307 )
3129 PWARN(
"Test_DBI_Library: Double Failed %17e != %17e",
3130 testdouble, resultdouble );
3131 retval = GNC_DBI_FAIL_TEST;
3145 g_assert( dbi_conn != NULL );
3147 dbi_conn->base.dispose = conn_dispose;
3150 dbi_conn->base.createStatementFromSql = conn_create_statement_from_sql;
3158 dbi_conn->base.quoteString = conn_quote_string;
3159 dbi_conn->qbe = qbe;
3160 dbi_conn->conn = conn;
3161 dbi_conn->provider = provider;
3162 dbi_conn->conn_ok = TRUE;
3163 gnc_dbi_init_error(dbi_conn);
G_MODULE_EXPORT void qof_backend_module_init(void)
void gnc_sql_begin_edit(GncSqlBackend *be, QofInstance *inst)
void gnc_sql_finalize_version_info(GncSqlBackend *be)
QofBackend *(* backend_new)(void)
void qof_backend_set_error(QofBackend *be, QofBackendError err)
load and save data to SQL via libdbi
void(* provider_free)(QofBackendProvider *)
gint gnc_sql_get_table_version(const GncSqlBackend *be, const gchar *table_name)
void gnc_sql_rollback_edit(GncSqlBackend *be, QofInstance *inst)
void qof_backend_register_provider(QofBackendProvider *)
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
#define PINFO(format, args...)
void gnc_sql_init(GncSqlBackend *be)
const gchar * QofIdTypeConst
#define DEBUG(format, args...)
gboolean(* doesTableExist)(GncSqlConnection *, const gchar *)
gchar * gnc_uri_get_path(const gchar *uri)
void(* export_fn)(QofBackend *, QofBook *)
#define PERR(format, args...)
#define ENTER(format, args...)
void gnc_module_init_backend_dbi(void)
#define PWARN(format, args...)
gboolean(* addColumnsToTable)(GncSqlConnection *, const gchar *table, GList *)
GncSqlBasicColumnType type
Account handling public routines.
void qof_backend_set_message(QofBackend *be, const char *format,...)
Anchor Scheduled Transaction info in a book. See src/doc/books.txt for design overview.
void gnc_uri_get_components(const gchar *uri, gchar **protocol, gchar **hostname, gint32 *port, gchar **username, gchar **password, gchar **path)
gchar * gnc_sql_get_sql_value(const GncSqlConnection *conn, const GValue *value)
gboolean(* check_data_type)(const char *)
Distinguish two providers with same access method.
gboolean(* createIndex)(GncSqlConnection *, const gchar *, const gchar *, const GncSqlColumnTableEntry *)
QofBackendError qof_backend_get_error(QofBackend *be)
All type declarations for the whole Gnucash engine.
gchar * gnc_build_translog_path(const gchar *filename)
Make a path to filename in the translog subdirectory of the user's configuration directory.
Generic api to store and retrieve preferences.
void gnc_sql_commit_edit(GncSqlBackend *be, QofInstance *inst)
API for the transaction logger.
gboolean(* createTable)(GncSqlConnection *, const gchar *, GList *)
const char * provider_name
void gnc_sql_sync_all(GncSqlBackend *be, QofBook *book)
void xaccLogSetBaseName(const char *basepath)
gint(* executeNonSelectStatement)(GncSqlConnection *, GncSqlStatement *)
const char * access_method
#define LEAVE(format, args...)
gboolean(* rollbackTransaction)(GncSqlConnection *)
Utility functions for convert uri in separate components and back.
void(* create_tables)(GncSqlBackend *be)
const gchar * timespec_format
File path resolution utility functions.
gboolean(* beginTransaction)(GncSqlConnection *)
gboolean(* commitTransaction)(GncSqlConnection *)
void gnc_module_finalize_backend_dbi(void)
void gnc_sql_init_version_info(GncSqlBackend *be)
void gnc_sql_load(GncSqlBackend *be, QofBook *book, QofBackendLoadType loadType)
const gchar * QofLogModule
GncSqlResult *(* executeSelectStatement)(GncSqlConnection *, GncSqlStatement *)