mirror of
https://github.com/haiwen/seafile-server.git
synced 2025-09-16 07:10:07 +00:00
Rewrite database access layer.
Remove support for PostgreSQL at the same time.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
SUBDIRS = cdc db-wrapper
|
||||
SUBDIRS = cdc
|
||||
|
||||
proc_headers = \
|
||||
$(addprefix processors/, \
|
||||
|
@@ -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@
|
@@ -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);
|
||||
}
|
@@ -1,140 +0,0 @@
|
||||
#ifndef DB_WRAPPER_H
|
||||
#define DB_WARPPER_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#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
|
@@ -1,585 +0,0 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "db-wrapper.h"
|
||||
#include "mysql-db-ops.h"
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
/* 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);
|
||||
}
|
@@ -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
|
@@ -1,492 +0,0 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "db-wrapper.h"
|
||||
#include "pgsql-db-ops.h"
|
||||
|
||||
#include <libpq-fe.h>
|
||||
|
||||
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;
|
||||
}
|
@@ -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
|
@@ -1,477 +0,0 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "db-wrapper.h"
|
||||
#include "sqlite-db-ops.h"
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* 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;
|
||||
}
|
@@ -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
|
1669
common/seaf-db.c
1669
common/seaf-db.c
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
@@ -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);
|
||||
|
121
configure.ac
121
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>)],
|
||||
[Path is optional and if given should specify the full path to the MySQL
|
||||
configure script, mysql_config. E.g. --with-mysql=/<path>/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>)],
|
||||
[Path is optional and if given should specify the full path to the PostgreSQL
|
||||
configure script, pg_config. E.g. --with-postgresql=/<path>/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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user