1
0
mirror of https://github.com/haiwen/seafile-server.git synced 2025-08-24 09:38:35 +00:00

Support dm8 database

This commit is contained in:
杨赫然 2023-10-10 15:05:32 +08:00
parent 7bb8866889
commit e5e577b282
18 changed files with 1249 additions and 49 deletions

View File

@ -141,6 +141,13 @@ open_db (SeafBranchManager *mgr)
char *sql;
switch (seaf_db_type (mgr->seaf->db)) {
case SEAF_DB_TYPE_DM:
sql = "CREATE TABLE IF NOT EXISTS Branch ("
"id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
"name VARCHAR(10), repo_id VARCHAR(41), commit_id VARCHAR(41))";
if (seaf_db_query (mgr->seaf->db, sql) < 0)
return -1;
break;
case SEAF_DB_TYPE_MYSQL:
sql = "CREATE TABLE IF NOT EXISTS Branch ("
"id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
@ -200,7 +207,7 @@ seaf_branch_manager_add_branch (SeafBranchManager *mgr, SeafBranch *branch)
char *sql;
SeafDB *db = mgr->seaf->db;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
gboolean exists, err;
int rc;
@ -382,6 +389,7 @@ seaf_branch_manager_test_and_update_branch (SeafBranchManager *mgr,
switch (seaf_db_type (mgr->seaf->db)) {
case SEAF_DB_TYPE_MYSQL:
case SEAF_DB_TYPE_PGSQL:
case SEAF_DB_TYPE_DM:
sql = "SELECT commit_id FROM Branch WHERE name=? "
"AND repo_id=? FOR UPDATE";
break;

View File

@ -87,6 +87,7 @@ open_db (CcnetGroupManager *manager)
db = open_sqlite_db (manager);
break;
case SEAF_DB_TYPE_PGSQL:
case SEAF_DB_TYPE_DM:
case SEAF_DB_TYPE_MYSQL:
db = manager->session->ccnet_db;
break;
@ -225,6 +226,46 @@ static int check_db_table (CcnetGroupManager *manager, CcnetDB *db)
// return -1;
//}
} else if (db_type == SEAF_DB_TYPE_DM) {
g_string_printf (group_sql,
"CREATE TABLE IF NOT EXISTS \"%s\" (group_id INTEGER"
" PRIMARY KEY AUTO_INCREMENT, group_name VARCHAR(255),"
" creator_name VARCHAR(255), timestamp BIGINT,"
" type VARCHAR(32), parent_group_id INTEGER)", table_name);
if (seaf_db_query (db, group_sql->str) < 0) {
g_string_free (group_sql, TRUE);
return -1;
}
sql = "CREATE TABLE IF NOT EXISTS GroupUser (group_id INTEGER, "
"user_name VARCHAR(255), is_staff tinyint)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS groupid_username_indx on "
"GroupUser (group_id, user_name)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS username_indx on "
"GroupUser (user_name)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS GroupDNPair (group_id INTEGER,"
" dn VARCHAR(255))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS GroupStructure (group_id INTEGER PRIMARY KEY, "
"path VARCHAR(1024))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS path_indx on "
"GroupStructure (path)";
if (seaf_db_query (db, sql) < 0)
return -1;
}
g_string_free (group_sql, TRUE);
@ -267,7 +308,7 @@ create_group_common (CcnetGroupManager *mgr,
char *user_name_l = g_ascii_strdown (user_name, -1);
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL)
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM)
g_string_printf (sql,
"INSERT INTO \"%s\"(group_name, "
"creator_name, timestamp, parent_group_id) VALUES(?, ?, ?, ?)", table_name);
@ -281,7 +322,7 @@ create_group_common (CcnetGroupManager *mgr,
"int64", now, "int", parent_group_id) < 0)
goto error;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL)
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM)
g_string_printf (sql,
"SELECT group_id FROM \"%s\" WHERE "
"group_name = ? AND creator_name = ? "
@ -472,7 +513,7 @@ int ccnet_group_manager_remove_group (CcnetGroupManager *mgr,
* can remove group.
*/
if (remove_anyway != TRUE) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL)
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM)
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);
@ -489,7 +530,7 @@ int ccnet_group_manager_remove_group (CcnetGroupManager *mgr,
}
}
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL)
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM)
g_string_printf (sql, "DELETE FROM \"%s\" WHERE group_id=?", table_name);
else
g_string_printf (sql, "DELETE FROM `%s` WHERE group_id=?", table_name);
@ -499,7 +540,7 @@ int ccnet_group_manager_remove_group (CcnetGroupManager *mgr,
seaf_db_statement_query (db, sql->str, 1, "int", group_id);
g_string_printf (sql, "DELETE FROM GroupStructure WHERE group_id=?");
seaf_db_statement_query (db, sql->str, 1, "int", group_id);
int ret = seaf_db_statement_query (db, sql->str, 1, "int", group_id);
g_string_free (sql, TRUE);
@ -513,7 +554,7 @@ check_group_exists (CcnetGroupManager *mgr, CcnetDB *db, int group_id)
const char *table_name = mgr->priv->table_name;
gboolean exists, err;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
g_string_printf (sql, "SELECT group_id FROM \"%s\" WHERE group_id=?", table_name);
exists = seaf_db_statement_exists (db, sql->str, &err, 1, "int", group_id);
} else {
@ -622,7 +663,7 @@ int ccnet_group_manager_set_group_name (CcnetGroupManager *mgr,
GString *sql = g_string_new ("");
CcnetDB *db = mgr->priv->db;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
g_string_printf (sql, "UPDATE \"%s\" SET group_name = ? "
"WHERE group_id = ?", table_name);
seaf_db_statement_query (db, sql->str, 2, "string", group_name, "int", group_id);
@ -697,7 +738,7 @@ ccnet_group_manager_get_ancestor_groups (CcnetGroupManager *mgr, int group_id)
char *path = seaf_db_statement_get_string (db, sql->str, 1, "int", group_id);
if (path) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL)
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM)
g_string_printf (sql, "SELECT g.group_id, group_name, creator_name, timestamp, parent_group_id FROM "
"\"%s\" g WHERE g.group_id IN(%s) "
"ORDER BY g.group_id",
@ -768,7 +809,7 @@ ccnet_group_manager_get_groups_by_user (CcnetGroupManager *mgr,
CcnetGroup *group;
int parent_group_id = 0, group_id = 0;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL)
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM)
g_string_printf (sql,
"SELECT g.group_id, group_name, creator_name, timestamp, parent_group_id FROM "
"\"%s\" g, GroupUser u WHERE g.group_id = u.group_id AND user_name=? ORDER BY g.group_id DESC",
@ -827,9 +868,14 @@ ccnet_group_manager_get_groups_by_user (CcnetGroupManager *mgr,
goto out;
}
g_string_printf (sql, "SELECT g.group_id, group_name, creator_name, timestamp, parent_group_id FROM "
"`%s` g WHERE g.group_id IN (%s) ORDER BY g.group_id DESC",
table_name, paths->str);
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM)
g_string_printf (sql, "SELECT g.group_id, group_name, creator_name, timestamp, parent_group_id FROM "
"\"%s\" g WHERE g.group_id IN (%s) ORDER BY g.group_id DESC",
table_name, paths->str);
else
g_string_printf (sql, "SELECT g.group_id, group_name, creator_name, timestamp, parent_group_id FROM "
"`%s` g WHERE g.group_id IN (%s) ORDER BY g.group_id DESC",
table_name, paths->str);
if (seaf_db_statement_foreach_row (db,
sql->str,
get_user_groups_cb,
@ -888,7 +934,7 @@ ccnet_group_manager_get_child_groups (CcnetGroupManager *mgr, int group_id,
GList *ret = NULL;
const char *table_name = mgr->priv->table_name;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL)
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM)
g_string_printf (sql,
"SELECT group_id, group_name, creator_name, timestamp, parent_group_id FROM "
"\"%s\" WHERE parent_group_id=?", table_name);
@ -916,7 +962,7 @@ ccnet_group_manager_get_descendants_groups(CcnetGroupManager *mgr, int group_id,
const char *table_name = mgr->priv->table_name;
GString *sql = g_string_new("");
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL)
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM)
g_string_printf (sql, "SELECT g.group_id, group_name, creator_name, timestamp, "
"parent_group_id FROM \"%s\" g, GroupStructure s "
"WHERE g.group_id=s.group_id "
@ -952,7 +998,7 @@ ccnet_group_manager_get_group (CcnetGroupManager *mgr, int group_id,
CcnetGroup *ccnetgroup = NULL;
const char *table_name = mgr->priv->table_name;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL)
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM)
g_string_printf (sql,
"SELECT group_id, group_name, creator_name, timestamp, parent_group_id FROM "
"\"%s\" WHERE group_id = ?", table_name);
@ -1174,7 +1220,7 @@ ccnet_group_manager_get_top_groups (CcnetGroupManager *mgr,
const char *table_name = mgr->priv->table_name;
int rc;
if (seaf_db_type(mgr->priv->db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(mgr->priv->db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(mgr->priv->db) == SEAF_DB_TYPE_DM) {
if (including_org)
g_string_printf (sql, "SELECT group_id, group_name, "
"creator_name, timestamp, parent_group_id FROM \"%s\" "
@ -1217,7 +1263,7 @@ ccnet_group_manager_list_all_departments (CcnetGroupManager *mgr,
int rc;
int db_type = seaf_db_type(db);
if (db_type == SEAF_DB_TYPE_PGSQL) {
if (db_type == SEAF_DB_TYPE_PGSQL || db_type == SEAF_DB_TYPE_DM) {
g_string_printf (sql, "SELECT group_id, group_name, "
"creator_name, timestamp, type, "
"parent_group_id FROM \"%s\" "
@ -1251,7 +1297,7 @@ ccnet_group_manager_get_all_groups (CcnetGroupManager *mgr,
const char *table_name = mgr->priv->table_name;
int rc;
if (seaf_db_type(mgr->priv->db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(mgr->priv->db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(mgr->priv->db) == SEAF_DB_TYPE_DM) {
if (start == -1 && limit == -1) {
g_string_printf (sql, "SELECT group_id, group_name, "
"creator_name, timestamp, parent_group_id FROM \"%s\" "
@ -1301,7 +1347,7 @@ ccnet_group_manager_set_group_creator (CcnetGroupManager *mgr,
const char *table_name = mgr->priv->table_name;
GString *sql = g_string_new ("");
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
g_string_printf (sql, "UPDATE \"%s\" SET creator_name = ? WHERE group_id = ?",
table_name);
} else {
@ -1329,7 +1375,7 @@ ccnet_group_manager_search_groups (CcnetGroupManager *mgr,
int rc;
char *db_patt = g_strdup_printf ("%%%s%%", keyword);
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
if (start == -1 && limit == -1) {
g_string_printf (sql,
"SELECT group_id, group_name, "

View File

@ -77,6 +77,7 @@ open_db (CcnetOrgManager *manager)
db = open_sqlite_db (manager);
break;
case SEAF_DB_TYPE_PGSQL:
case SEAF_DB_TYPE_DM:
case SEAF_DB_TYPE_MYSQL:
db = manager->session->ccnet_db;
break;
@ -203,6 +204,47 @@ static int check_db_table (CcnetDB *db)
// if (seaf_db_query (db, sql) < 0)
// return -1;
//}
} else if (db_type == SEAF_DB_TYPE_DM) {
sql = "CREATE TABLE IF NOT EXISTS Organization (org_id INTEGER"
" PRIMARY KEY, org_name VARCHAR(255),"
" url_prefix VARCHAR(255), "
" creator VARCHAR(255), ctime BIGINT)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS url_prefix_indx on "
"Organization (url_prefix)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS OrgUser (org_id INTEGER, "
"email VARCHAR(255), is_staff INTEGER NOT NULL)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS email_indx on "
"OrgUser (email)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS orgid_email_indx on "
"OrgUser (org_id, email)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS OrgGroup (org_id INTEGER, "
"group_id INTEGER)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS groupid_indx on OrgGroup (group_id)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS org_group_indx on "
"OrgGroup (org_id, group_id)";
if (seaf_db_query (db, sql) < 0)
return -1;
}
return 0;

View File

@ -13,6 +13,12 @@
#include <sqlite3.h>
#include <pthread.h>
#ifdef HAVE_ODBC
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
#endif
struct DBConnPool {
GPtrArray *connections;
pthread_mutex_t lock;
@ -38,6 +44,7 @@ struct SeafDBRow {
struct SeafDBTrans {
DBConnection *conn;
gboolean need_close;
int type;
};
typedef struct DBOperations {
@ -320,6 +327,210 @@ seaf_db_new_sqlite (const char *db_path, int max_connections)
return db;
}
#ifdef HAVE_ODBC
#define BUFFER_NOT_ENOUGH -70018
#define SUCCESS(rc) ((rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO || (rc) == SQL_NO_DATA || (rc) == SQL_NO_DATA_FOUND)
typedef struct DMDBConnection {
struct DBConnection parent;
HDBC db_conn;
} DMDBConnection;
/* MySQL Ops */
static SeafDB *
dm_db_new (const char *user,
const char *password,
const char *db_name);
static DBConnection *
dm_db_get_connection (SeafDB *db);
static void
dm_db_release_connection (DBConnection *vconn);
static int
dm_db_execute_sql_no_stmt (DBConnection *vconn, const char *sql, gboolean *retry);
static int
dm_db_execute_sql (DBConnection *vconn, const char *sql, int n, va_list args, gboolean *retry);
static int
dm_db_query_foreach_row (DBConnection *vconn, const char *sql,
SeafDBRowFunc callback, void *data,
int n, va_list args, gboolean *retry);
static int
dm_db_row_get_column_count (SeafDBRow *row);
static const char *
dm_db_row_get_column_string (SeafDBRow *row, int idx);
static int
dm_db_row_get_column_int (SeafDBRow *row, int idx);
static gint64
dm_db_row_get_column_int64 (SeafDBRow *row, int idx);
static DBConnPool *
init_dm_conn_pool_common (int max_connections)
{
DBConnPool *pool = g_new0(DBConnPool, 1);
pool->connections = g_ptr_array_sized_new (max_connections);
pthread_mutex_init (&pool->lock, NULL);
pool->max_connections = max_connections;
return pool;
}
static DBConnection *
dm_conn_pool_get_connection (SeafDB *db)
{
DBConnPool *pool = db->pool;
DBConnection *conn = NULL;
DBConnection *d_conn = NULL;
if (pool->max_connections == 0) {
conn = dm_db_get_connection (db);
conn->pool = pool;
return conn;
}
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) {
continue;
}
conn->is_available = FALSE;
goto out;
}
conn = NULL;
if (size < pool->max_connections) {
conn = dm_db_get_connection (db);
if (conn) {
conn->pool = pool;
conn->is_available = FALSE;
g_ptr_array_add (pool->connections, conn);
}
}
out:
size = pool->connections->len;
if (size > 0) {
int index;
for (index = size - 1; index >= 0; index--) {
d_conn = g_ptr_array_index (pool->connections, index);
if (d_conn->delete_pending) {
g_ptr_array_remove (conn->pool->connections, d_conn);
dm_db_release_connection (d_conn);
}
}
}
pthread_mutex_unlock (&pool->lock);
return conn;
}
static void
dm_conn_pool_release_connection (DBConnection *conn, gboolean need_close)
{
if (!conn)
return;
if (conn->pool->max_connections == 0) {
dm_db_release_connection (conn);
return;
}
if (need_close) {
pthread_mutex_lock (&conn->pool->lock);
g_ptr_array_remove (conn->pool->connections, conn);
pthread_mutex_unlock (&conn->pool->lock);
dm_db_release_connection (conn);
return;
}
pthread_mutex_lock (&conn->pool->lock);
conn->is_available = TRUE;
pthread_mutex_unlock (&conn->pool->lock);
}
#define KEEPALIVE_INTERVAL 30
static void *
dm_conn_keepalive (void *arg)
{
DBConnPool *pool = arg;
DBConnection *conn = NULL;
DBConnection *d_conn = NULL;
char *sql = "SELECT 1;";
int rc = 0;
va_list args;
while (1) {
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) {
rc = db_ops.execute_sql (conn, sql, 0, args, NULL);
if (rc < 0) {
conn->is_available = FALSE;
conn->delete_pending = TRUE;
}
}
}
if (size > 0) {
int index;
for (index = size - 1; index >= 0; index--) {
d_conn = g_ptr_array_index (pool->connections, index);
if (d_conn->delete_pending) {
g_ptr_array_remove (pool->connections, d_conn);
dm_db_release_connection (d_conn);
}
}
}
pthread_mutex_unlock (&pool->lock);
sleep (KEEPALIVE_INTERVAL);
}
return NULL;
}
SeafDB *
seaf_db_new_dm (const char *user,
const char *passwd,
const char *db_name,
int max_connections)
{
SeafDB *db;
db = dm_db_new (user, passwd, db_name);
if (!db)
return NULL;
db->type = SEAF_DB_TYPE_DM;
db_ops.get_connection = dm_conn_pool_get_connection;
db_ops.release_connection = dm_conn_pool_release_connection;
db_ops.execute_sql_no_stmt = dm_db_execute_sql_no_stmt;
db_ops.execute_sql = dm_db_execute_sql;
db_ops.query_foreach_row = dm_db_query_foreach_row;
db_ops.row_get_column_count = dm_db_row_get_column_count;
db_ops.row_get_column_string = dm_db_row_get_column_string;
db_ops.row_get_column_int = dm_db_row_get_column_int;
db_ops.row_get_column_int64 = dm_db_row_get_column_int64;
db->pool = init_dm_conn_pool_common (max_connections);
pthread_t tid;
int ret = pthread_create (&tid, NULL, dm_conn_keepalive, db->pool);
if (ret != 0) {
seaf_warning ("Failed to create dm connection keepalive thread.\n");
return NULL;
}
pthread_detach (tid);
return db;
}
#endif
int
seaf_db_type (SeafDB *db)
{
@ -635,13 +846,21 @@ seaf_db_begin_transaction (SeafDB *db)
return trans;
}
if (db_ops.execute_sql_no_stmt (conn, "BEGIN", NULL) < 0) {
db_ops.release_connection (conn, TRUE);
return trans;
if (db->type == SEAF_DB_TYPE_DM) {
#ifdef HAVE_ODBC
DMDBConnection *dm_conn = (DMDBConnection *)conn;
SQLSetConnectAttr(dm_conn->db_conn, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_IS_INTEGER);
#endif
} else {
if (db_ops.execute_sql_no_stmt (conn, "BEGIN", NULL) < 0) {
db_ops.release_connection (conn, TRUE);
return trans;
}
}
trans = g_new0 (SeafDBTrans, 1);
trans->conn = conn;
trans->type = db->type;
return trans;
}
@ -649,6 +868,12 @@ seaf_db_begin_transaction (SeafDB *db)
void
seaf_db_trans_close (SeafDBTrans *trans)
{
if (trans->type == SEAF_DB_TYPE_DM) {
#ifdef HAVE_ODBC
DMDBConnection *dm_conn = (DMDBConnection *)trans->conn;
SQLSetConnectAttr(dm_conn->db_conn, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_IS_INTEGER);
#endif
}
db_ops.release_connection (trans->conn, trans->need_close);
g_free (trans);
}
@ -658,9 +883,21 @@ seaf_db_commit (SeafDBTrans *trans)
{
DBConnection *conn = trans->conn;
if (db_ops.execute_sql_no_stmt (conn, "COMMIT", NULL) < 0) {
trans->need_close = TRUE;
return -1;
if (trans->type == SEAF_DB_TYPE_DM) {
#ifdef HAVE_ODBC
DMDBConnection *dm_conn = (DMDBConnection *)conn;
SQLRETURN ret;
ret = SQLEndTran (SQL_HANDLE_DBC, dm_conn->db_conn, SQL_COMMIT);
if (!SUCCESS(ret)) {
trans->need_close = TRUE;
return -1;
}
#endif
} else {
if (db_ops.execute_sql_no_stmt (conn, "COMMIT", NULL) < 0) {
trans->need_close = TRUE;
return -1;
}
}
return 0;
@ -671,9 +908,21 @@ seaf_db_rollback (SeafDBTrans *trans)
{
DBConnection *conn = trans->conn;
if (db_ops.execute_sql_no_stmt (conn, "ROLLBACK", NULL) < 0) {
trans->need_close = TRUE;
return -1;
if (trans->type == SEAF_DB_TYPE_DM) {
#ifdef HAVE_ODBC
DMDBConnection *dm_conn = (DMDBConnection *)conn;
SQLRETURN ret;
ret = SQLEndTran (SQL_HANDLE_DBC, dm_conn->db_conn, SQL_ROLLBACK);
if (!SUCCESS(ret)) {
trans->need_close = TRUE;
return -1;
}
#endif
} else {
if (db_ops.execute_sql_no_stmt (conn, "ROLLBACK", NULL) < 0) {
trans->need_close = TRUE;
return -1;
}
}
return 0;
@ -1575,3 +1824,450 @@ sqlite_db_row_get_column_int64 (SeafDBRow *vrow, int idx)
return sqlite3_column_int64 (row->stmt, idx);
}
#ifdef HAVE_ODBC
/* DM DB */
static int
dm_get_error_state (SQLSMALLINT type, SQLHANDLE handle)
{
SQLINTEGER native_err;
unsigned char errmsg[255];
SQLGetDiagRec(type, handle, 1, NULL, &native_err, errmsg, sizeof(errmsg), NULL);
return native_err;
}
char *
dm_db_error (SQLSMALLINT type, SQLHANDLE handle)
{
SQLINTEGER native_err;
unsigned char errmsg[255];
SQLGetDiagRec(type, handle, 1, NULL, &native_err, errmsg, sizeof(errmsg), NULL);
return g_strdup(errmsg);
}
typedef struct DMDB {
struct SeafDB parent;
char *user;
char *password;
char *db_name;
HENV env;
} DMDB;
typedef struct DM_BIND {
void *buffer;
int buffer_length;
SQLLEN length;
} DM_BIND;
static SeafDB *
dm_db_new (const char *user,
const char *password,
const char *db_name)
{
DMDB *db = g_new0 (DMDB, 1);
db->user = g_strdup (user);
db->password = g_strdup (password);
db->db_name = g_strdup(db_name);
SQLAllocHandle(SQL_HANDLE_ENV, NULL, &db->env);
SQLSetEnvAttr(db->env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
return (SeafDB *)db;
}
typedef char my_bool;
static DBConnection *
dm_db_get_connection (SeafDB *vdb)
{
DMDB *db = (DMDB *)vdb;
HDBC db_conn;
DMDBConnection *conn = NULL;
SQLRETURN ret;
SQLAllocHandle(SQL_HANDLE_DBC, db->env, &db_conn);
ret = SQLConnect(db_conn, (SQLCHAR *)db->db_name, SQL_NTS, (SQLCHAR *)db->user, SQL_NTS, (SQLCHAR *)db->password, SQL_NTS);
if (!SUCCESS(ret)) {
char *errmsg = dm_db_error (SQL_HANDLE_DBC, db_conn);
seaf_warning ("Failed to connect dm server: %s\n", errmsg);
g_free (errmsg);
SQLFreeHandle(SQL_HANDLE_DBC, db_conn);
return NULL;
}
conn = g_new0 (DMDBConnection, 1);
conn->db_conn = db_conn;
return (DBConnection *)conn;
}
static void
dm_db_release_connection (DBConnection *vconn)
{
if (!vconn)
return;
DMDBConnection *conn = (DMDBConnection *)vconn;
SQLDisconnect(conn->db_conn);
SQLFreeHandle(SQL_HANDLE_DBC, conn->db_conn);
g_free (conn);
}
static int
dm_db_execute_sql_no_stmt (DBConnection *vconn, const char *sql, gboolean *retry)
{
DMDBConnection *conn = (DMDBConnection *)vconn;
HSTMT stmt;
SQLRETURN ret;
SQLAllocHandle(SQL_HANDLE_STMT, conn->db_conn, &stmt);
ret = SQLExecDirect(stmt, (SQLCHAR *)sql, SQL_NTS);
if (!SUCCESS(ret)) {
char *errmsg = dm_db_error (SQL_HANDLE_STMT, stmt);
seaf_warning ("Failed to execute sql %s: %s\n", sql, errmsg);
g_free (errmsg);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
return -1;
}
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
return 0;
}
static HSTMT
_prepare_stmt_dm (HDBC db, const char *sql, gboolean *retry)
{
HSTMT stmt;
SQLRETURN ret;
SQLAllocHandle(SQL_HANDLE_STMT, db, &stmt);
ret = SQLPrepare(stmt, sql, SQL_NTS);
if (!SUCCESS(ret)) {
char * errmsg = dm_db_error (SQL_HANDLE_STMT, stmt);
seaf_warning ("Failed to prepare sql %s: %s\n", sql, errmsg);
g_free (errmsg);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
return NULL;
}
return stmt;
}
static int
_bind_params_dm (HSTMT stmt, DM_BIND *params, int n, va_list args)
{
int i;
const char *type;
SQLRETURN ret;
char *errmsg = NULL;
for (i = 0; i < n; ++i) {
type = va_arg (args, const char *);
if (strcmp(type, "int") == 0) {
int x = va_arg (args, int);
int *pval = g_new (int, 1);
*pval = x;
params[i].buffer = pval;
ret = SQLBindParameter(stmt, i+1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, sizeof(x), 0, params[i].buffer, sizeof(x), NULL);
if (!SUCCESS(ret)) {
errmsg = dm_db_error (SQL_HANDLE_STMT, stmt);
seaf_warning ("Failed to bid params: %s\n", errmsg);
g_free (errmsg);
return -1;
}
} else if (strcmp (type, "int64") == 0) {
gint64 x = va_arg (args, gint64);
gint64 *pval = g_new (gint64, 1);
*pval = x;
params[i].buffer = pval;
ret = SQLBindParameter(stmt, i+1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, sizeof(x), 0, params[i].buffer, sizeof(x), NULL);
if (!SUCCESS(ret)) {
errmsg = dm_db_error (SQL_HANDLE_STMT, stmt);
seaf_warning ("Failed to bid params: %s\n", errmsg);
g_free (errmsg);
return -1;
}
} else if (strcmp (type, "string") == 0) {
const char *s = va_arg (args, const char *);
int len = 0;
if (s) {
len = strlen(s);
}
params[i].buffer = g_strdup(s);
ret = SQLBindParameter(stmt, i+1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, len, 0, params[i].buffer, len, NULL);
if (!SUCCESS(ret)) {
errmsg = dm_db_error (SQL_HANDLE_STMT, stmt);
seaf_warning ("Failed to bid params: %s\n", errmsg);
g_free (errmsg);
return -1;
}
} else {
seaf_warning ("BUG: invalid prep stmt parameter type %s.\n", type);
g_return_val_if_reached (-1);
}
}
return 0;
}
static int
dm_db_execute_sql (DBConnection *vconn, const char *sql, int n, va_list args, gboolean *retry)
{
DMDBConnection *conn = (DMDBConnection *)vconn;
HDBC db = conn->db_conn;
HSTMT stmt = NULL;
DM_BIND *params = NULL;
SQLRETURN rc;
int ret = 0;
stmt = _prepare_stmt_dm (db, sql, retry);
if (!stmt) {
return -1;
}
if (n > 0) {
params = g_new0 (DM_BIND, n);
if (_bind_params_dm(stmt, params, n, args) < 0) {
seaf_warning ("Failed to bind parameters for %s.\n", sql);
ret = -1;
goto out;
}
}
rc = SQLExecute (stmt);
if (!SUCCESS(rc)) {
char *errmsg = dm_db_error (SQL_HANDLE_STMT, stmt);
seaf_warning ("Failed to execute sql %s: %s\n", sql, errmsg);
g_free (errmsg);
ret = -1;
goto out;
}
out:
if (stmt) {
SQLCloseCursor(stmt);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
}
if (params) {
int i;
for (i = 0; i < n; ++i) {
g_free (params[i].buffer);
}
g_free (params);
}
return ret;
}
typedef struct DMDBRow {
SeafDBRow parent;
int column_count;
HSTMT stmt;
DM_BIND *results;
gboolean over_buffer;
} DMDBRow;
#define DEFAULT_DM_COLUMN_SIZE 1024
static int
dm_db_query_foreach_row (DBConnection *vconn, const char *sql,
SeafDBRowFunc callback, void *data,
int n, va_list args, gboolean *retry)
{
DMDBConnection *conn = (DMDBConnection *)vconn;
HDBC db = conn->db_conn;
HSTMT stmt = NULL;
DM_BIND *params = NULL;
DMDBRow row;
SQLRETURN rc;
short cols;
int nrows = 0;
int i;
memset (&row, 0, sizeof(row));
stmt = _prepare_stmt_dm (db, sql, retry);
if (!stmt) {
return -1;
}
if (n > 0) {
params = g_new0 (DM_BIND, n);
if (_bind_params_dm (stmt, params, n, args) < 0) {
nrows = -1;
goto out;
}
}
rc = SQLExecute (stmt);
if (!SUCCESS(rc)) {
char *errmsg = dm_db_error (SQL_HANDLE_STMT, stmt);
seaf_warning ("Failed to execute sql %s: error: %s\n", sql, errmsg);
g_free (errmsg);
nrows = -1;
goto out;
}
SQLNumResultCols(stmt, &cols);
row.column_count = cols;
row.stmt = stmt;
row.results = g_new0 (DM_BIND, row.column_count);
for (i = 0; i < row.column_count; ++i) {
row.results[i].buffer = g_new0(char, DEFAULT_DM_COLUMN_SIZE + 1);
/* Ask DM to convert fields to string, to avoid the trouble of
* checking field types.
*/
row.results[i].buffer_length = DEFAULT_DM_COLUMN_SIZE;
row.results[i].length = 0;
SQLBindCol(stmt, i+1, SQL_C_CHAR, row.results[i].buffer, row.results[i].buffer_length, &row.results[i].length);
}
gboolean next_row = TRUE;
while (1) {
rc = SQLFetch(stmt);
if (!SUCCESS(rc)) {
if (rc != SQL_ERROR || dm_get_error_state(SQL_HANDLE_STMT, stmt) != BUFFER_NOT_ENOUGH) {
char *err_msg = dm_db_error (SQL_HANDLE_STMT, stmt);
seaf_warning ("Failed to fetch result for sql %s: %s\n",
sql, err_msg);
g_free (err_msg);
nrows = -1;
goto out;
} else {
row.over_buffer = TRUE;
}
} else {
row.over_buffer = FALSE;
}
if (rc == SQL_NO_DATA_FOUND || rc == SQL_NO_DATA)
break;
++nrows;
if (callback)
next_row = callback ((SeafDBRow *)&row, data);
if (!next_row)
break;
}
out:
if (stmt) {
SQLCloseCursor(stmt);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
}
if (params) {
int i;
for (i = 0; i < n; ++i) {
g_free (params[i].buffer);
}
g_free (params);
}
if (row.results) {
for (i = 0; i < row.column_count; ++i) {
g_free (row.results[i].buffer);
}
g_free (row.results);
}
return nrows;
}
static int
dm_db_row_get_column_count (SeafDBRow *vrow)
{
DMDBRow *row = (DMDBRow *)vrow;
return row->column_count;
}
static const char *
dm_db_row_get_column_string (SeafDBRow *vrow, int i)
{
DMDBRow *row = (DMDBRow *)vrow;
if (row->results[i].length == -1) {
return NULL;
}
SQLRETURN rc;
char *ret = NULL;
int j = 1;
/* If column size is larger then allocated buffer size, re-allocate a new buffer
* and fetch the column directly.
*/
alloc_buffer:
if (row->results[i].length == 0 && row->over_buffer) {
g_free (row->results[i].buffer);
row->results[i].buffer = g_new0 (char, 2*j * DEFAULT_DM_COLUMN_SIZE + 1);
row->results[i].buffer_length = 2*j * DEFAULT_DM_COLUMN_SIZE;
rc = SQLGetData(row->stmt, i+1, SQL_C_CHAR, row->results[i].buffer, row->results[i].buffer_length, &row->results[i].length);
if (SUCCESS(rc)) {
ret = row->results[i].buffer;
} else {
if (dm_get_error_state(SQL_HANDLE_STMT, row->stmt) != BUFFER_NOT_ENOUGH) {
return NULL;
} else {
j++;
goto alloc_buffer;
}
}
} else {
ret = row->results[i].buffer;
}
ret[row->results[i].length] = 0;
return ret;
}
static int
dm_db_row_get_column_int (SeafDBRow *vrow, int idx)
{
const char *str;
char *e;
int ret;
str = dm_db_row_get_column_string (vrow, idx);
if (!str) {
return 0;
}
errno = 0;
ret = strtol (str, &e, 10);
if (errno || (e == str)) {
seaf_warning ("Number conversion failed.\n");
return -1;
}
return ret;
}
static gint64
dm_db_row_get_column_int64 (SeafDBRow *vrow, int idx)
{
const char *str;
char *e;
gint64 ret;
str = dm_db_row_get_column_string (vrow, idx);
if (!str) {
return 0;
}
errno = 0;
ret = strtoll (str, &e, 10);
if (errno || (e == str)) {
seaf_warning ("Number conversion failed.\n");
return -1;
}
return ret;
}
#endif /* HAVE_ODBC */

View File

@ -5,6 +5,7 @@ enum {
SEAF_DB_TYPE_SQLITE,
SEAF_DB_TYPE_MYSQL,
SEAF_DB_TYPE_PGSQL,
SEAF_DB_TYPE_DM,
};
typedef struct SeafDB SeafDB;
@ -44,6 +45,12 @@ seaf_db_new_pgsql (const char *host,
SeafDB *
seaf_db_new_sqlite (const char *db_path, int max_connections);
SeafDB *
seaf_db_new_dm (const char *user,
const char *passwd,
const char *db_name,
int max_connections);
int
seaf_db_type (SeafDB *db);

View File

@ -145,6 +145,58 @@ mysql_db_start (SeafileSession *session)
#endif
#ifdef HAVE_ODBC
static int
dm_db_start (SeafileSession *session)
{
char *user, *passwd, *db;
int max_connections = 0;
GError *error = NULL;
user = seaf_key_file_get_string (session->config, "database", "user", &error);
if (!user) {
seaf_warning ("DB user not set in config.\n");
return -1;
}
passwd = seaf_key_file_get_string (session->config, "database", "password", &error);
if (!passwd) {
seaf_warning ("DB passwd not set in config.\n");
return -1;
}
db = seaf_key_file_get_string (session->config, "database", "db_name", &error);
if (!db) {
seaf_warning ("DB name not set in config.\n");
return -1;
}
if (error)
g_clear_error (&error);
max_connections = g_key_file_get_integer (session->config,
"database", "max_connections",
&error);
if (error || max_connections < 0) {
g_clear_error (&error);
max_connections = DEFAULT_MAX_CONNECTIONS;
}
session->db = seaf_db_new_dm (user, passwd, db, max_connections);
if (!session->db) {
seaf_warning ("Failed to start dm db.\n");
return -1;
}
g_free (user);
g_free (passwd);
g_free (db);
return 0;
}
#endif
#ifdef HAVE_POSTGRESQL
static int
@ -223,6 +275,11 @@ load_database_config (SeafileSession *session)
ret = mysql_db_start (session);
}
#endif
#ifdef HAVE_ODBC
else if (strcasecmp (type, "dm") == 0) {
ret = dm_db_start (session);
}
#endif
#ifdef HAVE_POSTGRESQL
else if (strcasecmp (type, "pgsql") == 0) {
ret = pgsql_db_start (session);
@ -341,6 +398,56 @@ ccnet_init_mysql_database (SeafileSession *session)
#endif
#ifdef HAVE_ODBC
static int
ccnet_init_dm_database (SeafileSession *session)
{
char *user, *passwd, *db;
int max_connections = 0;
user = ccnet_key_file_get_string (session->ccnet_config, "Database", "USER");
passwd = ccnet_key_file_get_string (session->ccnet_config, "Database", "PASSWD");
db = ccnet_key_file_get_string (session->ccnet_config, "Database", "DB");
if (!user) {
seaf_warning ("DB user not set in config.\n");
return -1;
}
if (!passwd) {
seaf_warning ("DB passwd not set in config.\n");
return -1;
}
if (!db) {
seaf_warning ("DB name not set in config.\n");
return -1;
}
GError *error = NULL;
max_connections = g_key_file_get_integer (session->ccnet_config,
"Database", "MAX_CONNECTIONS",
&error);
if (error || max_connections < 0) {
max_connections = DEFAULT_MAX_CONNECTIONS;
g_clear_error (&error);
}
session->ccnet_db = seaf_db_new_dm (user, passwd, db, max_connections);
if (!session->ccnet_db) {
seaf_warning ("Failed to open ccnet database.\n");
return -1;
}
g_free (user);
g_free (passwd);
g_free (db);
return 0;
}
#endif
int
load_ccnet_database_config (SeafileSession *session)
{
@ -359,6 +466,11 @@ load_ccnet_database_config (SeafileSession *session)
ret = ccnet_init_mysql_database (session);
}
#endif
#ifdef HAVE_ODBC
else if (strcasecmp (engine, "dm") == 0) {
ret = ccnet_init_dm_database (session);
}
#endif
#if 0
else if (strncasecmp (engine, DB_PGSQL, sizeof(DB_PGSQL)) == 0) {
ccnet_debug ("Use database PostgreSQL\n");

View File

@ -707,6 +707,67 @@ static int check_db_table (SeafDB *db)
// 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)";
if (seaf_db_query (db, sql) < 0)
return -1;
} else if (db_type == SEAF_DB_TYPE_DM) {
sql = "CREATE TABLE IF NOT EXISTS EmailUser ("
"id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,"
"email VARCHAR(255), passwd VARCHAR(256), is_staff INTEGER NOT NULL, "
"is_active INTEGER NOT NULL, ctime BIGINT, "
"reference_id VARCHAR(255))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS email_index on EmailUser (email)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS reference_id_index on EmailUser (reference_id)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS Binding (email VARCHAR(255), peer_id VARCHAR(41))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS email_index on Binding (email)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS peer_index on Binding (peer_id)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS UserRole (email VARCHAR(255), role VARCHAR(255))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS userrole_email_index on UserRole (email)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS userrole_userrole_index on UserRole (email, role)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS LDAPUsers ("
"id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, "
"email VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, "
"is_staff INTEGER NOT NULL, is_active INTEGER NOT NULL, extra_attrs TEXT, "
"reference_id VARCHAR(255))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS ldapusers_email_index on LDAPUsers(email)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS ldapusers_reference_id_index on LDAPUsers(reference_id)";
if (seaf_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)";
if (seaf_db_query (db, sql) < 0)
@ -754,6 +815,7 @@ open_db (CcnetUserManager *manager)
db = open_sqlite_db (manager);
break;
case SEAF_DB_TYPE_PGSQL:
case SEAF_DB_TYPE_DM:
case SEAF_DB_TYPE_MYSQL:
db = manager->session->ccnet_db;
break;

View File

@ -86,6 +86,11 @@ AC_ARG_ENABLE(python,
[compile_python=$enableval],
[compile_python=yes])
AC_ARG_ENABLE(odbc,
AC_HELP_STRING([--enable-odbc],[build seafile with odbc]),
[compile_odbc=$enableval],
[compile_odbc=yes])
AC_ARG_WITH(mysql,
AC_HELP_STRING([--with-mysql],[path to mysql_config]),
[MYSQL_CONFIG=$with_mysql],
@ -287,6 +292,14 @@ if test "${compile_fuse}" = "yes"; then
AC_SUBST(FUSE_LIBS)
fi
if test "${compile_odbc}" = "yes"; then
PKG_CHECK_MODULES(ODBC, [odbc])
AC_SUBST(ODBC_FLAGS)
AC_SUBST(ODBC_LIBS)
AC_DEFINE([DM64], [1], [Define to 1 if dm support is enabled])
AC_DEFINE([HAVE_ODBC], [1], [Define to 1 if dm support is enabled])
fi
dnl check libarchive
LIBARCHIVE_REQUIRED=2.8.5
PKG_CHECK_MODULES(LIBARCHIVE, [libarchive >= $LIBARCHIVE_REQUIRED])

View File

@ -42,5 +42,5 @@ seaf_fuse_LDADD = @GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ \
-lsqlite3 @LIBEVENT_LIBS@ \
$(top_builddir)/common/cdc/libcdc.la \
@SEARPC_LIBS@ @JANSSON_LIBS@ @FUSE_LIBS@ @ZLIB_LIBS@ \
@LDAP_LIBS@ @MYSQL_LIBS@ -lsqlite3
@LDAP_LIBS@ @MYSQL_LIBS@ -lsqlite3 @ODBC_LIBS@

View File

@ -86,4 +86,4 @@ seaf_server_LDADD = $(top_builddir)/lib/libseafile_common.la \
@SEARPC_LIBS@ @JANSSON_LIBS@ ${LIB_WS32} @ZLIB_LIBS@ \
@LIBARCHIVE_LIBS@ @LIB_ICONV@ \
@LDAP_LIBS@ @MYSQL_LIBS@ -lsqlite3 \
@CURL_LIBS@ @JWT_LIBS@
@CURL_LIBS@ @JWT_LIBS@ @ODBC_LIBS@

View File

@ -48,7 +48,7 @@ seafserv_gc_LDADD = $(top_builddir)/common/cdc/libcdc.la \
$(top_builddir)/lib/libseafile_common.la \
@GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 @LIBEVENT_LIBS@ \
@SEARPC_LIBS@ @JANSSON_LIBS@ ${LIB_WS32} @ZLIB_LIBS@ \
@MYSQL_LIBS@ -lsqlite3
@MYSQL_LIBS@ -lsqlite3 @ODBC_LIBS@
seaf_fsck_SOURCES = \
seaf-fsck.c \
@ -59,4 +59,4 @@ seaf_fsck_LDADD = $(top_builddir)/common/cdc/libcdc.la \
$(top_builddir)/lib/libseafile_common.la \
@GLIB2_LIBS@ @GOBJECT_LIBS@ @SSL_LIBS@ @LIB_RT@ @LIB_UUID@ -lsqlite3 @LIBEVENT_LIBS@ \
@SEARPC_LIBS@ @JANSSON_LIBS@ ${LIB_WS32} @ZLIB_LIBS@ \
@MYSQL_LIBS@ -lsqlite3
@MYSQL_LIBS@ -lsqlite3 @ODBC_LIBS@

View File

@ -427,7 +427,7 @@ seaf_repo_manager_set_repo_history_limit (SeafRepoManager *mgr,
return 0;
}
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
gboolean err;
snprintf(sql, sizeof(sql),
"SELECT repo_id FROM RepoHistoryLimit "
@ -512,7 +512,7 @@ seaf_repo_manager_set_repo_valid_since (SeafRepoManager *mgr,
SeafDB *db = mgr->seaf->db;
char sql[256];
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
gboolean err;
snprintf(sql, sizeof(sql),
"SELECT repo_id FROM RepoValidSince WHERE "

View File

@ -154,6 +154,28 @@ seaf_quota_manager_init (SeafQuotaManager *mgr)
if (seaf_db_query (db, sql) < 0)
return -1;
break;
case SEAF_DB_TYPE_DM:
sql = "CREATE TABLE IF NOT EXISTS UserQuota (\"user\" VARCHAR(255) PRIMARY KEY,"
"quota BIGINT)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS UserShareQuota (\"user\" VARCHAR(255) PRIMARY KEY,"
"quota BIGINT)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS OrgQuota (org_id INTEGER PRIMARY KEY,"
"quota BIGINT)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS OrgUserQuota (org_id INTEGER,"
"\"user\" VARCHAR(255), quota BIGINT, PRIMARY KEY (org_id, \"user\"))";
if (seaf_db_query (db, sql) < 0)
return -1;
break;
}
@ -166,7 +188,7 @@ seaf_quota_manager_set_user_quota (SeafQuotaManager *mgr,
gint64 quota)
{
SeafDB *db = mgr->session->db;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
gboolean exists, err;
int rc;
@ -203,7 +225,7 @@ seaf_quota_manager_get_user_quota (SeafQuotaManager *mgr,
char *sql;
gint64 quota;
if (seaf_db_type(mgr->session->db) != SEAF_DB_TYPE_PGSQL)
if (seaf_db_type(mgr->session->db) != SEAF_DB_TYPE_PGSQL && seaf_db_type(mgr->session->db) != SEAF_DB_TYPE_DM)
sql = "SELECT quota FROM UserQuota WHERE user=?";
else
sql = "SELECT quota FROM UserQuota WHERE \"user\"=?";
@ -223,7 +245,7 @@ seaf_quota_manager_set_org_quota (SeafQuotaManager *mgr,
{
SeafDB *db = mgr->session->db;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
gboolean exists, err;
int rc;
@ -274,7 +296,7 @@ seaf_quota_manager_set_org_user_quota (SeafQuotaManager *mgr,
SeafDB *db = mgr->session->db;
int rc;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
gboolean exists, err;
exists = seaf_db_statement_exists (db,
@ -313,7 +335,7 @@ seaf_quota_manager_get_org_user_quota (SeafQuotaManager *mgr,
char *sql;
gint64 quota;
if (seaf_db_type(mgr->session->db) != SEAF_DB_TYPE_PGSQL)
if (seaf_db_type(mgr->session->db) != SEAF_DB_TYPE_PGSQL && seaf_db_type(mgr->session->db) != SEAF_DB_TYPE_DM)
sql = "SELECT quota FROM OrgUserQuota WHERE org_id=? AND user=?";
else
sql = "SELECT quota FROM OrgUserQuota WHERE org_id=? AND \"user\"=?";

View File

@ -380,7 +380,7 @@ seaf_repo_manager_add_repo (SeafRepoManager *manager,
static int
add_deleted_repo_record (SeafRepoManager *mgr, const char *repo_id)
{
if (seaf_db_type(seaf->db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(seaf->db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(seaf->db) == SEAF_DB_TYPE_DM) {
gboolean exists, err;
exists = seaf_db_statement_exists (seaf->db,
@ -803,7 +803,7 @@ seaf_repo_manager_repo_exists (SeafRepoManager *manager, const gchar *id)
static int
save_branch_repo_map (SeafRepoManager *manager, SeafBranch *branch)
{
if (seaf_db_type(seaf->db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(seaf->db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(seaf->db) == SEAF_DB_TYPE_DM) {
gboolean exists, err;
int rc;
@ -1240,6 +1240,160 @@ create_tables_sqlite (SeafRepoManager *mgr)
return 0;
}
static int
create_tables_dm (SeafRepoManager *mgr)
{
SeafDB *db = mgr->seaf->db;
char *sql;
sql = "CREATE TABLE IF NOT EXISTS Repo (repo_id VARCHAR(37) PRIMARY KEY)";
if (seaf_db_query (db, sql) < 0)
return -1;
/* Owner */
sql = "CREATE TABLE IF NOT EXISTS RepoOwner ("
"repo_id VARCHAR(37) PRIMARY KEY, "
"owner_id VARCHAR(255))";
if (seaf_db_query (db, sql) < 0)
return -1;
/* Group repo */
sql = "CREATE TABLE IF NOT EXISTS RepoGroup (repo_id VARCHAR(37), "
"group_id INTEGER, user_name VARCHAR(255), permission VARCHAR(15))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS groupid_repoid_indx on "
"RepoGroup (group_id, repo_id)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS repogroup_repoid_index on "
"RepoGroup (repo_id)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS repogroup_username_indx on "
"RepoGroup (user_name)";
if (seaf_db_query (db, sql) < 0)
return -1;
/* Public repo */
sql = "CREATE TABLE IF NOT EXISTS InnerPubRepo ("
"repo_id VARCHAR(37) PRIMARY KEY,"
"permission VARCHAR(15))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS RepoUserToken ("
"repo_id VARCHAR(37), "
"email VARCHAR(255), "
"token VARCHAR(41))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE UNIQUE INDEX IF NOT EXISTS repo_token_indx on "
"RepoUserToken (repo_id, token)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS repo_token_email_indx on "
"RepoUserToken (email)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS RepoTokenPeerInfo ("
"token VARCHAR(41) PRIMARY KEY, "
"peer_id VARCHAR(41), "
"peer_ip VARCHAR(50), "
"peer_name VARCHAR(255), "
"sync_time BIGINT, "
"client_ver VARCHAR(20))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS RepoHead ("
"repo_id VARCHAR(37) PRIMARY KEY, branch_name VARCHAR(10))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS RepoSize ("
"repo_id VARCHAR(37) PRIMARY KEY,"
"size BIGINT,"
"head_id VARCHAR(41))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS RepoHistoryLimit ("
"repo_id VARCHAR(37) PRIMARY KEY, days INTEGER)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS RepoValidSince ("
"repo_id VARCHAR(37) PRIMARY KEY, timestamp BIGINT)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS WebAP (repo_id VARCHAR(37) PRIMARY KEY, "
"access_property VARCHAR(10))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS VirtualRepo (repo_id VARCHAR(36) PRIMARY KEY,"
"origin_repo VARCHAR(36), path TEXT, base_commit VARCHAR(40))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS virtualrepo_origin_repo_idx "
"ON VirtualRepo (origin_repo)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS GarbageRepos (repo_id VARCHAR(36) PRIMARY KEY)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS RepoTrash (repo_id VARCHAR(36) PRIMARY KEY,"
"repo_name VARCHAR(255), head_id VARCHAR(40), owner_id VARCHAR(255), size BIGINT,"
"org_id INTEGER, del_time BIGINT)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS repotrash_owner_id_idx ON RepoTrash(owner_id)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS repotrash_org_id_idx ON RepoTrash(org_id)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS RepoFileCount ("
"repo_id VARCHAR(36) PRIMARY KEY,"
"file_count BIGINT)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS RepoInfo (repo_id VARCHAR(36) PRIMARY KEY, "
"name VARCHAR(255) NOT NULL, update_time INTEGER, version INTEGER, "
"is_encrypted INTEGER, last_modifier VARCHAR(255), status INTEGER DEFAULT 0)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE TABLE IF NOT EXISTS WebUploadTempFiles (repo_id VARCHAR(40) NOT NULL, "
"file_path TEXT NOT NULL, tmp_file_path TEXT NOT NULL)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS webuploadtempfiles_repo_id_idx ON WebUploadTempFiles(repo_id)";
if (seaf_db_query (db, sql) < 0)
return -1;
return 0;
}
/* static int */
/* create_tables_pgsql (SeafRepoManager *mgr) */
/* { */
@ -1402,6 +1556,8 @@ create_db_tables_if_not_exist (SeafRepoManager *mgr)
return create_tables_mysql (mgr);
else if (db_type == SEAF_DB_TYPE_SQLITE)
return create_tables_sqlite (mgr);
else if (db_type == SEAF_DB_TYPE_DM)
return create_tables_dm (mgr);
/* else if (db_type == SEAF_DB_TYPE_PGSQL) */
/* return create_tables_pgsql (mgr); */
@ -1745,7 +1901,7 @@ seaf_repo_manager_delete_repo_tokens_by_peer_id (SeafRepoManager *mgr,
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_INTERNAL, "DB error");
goto out;
}
} else if (db_type == SEAF_DB_TYPE_SQLITE) {
} else if (db_type == SEAF_DB_TYPE_SQLITE || db_type == SEAF_DB_TYPE_DM) {
GString *sql = g_string_new ("");
GList *iter;
int i = 0;
@ -1922,7 +2078,7 @@ seaf_repo_manager_set_repo_history_limit (SeafRepoManager *mgr,
return 0;
}
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
gboolean exists, err;
int rc;
@ -2004,7 +2160,7 @@ seaf_repo_manager_set_repo_valid_since (SeafRepoManager *mgr,
{
SeafDB *db = mgr->seaf->db;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
gboolean exists, err;
int rc;
@ -2086,7 +2242,7 @@ seaf_repo_manager_set_repo_owner (SeafRepoManager *mgr,
if (g_strcmp0 (orig_owner, email) == 0)
goto out;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
gboolean err;
snprintf(sql, sizeof(sql),
"SELECT repo_id FROM RepoOwner WHERE repo_id=?");
@ -2463,6 +2619,21 @@ seaf_repo_manager_search_repos_by_name (SeafRepoManager *mgr, const char *name)
char *db_patt = g_strdup_printf ("%%%s%%", name);
switch (seaf_db_type(seaf->db)) {
case SEAF_DB_TYPE_DM:
g_free (db_patt);
db_patt = g_strdup(name);
sql = "SELECT i.repo_id, s.size, b.commit_id, i.name, i.update_time, "
"i.version, i.is_encrypted, i.last_modifier, i.status, fc.file_count FROM "
"RepoInfo i LEFT JOIN RepoSize s ON i.repo_id = s.repo_id "
"LEFT JOIN Branch b ON i.repo_id = b.repo_id "
"LEFT JOIN RepoFileCount fc ON i.repo_id = fc.repo_id "
"LEFT JOIN Repo r ON i.repo_id = r.repo_id "
"LEFT JOIN VirtualRepo v ON i.repo_id = v.repo_id "
"WHERE REGEXP_LIKE(i.name, ?, 'i') AND "
"r.repo_id IS NOT NULL AND "
"v.repo_id IS NULL "
"ORDER BY i.update_time DESC, i.repo_id";
break;
case SEAF_DB_TYPE_MYSQL:
sql = "SELECT i.repo_id, s.size, b.commit_id, i.name, i.update_time, "
"i.version, i.is_encrypted, i.last_modifier, i.status, fc.file_count FROM "
@ -2540,6 +2711,7 @@ seaf_repo_manager_get_repo_list (SeafRepoManager *mgr, int start, int limit, con
if (start == -1 && limit == -1) {
switch (seaf_db_type(mgr->seaf->db)) {
case SEAF_DB_TYPE_DM:
case SEAF_DB_TYPE_MYSQL:
g_string_append (sql, "SELECT i.repo_id, s.size, b.commit_id, i.name, i.update_time, "
"i.version, i.is_encrypted, i.last_modifier, i.status, f.file_count FROM "
@ -2586,6 +2758,7 @@ seaf_repo_manager_get_repo_list (SeafRepoManager *mgr, int start, int limit, con
0);
} else {
switch (seaf_db_type(mgr->seaf->db)) {
case SEAF_DB_TYPE_DM:
case SEAF_DB_TYPE_MYSQL:
g_string_append (sql, "SELECT i.repo_id, s.size, b.commit_id, i.name, i.update_time, "
"i.version, i.is_encrypted, i.last_modifier, i.status, f.file_count FROM "
@ -3518,7 +3691,7 @@ seaf_repo_manager_set_inner_pub_repo (SeafRepoManager *mgr,
SeafDB *db = mgr->seaf->db;
char sql[256];
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL || seaf_db_type(db) == SEAF_DB_TYPE_DM) {
gboolean err;
snprintf(sql, sizeof(sql),
"SELECT repo_id FROM InnerPubRepo WHERE repo_id=?");

View File

@ -470,7 +470,7 @@ schedule_create_system_default_repo (SeafileSession *session)
int db_type = seaf_db_type (session->db);
char *sql;
if (db_type == SEAF_DB_TYPE_MYSQL)
if (db_type == SEAF_DB_TYPE_MYSQL || db_type == SEAF_DB_TYPE_DM)
sql = "CREATE TABLE IF NOT EXISTS SystemInfo "
"(id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
"info_key VARCHAR(256), info_value VARCHAR(1024))";

View File

@ -56,6 +56,21 @@ seaf_share_manager_start (SeafShareManager *mgr)
sql = "CREATE INDEX IF NOT EXISTS ToEmailIndex on SharedRepo (to_email)";
if (seaf_db_query (db, sql) < 0)
return -1;
} else if (db_type == SEAF_DB_TYPE_DM) {
sql = "CREATE TABLE IF NOT EXISTS SharedRepo "
"(repo_id VARCHAR(37) , from_email VARCHAR(255), to_email VARCHAR(255), "
"permission VARCHAR(15))";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS RepoIdIndex on SharedRepo (repo_id)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS FromEmailIndex on SharedRepo (from_email)";
if (seaf_db_query (db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS ToEmailIndex on SharedRepo (to_email)";
if (seaf_db_query (db, sql) < 0)
return -1;
}
/* else if (db_type == SEAF_DB_TYPE_PGSQL) { */
/* sql = "CREATE TABLE IF NOT EXISTS SharedRepo " */

View File

@ -256,6 +256,7 @@ get_old_repo_info_from_db (SeafDB *db, const char *repo_id, gboolean *is_db_err)
switch (seaf_db_type (db)) {
case SEAF_DB_TYPE_MYSQL:
case SEAF_DB_TYPE_PGSQL:
case SEAF_DB_TYPE_DM:
sql = "select s.head_id,s.size,f.file_count FROM "
"RepoSize s LEFT JOIN RepoFileCount f ON "
"s.repo_id=f.repo_id WHERE "

View File

@ -123,3 +123,6 @@ def test_repo_manipulation():
api.remove_repo(t_repo_id)
t_repo = api.get_repo(t_repo_id)
assert t_repo == None
api.remove_repo(t_enc_repo_id)
t_enc_repo = api.get_repo(t_enc_repo_id)
assert t_enc_repo == None