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:
commit
f014fc5263
125
configure.ac
125
configure.ac
@ -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
|
||||
|
@ -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
@ -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,
|
||||
|
@ -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@
|
@ -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);
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 *
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user