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:
parent
7bb8866889
commit
e5e577b282
@ -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;
|
||||
|
@ -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, "
|
||||
|
@ -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;
|
||||
|
714
common/seaf-db.c
714
common/seaf-db.c
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
13
configure.ac
13
configure.ac
@ -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])
|
||||
|
@ -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@
|
||||
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
@ -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 "
|
||||
|
@ -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\"=?";
|
||||
|
@ -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=?");
|
||||
|
@ -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))";
|
||||
|
@ -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 " */
|
||||
|
@ -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 "
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user