1
0
mirror of https://github.com/haiwen/ccnet-server.git synced 2025-04-27 10:20:49 +00:00

Merge pull request #36 from haiwen/remove-db-wrapper-723

Rewrite database access layer.
This commit is contained in:
Jiaqiang Xu 2019-07-24 09:47:19 +08:00 committed by GitHub
commit f014fc5263
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1114 additions and 3268 deletions

View File

@ -68,6 +68,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_PYTHON], [test "${compile_python}" = "yes"])
AM_CONDITIONAL([WIN32], [test "$bwin32" = "true"])
@ -124,6 +129,22 @@ if test "$bwin32" = "true"; then
fi
AC_SUBST(CONSOLE)
if test "x${MYSQL_CONFIG}" = "xdefault_mysql_config"; then
PKG_CHECK_MODULES(MYSQL, [mysqlclient], [have_mysql="yes"], [have_mysql="no"])
if test "x${have_mysql}" = "xyes"; then
AC_SUBST(MYSQL_CFLAGS)
AC_SUBST(MYSQL_LIBS)
AC_DEFINE([HAVE_MYSQL], 1, [Define to 1 if MySQL support is enabled])
fi
else
AC_MSG_CHECKING([for MySQL])
MYSQL_CFLAGS=`${MYSQL_CONFIG} --include`
MYSQL_LIBS=`${MYSQL_CONFIG} --libs`
AC_MSG_RESULT([${MYSQL_CFLAGS}])
AC_SUBST(MYSQL_CFLAGS)
AC_SUBST(MYSQL_LIBS)
fi
if test "$bwin32" = true; then
LIB_WS32=-lws2_32
LIB_GDI32=-lgdi32
@ -219,109 +240,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_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_ldap}" = "yes"; then
if test "$bwin32" != true; then
AC_CHECK_LIB(ldap, ldap_init, [have_ldap="yes"],
@ -348,7 +266,6 @@ AC_CONFIG_FILES(
net/Makefile
net/server/Makefile
net/common/Makefile
net/common/db-wrapper/Makefile
lib/Makefile
tools/Makefile
include/Makefile

View File

@ -1,5 +1,3 @@
SUBDIRS = db-wrapper
PROC_HEADER_FILES = \
$(addprefix processors/, \
rcvmsg-proc.h \

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,6 @@
#define DB_SQLITE "sqlite"
#define DB_MYSQL "mysql"
#define DB_PGSQL "pgsql"
enum {
CCNET_DB_TYPE_SQLITE,
@ -28,6 +27,7 @@ ccnet_db_new_mysql (const char *host,
const char *charset,
int max_connections);
#if 0
CcnetDB *
ccnet_db_new_pgsql (const char *host,
unsigned int port,
@ -36,13 +36,11 @@ ccnet_db_new_pgsql (const char *host,
const char *db_name,
const char *unix_socket,
int max_connections);
#endif
CcnetDB *
ccnet_db_new_sqlite (const char *db_path);
void
ccnet_db_free (CcnetDB *db);
int
ccnet_db_type (CcnetDB *db);
@ -102,21 +100,13 @@ ccnet_db_trans_foreach_selected_row (CcnetDBTrans *trans, const char *sql,
CcnetDBRowFunc callback, void *data,
int n, ...);
/* Escape a string contant by doubling '\" characters.
*/
char *
ccnet_db_escape_string (CcnetDB *db, const char *from);
gboolean
pgsql_index_exists (CcnetDB *db, const char *index_name);
/* Prepared Statements */
int
ccnet_db_statement_query (CcnetDB *db, const char *sql, int n, ...);
gboolean
ccnet_db_statement_exists (CcnetDB *db, const char *sql, int n, ...);
ccnet_db_statement_exists (CcnetDB *db, const char *sql, gboolean *db_err, int n, ...);
int
ccnet_db_statement_foreach_row (CcnetDB *db, const char *sql,

View File

@ -1,24 +0,0 @@
AM_CFLAGS = -I$(top_srcdir)/net/common -I$(top_srcdir)/lib \
-I$(top_srcdir)/include -I$(top_srcdir)/include/ccnet \
-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@

View File

@ -1,453 +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;
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);
}

View File

@ -1,139 +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;
};
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

View File

@ -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].buffer_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);
}

