From 2327ed11ccd9355ebac7fa40dfa90f67735aaca2 Mon Sep 17 00:00:00 2001 From: Jonathan Xu Date: Tue, 18 Jun 2019 18:10:28 +0800 Subject: [PATCH] Rewrite database access layer. Remove support for PostgreSQL at the same time. --- common/Makefile.am | 2 +- common/db-wrapper/Makefile.am | 23 - common/db-wrapper/db-wrapper.c | 454 -------- common/db-wrapper/db-wrapper.h | 140 --- common/db-wrapper/mysql-db-ops.c | 585 ---------- common/db-wrapper/mysql-db-ops.h | 74 -- common/db-wrapper/pgsql-db-ops.c | 492 --------- common/db-wrapper/pgsql-db-ops.h | 72 -- common/db-wrapper/sqlite-db-ops.c | 477 --------- common/db-wrapper/sqlite-db-ops.h | 67 -- common/seaf-db.c | 1669 +++++++++++++++++------------ common/seaf-db.h | 13 +- common/seaf-utils.c | 6 - configure.ac | 121 +-- fuse/Makefile.am | 4 +- server/Makefile.am | 4 +- server/gc/Makefile.am | 34 +- server/repo-mgr.c | 252 ++--- server/share-mgr.c | 45 +- tools/Makefile.am | 4 +- 20 files changed, 1143 insertions(+), 3395 deletions(-) delete mode 100644 common/db-wrapper/Makefile.am delete mode 100644 common/db-wrapper/db-wrapper.c delete mode 100644 common/db-wrapper/db-wrapper.h delete mode 100644 common/db-wrapper/mysql-db-ops.c delete mode 100644 common/db-wrapper/mysql-db-ops.h delete mode 100644 common/db-wrapper/pgsql-db-ops.c delete mode 100644 common/db-wrapper/pgsql-db-ops.h delete mode 100644 common/db-wrapper/sqlite-db-ops.c delete mode 100644 common/db-wrapper/sqlite-db-ops.h diff --git a/common/Makefile.am b/common/Makefile.am index 6dfebde..3d2b631 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = cdc db-wrapper +SUBDIRS = cdc proc_headers = \ $(addprefix processors/, \ diff --git a/common/db-wrapper/Makefile.am b/common/db-wrapper/Makefile.am deleted file mode 100644 index 24dd035..0000000 --- a/common/db-wrapper/Makefile.am +++ /dev/null @@ -1,23 +0,0 @@ -AM_CFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/lib \ - -Wall @GLIB2_CFLAGS@ @MSVC_CFLAGS@ @MYSQL_CFLAGS@ @PGSQL_CFLAGS@ - -noinst_LTLIBRARIES = libdbwrapper.la - -noinst_HEADERS = db-wrapper.h mysql-db-ops.h sqlite-db-ops.h pgsql-db-ops.h - -if WITH_MYSQL - MYSQL_DB_SRC = mysql-db-ops.c -else - MYSQL_DB_SRC = -endif - -if WITH_POSTGRESQL - PGSQL_DB_SRC = pgsql-db-ops.c -else - PGSQL_DB_SRC = -endif - -libdbwrapper_la_SOURCES = db-wrapper.c sqlite-db-ops.c $(MYSQL_DB_SRC) $(PGSQL_DB_SRC) - -libdbwrapper_la_LDFLAGS = -Wl,-z -Wl,defs -libdbwrapper_la_LIBADD = @SSL_LIBS@ @GLIB2_LIBS@ @MYSQL_LIBS@ -lsqlite3 @PGSQL_LIBS@ diff --git a/common/db-wrapper/db-wrapper.c b/common/db-wrapper/db-wrapper.c deleted file mode 100644 index 4757aca..0000000 --- a/common/db-wrapper/db-wrapper.c +++ /dev/null @@ -1,454 +0,0 @@ -#include "common.h" - -#include "db-wrapper.h" -#include "sqlite-db-ops.h" - -#ifdef HAVE_MYSQL -#include "mysql-db-ops.h" -#endif - -#ifdef HAVE_POSTGRESQL -#include "pgsql-db-ops.h" -#endif - -typedef struct DBOperations { - void (*db_conn_pool_free) (DBConnPool *); - DBConnection* (*get_db_connection) (DBConnPool *, GError **); - void (*db_connection_close) (DBConnection *); - gboolean (*db_connection_ping) (DBConnection *); - gboolean (*db_connection_execute) (DBConnection *, const char *, GError **); - ResultSet* (*db_connection_execute_query) (DBConnection *, const char *, GError **); - gboolean (*result_set_next) (ResultSet *, GError **); - const char* (*result_set_get_string) (ResultSet *, int, GError **); - void (*result_set_free) (ResultSet *); - int (*result_set_get_column_count) (ResultSet *); - DBStmt* (*db_connection_prepare_statement) (DBConnection *, const char *, GError **); - gboolean (*db_stmt_set_int) (DBStmt *, int, int, GError **); - gboolean (*db_stmt_set_int64) (DBStmt *, int, gint64, GError **); - gboolean (*db_stmt_set_string) (DBStmt *, int, const char *, GError **); - gboolean (*db_stmt_execute) (DBStmt *, GError **); - ResultSet* (*db_stmt_execute_query) (DBStmt *, GError **); - void (*db_stmt_free) (DBStmt *); - gboolean (*db_connection_begin_transaction) (DBConnection *, GError **); - gboolean (*db_connection_commit) (DBConnection *, GError **); - gboolean (*db_connection_rollback) (DBConnection *, GError **); -} DBOperations; - -static DBOperations db_ops; - -/* DB Connection Pool. */ - -static void -init_conn_pool_common (DBConnPool *pool, int max_connections) -{ - pool->connections = g_ptr_array_sized_new (max_connections); - pthread_mutex_init (&pool->lock, NULL); - pool->max_connections = max_connections; -} - -#ifdef HAVE_MYSQL - -DBConnPool * -db_conn_pool_new_mysql (const char *host, - const char *user, - const char *password, - unsigned int port, - const char *db_name, - const char *unix_socket, - gboolean use_ssl, - const char *charset, - int max_connections) -{ - db_ops.db_conn_pool_free = mysql_db_conn_pool_free; - db_ops.get_db_connection = mysql_get_db_connection; - db_ops.db_connection_close = mysql_db_connection_close; - db_ops.db_connection_ping = mysql_db_connection_ping; - db_ops.db_connection_execute = mysql_db_connection_execute; - db_ops.db_connection_execute_query = mysql_execute_query; - db_ops.result_set_next = mysql_result_set_next; - db_ops.result_set_get_string = mysql_result_set_get_string; - db_ops.result_set_free = mysql_result_set_free; - db_ops.result_set_get_column_count = mysql_result_set_get_column_count; - db_ops.db_connection_prepare_statement = mysql_prepare_statement; - db_ops.db_stmt_set_int = mysql_stmt_set_int; - db_ops.db_stmt_set_int64 = mysql_stmt_set_int64; - db_ops.db_stmt_set_string = mysql_stmt_set_string; - db_ops.db_stmt_execute = mysql_db_stmt_execute; - db_ops.db_stmt_execute_query = mysql_db_stmt_execute_query; - db_ops.db_stmt_free = mysql_db_stmt_free; - db_ops.db_connection_begin_transaction = mysql_db_begin_transaction; - db_ops.db_connection_commit = mysql_db_commit; - db_ops.db_connection_rollback = mysql_db_rollback; - - DBConnPool *pool; - - pool = mysql_db_conn_pool_new (host, user, password, port, db_name, unix_socket, - use_ssl, charset); - init_conn_pool_common (pool, max_connections); - - return pool; -} - -#endif - -#ifdef HAVE_POSTGRESQL - -DBConnPool * -db_conn_pool_new_pgsql (const char *host, - unsigned int port, - const char *user, - const char *password, - const char *db_name, - const char *unix_socket, - int max_connections) -{ - db_ops.db_conn_pool_free = pgsql_db_conn_pool_free; - db_ops.get_db_connection = pgsql_get_db_connection; - db_ops.db_connection_close = pgsql_db_connection_close; - db_ops.db_connection_ping = pgsql_db_connection_ping; - db_ops.db_connection_execute = pgsql_db_connection_execute; - db_ops.db_connection_execute_query = pgsql_execute_query; - db_ops.result_set_next = pgsql_result_set_next; - db_ops.result_set_get_string = pgsql_result_set_get_string; - db_ops.result_set_free = pgsql_result_set_free; - db_ops.result_set_get_column_count = pgsql_result_set_get_column_count; - db_ops.db_connection_prepare_statement = pgsql_prepare_statement; - db_ops.db_stmt_set_int = pgsql_stmt_set_int; - db_ops.db_stmt_set_int64 = pgsql_stmt_set_int64; - db_ops.db_stmt_set_string = pgsql_stmt_set_string; - db_ops.db_stmt_execute = pgsql_db_stmt_execute; - db_ops.db_stmt_execute_query = pgsql_db_stmt_execute_query; - db_ops.db_stmt_free = pgsql_db_stmt_free; - db_ops.db_connection_begin_transaction = pgsql_db_begin_transaction; - db_ops.db_connection_commit = pgsql_db_commit; - db_ops.db_connection_rollback = pgsql_db_rollback; - - DBConnPool *pool; - - pool = pgsql_db_conn_pool_new (host, port, user, password, db_name, unix_socket); - init_conn_pool_common (pool, max_connections); - - return pool; -} - -#endif - -DBConnPool * -db_conn_pool_new_sqlite (const char *db_path, int max_connections) -{ - db_ops.db_conn_pool_free = sqlite_db_conn_pool_free; - db_ops.get_db_connection = sqlite_get_db_connection; - db_ops.db_connection_close = sqlite_db_connection_close; - db_ops.db_connection_ping = sqlite_db_connection_ping; - db_ops.db_connection_execute = sqlite_db_connection_execute; - db_ops.db_connection_execute_query = sqlite_execute_query; - db_ops.result_set_next = sqlite_result_set_next; - db_ops.result_set_get_string = sqlite_result_set_get_string; - db_ops.result_set_free = sqlite_result_set_free; - db_ops.result_set_get_column_count = sqlite_result_set_get_column_count; - db_ops.db_connection_prepare_statement = sqlite_prepare_statement; - db_ops.db_stmt_set_int = sqlite_stmt_set_int; - db_ops.db_stmt_set_int64 = sqlite_stmt_set_int64; - db_ops.db_stmt_set_string = sqlite_stmt_set_string; - db_ops.db_stmt_execute = sqlite_db_stmt_execute; - db_ops.db_stmt_execute_query = sqlite_db_stmt_execute_query; - db_ops.db_stmt_free = sqlite_db_stmt_free; - db_ops.db_connection_begin_transaction = sqlite_db_begin_transaction; - db_ops.db_connection_commit = sqlite_db_commit; - db_ops.db_connection_rollback = sqlite_db_rollback; - - DBConnPool *pool; - - pool = sqlite_db_conn_pool_new (db_path); - init_conn_pool_common (pool, max_connections); - - return pool; -} - -void -db_conn_pool_free (DBConnPool *pool) -{ - g_ptr_array_free (pool->connections, TRUE); - pthread_mutex_destroy (&pool->lock); - - return db_ops.db_conn_pool_free (pool); -} - -/* DB Connections. */ - -DBConnection * -db_conn_pool_get_connection (DBConnPool *pool, GError **error) -{ - DBConnection *conn = NULL; - - pthread_mutex_lock (&pool->lock); - - guint i, size = pool->connections->len; - for (i = 0; i < size; ++i) { - conn = g_ptr_array_index (pool->connections, i); - if (conn->is_available && db_connection_ping (conn)) { - conn->is_available = FALSE; - goto out; - } - } - conn = NULL; - if (size < pool->max_connections) { - conn = db_ops.get_db_connection (pool, error); - if (conn) { - conn->is_available = FALSE; - conn->pool = pool; - conn->conn_no = size; - g_ptr_array_add (pool->connections, conn); - } - } - -out: - pthread_mutex_unlock (&pool->lock); - return conn; -} - -static void -db_connection_clear (DBConnection *conn) -{ - result_set_free (conn->result_set); - db_stmt_free (conn->stmt); - conn->result_set = NULL; - conn->stmt = NULL; -} - -void -db_connection_close (DBConnection *conn) -{ - if (!conn) - return; - - if (conn->in_transaction) - db_connection_rollback (conn, NULL); - - db_connection_clear (conn); - - pthread_mutex_lock (&conn->pool->lock); - conn->is_available = TRUE; - pthread_mutex_unlock (&conn->pool->lock); -} - -gboolean -db_connection_execute (DBConnection *conn, const char *sql, GError **error) -{ - return db_ops.db_connection_execute (conn, sql, error); -} - -gboolean -db_connection_ping (DBConnection *conn) -{ - return db_ops.db_connection_ping (conn); -} - -/* Result Sets. */ - -void -result_set_free (ResultSet *r) -{ - if (!r) - return; - - return db_ops.result_set_free (r); -} - -ResultSet * -db_connection_execute_query (DBConnection *conn, const char *sql, GError **error) -{ - ResultSet *result_set; - - if (conn->result_set) { - result_set_free (conn->result_set); - conn->result_set = NULL; - } - - result_set = db_ops.db_connection_execute_query (conn, sql, error); - - if (result_set) - conn->result_set = result_set; - - return result_set; -} - -gboolean -result_set_next (ResultSet *r, GError **error) -{ - return db_ops.result_set_next (r, error); -} - -const char * -result_set_get_string (ResultSet *r, int idx, GError **error) -{ - return db_ops.result_set_get_string (r, idx, error); -} - -int -result_set_get_int (ResultSet *r, int idx, GError **error) -{ - const char *str; - char *e; - int ret; - - str = db_ops.result_set_get_string (r, idx, error); - if (*error) { - return -1; - } - - if (!str) { - return 0; - } - - errno = 0; - ret = strtol (str, &e, 10); - if (errno || (e == str)) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Number conversion failed."); - return -1; - } - - return ret; -} - -gint64 -result_set_get_int64 (ResultSet *r, int idx, GError **error) -{ - const char *str; - char *e; - gint64 ret; - - str = db_ops.result_set_get_string (r, idx, error); - if (*error) { - return -1; - } - - if (!str) { - return 0; - } - - errno = 0; - ret = strtoll (str, &e, 10); - if (errno || (e == str)) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Number conversion failed."); - return -1; - } - - return ret; -} - -int -result_set_get_column_count (ResultSet *r) -{ - return db_ops.result_set_get_column_count (r); -} - -/* Prepared Statements. */ - -DBStmt * -db_connection_prepare_statement (DBConnection *conn, const char *sql, GError **error) -{ - DBStmt *stmt; - - if (conn->stmt) { - db_stmt_free (conn->stmt); - conn->stmt = NULL; - } - - stmt = db_ops.db_connection_prepare_statement (conn, sql, error); - - if (stmt) - conn->stmt = stmt; - - return stmt; -} - -int -db_stmt_set_int (DBStmt *stmt, int idx, int x, GError **error) -{ - return db_ops.db_stmt_set_int (stmt, idx, x, error); -} - -int -db_stmt_set_int64 (DBStmt *stmt, int idx, gint64 x, GError **error) -{ - return db_ops.db_stmt_set_int64 (stmt, idx, x, error); -} - -int -db_stmt_set_string (DBStmt *stmt, int idx, const char *s, GError **error) -{ - return db_ops.db_stmt_set_string (stmt, idx, s, error); -} - -gboolean -db_stmt_execute (DBStmt *stmt, GError **error) -{ - return db_ops.db_stmt_execute (stmt, error); -} - -ResultSet * -db_stmt_execute_query (DBStmt *stmt, GError **error) -{ - ResultSet *result_set; - - if (stmt->result_set) { - result_set_free (stmt->result_set); - stmt->result_set = NULL; - } - - result_set = db_ops.db_stmt_execute_query (stmt, error); - - if (result_set) - stmt->result_set = result_set; - - return result_set; -} - -void -db_stmt_free (DBStmt *stmt) -{ - if (!stmt) - return; - - if (stmt->result_set) - result_set_free (stmt->result_set); - - return db_ops.db_stmt_free (stmt); -} - -/* Transactions. */ - -gboolean -db_connection_begin_transaction (DBConnection *conn, GError **error) -{ - gboolean ret; - - ret = db_ops.db_connection_begin_transaction (conn, error); - if (ret) - conn->in_transaction++; - - return ret; -} - -gboolean -db_connection_commit (DBConnection *conn, GError **error) -{ - if (conn->in_transaction) - conn->in_transaction = 0; - - return db_ops.db_connection_commit (conn, error); -} - -gboolean -db_connection_rollback (DBConnection *conn, GError **error) -{ - if (conn->in_transaction) { - db_connection_clear (conn); - conn->in_transaction = 0; - } - - return db_ops.db_connection_rollback (conn, error); -} diff --git a/common/db-wrapper/db-wrapper.h b/common/db-wrapper/db-wrapper.h deleted file mode 100644 index 18bfaa9..0000000 --- a/common/db-wrapper/db-wrapper.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef DB_WRAPPER_H -#define DB_WARPPER_H - -#include -#include - -#define SEAF_DB_ERROR_DOMAIN g_quark_from_string("SEAF_DB") -#define SEAF_DB_ERROR_CODE 0 - -/* DB Connection Pool. */ - -struct DBConnPool { - GPtrArray *connections; - pthread_mutex_t lock; - int max_connections; -}; -typedef struct DBConnPool DBConnPool; - -DBConnPool * -db_conn_pool_new_mysql (const char *host, - const char *user, - const char *password, - unsigned int port, - const char *db_name, - const char *unix_socket, - gboolean use_ssl, - const char *charset, - int max_connections); - -DBConnPool * -db_conn_pool_new_pgsql (const char *host, - unsigned int port, - const char *user, - const char *password, - const char *db_name, - const char *unix_socket, - int max_connections); - -DBConnPool * -db_conn_pool_new_sqlite (const char *db_path, int max_connections); - -void -db_conn_pool_free (DBConnPool *pool); - -/* DB Connections. */ - -struct ResultSet; -typedef struct ResultSet ResultSet; - -struct DBStmt; -typedef struct DBStmt DBStmt; - -struct DBConnection { - gboolean is_available; - int in_transaction; - DBConnPool *pool; - ResultSet *result_set; - DBStmt *stmt; - int conn_no; -}; -typedef struct DBConnection DBConnection; - -DBConnection * -db_conn_pool_get_connection (DBConnPool *pool, GError **error); - -void -db_connection_close (DBConnection *conn); - -gboolean -db_connection_ping (DBConnection *conn); - -gboolean -db_connection_execute (DBConnection *conn, const char *sql, GError **error); - -/* Result Sets. */ - -struct ResultSet { - /* Empty */ -}; - -ResultSet * -db_connection_execute_query (DBConnection *conn, const char *sql, GError **error); - -gboolean -result_set_next (ResultSet *r, GError **error); - -const char * -result_set_get_string (ResultSet *r, int idx, GError **error); - -int -result_set_get_int (ResultSet *r, int idx, GError **error); - -gint64 -result_set_get_int64 (ResultSet *r, int idx, GError **error); - -int -result_set_get_column_count (ResultSet *r); - -void -result_set_free (ResultSet *r); - -/* Prepared Statements. */ - -struct DBStmt { - ResultSet *result_set; -}; - -DBStmt * -db_connection_prepare_statement (DBConnection *conn, const char *sql, GError **error); - -gboolean -db_stmt_set_int (DBStmt *stmt, int idx, int x, GError **error); - -gboolean -db_stmt_set_int64 (DBStmt *stmt, int idx, gint64 x, GError **error); - -gboolean -db_stmt_set_string (DBStmt *stmt, int idx, const char *s, GError **error); - -gboolean -db_stmt_execute (DBStmt *stmt, GError **error); - -ResultSet * -db_stmt_execute_query (DBStmt *stmt, GError **error); - -void -db_stmt_free (DBStmt *stmt); - -/* Transactions. */ - -gboolean -db_connection_begin_transaction (DBConnection *conn, GError **error); - -gboolean -db_connection_commit (DBConnection *conn, GError **error); - -gboolean -db_connection_rollback (DBConnection *conn, GError **error); - -#endif diff --git a/common/db-wrapper/mysql-db-ops.c b/common/db-wrapper/mysql-db-ops.c deleted file mode 100644 index 4688991..0000000 --- a/common/db-wrapper/mysql-db-ops.c +++ /dev/null @@ -1,585 +0,0 @@ -#include "common.h" - -#include "db-wrapper.h" -#include "mysql-db-ops.h" - -#include - -/* Connection Pool. */ - -typedef struct MySQLDBConnPool { - DBConnPool parent; - char *host; - char *user; - char *password; - unsigned int port; - char *db_name; - char *unix_socket; - gboolean use_ssl; - char *charset; -} MySQLDBConnPool; - -DBConnPool * -mysql_db_conn_pool_new (const char *host, - const char *user, - const char *password, - unsigned int port, - const char *db_name, - const char *unix_socket, - gboolean use_ssl, - const char *charset) -{ - MySQLDBConnPool *pool = g_new0 (MySQLDBConnPool, 1); - - pool->host = g_strdup (host); - pool->user = g_strdup (user); - pool->password = g_strdup (password); - pool->port = port; - pool->db_name = g_strdup(db_name); - pool->unix_socket = g_strdup(unix_socket); - pool->use_ssl = use_ssl; - pool->charset = g_strdup(charset); - - mysql_library_init (0, NULL, NULL); - - return (DBConnPool *)pool; -} - -void -mysql_db_conn_pool_free (DBConnPool *vpool) -{ - MySQLDBConnPool *pool = (MySQLDBConnPool *)vpool; - - g_free (pool->host); - g_free (pool->user); - g_free (pool->password); - g_free (pool->db_name); - g_free (pool->unix_socket); - g_free (pool->charset); - - g_free (pool); -} - -/* Connection. */ - -typedef struct MySQLDBConnection { - DBConnection parent; - MYSQL *db; -} MySQLDBConnection; - -#define SQL_DEFAULT_TCP_TIMEOUT 3 - -static MYSQL * -connect_mysql (MySQLDBConnPool *pool, GError **error) -{ - my_bool yes = 1; - volatile int connect_timeout = SQL_DEFAULT_TCP_TIMEOUT; - unsigned long client_flags = CLIENT_MULTI_STATEMENTS; - MYSQL *db; - - db = mysql_init (NULL); - if (!db) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Failed to allocate mysql handle."); - return NULL; - } - - if (pool->use_ssl) - mysql_ssl_set(db, 0,0,0,0,0); - - if (pool->charset) - mysql_options(db, MYSQL_SET_CHARSET_NAME, pool->charset); - - mysql_options(db, MYSQL_OPT_CONNECT_TIMEOUT, (const char*)&connect_timeout); - mysql_options(db, MYSQL_OPT_RECONNECT, (const char*)&yes); - - if (mysql_real_connect(db, pool->host, pool->user, pool->password, - pool->db_name, pool->port, - pool->unix_socket, client_flags)) { - return db; - } else { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Failed to connect to MySQL: %s", mysql_error(db)); - mysql_close (db); - return NULL; - } -} - -DBConnection * -mysql_get_db_connection (DBConnPool *vpool, GError **error) -{ - MySQLDBConnPool *pool = (MySQLDBConnPool *)vpool; - MySQLDBConnection *conn; - MYSQL *db = connect_mysql (pool, error); - if (!db) - return NULL; - conn = g_new0 (MySQLDBConnection, 1); - conn->db = db; - return (DBConnection *)conn; -} - -void -mysql_db_connection_close (DBConnection *vconn) -{ - if (!vconn) - return; - - MySQLDBConnection *conn = (MySQLDBConnection *)vconn; - - mysql_close (conn->db); - - g_free (conn); -} - -gboolean -mysql_db_connection_ping (DBConnection *vconn) -{ - MySQLDBConnection *conn = (MySQLDBConnection *)vconn; - - return (mysql_ping (conn->db) == 0); -} - -gboolean -mysql_db_connection_execute (DBConnection *vconn, const char *sql, GError **error) -{ - MySQLDBConnection *conn = (MySQLDBConnection *)vconn; - - int rc = mysql_real_query (conn->db, sql, strlen(sql)); - if (rc != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "MySQL failed to execute: %s", mysql_error(conn->db)); - return FALSE; - } - return TRUE; -} - -/* Result Set. */ - -#define DEFAULT_COLUMN_SIZE 256 - -typedef struct MySQLResultSet { - ResultSet parent; - MYSQL_STMT *stmt; - int column_count; - MYSQL_BIND *bind; - int need_rebind; -} MySQLResultSet; - -void -mysql_result_set_free (ResultSet *vr) -{ - if (!vr) - return; - - MySQLResultSet *r = (MySQLResultSet *)vr; - - mysql_stmt_free_result (r->stmt); - mysql_stmt_close (r->stmt); - - int i; - for (i = 0; i < r->column_count; ++i) { - g_free (r->bind[i].buffer); - g_free (r->bind[i].length); - g_free (r->bind[i].is_null); - } - g_free (r->bind); - g_free (r); -} - -static MySQLResultSet * -mysql_result_set_new (MYSQL_STMT *stmt, GError **error) -{ - MySQLResultSet *r = g_new0 (MySQLResultSet, 1); - int i; - - r->stmt = stmt; - r->column_count = mysql_stmt_field_count (stmt); - r->bind = g_new0 (MYSQL_BIND, r->column_count); - for (i = 0; i < r->column_count; ++i) { - r->bind[i].buffer = g_malloc (DEFAULT_COLUMN_SIZE + 1); - r->bind[i].buffer_type = MYSQL_TYPE_STRING; - r->bind[i].buffer_length = DEFAULT_COLUMN_SIZE; - r->bind[i].length = g_new0 (unsigned long, 1); - r->bind[i].is_null = g_new0 (my_bool, 1); - } - - if (mysql_stmt_bind_result (stmt, r->bind) != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "mysql_stmt_bind_result failed: %s\n", mysql_stmt_error(stmt)); - mysql_result_set_free ((ResultSet*)r); - return NULL; - } - - return r; -} - -static MYSQL_STMT * -prepare (MYSQL *db, const char *sql, GError **error) -{ - MYSQL_STMT *stmt; - - stmt = mysql_stmt_init (db); - if (!stmt) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "mysql_stmt_init out of memory"); - return NULL; - } - - if (mysql_stmt_prepare (stmt, sql, strlen(sql)) != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "mysql_stmt_prepare failed: %s", - mysql_stmt_error(stmt)); - mysql_stmt_close (stmt); - return NULL; - } - - return stmt; -} - -ResultSet * -mysql_execute_query (DBConnection *vconn, const char *sql, GError **error) -{ - MySQLDBConnection *conn = (MySQLDBConnection *)vconn; - MYSQL_STMT *stmt; - MySQLResultSet *r; - - stmt = prepare (conn->db, sql, error); - if (!stmt) { - return NULL; - } - - unsigned long cursor = CURSOR_TYPE_READ_ONLY; - mysql_stmt_attr_set (stmt, STMT_ATTR_CURSOR_TYPE, &cursor); - - if (mysql_stmt_execute (stmt) != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "mysql_stmt_execute failed: %s", - mysql_stmt_error(stmt)); - mysql_stmt_close (stmt); - return NULL; - } - - r = mysql_result_set_new (stmt, error); - if (!r) { - mysql_stmt_close (stmt); - return NULL; - } - - return (ResultSet *)r; -} - -static gboolean -check_mysql_column_size (MySQLResultSet *r, int i, GError **error) -{ - unsigned long real_length = *(r->bind[i].length); - - if ((real_length > r->bind[i].buffer_length)) { - /* Column was truncated, resize and fetch column directly. */ - g_free (r->bind[i].buffer); - r->bind[i].buffer = g_malloc (real_length + 1); - r->bind[i].buffer_length = real_length; - if (mysql_stmt_fetch_column (r->stmt, &r->bind[i], i, 0) != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "mysql_stmt_fetch_column failed: %s", - mysql_stmt_error(r->stmt)); - return FALSE; - } - r->need_rebind = TRUE; - } - - return TRUE; -} - -gboolean -mysql_result_set_next (ResultSet *vr, GError **error) -{ - MySQLResultSet *r = (MySQLResultSet *)vr; - - if (r->need_rebind) { - if (mysql_stmt_bind_result (r->stmt, r->bind) != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "mysql_stmt_bind_result failed: %s", - mysql_stmt_error(r->stmt)); - return FALSE; - } - r->need_rebind = FALSE; - } - - int rc = mysql_stmt_fetch (r->stmt); - if (rc == 1) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "mysql_stmt_fetch failed: %s", mysql_stmt_error(r->stmt)); - return FALSE; - } - return ((rc == 0) || (rc == MYSQL_DATA_TRUNCATED)); -} - -const char * -mysql_result_set_get_string (ResultSet *vr, int i, GError **error) -{ - MySQLResultSet *r = (MySQLResultSet *)vr; - char *ret; - - if (i < 0 || i >= r->column_count) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Column index is out of range."); - return NULL; - } - - if (*(r->bind[i].is_null)) { - return NULL; - } - - if (!check_mysql_column_size (r, i, error)) { - return NULL; - } - - ret = r->bind[i].buffer; - ret[*(r->bind[i].length)] = 0; - return ret; -} - -int -mysql_result_set_get_column_count (ResultSet *vr) -{ - MySQLResultSet *r = (MySQLResultSet *)vr; - - return r->column_count; -} - -typedef struct MySQLDBStmt { - DBStmt parent; - int param_count; - MYSQL_STMT *stmt; - MYSQL_BIND *bind; -} MySQLDBStmt; - -static MySQLDBStmt * -mysql_stmt_new (MYSQL_STMT *stmt) -{ - MySQLDBStmt *p = g_new0 (MySQLDBStmt, 1); - - p->stmt = stmt; - p->param_count = (int)mysql_stmt_param_count(stmt); - if (p->param_count>0) { - p->bind = g_new0 (MYSQL_BIND, p->param_count); - } - - return p; -} - -DBStmt * -mysql_prepare_statement (DBConnection *vconn, const char *sql, GError **error) -{ - MySQLDBConnection *conn = (MySQLDBConnection *)vconn; - MYSQL_STMT *stmt; - MySQLDBStmt *ret; - - stmt = prepare (conn->db, sql, error); - if (!stmt) { - return NULL; - } - - ret = mysql_stmt_new (stmt); - - return (DBStmt*)ret; -} - -gboolean -mysql_stmt_set_int (DBStmt *vstmt, int i, int x, GError **error) -{ - MySQLDBStmt *stmt = (MySQLDBStmt *)vstmt; - int *pval; - - if (i < 0 || i >= stmt->param_count) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Column index is out of range."); - return FALSE; - } - - pval = g_new (int, 1); - *pval = x; - - stmt->bind[i].buffer_type = MYSQL_TYPE_LONG; - stmt->bind[i].buffer = (char *)pval; - stmt->bind[i].is_null = 0; - - return TRUE; -} - -gboolean -mysql_stmt_set_int64 (DBStmt *vstmt, int i, gint64 x, GError **error) -{ - MySQLDBStmt *stmt = (MySQLDBStmt *)vstmt; - gint64 *pval; - - if (i < 0 || i >= stmt->param_count) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Column index is out of range."); - return FALSE; - } - - pval = g_new (gint64, 1); - *pval = x; - - stmt->bind[i].buffer_type = MYSQL_TYPE_LONGLONG; - stmt->bind[i].buffer = (char *)pval; - stmt->bind[i].is_null = 0; - - return TRUE; -} - -gboolean -mysql_stmt_set_string (DBStmt *vstmt, int i, const char *s, GError **error) -{ - MySQLDBStmt *stmt = (MySQLDBStmt *)vstmt; - static my_bool yes = TRUE; - unsigned long *plen; - - if (i < 0 || i >= stmt->param_count) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Column index is out of range."); - return FALSE; - } - - stmt->bind[i].buffer_type = MYSQL_TYPE_STRING; - stmt->bind[i].buffer = g_strdup(s); - plen = g_new (unsigned long, 1); - stmt->bind[i].length = plen; - if (!s) { - *plen = 0; - stmt->bind[i].is_null = &yes; - } else { - *plen = strlen(s); - stmt->bind[i].is_null = 0; - } - - return TRUE; -} - -gboolean -mysql_db_stmt_execute (DBStmt *vstmt, GError **error) -{ - MySQLDBStmt *stmt = (MySQLDBStmt *)vstmt; - - if (stmt->param_count > 0 && - mysql_stmt_bind_param (stmt->stmt, stmt->bind) != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "mysql_stmt_bind_param failed: %s", - mysql_stmt_error(stmt->stmt)); - return FALSE; - } - - unsigned long cursor = CURSOR_TYPE_NO_CURSOR; - mysql_stmt_attr_set (stmt->stmt, STMT_ATTR_CURSOR_TYPE, &cursor); - - if (mysql_stmt_execute (stmt->stmt) != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "mysql_stmt_execute failed: %s", mysql_stmt_error(stmt->stmt)); - return FALSE; - } - - mysql_stmt_reset (stmt->stmt); - - return TRUE; -} - -ResultSet * -mysql_db_stmt_execute_query (DBStmt *vstmt, GError **error) -{ - MySQLDBStmt *stmt = (MySQLDBStmt *)vstmt; - - if (stmt->param_count > 0 && - mysql_stmt_bind_param (stmt->stmt, stmt->bind) != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "mysql_stmt_bind_param failed: %s", - mysql_stmt_error(stmt->stmt)); - return NULL; - } - - unsigned long cursor = CURSOR_TYPE_READ_ONLY; - mysql_stmt_attr_set (stmt->stmt, STMT_ATTR_CURSOR_TYPE, &cursor); - - if (mysql_stmt_execute (stmt->stmt) != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "mysql_stmt_execute failed: %s", mysql_stmt_error(stmt->stmt)); - return NULL; - } - - MySQLResultSet *r = mysql_result_set_new (stmt->stmt, error); - if (*error) { - return NULL; - } - - return (ResultSet *)r; -} - -void -mysql_db_stmt_free (DBStmt *vstmt) -{ - if (!vstmt) - return; - - MySQLDBStmt *stmt = (MySQLDBStmt *)vstmt; - - /* If there is a result set associated with this stmt, the mysql stmt - * will be freed when freeing the result set. - */ - if (!stmt->parent.result_set) { - mysql_stmt_free_result (stmt->stmt); - mysql_stmt_close (stmt->stmt); - } - - int i; - for (i = 0; i < stmt->param_count; ++i) { - g_free (stmt->bind[i].buffer); - g_free (stmt->bind[i].length); - } - g_free (stmt->bind); - - g_free (stmt); -} - -/* Transaction. */ - -gboolean -mysql_db_begin_transaction (DBConnection *vconn, GError **error) -{ - MySQLDBConnection *conn = (MySQLDBConnection *)vconn; - - int rc = mysql_query (conn->db, "START TRANSACTION;"); - if (rc != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Failed to begin transaction: %s", mysql_error(conn->db)); - } - - return (rc == 0); -} - -gboolean -mysql_db_commit (DBConnection *vconn, GError **error) -{ - MySQLDBConnection *conn = (MySQLDBConnection *)vconn; - - int rc = mysql_query (conn->db, "COMMIT;"); - if (rc != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Failed to commit transaction: %s", mysql_error(conn->db)); - } - - return (rc == 0); -} - -gboolean -mysql_db_rollback (DBConnection *vconn, GError **error) -{ - MySQLDBConnection *conn = (MySQLDBConnection *)vconn; - - int rc = mysql_query (conn->db, "ROLLBACK;"); - if (rc != 0) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Failed to rollback transaction: %s", mysql_error(conn->db)); - } - - return (rc == 0); -} diff --git a/common/db-wrapper/mysql-db-ops.h b/common/db-wrapper/mysql-db-ops.h deleted file mode 100644 index 8c70f52..0000000 --- a/common/db-wrapper/mysql-db-ops.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef MYSQL_DB_OPS_H -#define MYSQL_DB_OPS_H - -DBConnPool * -mysql_db_conn_pool_new (const char *host, - const char *user, - const char *password, - unsigned int port, - const char *db_name, - const char *unix_socket, - gboolean use_ssl, - const char *charset); - -void -mysql_db_conn_pool_free (DBConnPool *vpool); - -DBConnection * -mysql_get_db_connection (DBConnPool *vpool, GError **error); - -void -mysql_db_connection_close (DBConnection *vconn); - -gboolean -mysql_db_connection_ping (DBConnection *vconn); - -gboolean -mysql_db_connection_execute (DBConnection *vconn, const char *sql, GError **error); - -void -mysql_result_set_free (ResultSet *vr); - -ResultSet * -mysql_execute_query (DBConnection *vconn, const char *sql, GError **error); - -gboolean -mysql_result_set_next (ResultSet *vr, GError **error); - -const char * -mysql_result_set_get_string (ResultSet *vr, int i, GError **error); - -int -mysql_result_set_get_column_count (ResultSet *vr); - -DBStmt * -mysql_prepare_statement (DBConnection *vconn, const char *sql, GError **error); - -gboolean -mysql_stmt_set_int (DBStmt *vstmt, int i, int x, GError **error); - -gboolean -mysql_stmt_set_int64 (DBStmt *vstmt, int i, gint64 x, GError **error); - -gboolean -mysql_stmt_set_string (DBStmt *vstmt, int i, const char *s, GError **error); - -gboolean -mysql_db_stmt_execute (DBStmt *vstmt, GError **error); - -ResultSet * -mysql_db_stmt_execute_query (DBStmt *vstmt, GError **error); - -void -mysql_db_stmt_free (DBStmt *vstmt); - -gboolean -mysql_db_begin_transaction (DBConnection *vconn, GError **error); - -gboolean -mysql_db_commit (DBConnection *vconn, GError **error); - -gboolean -mysql_db_rollback (DBConnection *vconn, GError **error); - -#endif diff --git a/common/db-wrapper/pgsql-db-ops.c b/common/db-wrapper/pgsql-db-ops.c deleted file mode 100644 index 75c7249..0000000 --- a/common/db-wrapper/pgsql-db-ops.c +++ /dev/null @@ -1,492 +0,0 @@ -#include "common.h" - -#include "db-wrapper.h" -#include "pgsql-db-ops.h" - -#include - -typedef struct PGDBConnPool { - DBConnPool parent; - char *host; - unsigned int port; - char *user; - char *password; - char *db_name; - char *unix_socket; -} PGDBConnPool; - -DBConnPool * -pgsql_db_conn_pool_new (const char *host, - unsigned int port, - const char *user, - const char *password, - const char *db_name, - const char *unix_socket) -{ - PGDBConnPool *pool = g_new0 (PGDBConnPool, 1); - - pool->host = g_strdup (host); - pool->port = port; - pool->user = g_strdup (user); - pool->password = g_strdup (password); - pool->db_name = g_strdup(db_name); - pool->unix_socket = g_strdup(unix_socket); - - return (DBConnPool *)pool; -} - -void -pgsql_db_conn_pool_free (DBConnPool *vpool) -{ - PGDBConnPool *pool = (PGDBConnPool *)vpool; - - g_free (pool->host); - g_free (pool->user); - g_free (pool->password); - g_free (pool->db_name); - g_free (pool->unix_socket); - - g_free (pool); -} - -typedef struct PGDBConnection { - DBConnection parent; - PGconn *db; -} PGDBConnection; - -static char * -escape_string_pgsql_connect (const char *str) -{ - GString *buf = g_string_new (NULL); - const char *p; - - for (p = str; *p != '\0'; ++p) { - if (*p == '\'' || *p == '\\') { - g_string_append_c (buf, '\\'); - g_string_append_c (buf, *p); - } else { - g_string_append_c (buf, *p); - } - } - - return g_string_free (buf, FALSE); -} - -static PGconn * -connect_pgsql (PGDBConnPool *pool, GError **error) -{ - GString *buf = g_string_new(""); - char *esc_password = NULL; - PGconn *db; - - g_string_append_printf (buf, "user='%s' ", pool->user); - - esc_password = escape_string_pgsql_connect (pool->password); - g_string_append_printf (buf, "password='%s' ", esc_password); - g_free (esc_password); - - if (pool->unix_socket) { - g_string_append_printf (buf, "host='%s' ", pool->unix_socket); - } else { - g_string_append_printf (buf, "host='%s' ", pool->host); - } - - if (pool->port > 0) { - g_string_append_printf (buf, "port=%u ", pool->port); - } - - g_string_append_printf (buf, "dbname='%s' ", pool->db_name); - - db = PQconnectdb (buf->str); - if (PQstatus (db) != CONNECTION_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "PQconnectdb failed: %s", PQerrorMessage (db)); - PQfinish (db); - db = NULL; - } - - g_string_free (buf, TRUE); - return db; -} - -DBConnection * -pgsql_get_db_connection (DBConnPool *vpool, GError **error) -{ - PGDBConnPool *pool = (PGDBConnPool *)vpool; - PGDBConnection *conn; - - PGconn *db = connect_pgsql (pool, error); - if (!db) - return NULL; - - conn = g_new0 (PGDBConnection, 1); - conn->db = db; - - return (DBConnection *)conn; -} - -void -pgsql_db_connection_close (DBConnection *vconn) -{ - if (!vconn) - return; - - PGDBConnection *conn = (PGDBConnection *)vconn; - - PQfinish (conn->db); - - g_free (conn); -} - -gboolean -pgsql_db_connection_ping (DBConnection *vconn) -{ - PGDBConnection *conn = (PGDBConnection *)vconn; - - return (PQstatus(conn->db) == CONNECTION_OK); -} - -gboolean -pgsql_db_connection_execute (DBConnection *vconn, const char *sql, GError **error) -{ - PGDBConnection *conn = (PGDBConnection *)vconn; - PGresult *res; - gboolean ret = TRUE; - - res = PQexec (conn->db, sql); - if (PQresultStatus(res) != PGRES_COMMAND_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "PQexec failed: %s", PQresultErrorMessage(res)); - ret = FALSE; - } - PQclear (res); - - return ret; -} - -typedef struct PGResultSet { - ResultSet parent; - PGresult *res; - int curr_row; - int column_count; - int row_count; -} PGResultSet; - -void -pgsql_result_set_free (ResultSet *vr) -{ - if (!vr) - return; - - PGResultSet *r = (PGResultSet *)vr; - - PQclear (r->res); - g_free (r); -} - -static PGResultSet * -pgsql_result_set_new (PGresult *res) -{ - PGResultSet *r; - - r = g_new0 (PGResultSet, 1); - r->curr_row = -1; - r->column_count = PQnfields(res); - r->row_count = PQntuples(res); - r->res = res; - - return r; -} - -ResultSet * -pgsql_execute_query (DBConnection *vconn, const char *sql, GError **error) -{ - PGDBConnection *conn = (PGDBConnection *)vconn; - PGresult *res; - PGResultSet *r; - - res = PQexec (conn->db, sql); - if (PQresultStatus(res) != PGRES_TUPLES_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "PQexec failed: %s", PQresultErrorMessage(res)); - return NULL; - } - - r = pgsql_result_set_new (res); - - return (ResultSet *)r; -} - -gboolean -pgsql_result_set_next (ResultSet *vr, GError **error) -{ - PGResultSet *r = (PGResultSet *)vr; - - return ((r->curr_row)++ < (r->row_count - 1)); -} - -const char * -pgsql_result_set_get_string (ResultSet *vr, int i, GError **error) -{ - PGResultSet *r = (PGResultSet *)vr; - - if (PQgetisnull(r->res, r->curr_row, i)) - return NULL; - return PQgetvalue(r->res, r->curr_row, i); -} - -int -pgsql_result_set_get_column_count (ResultSet *vr) -{ - PGResultSet *r = (PGResultSet *)vr; - return r->column_count; -} - -typedef struct PGDBStmt { - DBStmt parent; - char *name; - PGconn *db; - int param_count; - char **values; - int *lengths; - int *formats; -} PGDBStmt; - -static PGDBStmt * -pgsql_stmt_new (PGconn *db, char *name, int param_count) -{ - PGDBStmt *stmt = g_new0 (PGDBStmt, 1); - - stmt->name = g_strdup(name); - stmt->db = db; - stmt->param_count = param_count; - - if (stmt->param_count) { - stmt->values = g_new0 (char *, param_count); - stmt->lengths = g_new0 (int, param_count); - stmt->formats = g_new0 (int, param_count); - } - - return stmt; -} - -/* Convert '?' in the query string to $1, $2, etc. */ -static char * -pgsql_format_query_string (const char *sql, int *param_count) -{ - GString *buf = g_string_new (NULL); - const char *p; - int i = 0; - - for (p = sql; *p != '\0'; ++p) { - if (*p == '?') { - ++i; - g_string_append_c (buf, '$'); - g_string_append_printf (buf, "%d", i); - } else { - g_string_append_c (buf, *p); - } - } - - *param_count = i; - - return g_string_free (buf, FALSE); -} - -static gint stmt_id = 0; - -DBStmt * -pgsql_prepare_statement (DBConnection *vconn, const char *sql, GError **error) -{ - PGDBConnection *conn = (PGDBConnection *)vconn; - char *query; - int param_count; - char *name; - PGresult *res; - PGDBStmt *stmt = NULL; - - query = pgsql_format_query_string (sql, ¶m_count); - - g_atomic_int_inc (&stmt_id); - name = g_strdup_printf ("%d", stmt_id); - - res = PQprepare (conn->db, name, query, 0, NULL); - ExecStatusType status = PQresultStatus(res); - if (res && (status == PGRES_EMPTY_QUERY || status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK)) { - stmt = pgsql_stmt_new (conn->db, name, param_count); - } else { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "PQprepare failed: %s", PQresultErrorMessage(res)); - } - - PQclear (res); - g_free (name); - g_free (query); - return (DBStmt *)stmt; -} - -gboolean -pgsql_stmt_set_int (DBStmt *vstmt, int i, int x, GError **error) -{ - PGDBStmt *stmt = (PGDBStmt *)vstmt; - - if (i < 0 || i >= stmt->param_count) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Column index is out of range."); - return FALSE; - } - - stmt->values[i] = g_strdup_printf("%d", x); - stmt->lengths[i] = 0; - stmt->formats[i] = 0; - - return TRUE; -} - -gboolean -pgsql_stmt_set_int64 (DBStmt *vstmt, int i, gint64 x, GError **error) -{ - PGDBStmt *stmt = (PGDBStmt *)vstmt; - - if (i < 0 || i >= stmt->param_count) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Column index is out of range."); - return FALSE; - } - - stmt->values[i] = g_strdup_printf("%"G_GINT64_FORMAT, x); - stmt->lengths[i] = 0; - stmt->formats[i] = 0; - - return TRUE; -} - -gboolean -pgsql_stmt_set_string (DBStmt *vstmt, int i, const char *s, GError **error) -{ - PGDBStmt *stmt = (PGDBStmt *)vstmt; - - if (i < 0 || i >= stmt->param_count) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Column index is out of range."); - return FALSE; - } - - stmt->values[i] = g_strdup(s); - stmt->lengths[i] = 0; - stmt->formats[i] = 0; - - return TRUE; -} - -gboolean -pgsql_db_stmt_execute (DBStmt *vstmt, GError **error) -{ - PGDBStmt *stmt = (PGDBStmt *)vstmt; - PGresult *res; - gboolean ret; - - res = PQexecPrepared (stmt->db, stmt->name, stmt->param_count, - (const char **)stmt->values, stmt->lengths, stmt->formats, 0); - if (PQresultStatus(res) != PGRES_COMMAND_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "PGexecPrepared failed: %s", PQresultErrorMessage(res)); - ret = FALSE; - } - - ret = TRUE; - - PQclear(res); - - return ret; -} - -ResultSet * -pgsql_db_stmt_execute_query (DBStmt *vstmt, GError **error) -{ - PGDBStmt *stmt = (PGDBStmt *)vstmt; - PGresult *res; - PGResultSet *ret = NULL; - - res = PQexecPrepared (stmt->db, stmt->name, stmt->param_count, - (const char **)stmt->values, stmt->lengths, stmt->formats, 0); - if (PQresultStatus(res) != PGRES_TUPLES_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "PGexecPrepared failed: %s", PQresultErrorMessage(res)); - } - - ret = pgsql_result_set_new (res); - - return (ResultSet *)ret; -} - -void -pgsql_db_stmt_free (DBStmt *vstmt) -{ - if (!vstmt) - return; - - char Stmt[256]; - PGDBStmt *stmt = (PGDBStmt *)vstmt; - snprintf(Stmt, sizeof(Stmt), "DEALLOCATE \"%s\";", stmt->name); - PQclear(PQexec(stmt->db, Stmt)); - - g_free (stmt->name); - - int i; - for (i = 0; i < stmt->param_count; ++i) - g_free (stmt->values[i]); - g_free (stmt->values); - - g_free (stmt->lengths); - g_free (stmt->formats); - g_free (stmt); -} - -gboolean -pgsql_db_begin_transaction (DBConnection *vconn, GError **error) -{ - PGDBConnection *conn = (PGDBConnection *)vconn; - gboolean ret = TRUE; - - PGresult *res = PQexec(conn->db, "BEGIN TRANSACTION;"); - if (PQresultStatus(res) != PGRES_COMMAND_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Begin transaction failed: %s", PQresultErrorMessage(res)); - ret = FALSE; - } - PQclear(res); - return ret; -} - -gboolean -pgsql_db_commit (DBConnection *vconn, GError **error) -{ - PGDBConnection *conn = (PGDBConnection *)vconn; - gboolean ret = TRUE; - - PGresult *res = PQexec(conn->db, "COMMIT TRANSACTION;"); - if (PQresultStatus(res) != PGRES_COMMAND_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Commit transaction failed: %s", PQresultErrorMessage(res)); - ret = FALSE; - } - PQclear(res); - return ret; -} - -gboolean -pgsql_db_rollback (DBConnection *vconn, GError **error) -{ - PGDBConnection *conn = (PGDBConnection *)vconn; - gboolean ret = TRUE; - - PGresult *res = PQexec(conn->db, "ROLLBACK TRANSACTION;"); - if (PQresultStatus(res) != PGRES_COMMAND_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Rollback transaction failed: %s", PQresultErrorMessage(res)); - ret = FALSE; - } - PQclear(res); - return ret; -} diff --git a/common/db-wrapper/pgsql-db-ops.h b/common/db-wrapper/pgsql-db-ops.h deleted file mode 100644 index f027aec..0000000 --- a/common/db-wrapper/pgsql-db-ops.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef PGSQL_DB_OPS_H -#define PGSQL_DB_OPS_H - -DBConnPool * -pgsql_db_conn_pool_new (const char *host, - unsigned int port, - const char *user, - const char *password, - const char *db_name, - const char *unix_socket); - -void -pgsql_db_conn_pool_free (DBConnPool *vpool); - -DBConnection * -pgsql_get_db_connection (DBConnPool *vpool, GError **error); - -void -pgsql_db_connection_close (DBConnection *vconn); - -gboolean -pgsql_db_connection_ping (DBConnection *vconn); - -gboolean -pgsql_db_connection_execute (DBConnection *vconn, const char *sql, GError **error); - -void -pgsql_result_set_free (ResultSet *vr); - -ResultSet * -pgsql_execute_query (DBConnection *vconn, const char *sql, GError **error); - -gboolean -pgsql_result_set_next (ResultSet *vr, GError **error); - -const char * -pgsql_result_set_get_string (ResultSet *vr, int i, GError **error); - -int -pgsql_result_set_get_column_count (ResultSet *vr); - -DBStmt * -pgsql_prepare_statement (DBConnection *vconn, const char *sql, GError **error); - -gboolean -pgsql_stmt_set_int (DBStmt *vstmt, int i, int x, GError **error); - -gboolean -pgsql_stmt_set_int64 (DBStmt *vstmt, int i, gint64 x, GError **error); - -gboolean -pgsql_stmt_set_string (DBStmt *vstmt, int i, const char *s, GError **error); - -gboolean -pgsql_db_stmt_execute (DBStmt *vstmt, GError **error); - -ResultSet * -pgsql_db_stmt_execute_query (DBStmt *vstmt, GError **error); - -void -pgsql_db_stmt_free (DBStmt *vstmt); - -gboolean -pgsql_db_begin_transaction (DBConnection *vconn, GError **error); - -gboolean -pgsql_db_commit (DBConnection *vconn, GError **error); - -gboolean -pgsql_db_rollback (DBConnection *vconn, GError **error); - -#endif diff --git a/common/db-wrapper/sqlite-db-ops.c b/common/db-wrapper/sqlite-db-ops.c deleted file mode 100644 index 87b7c55..0000000 --- a/common/db-wrapper/sqlite-db-ops.c +++ /dev/null @@ -1,477 +0,0 @@ -#include "common.h" - -#include "db-wrapper.h" -#include "sqlite-db-ops.h" - -#include -#include - -/* SQLite thread synchronization rountines. */ - -typedef struct UnlockNotification { - int fired; - pthread_cond_t cond; - pthread_mutex_t mutex; -} UnlockNotification; - -static void -unlock_notify_cb(void **ap_arg, int n_arg) -{ - int i; - - for (i = 0; i < n_arg; i++) { - UnlockNotification *p = (UnlockNotification *)ap_arg[i]; - pthread_mutex_lock (&p->mutex); - p->fired = 1; - pthread_cond_signal (&p->cond); - pthread_mutex_unlock (&p->mutex); - } -} - -static int -wait_for_unlock_notify(sqlite3 *db) -{ - UnlockNotification un; - un.fired = 0; - pthread_mutex_init (&un.mutex, NULL); - pthread_cond_init (&un.cond, NULL); - - int rc = sqlite3_unlock_notify(db, unlock_notify_cb, (void *)&un); - - if (rc == SQLITE_OK) { - pthread_mutex_lock(&un.mutex); - if (!un.fired) - pthread_cond_wait (&un.cond, &un.mutex); - pthread_mutex_unlock(&un.mutex); - } - - pthread_cond_destroy (&un.cond); - pthread_mutex_destroy (&un.mutex); - - return rc; -} - -static int -sqlite3_blocking_step(sqlite3_stmt *stmt) -{ - int rc; - while (SQLITE_LOCKED == (rc = sqlite3_step(stmt))) { - rc = wait_for_unlock_notify(sqlite3_db_handle(stmt)); - if (rc != SQLITE_OK) - break; - sqlite3_reset(stmt); - } - return rc; -} - -static int -sqlite3_blocking_prepare_v2(sqlite3 *db, const char *sql, int sql_len, sqlite3_stmt **pstmt, const char **pz) -{ - int rc; - while (SQLITE_LOCKED == (rc = sqlite3_prepare_v2(db, sql, sql_len, pstmt, pz))) { - rc = wait_for_unlock_notify(db); - if (rc != SQLITE_OK) - break; - } - return rc; -} - -static int -sqlite3_blocking_exec(sqlite3 *db, const char *sql, int (*callback)(void *, int, char **, char **), void *arg, char **errmsg) -{ - int rc; - while (SQLITE_LOCKED == (rc = sqlite3_exec(db, sql, callback, arg, errmsg))) { - rc = wait_for_unlock_notify(db); - if (rc != SQLITE_OK) - break; - } - return rc; -} - -#if 0 - -#define SQLITE_QUERY_TIMEOUT 3 - -#define EXEC_SQLITE(status, action) \ - do {\ - long t = (SQLITE_QUERY_TIMEOUT * G_USEC_PER_SEC);\ - int x = 0;\ - do {\ - status = (action);\ - if (((status == SQLITE_BUSY) || (status == SQLITE_LOCKED)) && (x++ <= 9))\ - g_usleep(t/(rand() % 3 + 10));\ - else\ - break;\ - } while (1);\ - } while (0) - -#endif /* 0 */ - -typedef struct SQLiteDBConnPool { - DBConnPool parent; - char *db_path; -} SQLiteDBConnPool; - -DBConnPool * -sqlite_db_conn_pool_new (const char *db_path) -{ - SQLiteDBConnPool *pool = g_new0 (SQLiteDBConnPool, 1); - pool->db_path = g_strdup(db_path); - - return (DBConnPool *)pool; -} - -void -sqlite_db_conn_pool_free (DBConnPool *vpool) -{ - if (!vpool) - return; - - SQLiteDBConnPool *pool = (SQLiteDBConnPool *)vpool; - - g_free (pool->db_path); - g_free (pool); -} - -typedef struct SQLiteDBConnection { - DBConnection parent; - sqlite3 *db; -} SQLiteDBConnection; - -DBConnection * -sqlite_get_db_connection (DBConnPool *vpool, GError **error) -{ - SQLiteDBConnPool *pool = (SQLiteDBConnPool *)vpool; - sqlite3 *db; - int result; - const char *errmsg; - SQLiteDBConnection *conn; - - result = sqlite3_open_v2 (pool->db_path, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_SHAREDCACHE, NULL); - if (result != SQLITE_OK) { - errmsg = sqlite3_errmsg(db); - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Failed to open sqlite db: %s", - errmsg ? errmsg : "no error given"); - return NULL; - } - - conn = g_new0 (SQLiteDBConnection, 1); - conn->db = db; - - return (DBConnection *)conn; -} - -void -sqlite_db_connection_close (DBConnection *vconn) -{ - if (!vconn) - return; - - SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; - - sqlite3_close (conn->db); - - g_free (conn); -} - -gboolean -sqlite_db_connection_ping (DBConnection *vconn) -{ - return TRUE; -} - -gboolean -sqlite_db_connection_execute (DBConnection *vconn, const char *sql, GError **error) -{ - SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; - char *errmsg = NULL; - int rc; - - rc = sqlite3_blocking_exec (conn->db, sql, NULL, NULL, &errmsg); - if (rc != SQLITE_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "sqlite3_exec failed: %s", - errmsg ? errmsg : "no error given"); - if (errmsg) - sqlite3_free (errmsg); - return FALSE; - } - - return TRUE; -} - -typedef struct SQLiteResultSet { - ResultSet parent; - sqlite3 *db; - sqlite3_stmt *stmt; - int column_count; -} SQLiteResultSet; - -void -sqlite_result_set_free (ResultSet *vr) -{ - if (!vr) - return; - - SQLiteResultSet *r = (SQLiteResultSet *)vr; - - sqlite3_finalize (r->stmt); - - g_free (r); -} - -ResultSet * -sqlite_execute_query (DBConnection *vconn, const char *sql, GError **error) -{ - SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; - sqlite3_stmt *stmt; - int rc; - SQLiteResultSet *r; - - rc = sqlite3_blocking_prepare_v2 (conn->db, sql, -1, &stmt, NULL); - if (rc != SQLITE_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "sqlite3_prepare_v2 failed: %s", sqlite3_errmsg(conn->db)); - return NULL; - } - - r = g_new0 (SQLiteResultSet, 1); - r->db = conn->db; - r->stmt = stmt; - r->column_count = sqlite3_column_count (stmt); - - return (ResultSet *)r; -} - -gboolean -sqlite_result_set_next (ResultSet *vr, GError **error) -{ - SQLiteResultSet *r = (SQLiteResultSet *)vr; - int rc; - - rc = sqlite3_blocking_step (r->stmt); - if (rc != SQLITE_ROW && rc != SQLITE_DONE) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "sqlite3_step failed: %s", sqlite3_errmsg(r->db)); - return FALSE; - } - - return (rc == SQLITE_ROW); -} - -const char * -sqlite_result_set_get_string (ResultSet *vr, int i, GError **error) -{ - SQLiteResultSet *r = (SQLiteResultSet *)vr; - - if (i < 0 || i >= r->column_count) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Column index is out of range."); - return NULL; - } - - return (const char *)sqlite3_column_text (r->stmt, i); -} - -int -sqlite_result_set_get_column_count (ResultSet *vr) -{ - return ((SQLiteResultSet *)vr)->column_count; -} - -typedef struct SQLiteDBStmt { - DBStmt parent; - int param_count; - sqlite3 *db; - sqlite3_stmt *stmt; -} SQLiteDBStmt; - -DBStmt * -sqlite_prepare_statement (DBConnection *vconn, const char *sql, GError **error) -{ - SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; - sqlite3_stmt *stmt; - int rc; - SQLiteDBStmt *ret; - - rc = sqlite3_blocking_prepare_v2 (conn->db, sql, -1, &stmt, NULL); - if (rc != SQLITE_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "sqlite3_prepare_v2 failed: %s", sqlite3_errmsg(conn->db)); - return NULL; - } - - ret = g_new0 (SQLiteDBStmt, 1); - ret->stmt = stmt; - ret->db = conn->db; - ret->param_count = sqlite3_bind_parameter_count (stmt); - - return (DBStmt *)ret; -} - -gboolean -sqlite_stmt_set_int (DBStmt *vstmt, int i, int x, GError **error) -{ - SQLiteDBStmt *stmt = (SQLiteDBStmt *)vstmt; - int rc; - - if (i < 0 || i >= stmt->param_count) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Column index is out of range."); - return FALSE; - } - - rc = sqlite3_bind_int (stmt->stmt, i+1, x); - if (rc != SQLITE_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "sqlite3_bind_int failed: %s", sqlite3_errmsg(stmt->db)); - return FALSE; - } - - return TRUE; -} - -gboolean -sqlite_stmt_set_int64 (DBStmt *vstmt, int i, gint64 x, GError **error) -{ - SQLiteDBStmt *stmt = (SQLiteDBStmt *)vstmt; - int rc; - - if (i < 0 || i >= stmt->param_count) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Column index is out of range."); - return FALSE; - } - - rc = sqlite3_bind_int64 (stmt->stmt, i+1, x); - if (rc != SQLITE_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "sqlite3_bind_int failed: %s", sqlite3_errmsg(stmt->db)); - return FALSE; - } - - return TRUE; -} - -gboolean -sqlite_stmt_set_string (DBStmt *vstmt, int i, const char *s, GError **error) -{ - SQLiteDBStmt *stmt = (SQLiteDBStmt *)vstmt; - int rc; - - if (i < 0 || i >= stmt->param_count) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Column index is out of range."); - return FALSE; - } - - rc = sqlite3_bind_text (stmt->stmt, i+1, s, -1, SQLITE_TRANSIENT); - if (rc != SQLITE_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "sqlite3_bind_int failed: %s", sqlite3_errmsg(stmt->db)); - return FALSE; - } - - return TRUE; -} - -gboolean -sqlite_db_stmt_execute (DBStmt *vstmt, GError **error) -{ - SQLiteDBStmt *stmt = (SQLiteDBStmt *)vstmt; - int rc; - - rc = sqlite3_blocking_step (stmt->stmt); - if (rc == SQLITE_DONE) { - sqlite3_reset (stmt->stmt); - return TRUE; - } else if (rc == SQLITE_ROW) { - sqlite3_reset (stmt->stmt); - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "Select statement not allowed in db_stmt_execute."); - return FALSE; - } else { - sqlite3_reset (stmt->stmt); - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "sqlite3_step failed: %s", sqlite3_errmsg(stmt->db)); - return FALSE; - } -} - -ResultSet * -sqlite_db_stmt_execute_query (DBStmt *vstmt, GError **error) -{ - SQLiteDBStmt *stmt = (SQLiteDBStmt *)vstmt; - SQLiteResultSet *r; - - r = g_new0 (SQLiteResultSet, 1); - r->db = stmt->db; - r->stmt = stmt->stmt; - r->column_count = sqlite3_column_count (r->stmt); - - return (ResultSet *)r; -} - -void -sqlite_db_stmt_free (DBStmt *vstmt) -{ - if (!vstmt) - return; - - SQLiteDBStmt *stmt = (SQLiteDBStmt *)vstmt; - - if (!stmt->parent.result_set) { - sqlite3_finalize (stmt->stmt); - } - - g_free (stmt); -} - -gboolean -sqlite_db_begin_transaction (DBConnection *vconn, GError **error) -{ - SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; - int rc; - - rc = sqlite3_blocking_exec (conn->db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (rc != SQLITE_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "begin transaction failed: %s", sqlite3_errmsg(conn->db)); - return FALSE; - } - - return TRUE; -} - -gboolean -sqlite_db_commit (DBConnection *vconn, GError **error) -{ - SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; - int rc; - - rc = sqlite3_blocking_exec (conn->db, "COMMIT TRANSACTION;", NULL, NULL, NULL); - if (rc != SQLITE_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "commit transaction failed: %s", sqlite3_errmsg(conn->db)); - return FALSE; - } - - return TRUE; -} - -gboolean -sqlite_db_rollback (DBConnection *vconn, GError **error) -{ - SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; - int rc; - - rc = sqlite3_blocking_exec (conn->db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL); - if (rc != SQLITE_OK) { - g_set_error (error, SEAF_DB_ERROR_DOMAIN, SEAF_DB_ERROR_CODE, - "rollback transaction failed: %s", sqlite3_errmsg(conn->db)); - return FALSE; - } - - return TRUE; -} diff --git a/common/db-wrapper/sqlite-db-ops.h b/common/db-wrapper/sqlite-db-ops.h deleted file mode 100644 index 9fb1bd8..0000000 --- a/common/db-wrapper/sqlite-db-ops.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef SQLITE_DB_OPS_H -#define SQLITE_DB_OPS_H - -DBConnPool * -sqlite_db_conn_pool_new (const char *db_path); - -void -sqlite_db_conn_pool_free (DBConnPool *vpool); - -DBConnection * -sqlite_get_db_connection (DBConnPool *vpool, GError **error); - -void -sqlite_db_connection_close (DBConnection *vconn); - -gboolean -sqlite_db_connection_ping (DBConnection *vconn); - -gboolean -sqlite_db_connection_execute (DBConnection *vconn, const char *sql, GError **error); - -void -sqlite_result_set_free (ResultSet *vr); - -ResultSet * -sqlite_execute_query (DBConnection *vconn, const char *sql, GError **error); - -gboolean -sqlite_result_set_next (ResultSet *vr, GError **error); - -const char * -sqlite_result_set_get_string (ResultSet *vr, int i, GError **error); - -int -sqlite_result_set_get_column_count (ResultSet *vr); - -DBStmt * -sqlite_prepare_statement (DBConnection *vconn, const char *sql, GError **error); - -gboolean -sqlite_stmt_set_int (DBStmt *vstmt, int i, int x, GError **error); - -gboolean -sqlite_stmt_set_int64 (DBStmt *vstmt, int i, gint64 x, GError **error); - -gboolean -sqlite_stmt_set_string (DBStmt *vstmt, int i, const char *s, GError **error); - -gboolean -sqlite_db_stmt_execute (DBStmt *vstmt, GError **error); - -ResultSet * -sqlite_db_stmt_execute_query (DBStmt *vstmt, GError **error); - -void -sqlite_db_stmt_free (DBStmt *vstmt); - -gboolean -sqlite_db_begin_transaction (DBConnection *vconn, GError **error); - -gboolean -sqlite_db_commit (DBConnection *vconn, GError **error); - -gboolean -sqlite_db_rollback (DBConnection *vconn, GError **error); - -#endif diff --git a/common/seaf-db.c b/common/seaf-db.c index f392794..998d876 100644 --- a/common/seaf-db.c +++ b/common/seaf-db.c @@ -3,25 +3,76 @@ #include "log.h" -#include "db-wrapper/db-wrapper.h" #include "seaf-db.h" -#define MAX_GET_CONNECTION_RETRIES 3 +#include +#include +#include +#include struct SeafDB { int type; - DBConnPool *pool; }; +typedef struct DBConnection { + /* Empty */ +} DBConnection; + struct SeafDBRow { - ResultSet *res; + /* Empty */ }; struct SeafDBTrans { DBConnection *conn; }; -#ifdef HAVE_MYSQL +typedef struct DBOperations { + DBConnection* (*get_connection)(SeafDB *db); + void (*release_connection)(DBConnection *conn); + int (*execute_sql_no_stmt)(DBConnection *conn, const char *sql); + int (*execute_sql)(DBConnection *conn, const char *sql, + int n, va_list args); + int (*query_foreach_row)(DBConnection *conn, + const char *sql, SeafDBRowFunc callback, void *data, + int n, va_list args); + int (*row_get_column_count)(SeafDBRow *row); + const char* (*row_get_column_string)(SeafDBRow *row, int idx); + int (*row_get_column_int)(SeafDBRow *row, int idx); + gint64 (*row_get_column_int64)(SeafDBRow *row, int idx); +} DBOperations; + +static DBOperations db_ops; + +/* MySQL Ops */ +static SeafDB * +mysql_db_new (const char *host, + int port, + const char *user, + const char *password, + const char *db_name, + const char *unix_socket, + gboolean use_ssl, + const char *charset); +static DBConnection * +mysql_db_get_connection (SeafDB *db); +static void +mysql_db_release_connection (DBConnection *vconn); +static int +mysql_db_execute_sql_no_stmt (DBConnection *vconn, const char *sql); +static int +mysql_db_execute_sql (DBConnection *vconn, const char *sql, int n, va_list args); +static int +mysql_db_query_foreach_row (DBConnection *vconn, const char *sql, + SeafDBRowFunc callback, void *data, + int n, va_list args); +static int +mysql_db_row_get_column_count (SeafDBRow *row); +static const char * +mysql_db_row_get_column_string (SeafDBRow *row, int idx); +static int +mysql_db_row_get_column_int (SeafDBRow *row, int idx); +static gint64 +mysql_db_row_get_column_int64 (SeafDBRow *row, int idx); SeafDB * seaf_db_new_mysql (const char *host, @@ -36,748 +87,313 @@ seaf_db_new_mysql (const char *host, { SeafDB *db; - db = g_new0 (SeafDB, 1); - if (!db) { - seaf_warning ("Failed to alloc db structure.\n"); + db = mysql_db_new (host, port, user, passwd, db_name, unix_socket, use_ssl, charset); + if (!db) return NULL; - } - db->type = SEAF_DB_TYPE_MYSQL; - db->pool = db_conn_pool_new_mysql (host, user, passwd, port, db_name, - unix_socket, use_ssl, charset, max_connections); + db_ops.get_connection = mysql_db_get_connection; + db_ops.release_connection = mysql_db_release_connection; + db_ops.execute_sql_no_stmt = mysql_db_execute_sql_no_stmt; + db_ops.execute_sql = mysql_db_execute_sql; + db_ops.query_foreach_row = mysql_db_query_foreach_row; + db_ops.row_get_column_count = mysql_db_row_get_column_count; + db_ops.row_get_column_string = mysql_db_row_get_column_string; + db_ops.row_get_column_int = mysql_db_row_get_column_int; + db_ops.row_get_column_int64 = mysql_db_row_get_column_int64; return db; } -#endif - -#ifdef HAVE_POSTGRESQL - -SeafDB * -seaf_db_new_pgsql (const char *host, - unsigned int port, - const char *user, - const char *passwd, - const char *db_name, - const char *unix_socket, - int max_connections) -{ - SeafDB *db; - - db = g_new0 (SeafDB, 1); - if (!db) { - seaf_warning ("Failed to alloc db structure.\n"); - return NULL; - } - - db->type = SEAF_DB_TYPE_PGSQL; - - db->pool = db_conn_pool_new_pgsql (host, port, user, passwd, db_name, unix_socket, - max_connections); - - return db; -} - -#endif +/* SQLite Ops */ +static SeafDB * +sqlite_db_new (const char *db_path); +static DBConnection * +sqlite_db_get_connection (SeafDB *db); +static void +sqlite_db_release_connection (DBConnection *vconn); +static int +sqlite_db_execute_sql_no_stmt (DBConnection *vconn, const char *sql); +static int +sqlite_db_execute_sql (DBConnection *vconn, const char *sql, int n, va_list args); +static int +sqlite_db_query_foreach_row (DBConnection *vconn, const char *sql, + SeafDBRowFunc callback, void *data, + int n, va_list args); +static int +sqlite_db_row_get_column_count (SeafDBRow *row); +static const char * +sqlite_db_row_get_column_string (SeafDBRow *row, int idx); +static int +sqlite_db_row_get_column_int (SeafDBRow *row, int idx); +static gint64 +sqlite_db_row_get_column_int64 (SeafDBRow *row, int idx); SeafDB * seaf_db_new_sqlite (const char *db_path, int max_connections) { SeafDB *db; - db = g_new0 (SeafDB, 1); - if (!db) { - seaf_warning ("Failed to alloc db structure.\n"); + db = sqlite_db_new (db_path); + if (!db) return NULL; - } - db->type = SEAF_DB_TYPE_SQLITE; - db->pool = db_conn_pool_new_sqlite (db_path, max_connections); + db_ops.get_connection = sqlite_db_get_connection; + db_ops.release_connection = sqlite_db_release_connection; + db_ops.execute_sql_no_stmt = sqlite_db_execute_sql_no_stmt; + db_ops.execute_sql = sqlite_db_execute_sql; + db_ops.query_foreach_row = sqlite_db_query_foreach_row; + db_ops.row_get_column_count = sqlite_db_row_get_column_count; + db_ops.row_get_column_string = sqlite_db_row_get_column_string; + db_ops.row_get_column_int = sqlite_db_row_get_column_int; + db_ops.row_get_column_int64 = sqlite_db_row_get_column_int64; return db; } -void -seaf_db_free (SeafDB *db) -{ - db_conn_pool_free (db->pool); - g_free (db); -} - int seaf_db_type (SeafDB *db) { return db->type; } -static DBConnection * -get_db_connection (SeafDB *db) -{ - DBConnection *conn; - GError *error = NULL; - - conn = db_conn_pool_get_connection (db->pool, &error); - - if (!conn) { - seaf_warning ("Failed to get database connection: %s.\n", error->message); - g_clear_error (&error); - } - - return conn; -} - int seaf_db_query (SeafDB *db, const char *sql) { - GError *error = NULL; - int ret = 0; - - DBConnection *conn = get_db_connection (db); + DBConnection *conn = db_ops.get_connection (db); if (!conn) return -1; - if (!db_connection_execute (conn, sql, &error)) { - seaf_warning ("Error exec query %s: %s.\n", sql, error->message); - g_clear_error (&error); - ret = -1; - } - - db_connection_close (conn); + int ret; + ret = db_ops.execute_sql_no_stmt (conn, sql); + db_ops.release_connection (conn); return ret; } gboolean seaf_db_check_for_existence (SeafDB *db, const char *sql, gboolean *db_err) { - DBConnection *conn; - ResultSet *result; - gboolean ret = TRUE; - GError *error = NULL; - - *db_err = FALSE; - - conn = get_db_connection (db); - if (!conn) { - *db_err = TRUE; - return FALSE; - } - - result = db_connection_execute_query (conn, sql, &error); - if (error) { - seaf_warning ("Error exec query %s: %s.\n", sql, error->message); - g_clear_error (&error); - *db_err = TRUE; - ret = FALSE; - goto out; - } - - ret = result_set_next (result, &error); - if (error) { - seaf_warning ("Error exec query %s: %s.\n", sql, error->message); - g_clear_error (&error); - *db_err = TRUE; - } - -out: - db_connection_close (conn); - - return ret; + return seaf_db_statement_exists (db, sql, db_err, 0); } int seaf_db_foreach_selected_row (SeafDB *db, const char *sql, SeafDBRowFunc callback, void *data) { - DBConnection *conn; - ResultSet *result; - SeafDBRow seaf_row; - int n_rows = 0; - GError *error = NULL; - - conn = get_db_connection (db); - if (!conn) - return -1; - - result = db_connection_execute_query (conn, sql, &error); - if (error) { - seaf_warning ("Error exec query %s: %s.\n", sql, error->message); - g_clear_error (&error); - n_rows = -1; - goto out; - } - - seaf_row.res = result; - - while (result_set_next (result, &error)) { - n_rows++; - if (!callback (&seaf_row, data)) - break; - } - - if (error) { - seaf_warning ("Error exec query %s: %s.\n", sql, error->message); - g_clear_error (&error); - n_rows = -1; - } - -out: - db_connection_close (conn); - return n_rows; + return seaf_db_statement_foreach_row (db, sql, callback, data, 0); } const char * seaf_db_row_get_column_text (SeafDBRow *row, guint32 idx) { - GError *error = NULL; - g_return_val_if_fail (idx < result_set_get_column_count(row->res), NULL); + g_return_val_if_fail (idx < db_ops.row_get_column_count(row), NULL); - return result_set_get_string (row->res, idx, &error); + return db_ops.row_get_column_string (row, idx); } int seaf_db_row_get_column_int (SeafDBRow *row, guint32 idx) { - GError *error = NULL; - g_return_val_if_fail (idx < result_set_get_column_count(row->res), -1); + g_return_val_if_fail (idx < db_ops.row_get_column_count(row), -1); - return result_set_get_int (row->res, idx, &error); + return db_ops.row_get_column_int (row, idx); } gint64 seaf_db_row_get_column_int64 (SeafDBRow *row, guint32 idx) { - GError *error = NULL; - g_return_val_if_fail (idx < result_set_get_column_count(row->res), -1); + g_return_val_if_fail (idx < db_ops.row_get_column_count(row), -1); - return result_set_get_int64 (row->res, idx, &error); + return db_ops.row_get_column_int64 (row, idx); } int seaf_db_get_int (SeafDB *db, const char *sql) { - int ret = -1; - DBConnection *conn; - ResultSet *result; - SeafDBRow seaf_row; - GError *error = NULL; - - conn = get_db_connection (db); - if (!conn) - return -1; - - result = db_connection_execute_query (conn, sql, &error); - if (error) { - seaf_warning ("Error exec query %s: %s.\n", sql, error->message); - g_clear_error (&error); - goto out; - } - - seaf_row.res = result; - if (!result_set_next (result, &error)) { - if (error) { - seaf_warning ("Error exec query %s: %s.\n", sql, error->message); - g_clear_error (&error); - } - goto out; - } - - ret = seaf_db_row_get_column_int (&seaf_row, 0); - -out: - db_connection_close (conn); - return ret; + return seaf_db_statement_get_int (db, sql, 0); } gint64 seaf_db_get_int64 (SeafDB *db, const char *sql) { - gint64 ret = -1; - DBConnection *conn; - ResultSet *result; - SeafDBRow seaf_row; - GError *error = NULL; - - conn = get_db_connection (db); - if (!conn) - return -1; - - result = db_connection_execute_query (conn, sql, &error); - if (error) { - seaf_warning ("Error exec query %s: %s.\n", sql, error->message); - g_clear_error (&error); - goto out; - } - - seaf_row.res = result; - if (!result_set_next (result, &error)) { - if (error) { - seaf_warning ("Error exec query %s: %s.\n", sql, error->message); - g_clear_error (&error); - } - goto out; - } - - ret = seaf_db_row_get_column_int64 (&seaf_row, 0); - -out: - db_connection_close (conn); - return ret; + return seaf_db_statement_get_int64 (db, sql, 0); } char * seaf_db_get_string (SeafDB *db, const char *sql) { - char *ret = NULL; - const char *s; - DBConnection *conn; - ResultSet *result; - SeafDBRow seaf_row; - GError *error = NULL; - - conn = get_db_connection (db); - if (!conn) - return NULL; - - result = db_connection_execute_query (conn, sql, &error); - if (error) { - seaf_warning ("Error exec query %s: %s.\n", sql, error->message); - g_clear_error (&error); - goto out; - } - - seaf_row.res = result; - if (!result_set_next (result, &error)) { - if (error) { - seaf_warning ("Error exec query %s: %s.\n", sql, error->message); - g_clear_error (&error); - } - goto out; - } - - s = seaf_db_row_get_column_text (&seaf_row, 0); - ret = g_strdup(s); - -out: - db_connection_close (conn); - return ret; -} - -char * -seaf_db_escape_string (SeafDB *db, const char *from) -{ - const char *p = from; - char *to, *q; - - to = g_malloc0 (2*strlen(from)+1); - q = to; - - while (*p != '\0') { - if (*p == '\'' || *p == '\\' || *p == '"') { - *q = *p; - *(++q) = *p; - } else - *q = *p; - ++p; - ++q; - } - - return to; -} - -gboolean -pgsql_index_exists (SeafDB *db, const char *index_name) -{ - char sql[256]; - gboolean db_err = FALSE; - - snprintf (sql, sizeof(sql), - "SELECT 1 FROM pg_class WHERE relname='%s'", - index_name); - return seaf_db_check_for_existence (db, sql, &db_err); -} - -/* Prepared Statements */ - -struct SeafDBStatement { - DBStmt *p; - DBConnection *conn; -}; -typedef struct SeafDBStatement SeafDBStatement; - -SeafDBStatement * -seaf_db_prepare_statement (SeafDB *db, const char *sql) -{ - DBStmt *p; - SeafDBStatement *ret = g_new0 (SeafDBStatement, 1); - GError *error = NULL; - - DBConnection *conn = get_db_connection (db); - if (!conn) { - g_free (ret); - return NULL; - } - - p = db_connection_prepare_statement (conn, sql, &error); - if (!p) { - seaf_warning ("Error prepare statement %s: %s.\n", sql, error->message); - g_clear_error (&error); - g_free (ret); - db_connection_close (conn); - return NULL; - } - - ret->p = p; - ret->conn = conn; - - return ret; -} - -void -seaf_db_statement_free (SeafDBStatement *p) -{ - db_connection_close (p->conn); - g_free (p); -} - -int -seaf_db_statement_set_int (DBStmt *p, int idx, int x) -{ - GError *error = NULL; - - if (!db_stmt_set_int (p, idx, x, &error)) { - seaf_warning ("Error set int in prep stmt: %s.\n", error->message); - g_clear_error (&error); - return -1; - } - - return 0; -} - -int -seaf_db_statement_set_string (DBStmt *p, int idx, const char *s) -{ - GError *error = NULL; - - if (!db_stmt_set_string (p, idx, s, &error)) { - seaf_warning ("Error set string in prep stmt: %s.\n", error->message); - g_clear_error (&error); - return -1; - } - - return 0; -} - -int -seaf_db_statement_set_int64 (DBStmt *p, int idx, gint64 x) -{ - GError *error = NULL; - - if (!db_stmt_set_int64 (p, idx, x, &error)) { - seaf_warning ("Error set int64 in prep stmt: %s.\n", error->message); - g_clear_error (&error); - return -1; - } - - return 0; -} - -static int -set_parameters_va (DBStmt *p, int n, va_list args) -{ - int i; - const char *type; - - for (i = 0; i < n; ++i) { - type = va_arg (args, const char *); - if (strcmp(type, "int") == 0) { - int x = va_arg (args, int); - if (seaf_db_statement_set_int (p, i, x) < 0) - return -1; - } else if (strcmp (type, "int64") == 0) { - gint64 x = va_arg (args, gint64); - if (seaf_db_statement_set_int64 (p, i, x) < 0) - return -1; - } else if (strcmp (type, "string") == 0) { - const char *s = va_arg (args, const char *); - if (seaf_db_statement_set_string (p, i, s) < 0) - return -1; - } else { - seaf_warning ("BUG: invalid prep stmt parameter type %s.\n", type); - g_return_val_if_reached (-1); - } - } - - return 0; + return seaf_db_statement_get_string (db, sql, 0); } int seaf_db_statement_query (SeafDB *db, const char *sql, int n, ...) { - SeafDBStatement *p; - int ret = 0; - GError *error = NULL; + int ret; + DBConnection *conn = NULL; - p = seaf_db_prepare_statement (db, sql); - if (!p) + conn = db_ops.get_connection (db); + if (!conn) return -1; va_list args; va_start (args, n); - if (set_parameters_va (p->p, n, args) < 0) { - seaf_db_statement_free (p); - va_end (args); - return -1; - } + ret = db_ops.execute_sql (conn, sql, n, args); va_end (args); - if (!db_stmt_execute (p->p, &error)) { - seaf_warning ("Error execute prep stmt: %s.\n", error->message); - g_clear_error (&error); - ret = -1; - } + db_ops.release_connection (conn); - seaf_db_statement_free (p); return ret; } gboolean seaf_db_statement_exists (SeafDB *db, const char *sql, gboolean *db_err, int n, ...) { - SeafDBStatement *p; - ResultSet *result; - gboolean ret = TRUE; - GError *error = NULL; + int n_rows; + DBConnection *conn = NULL; - *db_err = FALSE; - - p = seaf_db_prepare_statement (db, sql); - if (!p) { - *db_err = TRUE; + conn = db_ops.get_connection(db); + if (!conn) return FALSE; - } va_list args; va_start (args, n); - if (set_parameters_va (p->p, n, args) < 0) { - seaf_db_statement_free (p); - *db_err = TRUE; - va_end (args); - return FALSE; - } + n_rows = db_ops.query_foreach_row (conn, sql, NULL, NULL, n, args); va_end (args); - result = db_stmt_execute_query (p->p, &error); - if (error) { - seaf_warning ("Error exec prep stmt: %s.\n", error->message); - g_clear_error (&error); + db_ops.release_connection(conn); + + if (n_rows < 0) { *db_err = TRUE; - ret = FALSE; - goto out; + return FALSE; + } else { + *db_err = FALSE; + return (n_rows != 0); } - - if (!result_set_next (result, &error)) - ret = FALSE; - - if (error) { - seaf_warning ("Error get next result from prep stmt: %s.\n", error->message); - g_clear_error (&error); - *db_err = TRUE; - } - -out: - seaf_db_statement_free (p); - return ret; } int -seaf_db_statement_foreach_row (SeafDB *db, - const char *sql, - SeafDBRowFunc callback, void *data, - int n, ...) +seaf_db_statement_foreach_row (SeafDB *db, const char *sql, + SeafDBRowFunc callback, void *data, + int n, ...) { - SeafDBStatement *p; - ResultSet *result; - SeafDBRow seaf_row; - int n_rows = 0; - GError *error = NULL; + int ret; + DBConnection *conn = NULL; - p = seaf_db_prepare_statement (db, sql); - if (!p) + conn = db_ops.get_connection (db); + if (!conn) return -1; va_list args; va_start (args, n); - if (set_parameters_va (p->p, n, args) < 0) { - seaf_db_statement_free (p); - va_end (args); - return -1; - } + ret = db_ops.query_foreach_row (conn, sql, callback, data, n, args); va_end (args); - result = db_stmt_execute_query (p->p, &error); - if (error) { - seaf_warning ("Error exec prep stmt: %s.\n", error->message); - g_clear_error (&error); - n_rows = -1; - goto out; - } + db_ops.release_connection (conn); - seaf_row.res = result; + return ret; +} - while (result_set_next (result, &error)) { - n_rows++; - if (!callback (&seaf_row, data)) - break; - } +static gboolean +get_int_cb (SeafDBRow *row, void *data) +{ + int *pret = (int*)data; - if (error) { - seaf_warning ("Error get next result from prep stmt: %s.\n", error->message); - g_clear_error (&error); - n_rows = -1; - } + *pret = seaf_db_row_get_column_int (row, 0); -out: - seaf_db_statement_free (p); - return n_rows; + return FALSE; } int seaf_db_statement_get_int (SeafDB *db, const char *sql, int n, ...) { - SeafDBStatement *p; int ret = -1; - ResultSet *result; - SeafDBRow seaf_row; - GError *error = NULL; + int rc; + DBConnection *conn = NULL; - p = seaf_db_prepare_statement (db, sql); - if (!p) + conn = db_ops.get_connection (db); + if (!conn) return -1; va_list args; va_start (args, n); - if (set_parameters_va (p->p, n, args) < 0) { - seaf_db_statement_free (p); - va_end (args); - return -1; - } + rc = db_ops.query_foreach_row (conn, sql, get_int_cb, &ret, n, args); va_end (args); - result = db_stmt_execute_query (p->p, &error); - if (error) { - seaf_warning ("Error exec prep stmt: %s.\n", error->message); - g_clear_error (&error); - goto out; - } + db_ops.release_connection (conn); - seaf_row.res = result; - if (!result_set_next (result, &error)) { - if (error) { - seaf_warning ("Error get next result from prep stmt: %s.\n", error->message); - g_clear_error (&error); - } - goto out; - } + if (rc < 0) + return -1; - ret = seaf_db_row_get_column_int (&seaf_row, 0); - -out: - seaf_db_statement_free (p); return ret; } +static gboolean +get_int64_cb (SeafDBRow *row, void *data) +{ + gint64 *pret = (gint64*)data; + + *pret = seaf_db_row_get_column_int64 (row, 0); + + return FALSE; +} + gint64 seaf_db_statement_get_int64 (SeafDB *db, const char *sql, int n, ...) { - SeafDBStatement *p; gint64 ret = -1; - ResultSet *result; - SeafDBRow seaf_row; - GError *error = NULL; + int rc; + DBConnection *conn = NULL; - p = seaf_db_prepare_statement (db, sql); - if (!p) + conn = db_ops.get_connection (db); + if (!conn) return -1; va_list args; va_start (args, n); - if (set_parameters_va (p->p, n, args) < 0) { - seaf_db_statement_free (p); - va_end (args); + rc = db_ops.query_foreach_row (conn, sql, get_int64_cb, &ret, n, args); + va_end(args); + + db_ops.release_connection (conn); + + if (rc < 0) return -1; - } - va_end (args); - result = db_stmt_execute_query (p->p, &error); - if (error) { - seaf_warning ("Error exec prep stmt: %s.\n", error->message); - g_clear_error (&error); - goto out; - } - - seaf_row.res = result; - if (!result_set_next (result, &error)) { - if (error) { - seaf_warning ("Error get next result from prep stmt: %s.\n", error->message); - g_clear_error (&error); - } - goto out; - } - - ret = seaf_db_row_get_column_int64 (&seaf_row, 0); - -out: - seaf_db_statement_free (p); return ret; } +static gboolean +get_string_cb (SeafDBRow *row, void *data) +{ + char **pret = (char**)data; + + *pret = g_strdup(seaf_db_row_get_column_text (row, 0)); + + return FALSE; +} + char * seaf_db_statement_get_string (SeafDB *db, const char *sql, int n, ...) { - SeafDBStatement *p; char *ret = NULL; - const char *s; - ResultSet *result; - SeafDBRow seaf_row; - GError *error = NULL; + int rc; + DBConnection *conn = NULL; - p = seaf_db_prepare_statement (db, sql); - if (!p) + conn = db_ops.get_connection (db); + if (!conn) return NULL; va_list args; va_start (args, n); - if (set_parameters_va (p->p, n, args) < 0) { - seaf_db_statement_free (p); - va_end (args); + rc = db_ops.query_foreach_row (conn, sql, get_string_cb, &ret, n, args); + va_end(args); + + db_ops.release_connection (conn); + + if (rc < 0) return NULL; - } - va_end (args); - result = db_stmt_execute_query (p->p, &error); - if (error) { - seaf_warning ("Error exec prep stmt: %s.\n", error->message); - g_clear_error (&error); - goto out; - } - - seaf_row.res = result; - if (!result_set_next (result, &error)) { - if (error) { - seaf_warning ("Error get next result from prep stmt: %s.\n", error->message); - g_clear_error (&error); - } - goto out; - } - - s = seaf_db_row_get_column_text (&seaf_row, 0); - ret = g_strdup(s); - -out: - seaf_db_statement_free (p); return ret; } @@ -786,28 +402,19 @@ out: SeafDBTrans * seaf_db_begin_transaction (SeafDB *db) { - DBConnection *conn; - SeafDBTrans *trans; - GError *error = NULL; + SeafDBTrans *trans = NULL; + DBConnection *conn = db_ops.get_connection(db); + if (!conn) { + return trans; + } + + if (db_ops.execute_sql_no_stmt (conn, "BEGIN") < 0) { + db_ops.release_connection (conn); + return trans; + } trans = g_new0 (SeafDBTrans, 1); - if (!trans) - return NULL; - - conn = get_db_connection (db); - if (!conn) { - g_free (trans); - return NULL; - } - trans->conn = conn; - if (!db_connection_begin_transaction (trans->conn, &error)) { - seaf_warning ("Start transaction failed: %s.\n", error->message); - g_clear_error (&error); - db_connection_close (trans->conn); - g_free (trans); - return NULL; - } return trans; } @@ -815,7 +422,7 @@ seaf_db_begin_transaction (SeafDB *db) void seaf_db_trans_close (SeafDBTrans *trans) { - db_connection_close (trans->conn); + db_ops.release_connection (trans->conn); g_free (trans); } @@ -823,11 +430,8 @@ int seaf_db_commit (SeafDBTrans *trans) { DBConnection *conn = trans->conn; - GError *error = NULL; - if (!db_connection_commit (conn, &error)) { - seaf_warning ("Commit failed: %s.\n", error->message); - g_clear_error (&error); + if (db_ops.execute_sql_no_stmt (conn, "COMMIT") < 0) { return -1; } @@ -838,58 +442,25 @@ int seaf_db_rollback (SeafDBTrans *trans) { DBConnection *conn = trans->conn; - GError *error = NULL; - if (!db_connection_rollback (conn, &error)) { - seaf_warning ("Rollback failed: %s.\n", error->message); - g_clear_error (&error); + if (db_ops.execute_sql_no_stmt (conn, "ROLLBACK") < 0) { return -1; } return 0; } -static DBStmt * -trans_prepare_statement (DBConnection *conn, const char *sql) -{ - DBStmt *p; - GError *error = NULL; - - p = db_connection_prepare_statement (conn, sql, &error); - if (!p) { - seaf_warning ("Error prepare statement %s: %s.\n", sql, error->message); - g_clear_error (&error); - return NULL; - } - - return p; -} - int seaf_db_trans_query (SeafDBTrans *trans, const char *sql, int n, ...) { - DBStmt *p; - GError *error = NULL; - - p = trans_prepare_statement (trans->conn, sql); - if (!p) - return -1; + int ret; va_list args; va_start (args, n); - if (set_parameters_va (p, n, args) < 0) { - va_end (args); - return -1; - } + ret = db_ops.execute_sql (trans->conn, sql, n, args); va_end (args); - if (!db_stmt_execute (p, &error)) { - seaf_warning ("Error exec prep stmt: %s.\n", error->message); - g_clear_error (&error); - return -1; - } - - return 0; + return ret; } gboolean @@ -898,47 +469,20 @@ seaf_db_trans_check_for_existence (SeafDBTrans *trans, gboolean *db_err, int n, ...) { - ResultSet *result; - gboolean ret = TRUE; - GError *error = NULL; - - *db_err = FALSE; - - DBStmt *p; - - p = trans_prepare_statement (trans->conn, sql); - if (!p) { - *db_err = TRUE; - return FALSE; - } + int n_rows; va_list args; va_start (args, n); - if (set_parameters_va (p, n, args) < 0) { - *db_err = TRUE; - va_end (args); - return FALSE; - } + n_rows = db_ops.query_foreach_row (trans->conn, sql, NULL, NULL, n, args); va_end (args); - result = db_stmt_execute_query (p, &error); - if (error) { - seaf_warning ("Error exec prep stmt: %s.\n", error->message); - g_clear_error (&error); + if (n_rows < 0) { *db_err = TRUE; return FALSE; + } else { + *db_err = FALSE; + return (n_rows != 0); } - - if (!result_set_next (result, &error)) - ret = FALSE; - - if (error) { - seaf_warning ("Error get next result from prep stmt: %s.\n", error->message); - g_clear_error (&error); - *db_err = TRUE; - } - - return ret; } int @@ -946,45 +490,762 @@ seaf_db_trans_foreach_selected_row (SeafDBTrans *trans, const char *sql, SeafDBRowFunc callback, void *data, int n, ...) { - ResultSet *result; - SeafDBRow seaf_row; - int n_rows = 0; - GError *error = NULL; - - DBStmt *p; - - p = trans_prepare_statement (trans->conn, sql); - if (!p) - return FALSE; + int ret; va_list args; va_start (args, n); - if (set_parameters_va (p, n, args) < 0) { - va_end (args); - return -1; - } + ret = db_ops.query_foreach_row (trans->conn, sql, callback, data, n, args); va_end (args); - result = db_stmt_execute_query (p, &error); - if (error) { - seaf_warning ("Error exec prep stmt: %s.\n", error->message); - g_clear_error (&error); + return ret; +} + +/* MySQL DB */ + +typedef struct MySQLDB { + struct SeafDB parent; + char *host; + char *user; + char *password; + unsigned int port; + char *db_name; + char *unix_socket; + gboolean use_ssl; + char *charset; +} MySQLDB; + +typedef struct MySQLDBConnection { + struct DBConnection parent; + MYSQL *db_conn; +} MySQLDBConnection; + +static SeafDB * +mysql_db_new (const char *host, + int port, + const char *user, + const char *password, + const char *db_name, + const char *unix_socket, + gboolean use_ssl, + const char *charset) +{ + MySQLDB *db = g_new0 (MySQLDB, 1); + + db->host = g_strdup (host); + db->user = g_strdup (user); + db->password = g_strdup (password); + db->port = port; + db->db_name = g_strdup(db_name); + db->unix_socket = g_strdup(unix_socket); + db->use_ssl = use_ssl; + db->charset = g_strdup(charset); + + mysql_library_init (0, NULL, NULL); + + return (SeafDB *)db; +} + +static DBConnection * +mysql_db_get_connection (SeafDB *vdb) +{ + MySQLDB *db = (MySQLDB *)vdb; + my_bool yes = 1; + int conn_timeout = 1; + MYSQL *db_conn; + MySQLDBConnection *conn = NULL; + + db_conn = mysql_init (NULL); + if (!db_conn) { + seaf_warning ("Failed to init mysql connection object.\n"); + return NULL; + } + + if (db->use_ssl) + mysql_ssl_set(db_conn, 0,0,0,0,0); + + if (db->charset) + mysql_options(db_conn, MYSQL_SET_CHARSET_NAME, db->charset); + + mysql_options(db_conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char*)&conn_timeout); + mysql_options(db_conn, MYSQL_OPT_RECONNECT, (const char*)&yes); + + if (!mysql_real_connect(db_conn, db->host, db->user, db->password, + db->db_name, db->port, + db->unix_socket, CLIENT_MULTI_STATEMENTS)) { + seaf_warning ("Failed to connect to MySQL: %s\n", mysql_error(db_conn)); + mysql_close (db_conn); + return NULL; + } + + conn = g_new0 (MySQLDBConnection, 1); + conn->db_conn = db_conn; + + return (DBConnection *)conn; +} + +static void +mysql_db_release_connection (DBConnection *vconn) +{ + if (!vconn) + return; + + MySQLDBConnection *conn = (MySQLDBConnection *)vconn; + + mysql_close (conn->db_conn); + + g_free (conn); +} + +static int +mysql_db_execute_sql_no_stmt (DBConnection *vconn, const char *sql) +{ + MySQLDBConnection *conn = (MySQLDBConnection *)vconn; + + if (mysql_query (conn->db_conn, sql) != 0) { + seaf_warning ("Failed to execute sql %s: %s\n", sql, mysql_error(conn->db_conn)); return -1; } - seaf_row.res = result; + return 0; +} - while (result_set_next (result, &error)) { - n_rows++; - if (!callback (&seaf_row, data)) +static MYSQL_STMT * +_prepare_stmt_mysql (MYSQL *db, const char *sql) +{ + MYSQL_STMT *stmt; + + stmt = mysql_stmt_init (db); + if (!stmt) { + seaf_warning ("mysql_stmt_init failed.\n"); + return NULL; + } + + if (mysql_stmt_prepare (stmt, sql, strlen(sql)) != 0) { + seaf_warning ("Failed to prepare sql %s: %s\n", sql, mysql_stmt_error(stmt)); + mysql_stmt_close (stmt); + return NULL; + } + + return stmt; +} + +static int +_bind_params_mysql (MYSQL_STMT *stmt, MYSQL_BIND *params, int n, va_list args) +{ + int i; + const char *type; + + for (i = 0; i < n; ++i) { + type = va_arg (args, const char *); + if (strcmp(type, "int") == 0) { + int x = va_arg (args, int); + int *pval = g_new (int, 1); + *pval = x; + params[i].buffer_type = MYSQL_TYPE_LONG; + params[i].buffer = pval; + params[i].is_null = 0; + } else if (strcmp (type, "int64") == 0) { + gint64 x = va_arg (args, gint64); + gint64 *pval = g_new (gint64, 1); + *pval = x; + params[i].buffer_type = MYSQL_TYPE_LONGLONG; + params[i].buffer = pval; + params[i].is_null = 0; + } else if (strcmp (type, "string") == 0) { + const char *s = va_arg (args, const char *); + static my_bool yes = TRUE; + params[i].buffer_type = MYSQL_TYPE_STRING; + params[i].buffer = g_strdup(s); + unsigned long *plen = g_new (unsigned long, 1); + params[i].length = plen; + if (!s) { + *plen = 0; + params[i].buffer_length = 0; + params[i].is_null = &yes; + } else { + *plen = strlen(s); + params[i].buffer_length = *plen + 1; + params[i].is_null = 0; + } + } else { + seaf_warning ("BUG: invalid prep stmt parameter type %s.\n", type); + g_return_val_if_reached (-1); + } + } + + if (mysql_stmt_bind_param (stmt, params) != 0) { + return -1; + } + + return 0; +} + +static int +mysql_db_execute_sql (DBConnection *vconn, const char *sql, int n, va_list args) +{ + MySQLDBConnection *conn = (MySQLDBConnection *)vconn; + MYSQL *db = conn->db_conn; + MYSQL_STMT *stmt = NULL; + MYSQL_BIND *params = NULL; + int ret = 0; + + stmt = _prepare_stmt_mysql (db, sql); + if (!stmt) { + return -1; + } + + if (n > 0) { + params = g_new0 (MYSQL_BIND, n); + if (_bind_params_mysql (stmt, params, n, args) < 0) { + seaf_warning ("Failed to bind parameters for %s: %s.\n", + sql, mysql_stmt_error(stmt)); + ret = -1; + goto out; + } + } + + if (mysql_stmt_execute (stmt) != 0) { + seaf_warning ("Failed to execute sql %s: %s\n", sql, mysql_stmt_error(stmt)); + ret = -1; + goto out; + } + +out: + if (stmt) + mysql_stmt_close (stmt); + if (params) { + int i; + for (i = 0; i < n; ++i) { + g_free (params[i].buffer); + g_free (params[i].length); + } + g_free (params); + } + return ret; +} + +typedef struct MySQLDBRow { + SeafDBRow parent; + int column_count; + MYSQL_STMT *stmt; + MYSQL_BIND *results; + /* Used when returned columns are truncated. */ + MYSQL_BIND *new_binds; +} MySQLDBRow; + +#define DEFAULT_MYSQL_COLUMN_SIZE 1024 + +static int +mysql_db_query_foreach_row (DBConnection *vconn, const char *sql, + SeafDBRowFunc callback, void *data, + int n, va_list args) +{ + MySQLDBConnection *conn = (MySQLDBConnection *)vconn; + MYSQL *db = conn->db_conn; + MYSQL_STMT *stmt = NULL; + MYSQL_BIND *params = NULL; + MySQLDBRow row; + int nrows = 0; + int i; + + memset (&row, 0, sizeof(row)); + + stmt = _prepare_stmt_mysql (db, sql); + if (!stmt) { + return -1; + } + + if (n > 0) { + params = g_new0 (MYSQL_BIND, n); + if (_bind_params_mysql (stmt, params, n, args) < 0) { + nrows = -1; + goto out; + } + } + + if (mysql_stmt_execute (stmt) != 0) { + seaf_warning ("Failed to execute sql %s: %s\n", sql, mysql_stmt_error(stmt)); + nrows = -1; + goto out; + } + + row.column_count = mysql_stmt_field_count (stmt); + row.stmt = stmt; + row.results = g_new0 (MYSQL_BIND, row.column_count); + for (i = 0; i < row.column_count; ++i) { + row.results[i].buffer = g_malloc (DEFAULT_MYSQL_COLUMN_SIZE + 1); + /* Ask MySQL to convert fields to string, to avoid the trouble of + * checking field types. + */ + row.results[i].buffer_type = MYSQL_TYPE_STRING; + row.results[i].buffer_length = DEFAULT_MYSQL_COLUMN_SIZE; + row.results[i].length = g_new0 (unsigned long, 1); + row.results[i].is_null = g_new0 (my_bool, 1); + } + row.new_binds = g_new0 (MYSQL_BIND, row.column_count); + + if (mysql_stmt_bind_result (stmt, row.results) != 0) { + seaf_warning ("Failed to bind result for sql %s: %s\n", sql, mysql_stmt_error(stmt)); + nrows = -1; + goto out; + } + + int rc; + gboolean next_row = TRUE; + while (1) { + rc = mysql_stmt_fetch (stmt); + if (rc == 1) { + seaf_warning ("Failed to fetch result for sql %s: %s\n", + sql, mysql_stmt_error(stmt)); + nrows = -1; + goto out; + } + if (rc == MYSQL_NO_DATA) + break; + + /* rc == 0 or rc == MYSQL_DATA_TRUNCATED */ + + ++nrows; + if (callback) + next_row = callback ((SeafDBRow *)&row, data); + + for (i = 0; i < row.column_count; ++i) { + g_free (row.new_binds[i].buffer); + g_free (row.new_binds[i].length); + g_free (row.new_binds[i].is_null); + memset (&row.new_binds[i], 0, sizeof(MYSQL_BIND)); + } + + if (!next_row) break; } - if (error) { - seaf_warning ("Error get next result from prep stmt: %s.\n", error->message); - g_clear_error (&error); - n_rows = -1; +out: + if (stmt) { + mysql_stmt_free_result (stmt); + mysql_stmt_close (stmt); + } + if (params) { + for (i = 0; i < n; ++i) { + g_free (params[i].buffer); + g_free (params[i].length); + } + g_free (params); + } + if (row.results) { + for (i = 0; i < row.column_count; ++i) { + g_free (row.results[i].buffer); + g_free (row.results[i].length); + g_free (row.results[i].is_null); + } + g_free (row.results); + } + if (row.new_binds) { + for (i = 0; i < row.column_count; ++i) { + g_free (row.new_binds[i].buffer); + g_free (row.new_binds[i].length); + g_free (row.new_binds[i].is_null); + } + g_free (row.new_binds); + } + return nrows; +} + +static int +mysql_db_row_get_column_count (SeafDBRow *vrow) +{ + MySQLDBRow *row = (MySQLDBRow *)vrow; + return row->column_count; +} + +static const char * +mysql_db_row_get_column_string (SeafDBRow *vrow, int i) +{ + MySQLDBRow *row = (MySQLDBRow *)vrow; + + if (*(row->results[i].is_null)) { + return NULL; } - return n_rows; + char *ret = NULL; + unsigned long real_length = *(row->results[i].length); + /* If column size is larger then allocated buffer size, re-allocate a new buffer + * and fetch the column directly. + */ + if (real_length > row->results[i].buffer_length) { + row->new_binds[i].buffer = g_malloc (real_length + 1); + row->new_binds[i].buffer_type = MYSQL_TYPE_STRING; + row->new_binds[i].buffer_length = real_length; + row->new_binds[i].length = g_new0 (unsigned long, 1); + row->new_binds[i].is_null = g_new0 (my_bool, 1); + if (mysql_stmt_fetch_column (row->stmt, &row->new_binds[i], i, 0) != 0) { + seaf_warning ("Faield to fetch column: %s\n", mysql_stmt_error(row->stmt)); + return NULL; + } + + ret = row->new_binds[i].buffer; + } else { + ret = row->results[i].buffer; + } + ret[real_length] = 0; + + return ret; +} + +static int +mysql_db_row_get_column_int (SeafDBRow *vrow, int idx) +{ + const char *str; + char *e; + int ret; + + str = mysql_db_row_get_column_string (vrow, idx); + if (!str) { + return 0; + } + + errno = 0; + ret = strtol (str, &e, 10); + if (errno || (e == str)) { + seaf_warning ("Number conversion failed.\n"); + return -1; + } + + return ret; +} + +static gint64 +mysql_db_row_get_column_int64 (SeafDBRow *vrow, int idx) +{ + const char *str; + char *e; + gint64 ret; + + str = mysql_db_row_get_column_string (vrow, idx); + if (!str) { + return 0; + } + + errno = 0; + ret = strtoll (str, &e, 10); + if (errno || (e == str)) { + seaf_warning ("Number conversion failed.\n"); + return -1; + } + + return ret; +} + +/* SQLite DB */ + +/* SQLite thread synchronization rountines. + * See https://www.sqlite.org/unlock_notify.html + */ + +typedef struct UnlockNotification { + int fired; + pthread_cond_t cond; + pthread_mutex_t mutex; +} UnlockNotification; + +static void +unlock_notify_cb(void **ap_arg, int n_arg) +{ + int i; + + for (i = 0; i < n_arg; i++) { + UnlockNotification *p = (UnlockNotification *)ap_arg[i]; + pthread_mutex_lock (&p->mutex); + p->fired = 1; + pthread_cond_signal (&p->cond); + pthread_mutex_unlock (&p->mutex); + } +} + +static int +wait_for_unlock_notify(sqlite3 *db) +{ + UnlockNotification un; + un.fired = 0; + pthread_mutex_init (&un.mutex, NULL); + pthread_cond_init (&un.cond, NULL); + + int rc = sqlite3_unlock_notify(db, unlock_notify_cb, (void *)&un); + + if (rc == SQLITE_OK) { + pthread_mutex_lock(&un.mutex); + if (!un.fired) + pthread_cond_wait (&un.cond, &un.mutex); + pthread_mutex_unlock(&un.mutex); + } + + pthread_cond_destroy (&un.cond); + pthread_mutex_destroy (&un.mutex); + + return rc; +} + +static int +sqlite3_blocking_step(sqlite3_stmt *stmt) +{ + int rc; + while (SQLITE_LOCKED == (rc = sqlite3_step(stmt))) { + rc = wait_for_unlock_notify(sqlite3_db_handle(stmt)); + if (rc != SQLITE_OK) + break; + sqlite3_reset(stmt); + } + return rc; +} + +static int +sqlite3_blocking_prepare_v2(sqlite3 *db, const char *sql, int sql_len, sqlite3_stmt **pstmt, const char **pz) +{ + int rc; + while (SQLITE_LOCKED == (rc = sqlite3_prepare_v2(db, sql, sql_len, pstmt, pz))) { + rc = wait_for_unlock_notify(db); + if (rc != SQLITE_OK) + break; + } + return rc; +} + +static int +sqlite3_blocking_exec(sqlite3 *db, const char *sql, int (*callback)(void *, int, char **, char **), void *arg, char **errmsg) +{ + int rc; + while (SQLITE_LOCKED == (rc = sqlite3_exec(db, sql, callback, arg, errmsg))) { + rc = wait_for_unlock_notify(db); + if (rc != SQLITE_OK) + break; + } + return rc; +} + +typedef struct SQLiteDB { + SeafDB parent; + char *db_path; +} SQLiteDB; + +typedef struct SQLiteDBConnection { + DBConnection parent; + sqlite3 *db_conn; +} SQLiteDBConnection; + +static SeafDB * +sqlite_db_new (const char *db_path) +{ + SQLiteDB *db = g_new0 (SQLiteDB, 1); + db->db_path = g_strdup(db_path); + + return (SeafDB *)db; +} + +static DBConnection * +sqlite_db_get_connection (SeafDB *vdb) +{ + SQLiteDB *db = (SQLiteDB *)vdb; + sqlite3 *db_conn; + int result; + const char *errmsg; + SQLiteDBConnection *conn; + + result = sqlite3_open_v2 (db->db_path, &db_conn, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_SHAREDCACHE, NULL); + if (result != SQLITE_OK) { + errmsg = sqlite3_errmsg(db_conn); + seaf_warning ("Failed to open sqlite db: %s\n", errmsg ? errmsg : "no error given"); + return NULL; + } + + conn = g_new0 (SQLiteDBConnection, 1); + conn->db_conn = db_conn; + + return (DBConnection *)conn; +} + +static void +sqlite_db_release_connection (DBConnection *vconn) +{ + if (!vconn) + return; + + SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; + + sqlite3_close (conn->db_conn); + + g_free (conn); +} + +static int +sqlite_db_execute_sql_no_stmt (DBConnection *vconn, const char *sql) +{ + SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; + char *errmsg = NULL; + int rc; + + rc = sqlite3_blocking_exec (conn->db_conn, sql, NULL, NULL, &errmsg); + if (rc != SQLITE_OK) { + seaf_warning ("sqlite3_exec failed %s: %s", sql, errmsg ? errmsg : "no error given"); + if (errmsg) + sqlite3_free (errmsg); + return -1; + } + + return 0; +} + +static int +_bind_parameters_sqlite (sqlite3 *db, sqlite3_stmt *stmt, int n, va_list args) +{ + int i; + const char *type; + + for (i = 0; i < n; ++i) { + type = va_arg (args, const char *); + if (strcmp(type, "int") == 0) { + int x = va_arg (args, int); + if (sqlite3_bind_int (stmt, i+1, x) != SQLITE_OK) { + seaf_warning ("sqlite3_bind_int failed: %s\n", sqlite3_errmsg(db)); + return -1; + } + } else if (strcmp (type, "int64") == 0) { + gint64 x = va_arg (args, gint64); + if (sqlite3_bind_int64 (stmt, i+1, x) != SQLITE_OK) { + seaf_warning ("sqlite3_bind_int64 failed: %s\n", sqlite3_errmsg(db)); + return -1; + } + } else if (strcmp (type, "string") == 0) { + const char *s = va_arg (args, const char *); + if (sqlite3_bind_text (stmt, i+1, s, -1, SQLITE_TRANSIENT) != SQLITE_OK) { + seaf_warning ("sqlite3_bind_text failed: %s\n", sqlite3_errmsg(db)); + return -1; + } + } else { + seaf_warning ("BUG: invalid prep stmt parameter type %s.\n", type); + g_return_val_if_reached (-1); + } + } + + return 0; +} + +static int +sqlite_db_execute_sql (DBConnection *vconn, const char *sql, int n, va_list args) +{ + SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; + sqlite3 *db = conn->db_conn; + sqlite3_stmt *stmt; + int rc; + int ret = 0; + + rc = sqlite3_blocking_prepare_v2 (db, sql, -1, &stmt, NULL); + if (rc != SQLITE_OK) { + seaf_warning ("sqlite3_prepare_v2 failed %s: %s", sql, sqlite3_errmsg(db)); + return -1; + } + + if (_bind_parameters_sqlite (db, stmt, n, args) < 0) { + seaf_warning ("Failed to bind parameters for sql %s\n", sql); + ret = -1; + goto out; + } + + rc = sqlite3_blocking_step (stmt); + if (rc != SQLITE_DONE) { + seaf_warning ("sqlite3_step failed %s: %s", sql, sqlite3_errmsg(db)); + ret = -1; + goto out; + } + +out: + sqlite3_finalize (stmt); + return ret; +} + +typedef struct SQLiteDBRow { + SeafDBRow parent; + int column_count; + sqlite3 *db; + sqlite3_stmt *stmt; +} SQLiteDBRow; + +static int +sqlite_db_query_foreach_row (DBConnection *vconn, const char *sql, + SeafDBRowFunc callback, void *data, + int n, va_list args) +{ + SQLiteDBConnection *conn = (SQLiteDBConnection *)vconn; + sqlite3 *db = conn->db_conn; + sqlite3_stmt *stmt; + int rc; + int nrows = 0; + + rc = sqlite3_blocking_prepare_v2 (db, sql, -1, &stmt, NULL); + if (rc != SQLITE_OK) { + seaf_warning ("sqlite3_prepare_v2 failed %s: %s", sql, sqlite3_errmsg(db)); + return -1; + } + + if (_bind_parameters_sqlite (db, stmt, n, args) < 0) { + seaf_warning ("Failed to bind parameters for sql %s\n", sql); + nrows = -1; + goto out; + } + + SQLiteDBRow row; + memset (&row, 0, sizeof(row)); + row.db = db; + row.stmt = stmt; + row.column_count = sqlite3_column_count (stmt); + + while (1) { + rc = sqlite3_blocking_step (stmt); + if (rc == SQLITE_ROW) { + ++nrows; + if (callback && !callback ((SeafDBRow *)&row, data)) + break; + } else if (rc == SQLITE_DONE) { + break; + } else { + seaf_warning ("sqlite3_step failed %s: %s\n", sql, sqlite3_errmsg(db)); + nrows = -1; + goto out; + } + } + +out: + sqlite3_finalize (stmt); + return nrows; +} + +static int +sqlite_db_row_get_column_count (SeafDBRow *vrow) +{ + SQLiteDBRow *row = (SQLiteDBRow *)vrow; + + return row->column_count; +} + +static const char * +sqlite_db_row_get_column_string (SeafDBRow *vrow, int idx) +{ + SQLiteDBRow *row = (SQLiteDBRow *)vrow; + + return (const char *)sqlite3_column_text (row->stmt, idx); +} + +static int +sqlite_db_row_get_column_int (SeafDBRow *vrow, int idx) +{ + SQLiteDBRow *row = (SQLiteDBRow *)vrow; + + return sqlite3_column_int (row->stmt, idx); +} + +static gint64 +sqlite_db_row_get_column_int64 (SeafDBRow *vrow, int idx) +{ + SQLiteDBRow *row = (SQLiteDBRow *)vrow; + + return sqlite3_column_int64 (row->stmt, idx); } diff --git a/common/seaf-db.h b/common/seaf-db.h index db46074..c6dd056 100644 --- a/common/seaf-db.h +++ b/common/seaf-db.h @@ -24,6 +24,7 @@ seaf_db_new_mysql (const char *host, const char *charset, int max_connections); +#if 0 SeafDB * seaf_db_new_pgsql (const char *host, unsigned int port, @@ -32,13 +33,11 @@ seaf_db_new_pgsql (const char *host, const char *db_name, const char *unix_socket, int max_connections); +#endif SeafDB * seaf_db_new_sqlite (const char *db_path, int max_connections); -void -seaf_db_free (SeafDB *db); - int seaf_db_type (SeafDB *db); @@ -98,14 +97,6 @@ seaf_db_trans_foreach_selected_row (SeafDBTrans *trans, const char *sql, SeafDBRowFunc callback, void *data, int n, ...); -/* Escape a string contant by doubling '\" characters. - */ -char * -seaf_db_escape_string (SeafDB *db, const char *from); - -gboolean -pgsql_index_exists (SeafDB *db, const char *index_name); - /* Prepared Statements */ int diff --git a/common/seaf-utils.c b/common/seaf-utils.c index ef1c750..fc6066c 100644 --- a/common/seaf-utils.c +++ b/common/seaf-utils.c @@ -51,8 +51,6 @@ sqlite_db_start (SeafileSession *session) return 0; } -#ifdef HAVE_MYSQL - #define MYSQL_DEFAULT_PORT 3306 static int @@ -126,8 +124,6 @@ mysql_db_start (SeafileSession *session) return 0; } -#endif - #ifdef HAVE_POSTGRESQL static int @@ -201,11 +197,9 @@ load_database_config (SeafileSession *session) if (!type || strcasecmp (type, "sqlite") == 0) { ret = sqlite_db_start (session); } -#ifdef HAVE_MYSQL else if (strcasecmp (type, "mysql") == 0) { ret = mysql_db_start (session); } -#endif #ifdef HAVE_POSTGRESQL else if (strcasecmp (type, "pgsql") == 0) { ret = pgsql_db_start (session); diff --git a/configure.ac b/configure.ac index f1ece57..d18c2b5 100644 --- a/configure.ac +++ b/configure.ac @@ -83,6 +83,11 @@ AC_ARG_ENABLE(python, [compile_python=$enableval], [compile_python=yes]) +AC_ARG_WITH(mysql, + AC_HELP_STRING([--with-mysql],[path to mysql_config]), + [MYSQL_CONFIG=$with_mysql], + [MYSQL_CONFIG="default_mysql_config"]) + AM_CONDITIONAL([COMPILE_TOOLS], [test "${compile_tools}" = "yes"]) AM_CONDITIONAL([COMPILE_PYTHON], [test "${compile_python}" = "yes"]) AM_CONDITIONAL([COMPILE_FUSE], [test "${compile_fuse}" = "yes"]) @@ -222,6 +227,17 @@ PKG_CHECK_MODULES(ZLIB, [zlib >= $ZLIB_REQUIRED]) AC_SUBST(ZLIB_CFLAGS) AC_SUBST(ZLIB_LIBS) +if test "x${MYSQL_CONFIG}" = "xdefault_mysql_config"; then + PKG_CHECK_MODULES(MYSQL, [mysqlclient]) + AC_SUBST(MYSQL_CFLAGS) + AC_SUBST(MYSQL_LIBS) +else + MYSQL_CFLAGS=`${MYSQL_CONFIG} --include` + MYSQL_LIBS=`${MYSQL_CONFIG} --libs` + AC_SUBST(MYSQL_CFLAGS) + AC_SUBST(MYSQL_LIBS) +fi + if test x${compile_python} = xyes; then AM_PATH_PYTHON([2.6]) if test "$bwin32" = true; then @@ -235,110 +251,6 @@ if test x${compile_python} = xyes; then fi fi -mysql="yes" -if test "$bwin32" != "true"; then - AC_MSG_CHECKING(for mysql in unix) - check_mysql_config() - { - AC_PATH_PROG([MYSQLCONFIG], [mysql_config], [no], [$PATH:/usr/local/bin:/usr/local/mysql/bin]) - if test "x$MYSQLCONFIG" = "xno" - then - AC_MSG_WARN([mysql_config is required to build seafile server with mysql]) - mysql="no" - fi - } - AC_MSG_CHECKING(for mysql) - AC_ARG_WITH([mysql], - AS_HELP_STRING([--with-mysql(=)], - [Path is optional and if given should specify the full path to the MySQL - configure script, mysql_config. E.g. --with-mysql=//mysql_config]), - [ - if test "xno" = "x$with_mysql"; then - AC_MSG_RESULT([no]) - mysql="no" - else - AC_MSG_RESULT([yes]) - AC_CHECK_FILE([$with_mysql], [MYSQLCONFIG=$with_mysql], [check_mysql_config]) - fi - ], - [ - AC_MSG_RESULT([yes]) - check_mysql_config - ]) - if test "xyes" = "x$mysql"; then - tmp_CPPFLAGS=$CPPFLAGS - tmp_LDFLAGS=$LDFLAGS - CPPFLAGS="`$MYSQLCONFIG --include` $CPPFLAGS" - LDFLAGS="`$MYSQLCONFIG --libs` $LDFLAGS" - AC_CHECK_HEADERS([mysql.h], [], [mysql="no"]) - if test "xyes" = "x$mysql"; then - echo "found mysql client library" - MYSQL_CFLAGS=`$MYSQLCONFIG --include` - MYSQL_LIBS=`$MYSQLCONFIG --libs` - AC_SUBST(MYSQL_CFLAGS) - AC_SUBST(MYSQL_LIBS) - AC_DEFINE([HAVE_MYSQL], 1, [Define to 1 to enable mysql]) - fi - CPPFLAGS=$tmp_CPPFLAGS - LDFLAGS=$tmp_LDFLAGS - fi -else - AC_MSG_CHECKING(for mysql in windows) - AC_CHECK_HEADERS([mysql.h], [], [mysql="no"]) - if test "xyes" = "x$mysql"; then - AC_DEFINE([HAVE_MYSQL], 1, [Define to 1 to enable mysql]) - LDFLAGS="$LDFLAGS -lmysql -lws2_32" - fi -fi -AM_CONDITIONAL([WITH_MYSQL], test "xyes" = "x$mysql") - -postgresql="yes" -check_postgres_config() -{ - AC_PATH_PROG([PGCONFIG], [pg_config], [no], [$PATH:/usr/local/bin:/usr/local/pgsql/bin]) - if test "x$PGCONFIG" = "xno" - then - AC_MSG_WARN([pg_config is required to build seafile server with postgresql]) - postgresql="no" - fi -} -AC_MSG_CHECKING(for postgresql) -AC_ARG_WITH([postgresql], - AS_HELP_STRING([--with-postgresql(=)], - [Path is optional and if given should specify the full path to the PostgreSQL - configure script, pg_config. E.g. --with-postgresql=//pg_config]), - [ - if test "xno" = "x$with_postgresql"; then - AC_MSG_RESULT([no]) - postgresql="no" - else - AC_MSG_RESULT([yes]) - AC_CHECK_FILE([$with_postgresql], [PGCONFIG=$with_postgresql],[check_postgres_config]) - fi - ], - [ - AC_MSG_RESULT([yes]) - check_postgres_config - ]) -if test "xyes" = "x$postgresql"; then - tmp_CPPFLAGS=$CPPFLAGS - tmp_LDFLAGS=$LDFLAGS - CPPFLAGS="-I`$PGCONFIG --includedir` $CPPFLAGS" - LDFLAGS="-L`$PGCONFIG --libdir` $LDFLAGS" - AC_CHECK_HEADERS([libpq-fe.h], [], [postgresql="no"]) - if test "xyes" = "x$postgresql"; then - echo "found postgresql client library" - PGSQL_CFLAGS="-I`$PGCONFIG --includedir`" - PGSQL_LIBS="-L`$PGCONFIG --libdir` -lpq" - AC_SUBST(PGSQL_CFLAGS) - AC_SUBST(PGSQL_LIBS) - AC_DEFINE([HAVE_POSTGRESQL], 1, [Define to 1 to enable postgresql]) - fi - CPPFLAGS=$tmp_CPPFLAGS - LDFLAGS=$tmp_LDFLAGS -fi -AM_CONDITIONAL([WITH_POSTGRESQL], test "xyes" = "x$postgresql") - if test "${compile_fuse}" = "yes"; then PKG_CHECK_MODULES(FUSE, [fuse >= $FUSE_REQUIRED]) AC_SUBST(FUSE_CFLAGS) @@ -361,7 +273,6 @@ AC_CONFIG_FILES( lib/libseafile.pc common/Makefile common/cdc/Makefile - common/db-wrapper/Makefile server/Makefile server/gc/Makefile python/Makefile diff --git a/fuse/Makefile.am b/fuse/Makefile.am index 096d67b..62fb455 100644 --- a/fuse/Makefile.am +++ b/fuse/Makefile.am @@ -9,6 +9,7 @@ AM_CFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" \ @SEARPC_CFLAGS@ \ @GLIB2_CFLAGS@ \ @FUSE_CFLAGS@ \ + @MYSQL_CFLAGS@ \ -Wall bin_PROGRAMS = seaf-fuse @@ -39,7 +40,6 @@ seaf_fuse_LDADD = @CCNET_LIBS@ \ @GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ \ -lsqlite3 @LIBEVENT_LIBS@ \ $(top_builddir)/common/cdc/libcdc.la \ - $(top_builddir)/common/db-wrapper/libdbwrapper.la \ @SEARPC_LIBS@ @JANSSON_LIBS@ @FUSE_LIBS@ @ZLIB_LIBS@ \ - @MYSQL_LIBS@ @PGSQL_LIBS@ + @MYSQL_LIBS@ -lsqlite3 diff --git a/server/Makefile.am b/server/Makefile.am index 7af1200..2e93613 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -13,6 +13,7 @@ AM_CFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" \ @GLIB2_CFLAGS@ \ @MSVC_CFLAGS@ \ @LIBARCHIVE_CFLAGS@ \ + @MYSQL_CFLAGS@ \ -Wall bin_PROGRAMS = seaf-server @@ -118,7 +119,6 @@ seaf_server_LDADD = @CCNET_LIBS@ \ $(top_builddir)/lib/libseafile_common.la \ @GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 @LIBEVENT_LIBS@ -levhtp \ $(top_builddir)/common/cdc/libcdc.la \ - $(top_builddir)/common/db-wrapper/libdbwrapper.la \ @SEARPC_LIBS@ @JANSSON_LIBS@ ${LIB_WS32} @ZLIB_LIBS@ \ @LIBARCHIVE_LIBS@ @LIB_ICONV@ \ - @MYSQL_LIBS@ @PGSQL_LIBS@ + @MYSQL_LIBS@ -lsqlite3 diff --git a/server/gc/Makefile.am b/server/gc/Makefile.am index 7f113fc..07063fd 100644 --- a/server/gc/Makefile.am +++ b/server/gc/Makefile.am @@ -10,9 +10,10 @@ AM_CFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" \ @SEARPC_CFLAGS@ \ @GLIB2_CFLAGS@ \ @MSVC_CFLAGS@ \ + @MYSQL_CFLAGS@ \ -Wall -bin_PROGRAMS = seafserv-gc seaf-fsck seaf-migrate +bin_PROGRAMS = seafserv-gc seaf-fsck noinst_HEADERS = \ seafile-session.h \ @@ -47,10 +48,9 @@ seafserv_gc_SOURCES = \ seafserv_gc_LDADD = @CCNET_LIBS@ \ $(top_builddir)/common/cdc/libcdc.la \ $(top_builddir)/lib/libseafile_common.la \ - $(top_builddir)/common/db-wrapper/libdbwrapper.la \ @GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 @LIBEVENT_LIBS@ \ @SEARPC_LIBS@ @JANSSON_LIBS@ ${LIB_WS32} @ZLIB_LIBS@ \ - @MYSQL_LIBS@ @PGSQL_LIBS@ + @MYSQL_LIBS@ -lsqlite3 seaf_fsck_SOURCES = \ seaf-fsck.c \ @@ -59,33 +59,7 @@ seaf_fsck_SOURCES = \ seaf_fsck_LDADD = @CCNET_LIBS@ \ $(top_builddir)/common/cdc/libcdc.la \ - $(top_builddir)/common/db-wrapper/libdbwrapper.la \ $(top_builddir)/lib/libseafile_common.la \ @GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 @LIBEVENT_LIBS@ \ @SEARPC_LIBS@ @JANSSON_LIBS@ ${LIB_WS32} @ZLIB_LIBS@ \ - @MYSQL_LIBS@ @PGSQL_LIBS@ - -seaf_migrate_SOURCES = \ - seaf-migrate.c \ - $(common_sources) - -seaf_migrate_LDADD = @CCNET_LIBS@ \ - $(top_builddir)/common/cdc/libcdc.la \ - $(top_builddir)/common/db-wrapper/libdbwrapper.la \ - $(top_builddir)/lib/libseafile_common.la \ - @GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 @LIBEVENT_LIBS@ \ - @SEARPC_LIBS@ @JANSSON_LIBS@ ${LIB_WS32} @ZLIB_LIBS@ \ - @MYSQL_LIBS@ @PGSQL_LIBS@ - -seaf_migrate_CFLAGS = -DPKGDATADIR=\"$(pkgdatadir)\" \ - -DPACKAGE_DATA_DIR=\""$(pkgdatadir)"\" \ - -DSEAFILE_SERVER -DMIGRATION \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/lib \ - -I$(top_builddir)/lib \ - -I$(top_srcdir)/common \ - @CCNET_CFLAGS@ \ - @SEARPC_CFLAGS@ \ - @GLIB2_CFLAGS@ \ - @MSVC_CFLAGS@ \ - -Wall + @MYSQL_LIBS@ -lsqlite3 diff --git a/server/repo-mgr.c b/server/repo-mgr.c index 95a9bd2..d82ce4c 100644 --- a/server/repo-mgr.c +++ b/server/repo-mgr.c @@ -1225,154 +1225,154 @@ create_tables_sqlite (SeafRepoManager *mgr) return 0; } -static int -create_tables_pgsql (SeafRepoManager *mgr) -{ - SeafDB *db = mgr->seaf->db; - char *sql; +/* static int */ +/* create_tables_pgsql (SeafRepoManager *mgr) */ +/* { */ +/* SeafDB *db = mgr->seaf->db; */ +/* char *sql; */ - sql = "CREATE TABLE IF NOT EXISTS Repo (repo_id CHAR(36) PRIMARY KEY)"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS Repo (repo_id CHAR(36) PRIMARY KEY)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - sql = "CREATE TABLE IF NOT EXISTS RepoOwner (" - "repo_id CHAR(36) PRIMARY KEY, " - "owner_id VARCHAR(255))"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS RepoOwner (" */ +/* "repo_id CHAR(36) PRIMARY KEY, " */ +/* "owner_id VARCHAR(255))"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - if (!pgsql_index_exists (db, "repoowner_owner_idx")) { - sql = "CREATE INDEX repoowner_owner_idx ON RepoOwner (owner_id)"; - if (seaf_db_query (db, sql) < 0) - return -1; - } +/* if (!pgsql_index_exists (db, "repoowner_owner_idx")) { */ +/* sql = "CREATE INDEX repoowner_owner_idx ON RepoOwner (owner_id)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ +/* } */ - sql = "CREATE TABLE IF NOT EXISTS RepoGroup (repo_id CHAR(36), " - "group_id INTEGER, user_name VARCHAR(255), permission VARCHAR(15), " - "UNIQUE (group_id, repo_id))"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS RepoGroup (repo_id CHAR(36), " */ +/* "group_id INTEGER, user_name VARCHAR(255), permission VARCHAR(15), " */ +/* "UNIQUE (group_id, repo_id))"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - if (!pgsql_index_exists (db, "repogroup_repoid_idx")) { - sql = "CREATE INDEX repogroup_repoid_idx ON RepoGroup (repo_id)"; - if (seaf_db_query (db, sql) < 0) - return -1; - } +/* if (!pgsql_index_exists (db, "repogroup_repoid_idx")) { */ +/* sql = "CREATE INDEX repogroup_repoid_idx ON RepoGroup (repo_id)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ +/* } */ - if (!pgsql_index_exists (db, "repogroup_username_idx")) { - sql = "CREATE INDEX repogroup_username_idx ON RepoGroup (user_name)"; - if (seaf_db_query (db, sql) < 0) - return -1; - } +/* if (!pgsql_index_exists (db, "repogroup_username_idx")) { */ +/* sql = "CREATE INDEX repogroup_username_idx ON RepoGroup (user_name)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ +/* } */ - sql = "CREATE TABLE IF NOT EXISTS InnerPubRepo (" - "repo_id CHAR(36) PRIMARY KEY," - "permission VARCHAR(15))"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS InnerPubRepo (" */ +/* "repo_id CHAR(36) PRIMARY KEY," */ +/* "permission VARCHAR(15))"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - sql = "CREATE TABLE IF NOT EXISTS RepoUserToken (" - "repo_id CHAR(36), " - "email VARCHAR(255), " - "token CHAR(40), " - "UNIQUE (repo_id, token))"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS RepoUserToken (" */ +/* "repo_id CHAR(36), " */ +/* "email VARCHAR(255), " */ +/* "token CHAR(40), " */ +/* "UNIQUE (repo_id, token))"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - if (!pgsql_index_exists (db, "repousertoken_email_idx")) { - sql = "CREATE INDEX repousertoken_email_idx ON RepoUserToken (email)"; - if (seaf_db_query (db, sql) < 0) - return -1; - } +/* if (!pgsql_index_exists (db, "repousertoken_email_idx")) { */ +/* sql = "CREATE INDEX repousertoken_email_idx ON RepoUserToken (email)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ +/* } */ - sql = "CREATE TABLE IF NOT EXISTS RepoTokenPeerInfo (" - "token CHAR(40) PRIMARY KEY, " - "peer_id CHAR(40), " - "peer_ip VARCHAR(40), " - "peer_name VARCHAR(255), " - "sync_time BIGINT, " - "client_ver VARCHAR(20))"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS RepoTokenPeerInfo (" */ +/* "token CHAR(40) PRIMARY KEY, " */ +/* "peer_id CHAR(40), " */ +/* "peer_ip VARCHAR(40), " */ +/* "peer_name VARCHAR(255), " */ +/* "sync_time BIGINT, " */ +/* "client_ver VARCHAR(20))"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - sql = "CREATE TABLE IF NOT EXISTS RepoHead (" - "repo_id CHAR(36) PRIMARY KEY, branch_name VARCHAR(10))"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS RepoHead (" */ +/* "repo_id CHAR(36) PRIMARY KEY, branch_name VARCHAR(10))"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - sql = "CREATE TABLE IF NOT EXISTS RepoSize (" - "repo_id CHAR(36) PRIMARY KEY," - "size BIGINT," - "head_id CHAR(40))"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS RepoSize (" */ +/* "repo_id CHAR(36) PRIMARY KEY," */ +/* "size BIGINT," */ +/* "head_id CHAR(40))"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - sql = "CREATE TABLE IF NOT EXISTS RepoHistoryLimit (" - "repo_id CHAR(36) PRIMARY KEY, days INTEGER)"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS RepoHistoryLimit (" */ +/* "repo_id CHAR(36) PRIMARY KEY, days INTEGER)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - sql = "CREATE TABLE IF NOT EXISTS RepoValidSince (" - "repo_id CHAR(36) PRIMARY KEY, timestamp BIGINT)"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS RepoValidSince (" */ +/* "repo_id CHAR(36) PRIMARY KEY, timestamp BIGINT)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - sql = "CREATE TABLE IF NOT EXISTS WebAP (repo_id CHAR(36) PRIMARY KEY, " - "access_property VARCHAR(10))"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS WebAP (repo_id CHAR(36) PRIMARY KEY, " */ +/* "access_property VARCHAR(10))"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - sql = "CREATE TABLE IF NOT EXISTS VirtualRepo (repo_id CHAR(36) PRIMARY KEY," - "origin_repo CHAR(36), path TEXT, base_commit CHAR(40))"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS VirtualRepo (repo_id CHAR(36) PRIMARY KEY," */ +/* "origin_repo CHAR(36), path TEXT, base_commit CHAR(40))"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - if (!pgsql_index_exists (db, "virtualrepo_origin_repo_idx")) { - sql = "CREATE INDEX virtualrepo_origin_repo_idx ON VirtualRepo (origin_repo)"; - if (seaf_db_query (db, sql) < 0) - return -1; - } +/* if (!pgsql_index_exists (db, "virtualrepo_origin_repo_idx")) { */ +/* sql = "CREATE INDEX virtualrepo_origin_repo_idx ON VirtualRepo (origin_repo)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ +/* } */ - sql = "CREATE TABLE IF NOT EXISTS GarbageRepos (repo_id CHAR(36) PRIMARY KEY)"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS GarbageRepos (repo_id CHAR(36) PRIMARY KEY)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - sql = "CREATE TABLE IF NOT EXISTS RepoTrash (repo_id CHAR(36) PRIMARY KEY," - "repo_name VARCHAR(255), head_id CHAR(40), owner_id VARCHAR(255), size bigint," - "org_id INTEGER, del_time BIGINT)"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS RepoTrash (repo_id CHAR(36) PRIMARY KEY," */ +/* "repo_name VARCHAR(255), head_id CHAR(40), owner_id VARCHAR(255), size bigint," */ +/* "org_id INTEGER, del_time BIGINT)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - if (!pgsql_index_exists (db, "repotrash_owner_id")) { - sql = "CREATE INDEX repotrash_owner_id on RepoTrash(owner_id)"; - if (seaf_db_query (db, sql) < 0) - return -1; - } - if (!pgsql_index_exists (db, "repotrash_org_id")) { - sql = "CREATE INDEX repotrash_org_id on RepoTrash(org_id)"; - if (seaf_db_query (db, sql) < 0) - return -1; - } +/* if (!pgsql_index_exists (db, "repotrash_owner_id")) { */ +/* sql = "CREATE INDEX repotrash_owner_id on RepoTrash(owner_id)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ +/* } */ +/* if (!pgsql_index_exists (db, "repotrash_org_id")) { */ +/* sql = "CREATE INDEX repotrash_org_id on RepoTrash(org_id)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ +/* } */ - sql = "CREATE TABLE IF NOT EXISTS RepoFileCount (" - "repo_id CHAR(36) PRIMARY KEY," - "file_count BIGINT)"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS RepoFileCount (" */ +/* "repo_id CHAR(36) PRIMARY KEY," */ +/* "file_count BIGINT)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - sql = "CREATE TABLE IF NOT EXISTS WebUploadTempFiles (repo_id CHAR(40) NOT NULL, " - "file_path TEXT NOT NULL, tmp_file_path TEXT NOT NULL)"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS WebUploadTempFiles (repo_id CHAR(40) NOT NULL, " */ +/* "file_path TEXT NOT NULL, tmp_file_path TEXT NOT NULL)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - sql = "CREATE TABLE IF NOT EXISTS RepoInfo (repo_id CHAR(36) PRIMARY KEY, " - "name VARCHAR(255) NOT NULL, update_time BIGINT, version INTEGER, " - "is_encrypted INTEGER, last_modifier VARCHAR(255), status INTEGER DEFAULT 0)"; - if (seaf_db_query (db, sql) < 0) - return -1; +/* sql = "CREATE TABLE IF NOT EXISTS RepoInfo (repo_id CHAR(36) PRIMARY KEY, " */ +/* "name VARCHAR(255) NOT NULL, update_time BIGINT, version INTEGER, " */ +/* "is_encrypted INTEGER, last_modifier VARCHAR(255), status INTEGER DEFAULT 0)"; */ +/* if (seaf_db_query (db, sql) < 0) */ +/* return -1; */ - return 0; -} +/* return 0; */ +/* } */ static int create_db_tables_if_not_exist (SeafRepoManager *mgr) @@ -1387,8 +1387,8 @@ create_db_tables_if_not_exist (SeafRepoManager *mgr) return create_tables_mysql (mgr); else if (db_type == SEAF_DB_TYPE_SQLITE) return create_tables_sqlite (mgr); - else if (db_type == SEAF_DB_TYPE_PGSQL) - return create_tables_pgsql (mgr); + /* else if (db_type == SEAF_DB_TYPE_PGSQL) */ + /* return create_tables_pgsql (mgr); */ g_return_val_if_reached (-1); } diff --git a/server/share-mgr.c b/server/share-mgr.c index 4f1a1a6..8f72b41 100644 --- a/server/share-mgr.c +++ b/server/share-mgr.c @@ -57,29 +57,30 @@ seaf_share_manager_start (SeafShareManager *mgr) sql = "CREATE INDEX IF NOT EXISTS ToEmailIndex on SharedRepo (to_email)"; if (seaf_db_query (db, sql) < 0) return -1; - } else if (db_type == SEAF_DB_TYPE_PGSQL) { - sql = "CREATE TABLE IF NOT EXISTS SharedRepo " - "(repo_id CHAR(36) , from_email VARCHAR(255), to_email VARCHAR(255), " - "permission VARCHAR(15))"; - if (seaf_db_query (db, sql) < 0) - return -1; - - if (!pgsql_index_exists (db, "sharedrepo_repoid_idx")) { - sql = "CREATE INDEX sharedrepo_repoid_idx ON SharedRepo (repo_id)"; - if (seaf_db_query (db, sql) < 0) - return -1; - } - if (!pgsql_index_exists (db, "sharedrepo_from_email_idx")) { - sql = "CREATE INDEX sharedrepo_from_email_idx ON SharedRepo (from_email)"; - if (seaf_db_query (db, sql) < 0) - return -1; - } - if (!pgsql_index_exists (db, "sharedrepo_to_email_idx")) { - sql = "CREATE INDEX sharedrepo_to_email_idx ON SharedRepo (to_email)"; - if (seaf_db_query (db, sql) < 0) - return -1; - } } + /* else if (db_type == SEAF_DB_TYPE_PGSQL) { */ + /* sql = "CREATE TABLE IF NOT EXISTS SharedRepo " */ + /* "(repo_id CHAR(36) , from_email VARCHAR(255), to_email VARCHAR(255), " */ + /* "permission VARCHAR(15))"; */ + /* if (seaf_db_query (db, sql) < 0) */ + /* return -1; */ + + /* if (!pgsql_index_exists (db, "sharedrepo_repoid_idx")) { */ + /* sql = "CREATE INDEX sharedrepo_repoid_idx ON SharedRepo (repo_id)"; */ + /* if (seaf_db_query (db, sql) < 0) */ + /* return -1; */ + /* } */ + /* if (!pgsql_index_exists (db, "sharedrepo_from_email_idx")) { */ + /* sql = "CREATE INDEX sharedrepo_from_email_idx ON SharedRepo (from_email)"; */ + /* if (seaf_db_query (db, sql) < 0) */ + /* return -1; */ + /* } */ + /* if (!pgsql_index_exists (db, "sharedrepo_to_email_idx")) { */ + /* sql = "CREATE INDEX sharedrepo_to_email_idx ON SharedRepo (to_email)"; */ + /* if (seaf_db_query (db, sql) < 0) */ + /* return -1; */ + /* } */ + /* } */ return 0; } diff --git a/tools/Makefile.am b/tools/Makefile.am index 8fd99a4..cc93d38 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -5,9 +5,9 @@ bin_PROGRAMS = seaf-server-init seaf_server_init_SOURCES = seaf-server-init.c ../common/seaf-db.c -seaf_server_init_LDADD = @GLIB2_LIBS@ $(top_builddir)/common/db-wrapper/libdbwrapper.la -lpthread @MYSQL_LIBS@ @PGSQL_LIBS@ +seaf_server_init_LDADD = @GLIB2_LIBS@ -lpthread @MYSQL_LIBS@ -lsqlite3 -seaf_server_init_CPPFLAGS = @GLIB2_CFLAGS@ @MSVC_CFLAGS@ +seaf_server_init_CPPFLAGS = @GLIB2_CFLAGS@ @MSVC_CFLAGS@ @MYSQL_CFLAGS@ EXTRA_DIST = seafile-admin