IoObject *IoDBI_drivers(IoDBI *self, IoObject *locals, IoMessage *m) { /*doc DBI drivers Get a list of drivers and its associated information: <ol> <li>name</li> <li>description</li> <li>filename</li> <li>version</li> <li>date compiled</li> <li>maintainer</li> <li>url</li> </ol> */ IoList *list = IOREF(IoList_new(IOSTATE)); dbi_driver driver = NULL; while((driver = dbi_driver_list(driver)) != NULL) { IoList *dlist = IOREF(IoList_new(IOSTATE)); IoList_rawAppend_(dlist, IOSYMBOL(dbi_driver_get_name(driver))); IoList_rawAppend_(dlist, IOSYMBOL(dbi_driver_get_description(driver))); IoList_rawAppend_(dlist, IOSYMBOL(dbi_driver_get_filename(driver))); IoList_rawAppend_(dlist, IOSYMBOL(dbi_driver_get_version(driver))); IoList_rawAppend_(dlist, IOSYMBOL(dbi_driver_get_date_compiled(driver))); IoList_rawAppend_(dlist, IOSYMBOL(dbi_driver_get_maintainer(driver))); IoList_rawAppend_(dlist, IOSYMBOL(dbi_driver_get_url(driver))); IoList_rawAppend_(list, dlist); } return list; }
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); }
/** * check if requested driver is provided by local DBI installation * * @param driver_name string with the name of the driver * @return 1 if exists, 0 otherwise */ int tagsistant_driver_is_available(const char *driver_name) { int counter = 0; int driver_found = 0; dbi_driver driver = NULL; dbg('b', LOG_INFO, "Available drivers:"); #if TAGSISTANT_REENTRANT_DBI while ((driver = dbi_driver_list_r(driver, tagsistant.dbi_instance)) != NULL) { #else while ((driver = dbi_driver_list(driver)) != NULL) { #endif counter++; dbg('b', LOG_INFO, " Driver #%d: %s - %s", counter, dbi_driver_get_name(driver), dbi_driver_get_filename(driver)); if (g_strcmp0(dbi_driver_get_name(driver), driver_name) == 0) { driver_found = 1; } } if (!counter) { dbg('b', LOG_ERR, "No SQL driver found! Exiting now."); return(0); } if (!driver_found) { dbg('b', LOG_ERR, "No %s driver found!", driver_name); return(0); } return(1); } /** * Contains DBI parsed options */ struct { int backend; gchar *backend_name; gchar *host; gchar *db; gchar *username; gchar *password; } dboptions; #if TAGSISTANT_ENABLE_TAG_ID_CACHE /** a map tag_name -> tag_id */ GHashTable *tagsistant_tag_cache = NULL; #endif /** regular expressions used to escape query parameters */ GRegex *RX1, *RX2, *RX3; /** * Initialize libDBI structures */ void tagsistant_db_init() { // initialize DBI library #if TAGSISTANT_REENTRANT_DBI dbi_initialize_r(NULL, &(tagsistant.dbi_instance)); #else dbi_initialize(NULL); #endif #if TAGSISTANT_USE_QUERY_MUTEX g_mutex_init(&tagsistant_query_mutex); #endif #if TAGSISTANT_ENABLE_TAG_ID_CACHE tagsistant_tag_cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); #endif // by default, DBI backend provides intersect tagsistant.sql_backend_have_intersect = 1; tagsistant.sql_database_driver = TAGSISTANT_NULL_BACKEND; dboptions.backend = TAGSISTANT_NULL_BACKEND; // if no database option has been passed, use default SQLite3 if (strlen(tagsistant.dboptions) == 0) { tagsistant.dboptions = g_strdup("sqlite3::::"); dboptions.backend_name = g_strdup("sqlite3"); dboptions.backend = TAGSISTANT_DBI_SQLITE_BACKEND; dbg('b', LOG_INFO, "Using default driver: sqlite3"); } dbg('b', LOG_INFO, "Database options: %s", tagsistant.dboptions); // split database option value up to 5 tokens gchar **_dboptions = g_strsplit(tagsistant.dboptions, ":", 5); // set failsafe DB options if (_dboptions[0]) { if (strcmp(_dboptions[0], "sqlite3") == 0) { tagsistant.sql_database_driver = TAGSISTANT_DBI_SQLITE_BACKEND; dboptions.backend = TAGSISTANT_DBI_SQLITE_BACKEND; dboptions.backend_name = g_strdup("sqlite3"); } else if (strcmp(_dboptions[0], "mysql") == 0) { tagsistant.sql_database_driver = TAGSISTANT_DBI_MYSQL_BACKEND; dboptions.backend = TAGSISTANT_DBI_MYSQL_BACKEND; dboptions.backend_name = g_strdup("mysql"); } } if (TAGSISTANT_DBI_MYSQL_BACKEND == dboptions.backend) { if (_dboptions[1] && strlen(_dboptions[1])) { dboptions.host = g_strdup(_dboptions[1]); if (_dboptions[2] && strlen(_dboptions[2])) { dboptions.db = g_strdup(_dboptions[2]); if (_dboptions[3] && strlen(_dboptions[3])) { dboptions.username = g_strdup(_dboptions[3]); if (_dboptions[4] && strlen(_dboptions[4])) { dboptions.password = g_strdup(_dboptions[4]); } else { dboptions.password = g_strdup("tagsistant"); } } else { dboptions.password = g_strdup("tagsistant"); dboptions.username = g_strdup("tagsistant"); } } else { dboptions.password = g_strdup("tagsistant"); dboptions.username = g_strdup("tagsistant"); dboptions.db = g_strdup("tagsistant"); } } else { dboptions.password = g_strdup("tagsistant"); dboptions.username = g_strdup("tagsistant"); dboptions.db = g_strdup("tagsistant"); dboptions.host = g_strdup("localhost"); } } g_strfreev(_dboptions); #if 0 dbg('b', LOG_INFO, "Database driver: %s", dboptions.backend_name); // list configured options const char *option = NULL; int counter = 0; dbg('b', LOG_INFO, "Connection settings: "); while ((option = dbi_conn_get_option_list(tagsistant_dbi_conn, option)) != NULL ) { counter++; dbg('b', LOG_INFO, " Option #%d: %s = %s", counter, option, dbi_conn_get_option(tagsistant_dbi_conn, option)); } // tell if backend have INTERSECT if (tagsistant.sql_backend_have_intersect) { dbg('b', LOG_INFO, "Database supports INTERSECT operator"); } else { dbg('b', LOG_INFO, "Database does not support INTERSECT operator"); } #endif /* initialize the regular expressions used to escape the SQL queries */ RX1 = g_regex_new("[\"']", 0, 0, NULL); RX2 = g_regex_new("'", 0, 0, NULL); RX3 = g_regex_new("<><>", 0, 0, NULL); }