int main (int argc, char *argv[]) { dbi_conn conn; dbi_result result; const char *err_msg; int err_code; if (argc < 2) { fprintf (stderr, "%s: Need a libdir as argument!\n", argv[0]); return 1; } dbi_initialize (argv[1]); conn = dbi_conn_new ("null"); dbi_conn_connect (conn); /* * Queries */ result = dbi_conn_query (conn, "COMMIT"); assert (result != NULL); dbi_result_free (result); dbi_conn_set_option_numeric (conn, "null.error.commit", 1); result = dbi_conn_query (conn, "COMMIT"); assert (result == NULL); dbi_conn_set_option_numeric (conn, "null.error.commit", 0); result = dbi_conn_query (conn, "COMMIT"); assert (result != NULL); dbi_result_free (result); /* * Normal queries */ result = dbi_conn_query (conn, "SELECT * FROM DUAL"); assert (result != NULL); dbi_result_free (result); dbi_conn_set_option_numeric (conn, "null.error.query", 1); result = dbi_conn_query (conn, "SELECT * FROM DUAL"); assert (result == NULL); dbi_conn_set_option_numeric (conn, "null.error.query", 0); result = dbi_conn_query (conn, "SELECT * FROM DUAL"); assert (result != NULL); dbi_result_free (result); /* * Cleanup */ dbi_conn_close (conn); dbi_shutdown (); return 0; }
BEGINcreateInstance CODESTARTcreateInstance ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature /* we do not like repeated message reduction inside the database */ ENDisCompatibleWithFeature /* The following function is responsible for closing a * database connection. */ static void closeConn(instanceData *pData) { ASSERT(pData != NULL); if(pData->conn != NULL) { /* just to be on the safe side... */ dbi_conn_close(pData->conn); pData->conn = NULL; } }
void dbi_shutdown_r(dbi_inst Inst) { dbi_inst_t *inst = (dbi_inst_t*) Inst; dbi_conn_t *curconn = inst->rootconn; dbi_conn_t *nextconn; dbi_driver_t *curdriver = inst->rootdriver; dbi_driver_t *nextdriver; while (curconn) { nextconn = curconn->next; dbi_conn_close((dbi_conn)curconn); curconn = nextconn; } while (curdriver) { nextdriver = curdriver->next; curdriver->functions->finalize(curdriver); _safe_dlclose(curdriver); free(curdriver->functions); _free_custom_functions(curdriver); _free_caps(curdriver->caps); free(curdriver->filename); free(curdriver); curdriver = nextdriver; } #if HAVE_LTDL_H (void)lt_dlexit(); #endif free(inst); }
static void afsql_dd_disconnect(AFSqlDestDriver *self) { dbi_conn_close(self->dbi_ctx); self->dbi_ctx = NULL; g_hash_table_remove_all(self->validated_tables); }
static char query_handler(char *query_name, char *myq) { if(myq == NULL) { myq = "SELECT NULL"; } if(query_name == NULL) { query_name = "noname"; } if(query_name == "") { query_name = "noname"; } dbi_initialize(NULL); conn = dbi_conn_new("mysql"); dbi_conn_set_option(conn, "host", getenv("DB_HOSTNAME")); dbi_conn_set_option(conn, "username", getenv("DB_USERNAME")); dbi_conn_set_option(conn, "password", getenv("DB_PASSWORD")); dbi_conn_set_option(conn, "dbname", getenv("DB_DATABASE")); dbi_conn_set_option(conn, "encoding", "UTF-8"); if (dbi_conn_connect(conn) < 0) { printf("Could not connect. Please check the option settings and if the" \ "specific driver is available\n"); } else { result = dbi_conn_queryf(conn, myq, threshold); if (result) { xmlAddChild(sql_node,query_doc(result,query_name)); dbi_result_free(result); } dbi_conn_close(conn); } return 0; }
int db_wrap_dbi_init2(char const * driver, db_wrap_conn_params const * param, db_wrap ** tgt) { INIT_DBI(-1); if (! driver || !*driver || !tgt) { return DB_WRAP_E_BAD_ARG; } dbi_conn conn = #if USE_DEPRECATED_DBI_API dbi_conn_new(driver) #else dbi_conn_new_r(driver,DBI_INSTANCE) #endif ; if (! conn) { return DB_WRAP_E_UNKNOWN_ERROR; } db_wrap * db = NULL; int rc = db_wrap_dbi_init(conn, param, &db); if (rc) { dbi_conn_close(conn); return rc; } assert(db); *tgt = db; return rc; }
void close_database(database *db) { if (db && db->conn) { if (db->conn) dbi_conn_close(db->conn); free(db); } return; }
/* Disconnects from a database */ void SMSDDBI_Free(GSM_SMSDConfig * Config) { if (Config->conn.dbi != NULL) { dbi_conn_close(Config->conn.dbi); dbi_shutdown(); Config->conn.dbi = NULL; } }
template <DbType Type> dbi_conn conn_setup (QofBackend* qbe, PairVec& options, UriStrings& uri) { const char* dbstr = (Type == DbType::DBI_SQLITE ? "sqlite3" : Type == DbType::DBI_MYSQL ? "mysql" : "pgsql"); #if HAVE_LIBDBI_R dbi_conn conn = nullptr; if (dbi_instance) conn = dbi_conn_new_r (dbstr, dbi_instance); else PERR ("Attempt to connect with an uninitialized dbi_instance"); #else auto conn = dbi_conn_new (dbstr); #endif if (conn == nullptr) { PERR ("Unable to create %s dbi connection", dbstr); qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL); return nullptr; } dbi_conn_error_handler (conn, error_handler<Type>, qbe); if (!uri.m_dbname.empty() && !set_standard_connection_options(qbe, conn, uri)) { dbi_conn_close(conn); return nullptr; } if(!options.empty()) { try { set_options(conn, options); } catch (std::runtime_error& err) { dbi_conn_close(conn); qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); return nullptr; } } return conn; }
/** @brief Disconnect from the database. This function is called when the server drone is about to terminate. */ void osrfAppChildExit() { osrfLogDebug( OSRF_LOG_MARK, "Child is exiting, disconnecting from database..." ); if ( dbhandle ) { dbi_conn_query( dbhandle, "ROLLBACK;" ); dbi_conn_close( dbhandle ); dbhandle = NULL; } }
/** @brief Disconnect from the database. This function is called when the server drone is about to terminate. */ void osrfAppChildExit( void ) { osrfLogDebug(OSRF_LOG_MARK, "Child is exiting, disconnecting from database..."); int same = 0; if (writehandle == dbhandle) same = 1; if (writehandle) { dbi_conn_query(writehandle, "ROLLBACK;"); dbi_conn_close(writehandle); writehandle = NULL; } if (dbhandle && !same) dbi_conn_close(dbhandle); // XXX add cleanup of readHandles whenever that gets used return; }
int dbiw_cleanup(db_wrap * self) { DB_DECL(DB_WRAP_E_BAD_ARG); if (conn) { dbi_conn_close(conn); } *self = db_wrap_empty; return 0; }
static bool create_database(DbType type, QofBackend *qbe, dbi_conn conn, const char* db) { const char *dbname; const char *dbcreate; if (type == DbType::DBI_MYSQL) { dbname = "mysql"; dbcreate = "CREATE DATABASE %s CHARACTER SET utf8"; } else { dbname = "postgres"; dbcreate = "CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'"; } PairVec options; options.push_back(std::make_pair("dbname", dbname)); try { set_options(conn, options); } catch (std::runtime_error& err) { qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); return false; } auto result = dbi_conn_connect (conn); if (result < 0) { PERR ("Unable to connect to %s database", dbname); qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); return false; } if (type == DbType::DBI_MYSQL) adjust_sql_options(conn); auto dresult = dbi_conn_queryf (conn, dbcreate, db); if (dresult == nullptr) { PERR ("Unable to create database '%s'\n", db); qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); return false; } if (type == DbType::DBI_PGSQL) { const char *alterdb = "ALTER DATABASE %s SET " "standard_conforming_strings TO on"; dbi_conn_queryf (conn, alterdb, db); } dbi_conn_close(conn); conn = nullptr; return true; }
static apr_status_t safe_dbi_kill_conn(void *resource, void *params, apr_pool_t * pool) { /* dbi_config_rec *conf = params; */ ftpd_dbi_rest *res = resource; ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, pool, "[mod_ftpd_dbi.c] Disconnecting from Server"); dbi_conn_close(res->conn); dbi_conn_count--; return APR_SUCCESS; }
static void _sql_close(struct sql_table_helper* th) { /* close only if connected */ if (th->conn) { if (getenv("RRDDEBUGSQL")) { fprintf(stderr,"RRDDEBUGSQL: %li: close connection\n",time(NULL) ); } /* shutdown dbi */ dbi_conn_close(th->conn); if (getenv("RRDDEBUGSQL")) { fprintf(stderr,"RRDDEBUGSQL: %li: shutting down libdbi\n",time(NULL) ); } dbi_shutdown(); /* and assign empty */ th->conn=NULL; th->connected=0; } }
static int cdbi_shutdown (void) /* {{{ */ { for (size_t i = 0; i < databases_num; i++) { if (databases[i]->connection != NULL) { dbi_conn_close (databases[i]->connection); databases[i]->connection = NULL; } cdbi_database_free (databases[i]); } sfree (databases); databases_num = 0; udb_query_free (queries, queries_num); queries = NULL; queries_num = 0; return (0); } /* }}} int cdbi_shutdown */
/** @brief Initialize the application. @return Zero if successful, or non-zero if not. Load the IDL file into an internal data structure for future reference. Each non-virtual class in the IDL corresponds to a table or view in the database, or to a subquery defined in the IDL. Ignore all virtual tables and virtual fields. Register a number of methods, some of them general-purpose and others specific for particular classes. The name of the application is given by the MODULENAME macro, whose value depends on conditional compilation. The method names also incorporate MODULENAME, followed by a dot, as a prefix. The general-purpose methods are as follows (minus their MODULENAME prefixes): - json_query - transaction.begin - transaction.commit - transaction.rollback - savepoint.set - savepoint.release - savepoint.rollback For each non-virtual class, create up to eight class-specific methods: - create (not for readonly classes) - retrieve - update (not for readonly classes) - delete (not for readonly classes - search (atomic and non-atomic versions) - id_list (atomic and non-atomic versions) The full method names follow the pattern "MODULENAME.direct.XXX.method_type", where XXX is the fieldmapper name from the IDL, with every run of one or more consecutive colons replaced by a period. In addition, the names of atomic methods have a suffix of ".atomic". This function is called when the registering the application, and is executed by the listener before spawning the drones. */ int osrfAppInitialize( void ) { osrfLogInfo(OSRF_LOG_MARK, "Initializing the CStore Server..."); osrfLogInfo(OSRF_LOG_MARK, "Finding XML file..."); // Load the IDL into memory if ( !oilsIDLInit( osrf_settings_host_value( "/IDL" ))) return 1; /* return non-zero to indicate error */ // Open the database temporarily. Look up the datatypes of all // the non-virtual fields and record them with the IDL data. dbi_conn handle = oilsConnectDB( modulename ); if( !handle ) return -1; else if( oilsExtendIDL( handle )) { osrfLogError( OSRF_LOG_MARK, "Error extending the IDL" ); return -1; } dbi_conn_close( handle ); // Get the maximum flesh depth from the settings char* md = osrf_settings_host_value( "/apps/%s/app_settings/max_query_recursion", modulename ); int max_flesh_depth = 100; if( md ) max_flesh_depth = atoi( md ); if( max_flesh_depth < 0 ) max_flesh_depth = 1; else if( max_flesh_depth > 1000 ) max_flesh_depth = 1000; oilsSetSQLOptions( modulename, enforce_pcrud, max_flesh_depth ); // Now register all the methods growing_buffer* method_name = buffer_init(64); // Generic search thingy buffer_add( method_name, modulename ); buffer_add( method_name, ".json_query" ); osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ), "doJSONSearch", "", 1, OSRF_METHOD_STREAMING ); // Next we register all the transaction and savepoint methods buffer_reset(method_name); OSRF_BUFFER_ADD(method_name, modulename ); OSRF_BUFFER_ADD(method_name, ".transaction.begin"); osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR( method_name ), "beginTransaction", "", 0, 0 ); buffer_reset(method_name); OSRF_BUFFER_ADD(method_name, modulename ); OSRF_BUFFER_ADD(method_name, ".transaction.commit"); osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name), "commitTransaction", "", 0, 0 ); buffer_reset(method_name); OSRF_BUFFER_ADD(method_name, modulename ); OSRF_BUFFER_ADD(method_name, ".transaction.rollback"); osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name), "rollbackTransaction", "", 0, 0 ); buffer_reset(method_name); OSRF_BUFFER_ADD(method_name, modulename ); OSRF_BUFFER_ADD(method_name, ".savepoint.set"); osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name), "setSavepoint", "", 1, 0 ); buffer_reset(method_name); OSRF_BUFFER_ADD(method_name, modulename ); OSRF_BUFFER_ADD(method_name, ".savepoint.release"); osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name), "releaseSavepoint", "", 1, 0 ); buffer_reset(method_name); OSRF_BUFFER_ADD(method_name, modulename ); OSRF_BUFFER_ADD(method_name, ".savepoint.rollback"); osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name), "rollbackSavepoint", "", 1, 0 ); static const char* global_method[] = { "create", "retrieve", "update", "delete", "search", "id_list" }; const int global_method_count = sizeof( global_method ) / sizeof ( global_method[0] ); unsigned long class_count = osrfHashGetCount( oilsIDL() ); osrfLogDebug(OSRF_LOG_MARK, "%lu classes loaded", class_count ); osrfLogDebug(OSRF_LOG_MARK, "At most %lu methods will be generated", (unsigned long) (class_count * global_method_count) ); osrfHashIterator* class_itr = osrfNewHashIterator( oilsIDL() ); osrfHash* idlClass = NULL; // For each class in the IDL... while( (idlClass = osrfHashIteratorNext( class_itr ) ) ) { const char* classname = osrfHashIteratorKey( class_itr ); osrfLogInfo(OSRF_LOG_MARK, "Generating class methods for %s", classname); if (!osrfStringArrayContains( osrfHashGet(idlClass, "controller"), modulename )) { osrfLogInfo(OSRF_LOG_MARK, "%s is not listed as a controller for %s, moving on", modulename, classname); continue; } if ( str_is_true( osrfHashGet(idlClass, "virtual") ) ) { osrfLogDebug(OSRF_LOG_MARK, "Class %s is virtual, skipping", classname ); continue; } // Look up some other attributes of the current class const char* idlClass_fieldmapper = osrfHashGet(idlClass, "fieldmapper"); if( !idlClass_fieldmapper ) { osrfLogDebug( OSRF_LOG_MARK, "Skipping class \"%s\"; no fieldmapper in IDL", classname ); continue; } const char* readonly = osrfHashGet(idlClass, "readonly"); int i; for( i = 0; i < global_method_count; ++i ) { // for each global method const char* method_type = global_method[ i ]; osrfLogDebug(OSRF_LOG_MARK, "Using files to build %s class methods for %s", method_type, classname); // No create, update, or delete methods for a readonly class if ( str_is_true( readonly ) && ( *method_type == 'c' || *method_type == 'u' || *method_type == 'd') ) continue; buffer_reset( method_name ); // Build the method name: MODULENAME.MODULENAME.direct.XXX.method_type // where XXX is the fieldmapper name from the IDL, with every run of // one or more consecutive colons replaced by a period. char* st_tmp = NULL; char* part = NULL; char* _fm = strdup( idlClass_fieldmapper ); part = strtok_r(_fm, ":", &st_tmp); buffer_fadd(method_name, "%s.direct.%s", modulename, part); while ((part = strtok_r(NULL, ":", &st_tmp))) { OSRF_BUFFER_ADD_CHAR(method_name, '.'); OSRF_BUFFER_ADD(method_name, part); } OSRF_BUFFER_ADD_CHAR(method_name, '.'); OSRF_BUFFER_ADD(method_name, method_type); free(_fm); // For an id_list or search method we specify the OSRF_METHOD_STREAMING option. // The consequence is that we implicitly create an atomic method in addition to // the usual non-atomic method. int flags = 0; if (*method_type == 'i' || *method_type == 's') { // id_list or search flags = flags | OSRF_METHOD_STREAMING; } osrfHash* method_meta = osrfNewHash(); osrfHashSet( method_meta, idlClass, "class"); osrfHashSet( method_meta, buffer_data( method_name ), "methodname" ); osrfHashSet( method_meta, strdup(method_type), "methodtype" ); // Register the method, with a pointer to an osrfHash to tell the method // its name, type, and class. osrfAppRegisterExtendedMethod( modulename, OSRF_BUFFER_C_STR( method_name ), "dispatchCRUDMethod", "", 1, flags, (void*)method_meta ); } // end for each global method } // end for each class in IDL buffer_free( method_name ); osrfHashIteratorFree( class_itr ); return 0; }
int main( int argc, char* argv[] ) { // Parse command line const char* idl_file_name = NULL; const char* query_file_name = NULL; int verbose = 0; // boolean int opt; opterr = 0; const char optstring[] = ":f:i:v"; while( ( opt = getopt( argc, argv, optstring ) ) != -1 ) { switch( opt ) { case 'f' : // get file name of query if( query_file_name ) { fprintf( stderr, "Multiple input files not allowed\n" ); return EXIT_FAILURE; } else query_file_name = optarg; break; case 'i' : // get name of IDL file if( idl_file_name ) { fprintf( stderr, "Multiple IDL file names not allowed\n" ); return EXIT_FAILURE; } else idl_file_name = optarg; break; case 'v' : // Verbose verbose = 1; break; case '?' : // Invalid option fprintf( stderr, "Invalid option '-%c' on command line\n", (char) optopt ); return EXIT_FAILURE; default : // Huh? fprintf( stderr, "Internal error: unexpected value '%c'" "for optopt", (char) optopt ); return EXIT_FAILURE; } } // If the command line doesn't specify an IDL file, get it // from an environmental variable, or apply a default if( NULL == idl_file_name ) { idl_file_name = getenv( "OILS_IDL_FILENAME" ); if( NULL == idl_file_name ) idl_file_name = "/openils/conf/fm_IDL.xml"; } if( verbose ) printf( "IDL file: %s\n", idl_file_name ); char* loaded_json = NULL; const char* json_query = NULL; // Get the JSON query into a string if( query_file_name ) { // Got a file? Load it if( optind < argc ) fprintf( stderr, "Extra parameter(s) ignored\n" ); loaded_json = load_query( query_file_name ); if( !loaded_json ) return EXIT_FAILURE; json_query = loaded_json; } else { // No file? Use command line parameter if ( optind == argc ) { fprintf( stderr, "No JSON query specified\n" ); return EXIT_FAILURE; } else json_query = argv[ optind ]; } if( verbose ) printf( "JSON query: %s\n", json_query ); osrfLogSetLevel( OSRF_LOG_WARNING ); // Suppress informational messages (void) oilsIDLInit( idl_file_name ); // Load IDL into memory // Load a database driver, connect to it, and install the connection in // the cstore module. We don't actually connect to a database, but we // need the driver to process quoted strings correctly. if( dbi_initialize( NULL ) < 0 ) { printf( "Unable to load database driver\n" ); return EXIT_FAILURE; }; dbi_conn conn = dbi_conn_new( "pgsql" ); // change string if ever necessary if( !conn ) { printf( "Unable to establish dbi connection\n" ); dbi_shutdown(); return EXIT_FAILURE; } oilsSetDBConnection( conn ); // The foregoing is an inelegant kludge. The true, proper, and uniquely // correct thing to do is to load the system settings and then call // osrfAppInitialize() and osrfAppChildInit(). Maybe we'll actually // do that some day, but this will do for now. // Translate the JSON into SQL int rc = test_json_query( json_query ); dbi_conn_close( conn ); dbi_shutdown(); if( loaded_json ) free( loaded_json ); return rc ? EXIT_FAILURE : EXIT_SUCCESS; }
static int cdbi_connect_database (cdbi_database_t *db) /* {{{ */ { dbi_driver driver; dbi_conn connection; size_t i; int status; if (db->connection != NULL) { status = dbi_conn_ping (db->connection); if (status != 0) /* connection is alive */ return (0); dbi_conn_close (db->connection); db->connection = NULL; } driver = dbi_driver_open_r (db->driver, dbi_instance); if (driver == NULL) { ERROR ("dbi plugin: cdbi_connect_database: dbi_driver_open_r (%s) failed.", db->driver); INFO ("dbi plugin: Maybe the driver isn't installed? " "Known drivers are:"); for (driver = dbi_driver_list_r (NULL, dbi_instance); driver != NULL; driver = dbi_driver_list_r (driver, dbi_instance)) { INFO ("dbi plugin: * %s", dbi_driver_get_name (driver)); } return (-1); } connection = dbi_conn_open (driver); if (connection == NULL) { ERROR ("dbi plugin: cdbi_connect_database: dbi_conn_open (%s) failed.", db->driver); return (-1); } /* Set all the driver options. Because this is a very very very generic * interface, the error handling is kind of long. If an invalid option is * encountered, it will get a list of options understood by the driver and * report that as `INFO'. This way, users hopefully don't have too much * trouble finding out how to configure the plugin correctly.. */ for (i = 0; i < db->driver_options_num; i++) { if (db->driver_options[i].is_numeric) { status = dbi_conn_set_option_numeric (connection, db->driver_options[i].key, db->driver_options[i].value.numeric); if (status != 0) { char errbuf[1024]; ERROR ("dbi plugin: cdbi_connect_database (%s): " "dbi_conn_set_option_numeric (\"%s\", %i) failed: %s.", db->name, db->driver_options[i].key, db->driver_options[i].value.numeric, cdbi_strerror (connection, errbuf, sizeof (errbuf))); } } else { status = dbi_conn_set_option (connection, db->driver_options[i].key, db->driver_options[i].value.string); if (status != 0) { char errbuf[1024]; ERROR ("dbi plugin: cdbi_connect_database (%s): " "dbi_conn_set_option (\"%s\", \"%s\") failed: %s.", db->name, db->driver_options[i].key, db->driver_options[i].value.string, cdbi_strerror (connection, errbuf, sizeof (errbuf))); } } if (status != 0) { char const *opt; INFO ("dbi plugin: This is a list of all options understood " "by the `%s' driver:", db->driver); for (opt = dbi_conn_get_option_list (connection, NULL); opt != NULL; opt = dbi_conn_get_option_list (connection, opt)) { INFO ("dbi plugin: * %s", opt); } dbi_conn_close (connection); return (-1); } } /* for (i = 0; i < db->driver_options_num; i++) */ status = dbi_conn_connect (connection); if (status != 0) { char errbuf[1024]; ERROR ("dbi plugin: cdbi_connect_database (%s): " "dbi_conn_connect failed: %s", db->name, cdbi_strerror (connection, errbuf, sizeof (errbuf))); dbi_conn_close (connection); return (-1); } if (db->select_db != NULL) { status = dbi_conn_select_db (connection, db->select_db); if (status != 0) { char errbuf[1024]; WARNING ("dbi plugin: cdbi_connect_database (%s): " "dbi_conn_select_db (%s) failed: %s. Check the `SelectDB' option.", db->name, db->select_db, cdbi_strerror (connection, errbuf, sizeof (errbuf))); dbi_conn_close (connection); return (-1); } } db->connection = connection; return (0); } /* }}} int cdbi_connect_database */
/**************************** database functions. NOTE: Don't use with multithreaded programs! ***************************/ void close_database(dbi_conn conn) { dbi_conn_close(conn); }
template <> void gnc_dbi_session_begin<DbType::DBI_SQLITE>(QofBackend* qbe, QofSession* session, const char* book_id, gboolean ignore_lock, gboolean create, gboolean force) { GncDbiBackend* be = (GncDbiBackend*)qbe; const char* msg = nullptr; gboolean file_exists; PairVec options; g_return_if_fail (qbe != nullptr); g_return_if_fail (session != nullptr); g_return_if_fail (book_id != nullptr); ENTER (" "); /* Remove uri type if present */ auto path = gnc_uri_get_path (book_id); std::string filepath{path}; g_free(path); GFileTest ftest = static_cast<decltype (ftest)> ( G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS) ; file_exists = g_file_test (filepath.c_str(), ftest); if (!create && !file_exists) { qof_backend_set_error (qbe, ERR_FILEIO_FILE_NOT_FOUND); qof_backend_set_message (qbe, "Sqlite3 file %s not found", filepath.c_str()); PWARN ("Sqlite3 file %s not found", filepath.c_str()); LEAVE("Error"); return; } if (create && !force && file_exists) { qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS); msg = "Might clobber, no force"; PWARN ("%s", msg); LEAVE("Error"); return; } be->connect(nullptr); /* dbi-sqlite3 documentation says that sqlite3 doesn't take a "host" option */ options.push_back(std::make_pair("host", "localhost")); auto dirname = g_path_get_dirname (filepath.c_str()); auto basename = g_path_get_basename (filepath.c_str()); options.push_back(std::make_pair("dbname", basename)); options.push_back(std::make_pair("sqlite3_dbdir", dirname)); if (basename != nullptr) g_free (basename); if (dirname != nullptr) g_free (dirname); UriStrings uri; auto conn = conn_setup<DbType::DBI_SQLITE>(qbe, options, uri); if (conn == nullptr) { LEAVE("Error"); return; } auto result = dbi_conn_connect (conn); if (result < 0) { dbi_conn_close(conn); PERR ("Unable to connect to %s: %d\n", book_id, result); qof_backend_set_error (qbe, ERR_BACKEND_BAD_URL); LEAVE("Error"); return; } if (!conn_test_dbi_library(conn, qbe)) { if (create && !file_exists) { /* File didn't exist before, but it does now, and we don't want to * leave it lying around. */ dbi_conn_close (conn); conn = nullptr; g_unlink (filepath.c_str()); } dbi_conn_close(conn); LEAVE("Bad DBI Library"); return; } try { be->connect(new GncDbiSqlConnection(DbType::DBI_SQLITE, qbe, conn, ignore_lock)); } catch (std::runtime_error& err) { return; } /* We should now have a proper session set up. * Let's start logging */ xaccLogSetBaseName (filepath.c_str()); PINFO ("logpath=%s", filepath.c_str() ? filepath.c_str() : "(null)"); LEAVE (""); }
dbi_result _db_rawquery(const char *file, int line, database *db, int log_dupes, char *qry) { dbi_result result; const char *errmsg; int tries = 0; if (debug > 4) { LOGRAW(LOG_DEBUG, qry); } if (!dbi_conn_ping(db->conn)) { if (db->conn) dbi_conn_close(db->conn); db->conn = dbi_conn_new(db->driver); if (db->conn == NULL) { perror(db->driver); exit(1); } dbi_conn_set_option(db->conn, "host", db->host); dbi_conn_set_option(db->conn, "port", db->port); dbi_conn_set_option(db->conn, "username", db->username); dbi_conn_set_option(db->conn, "password", db->password); dbi_conn_set_option(db->conn, "dbname", db->name); retry: if (++tries == 3) exit(1); if (dbi_conn_connect(db->conn) < 0) { dbi_conn_error(db->conn, &errmsg); _logsrce = file; _logline = line; _LOG(LOG_ERR, "%s connection failed to %s:%s:%s %s", db->driver, db->host, db->port, db->name, errmsg); sleep(3); goto retry; } { char versionstring[VERSIONSTRING_LENGTH]; dbi_driver driver; driver = dbi_conn_get_driver(db->conn); dbi_conn_get_engine_version_string(db->conn, versionstring); LOG(LOG_INFO, "using driver: %s, version %s, compiled %s", dbi_driver_get_filename(driver), dbi_driver_get_version(driver), dbi_driver_get_date_compiled(driver)); LOG(LOG_INFO, "connected to %s:%s:%s, server version %s", db->host, db->port, db->name, versionstring); } } if (debug > 2) { char *src, *dst, buf[4096]; for (dst = buf, src = qry; *src; src++, dst++) { if (*src == '%') *dst++ = '%'; *dst = *src; } *dst = 0; LOG(LOG_INFO, buf); } result = dbi_conn_query(db->conn, qry); if (result == NULL) { int ret = dbi_conn_error(db->conn, &errmsg); _logsrce = file; _logline = line; _LOG(LOG_ERR, "query failed: %s (%s)", errmsg, qry); if (ret == DBI_ERROR_NOCONN) { dbi_conn_close(db->conn); db->conn = NULL; sleep(3); goto retry; } } return(result); }
/* Close the DB link */ static void log_sql_dbi_close(logsql_dbconnection *db) { dbi_conn_rec *dblink = db->handle; dbi_conn_close(dblink->conn); dblink->conn = NULL; }
template <DbType T> void gnc_dbi_session_begin (QofBackend* qbe, QofSession* session, const char* book_id, gboolean ignore_lock, gboolean create, gboolean force) { GncDbiBackend* be = (GncDbiBackend*)qbe; GncDbiTestResult dbi_test_result = GNC_DBI_PASS; PairVec options; g_return_if_fail (qbe != nullptr); g_return_if_fail (session != nullptr); g_return_if_fail (book_id != nullptr); ENTER (" "); /* Split the book-id * Format is protocol://username:password@hostname:port/dbname where username, password and port are optional) */ UriStrings uri(book_id); if (T == DbType::DBI_PGSQL) { if (uri.m_portnum == 0) uri.m_portnum = PGSQL_DEFAULT_PORT; /* Postgres's SQL interface coerces identifiers to lower case, but the * C interface is case-sensitive. This results in a mixed-case dbname * being created (with a lower case name) but then dbi can't conect to * it. To work around this, coerce the name to lowercase first. */ auto lcname = g_utf8_strdown (uri.dbname(), -1); uri.m_dbname = std::string{lcname}; g_free(lcname); } be->connect(nullptr); auto conn = conn_setup<T>(qbe, options, uri); if (conn == nullptr) { LEAVE("Error"); return; } be->set_exists(true); //May be unset in the error handler. auto result = dbi_conn_connect (conn); if (result == 0) { if (T == DbType::DBI_MYSQL) adjust_sql_options (conn); if(!conn_test_dbi_library(conn, qbe)) { dbi_conn_close(conn); LEAVE("Error"); return; } if (create && !force && save_may_clobber_data (conn, uri.quote_dbname(T))) { qof_backend_set_error (qbe, ERR_BACKEND_STORE_EXISTS); PWARN ("Databse already exists, Might clobber it."); dbi_conn_close(conn); LEAVE("Error"); return; } } else { if (be->exists()) { PERR ("Unable to connect to database '%s'\n", uri.dbname()); qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); dbi_conn_close(conn); LEAVE("Error"); return; } if (create) { if (!create_database(T, qbe, conn, uri.quote_dbname(T).c_str())) { dbi_conn_close(conn); LEAVE("Error"); return; } conn = conn_setup<T>(qbe, options, uri); result = dbi_conn_connect (conn); if (result < 0) { PERR ("Unable to create database '%s'\n", uri.dbname()); qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR); dbi_conn_close(conn); LEAVE("Error"); return; } if (T == DbType::DBI_MYSQL) adjust_sql_options (conn); if (!conn_test_dbi_library(conn, qbe)) { if (T == DbType::DBI_PGSQL) dbi_conn_select_db (conn, "template1"); dbi_conn_queryf (conn, "DROP DATABASE %s", uri.quote_dbname(T).c_str()); dbi_conn_close(conn); return; } } else { qof_backend_set_error (qbe, ERR_BACKEND_NO_SUCH_DB); qof_backend_set_message (qbe, "Database %s not found", uri.dbname()); } } be->connect(nullptr); try { be->connect(new GncDbiSqlConnection(T, qbe, conn, ignore_lock)); } catch (std::runtime_error& err) { return; } /* We should now have a proper session set up. * Let's start logging */ auto translog_path = gnc_build_translog_path (uri.basename().c_str()); xaccLogSetBaseName (translog_path); PINFO ("logpath=%s", translog_path ? translog_path : "(null)"); g_free (translog_path); LEAVE (" "); }
void swd::database::disconnect() { dbi_conn_close(conn_); #if defined(HAVE_DBI_NEW) dbi_shutdown_r(instance_); #endif }
/** * Parse command line options, create connection object, * start the connection and finally create database schema * * @return DBI connection handle */ dbi_conn *tagsistant_db_connection(int start_transaction) { /* DBI connection handler used by subsequent calls to dbi_* functions */ dbi_conn dbi = NULL; if (start_transaction) { g_rw_lock_writer_lock(&(tagsistant_query_rwlock)); } else { g_rw_lock_reader_lock(&(tagsistant_query_rwlock)); } /* lock the pool */ g_mutex_lock(&tagsistant_connection_pool_lock); GList *pool = tagsistant_connection_pool; while (pool) { dbi = (dbi_conn) pool->data; /* check if the connection is still alive */ if (!dbi_conn_ping(dbi) && dbi_conn_connect(dbi) < 0) { dbi_conn_close(dbi); tagsistant_connection_pool = g_list_delete_link(tagsistant_connection_pool, pool); connections--; } else { tagsistant_connection_pool = g_list_remove_link(tagsistant_connection_pool, pool); g_list_free_1(pool); break; } pool = pool->next; } /* * unlock the pool mutex only if the backend is not SQLite */ g_mutex_unlock(&tagsistant_connection_pool_lock); if (!dbi) { // initialize DBI drivers if (TAGSISTANT_DBI_MYSQL_BACKEND == dboptions.backend) { if (!tagsistant_driver_is_available("mysql")) { fprintf(stderr, "MySQL driver not installed\n"); dbg('s', LOG_ERR, "MySQL driver not installed"); exit (1); } // unlucky, MySQL does not provide INTERSECT operator tagsistant.sql_backend_have_intersect = 0; // create connection #if TAGSISTANT_REENTRANT_DBI dbi = dbi_conn_new_r("mysql", tagsistant.dbi_instance); #else dbi = dbi_conn_new("mysql"); #endif if (NULL == dbi) { dbg('s', LOG_ERR, "Error creating MySQL connection"); exit (1); } // set connection options dbi_conn_set_option(dbi, "host", dboptions.host); dbi_conn_set_option(dbi, "dbname", dboptions.db); dbi_conn_set_option(dbi, "username", dboptions.username); dbi_conn_set_option(dbi, "password", dboptions.password); dbi_conn_set_option(dbi, "encoding", "UTF-8"); } else if (TAGSISTANT_DBI_SQLITE_BACKEND == dboptions.backend) { if (!tagsistant_driver_is_available("sqlite3")) { fprintf(stderr, "SQLite3 driver not installed\n"); dbg('s', LOG_ERR, "SQLite3 driver not installed"); exit(1); } // create connection #if TAGSISTANT_REENTRANT_DBI dbi = dbi_conn_new_r("sqlite3", tagsistant.dbi_instance); #else dbi = dbi_conn_new("sqlite3"); #endif if (NULL == dbi) { dbg('s', LOG_ERR, "Error connecting to SQLite3"); exit (1); } // set connection options dbi_conn_set_option(dbi, "dbname", "tags.sql"); dbi_conn_set_option(dbi, "sqlite3_dbdir", tagsistant.repository); } else { dbg('s', LOG_ERR, "No or wrong database family specified!"); exit (1); } // try to connect if (dbi_conn_connect(dbi) < 0) { int error = dbi_conn_error(dbi, NULL); dbg('s', LOG_ERR, "Could not connect to DB (error %d). Please check the --db settings", error); exit(1); } connections++; dbg('s', LOG_INFO, "SQL connection established"); } /* start a transaction */ if (start_transaction) { #if TAGSISTANT_USE_INTERNAL_TRANSACTIONS switch (tagsistant.sql_database_driver) { case TAGSISTANT_DBI_SQLITE_BACKEND: tagsistant_query("begin transaction", dbi, NULL, NULL); break; case TAGSISTANT_DBI_MYSQL_BACKEND: tagsistant_query("start transaction", dbi, NULL, NULL); break; } #else dbi_conn_transaction_begin(dbi); #endif } return(dbi); }