View File

@ -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

View File

@ -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, &param_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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -7,6 +7,7 @@ AM_CPPFLAGS = @GLIB2_CFLAGS@ @GOBJECT_CFLAGS@ \
-I$(top_builddir)/include \
-I$(top_builddir)/lib \
@SEARPC_CFLAGS@ \
@MYSQL_CFLAGS@ \
-Wall
bin_PROGRAMS = ccnet-server
@ -46,11 +47,10 @@ ccnet_server_SOURCES = ccnet-server.c \
$(common_srcs)
ccnet_server_LDADD = @LIBEVENT_LIBS@ $(top_builddir)/lib/libccnetd.la \
$(top_builddir)/net/common/db-wrapper/libdbwrapper.la \
@GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 \
-lpthread \
@LIB_WS32@ @LIB_INTL@ @LIB_IPHLPAPI@ @SEARPC_LIBS@ \
@LDAP_LIBS@ @MYSQL_LIBS@ @PGSQL_LIBS@
@LDAP_LIBS@ @MYSQL_LIBS@ -lsqlite3
ccnet_server_LDFLAGS = @CONSOLE@ -no-undefined

View File

@ -197,11 +197,11 @@ static int check_db_table (CcnetGroupManager *manager, CcnetDB *db)
if (ccnet_db_query (db, sql) < 0)
return -1;
if (!pgsql_index_exists (db, "groupuser_username_idx")) {
sql = "CREATE INDEX groupuser_username_idx ON GroupUser (user_name)";
if (ccnet_db_query (db, sql) < 0)
return -1;
}
//if (!pgsql_index_exists (db, "groupuser_username_idx")) {
// sql = "CREATE INDEX groupuser_username_idx ON GroupUser (user_name)";
// if (ccnet_db_query (db, sql) < 0)
// return -1;
//}
sql = "CREATE TABLE IF NOT EXISTS GroupDNPair (group_id INTEGER,"
" dn VARCHAR(255))";
@ -213,11 +213,11 @@ static int check_db_table (CcnetGroupManager *manager, CcnetDB *db)
if (ccnet_db_query (db, sql) < 0)
return -1;
if (!pgsql_index_exists (db, "structure_path_idx")) {
sql = "CREATE INDEX structure_path_idx ON GroupStructure (path)";
if (ccnet_db_query (db, sql) < 0)
return -1;
}
//if (!pgsql_index_exists (db, "structure_path_idx")) {
// sql = "CREATE INDEX structure_path_idx ON GroupStructure (path)";
// if (ccnet_db_query (db, sql) < 0)
// return -1;
//}
}
g_string_free (group_sql, TRUE);
@ -410,14 +410,20 @@ int ccnet_group_manager_create_org_group (CcnetGroupManager *mgr,
static gboolean
check_group_staff (CcnetDB *db, int group_id, const char *user_name, gboolean in_structure)
{
gboolean exists, err;
if (!in_structure) {
return ccnet_db_statement_exists (db, "SELECT group_id FROM GroupUser WHERE "
"group_id = ? AND user_name = ? AND "
"is_staff = 1",
2, "int", group_id, "string", user_name);
exists = ccnet_db_statement_exists (db, "SELECT group_id FROM GroupUser WHERE "
"group_id = ? AND user_name = ? AND "
"is_staff = 1", &err,
2, "int", group_id, "string", user_name);
if (err) {
ccnet_warning ("DB error when check staff user exist in GroupUser.\n");
return FALSE;
}
return exists;
}
gboolean exists;
GString *sql = g_string_new("");
g_string_printf (sql, "SELECT path FROM GroupStructure WHERE group_id=?");
char *path = ccnet_db_statement_get_string (db, sql->str, 1, "int", group_id);
@ -426,18 +432,23 @@ check_group_staff (CcnetDB *db, int group_id, const char *user_name, gboolean in
if (!path) {
exists = ccnet_db_statement_exists (db, "SELECT group_id FROM GroupUser WHERE "
"group_id = ? AND user_name = ? AND "
"is_staff = 1",
"is_staff = 1", &err,
2, "int", group_id, "string", user_name);
} else {
g_string_printf (sql, "SELECT group_id FROM GroupUser WHERE "
"group_id IN (%s) AND user_name = ? AND "
"is_staff = 1", path);
exists = ccnet_db_statement_exists (db, sql->str,
exists = ccnet_db_statement_exists (db, sql->str, &err,
1, "string", user_name);
}
g_string_free (sql, TRUE);
g_free (path);
if (err) {
ccnet_warning ("DB error when check staff user exist in GroupUser.\n");
return FALSE;
}
return exists;
}
@ -448,7 +459,7 @@ int ccnet_group_manager_remove_group (CcnetGroupManager *mgr,
{
CcnetDB *db = mgr->priv->db;
GString *sql = g_string_new ("");
gboolean exists;
gboolean exists, err;
const char *table_name = mgr->priv->table_name;
/* No permission check here, since both group staff and seahub staff
@ -459,7 +470,12 @@ int ccnet_group_manager_remove_group (CcnetGroupManager *mgr,
g_string_printf (sql, "SELECT 1 FROM \"%s\" WHERE parent_group_id=?", table_name);
else
g_string_printf (sql, "SELECT 1 FROM `%s` WHERE parent_group_id=?", table_name);
exists = ccnet_db_statement_exists (db, sql->str, 1, "int", group_id);
exists = ccnet_db_statement_exists (db, sql->str, &err, 1, "int", group_id);
if (err) {
ccnet_warning ("DB error when check remove group.\n");
g_string_free (sql, TRUE);
return -1;
}
if (exists) {
ccnet_warning ("Failed to remove group [%d] whose child group must be removed first.\n", group_id);
g_string_free (sql, TRUE);
@ -489,17 +505,21 @@ check_group_exists (CcnetGroupManager *mgr, CcnetDB *db, int group_id)
{
GString *sql = g_string_new ("");
const char *table_name = mgr->priv->table_name;
gboolean exists;
gboolean exists, err;
if (ccnet_db_type(db) == CCNET_DB_TYPE_PGSQL) {
g_string_printf (sql, "SELECT group_id FROM \"%s\" WHERE group_id=?", table_name);
exists = ccnet_db_statement_exists (db, sql->str, 1, "int", group_id);
exists = ccnet_db_statement_exists (db, sql->str, &err, 1, "int", group_id);
} else {
g_string_printf (sql, "SELECT group_id FROM `%s` WHERE group_id=?", table_name);
exists = ccnet_db_statement_exists (db, sql->str, 1, "int", group_id);
exists = ccnet_db_statement_exists (db, sql->str, &err, 1, "int", group_id);
}
g_string_free (sql, TRUE);
if (err) {
ccnet_warning ("DB error when check group exist.\n");
return FALSE;
}
return exists;
}
@ -1088,9 +1108,14 @@ ccnet_group_manager_is_group_user (CcnetGroupManager *mgr,
{
CcnetDB *db = mgr->priv->db;
gboolean exists = ccnet_db_statement_exists (db, "SELECT group_id FROM GroupUser "
"WHERE group_id=? AND user_name=?",
2, "int", group_id, "string", user);
gboolean exists, err;
exists = ccnet_db_statement_exists (db, "SELECT group_id FROM GroupUser "
"WHERE group_id=? AND user_name=?", &err,
2, "int", group_id, "string", user);
if (err) {
ccnet_warning ("DB error when check user exist in GroupUser.\n");
return 0;
}
if (!in_structure || exists)
return exists ? 1 : 0;

View File

@ -175,11 +175,11 @@ static int check_db_table (CcnetDB *db)
if (ccnet_db_query (db, sql) < 0)
return -1;
if (!pgsql_index_exists (db, "orguser_email_idx")) {
sql = "CREATE INDEX orguser_email_idx ON OrgUser (email)";
if (ccnet_db_query (db, sql) < 0)
return -1;
}
//if (!pgsql_index_exists (db, "orguser_email_idx")) {
// sql = "CREATE INDEX orguser_email_idx ON OrgUser (email)";
// if (ccnet_db_query (db, sql) < 0)
// return -1;
//}
sql = "CREATE TABLE IF NOT EXISTS OrgGroup (org_id INTEGER, "
"group_id INTEGER, "
@ -187,11 +187,11 @@ static int check_db_table (CcnetDB *db)
if (ccnet_db_query (db, sql) < 0)
return -1;
if (!pgsql_index_exists (db, "orggroup_groupid_idx")) {
sql = "CREATE INDEX orggroup_groupid_idx ON OrgGroup (group_id)";
if (ccnet_db_query (db, sql) < 0)
return -1;
}
//if (!pgsql_index_exists (db, "orggroup_groupid_idx")) {
// sql = "CREATE INDEX orggroup_groupid_idx ON OrgGroup (group_id)";
// if (ccnet_db_query (db, sql) < 0)
// return -1;
//}
}
return 0;
@ -548,10 +548,17 @@ ccnet_org_manager_is_org_group (CcnetOrgManager *mgr,
int group_id,
GError **error)
{
gboolean exists, err;
CcnetDB *db = mgr->priv->db;
return ccnet_db_statement_exists (db, "SELECT group_id FROM OrgGroup "
"WHERE group_id = ?", 1, "int", group_id);
exists = ccnet_db_statement_exists (db, "SELECT group_id FROM OrgGroup "
"WHERE group_id = ?", &err, 1, "int", group_id);
if (err) {
ccnet_warning ("DB error when check group exist in OrgGroup.\n");
return 0;
}
return exists;
}
int
@ -724,11 +731,18 @@ ccnet_org_manager_org_user_exists (CcnetOrgManager *mgr,
const char *email,
GError **error)
{
gboolean exists, err;
CcnetDB *db = mgr->priv->db;
return ccnet_db_statement_exists (db, "SELECT org_id FROM OrgUser WHERE "
"org_id = ? AND email = ?",
2, "int", org_id, "string", email);
exists = ccnet_db_statement_exists (db, "SELECT org_id FROM OrgUser WHERE "
"org_id = ? AND email = ?", &err,
2, "int", org_id, "string", email);
if (err) {
ccnet_warning ("DB error when check user exist in OrgUser.\n");
return 0;
}
return exists;
}
char *

View File

@ -195,7 +195,7 @@ static int init_mysql_database (CcnetSession *session)
#endif
#ifdef HAVE_POSTGRESQL
#if 0
static int init_pgsql_database (CcnetSession *session)
{
@ -263,7 +263,7 @@ load_database_config (CcnetSession *session)
ret = init_mysql_database (session);
}
#endif
#ifdef HAVE_POSTGRESQL
#if 0
else if (strncasecmp (engine, DB_PGSQL, sizeof(DB_PGSQL)) == 0) {
ccnet_debug ("Use database PostgreSQL\n");
ret = init_pgsql_database (session);

View File

@ -666,11 +666,11 @@ static int check_db_table (CcnetDB *db)
if (ccnet_db_query (db, sql) < 0)
return -1;
if (!pgsql_index_exists (db, "emailuser_reference_id_idx")) {
sql = "CREATE UNIQUE INDEX emailuser_reference_id_idx ON EmailUser (reference_id)";
if (ccnet_db_query (db, sql) < 0)
return -1;
}
//if (!pgsql_index_exists (db, "emailuser_reference_id_idx")) {
// sql = "CREATE UNIQUE INDEX emailuser_reference_id_idx ON EmailUser (reference_id)";
// if (ccnet_db_query (db, sql) < 0)
// return -1;
//}
sql = "CREATE TABLE IF NOT EXISTS Binding (email VARCHAR(255), peer_id CHAR(41),"
"UNIQUE (peer_id))";
@ -682,11 +682,11 @@ static int check_db_table (CcnetDB *db)
if (ccnet_db_query (db, sql) < 0)
return -1;
if (!pgsql_index_exists (db, "userrole_email_idx")) {
sql = "CREATE INDEX userrole_email_idx ON UserRole (email)";
if (ccnet_db_query (db, sql) < 0)
return -1;
}
//if (!pgsql_index_exists (db, "userrole_email_idx")) {
// sql = "CREATE INDEX userrole_email_idx ON UserRole (email)";
// if (ccnet_db_query (db, sql) < 0)
// return -1;
//}
sql = "CREATE TABLE IF NOT EXISTS LDAPUsers ("
"id SERIAL PRIMARY KEY, "
@ -696,17 +696,17 @@ static int check_db_table (CcnetDB *db)
if (ccnet_db_query (db, sql) < 0)
return -1;
if (!pgsql_index_exists (db, "ldapusers_email_idx")) {
sql = "CREATE UNIQUE INDEX ldapusers_email_idx ON LDAPUsers (email)";
if (ccnet_db_query (db, sql) < 0)
return -1;
}
//if (!pgsql_index_exists (db, "ldapusers_email_idx")) {
// sql = "CREATE UNIQUE INDEX ldapusers_email_idx ON LDAPUsers (email)";
// if (ccnet_db_query (db, sql) < 0)
// return -1;
//}
if (!pgsql_index_exists (db, "ldapusers_reference_id_idx")) {
sql = "CREATE UNIQUE INDEX ldapusers_reference_id_idx ON LDAPUsers (reference_id)";
if (ccnet_db_query (db, sql) < 0)
return -1;
}
//if (!pgsql_index_exists (db, "ldapusers_reference_id_idx")) {
// sql = "CREATE UNIQUE INDEX ldapusers_reference_id_idx ON LDAPUsers (reference_id)";
// if (ccnet_db_query (db, sql) < 0)
// return -1;
//}
sql = "CREATE TABLE IF NOT EXISTS LDAPConfig (cfg_group VARCHAR(255) NOT NULL,"
"cfg_key VARCHAR(255) NOT NULL, value VARCHAR(255), property INTEGER)";
@ -1789,20 +1789,22 @@ ccnet_user_manager_set_reference_id (CcnetUserManager *manager,
{
int rc;
char *sql;
gboolean exists;
gboolean exists, err;
#ifdef HAVE_LDAP
if (manager->use_ldap) {
sql = "SELECT email FROM LDAPUsers WHERE email = ?";
exists = ccnet_db_statement_exists (manager->priv->db, sql,
exists = ccnet_db_statement_exists (manager->priv->db, sql, &err,
1, "string", primary_id);
if (err)
return -1;
/* Make sure reference_id is unique */
if (exists) {
sql = "SELECT 1 FROM EmailUser e, LDAPUsers l "
"WHERE (e.reference_id=? AND e.email!=?) OR "
"(l.reference_id=? AND l.email!=?) OR "
"(e.email=? AND e.email!=?) OR (l.email=? AND l.email!=?)";
exists = ccnet_db_statement_exists (manager->priv->db, sql,
exists = ccnet_db_statement_exists (manager->priv->db, sql, &err,
8, "string", reference_id,
"string", primary_id,
"string", reference_id,
@ -1811,6 +1813,8 @@ ccnet_user_manager_set_reference_id (CcnetUserManager *manager,
"string", primary_id,
"string", reference_id,
"string", primary_id);
if (err)
return -1;
if (exists) {
ccnet_warning ("Failed to set reference id, email '%s' exists\n", reference_id);
return -1;
@ -1828,15 +1832,17 @@ ccnet_user_manager_set_reference_id (CcnetUserManager *manager,
#endif
sql = "SELECT email FROM EmailUser WHERE email = ?";
exists = ccnet_db_statement_exists (manager->priv->db, sql,
exists = ccnet_db_statement_exists (manager->priv->db, sql, &err,
1, "string", primary_id);
if (err)
return -1;
/* Make sure reference_id is unique */
if (exists) {
sql = "SELECT 1 FROM EmailUser e, LDAPUsers l "
"WHERE (e.reference_id=? AND e.email!=?) OR "
"(l.reference_id=? AND l.email!=?) OR "
"(e.email=? AND e.email!=?) OR (l.email=? AND l.email!=?)";
exists = ccnet_db_statement_exists (manager->priv->db, sql,
exists = ccnet_db_statement_exists (manager->priv->db, sql, &err,
8, "string", reference_id,
"string", primary_id,
"string", reference_id,
@ -1845,6 +1851,8 @@ ccnet_user_manager_set_reference_id (CcnetUserManager *manager,
"string", primary_id,
"string", reference_id,
"string", primary_id);
if (err)
return -1;
if (exists) {
ccnet_warning ("Failed to set reference id, email '%s' exists\n", reference_id);
return -1;