예제 #1
0
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;
}
예제 #2
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;
	}
}
예제 #3
0
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);
}
예제 #4
0
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);
}
예제 #5
0
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;

}
예제 #6
0
파일: db_wrap_dbi.c 프로젝트: ageric/merlin
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;
}
예제 #7
0
void close_database(database *db)
{
    if (db && db->conn) {
        if (db->conn) dbi_conn_close(db->conn);
        free(db);
    }
    return;
}
예제 #8
0
파일: dbi.c 프로젝트: Bradan/gammu
/* 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;
	}
}
예제 #9
0
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;
}
예제 #10
0
/**
	@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;
	}
}
예제 #11
0
/**
	@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;
}
예제 #12
0
파일: db_wrap_dbi.c 프로젝트: ageric/merlin
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;
}
예제 #13
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;
}
예제 #14
0
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;
}
예제 #15
0
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;
  }
}
예제 #16
0
파일: dbi.c 프로젝트: brd/collectd
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 */
예제 #17
0
/**
	@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;
}
예제 #18
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;
}
예제 #19
0
파일: dbi.c 프로젝트: 4thAce/collectd
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 */
예제 #20
0
/****************************
 database functions. 
 NOTE: Don't use with multithreaded programs!
 ***************************/
void close_database(dbi_conn conn)
{
  dbi_conn_close(conn);
}
예제 #21
0
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 ("");
}
예제 #22
0
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);
}
예제 #23
0
/* 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;
}
예제 #24
0
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 (" ");
}
예제 #25
0
void swd::database::disconnect() {
    dbi_conn_close(conn_);
#if defined(HAVE_DBI_NEW)
    dbi_shutdown_r(instance_);
#endif
}
예제 #26
0
파일: sql.c 프로젝트: rowhit/Tagsistant
/**
 * 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);
}