mirror of
https://github.com/ONLYOFFICE/server.git
synced 2026-04-07 14:04:35 +08:00
add postgresql support
This commit is contained in:
@ -63,16 +63,17 @@
|
|||||||
"limits_image_types_copy": "jpg;png;gif;bmp;emf;wmf;svg;txt;bin"
|
"limits_image_types_copy": "jpg;png;gif;bmp;emf;wmf;svg;txt;bin"
|
||||||
},
|
},
|
||||||
"sql": {
|
"sql": {
|
||||||
"type": "mysql",
|
"type": "postgres",
|
||||||
"tableChanges": "doc_changes",
|
"tableChanges": "doc_changes",
|
||||||
"tableCallbacks": "doc_callbacks",
|
"tableCallbacks": "doc_callbacks",
|
||||||
"tableResult": "task_result",
|
"tableResult": "task_result",
|
||||||
"dbHost": "localhost",
|
"dbHost": "localhost",
|
||||||
"dbPort": 3306,
|
"dbPort": 5432,
|
||||||
"dbName": "onlyoffice",
|
"dbName": "onlyoffice",
|
||||||
"dbUser": "root",
|
"dbUser": "onlyoffice",
|
||||||
"dbPass": "onlyoffice",
|
"dbPass": "onlyoffice",
|
||||||
"charset": "utf8",
|
"charset": "utf8",
|
||||||
|
"connectionlimit": 10,
|
||||||
"max_allowed_packet": 1048575
|
"max_allowed_packet": 1048575
|
||||||
},
|
},
|
||||||
"redis": {
|
"redis": {
|
||||||
|
|||||||
@ -32,6 +32,12 @@
|
|||||||
},
|
},
|
||||||
"utils": {
|
"utils": {
|
||||||
"utils_common_fontdir": "/Library/Fonts"
|
"utils_common_fontdir": "/Library/Fonts"
|
||||||
|
},
|
||||||
|
"sql": {
|
||||||
|
"type": "mysql",
|
||||||
|
"dbPort": 3306,
|
||||||
|
"dbUser": "root",
|
||||||
|
"dbPass": "onlyoffice"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -32,6 +32,12 @@
|
|||||||
},
|
},
|
||||||
"utils": {
|
"utils": {
|
||||||
"utils_common_fontdir": "C:\\Windows\\Fonts"
|
"utils_common_fontdir": "C:\\Windows\\Fonts"
|
||||||
|
},
|
||||||
|
"sql": {
|
||||||
|
"type": "mysql",
|
||||||
|
"dbPort": 3306,
|
||||||
|
"dbUser": "root",
|
||||||
|
"dbPass": "onlyoffice"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -16,7 +16,8 @@
|
|||||||
"mime": "^1.3.4",
|
"mime": "^1.3.4",
|
||||||
"multiparty": "^4.1.2",
|
"multiparty": "^4.1.2",
|
||||||
"mysql": "^2.11.1",
|
"mysql": "^2.11.1",
|
||||||
"pg": "^6.0.3",
|
"pg": "^6.1.0",
|
||||||
|
"pg-escape": "^0.2.0",
|
||||||
"redis": "^2.6.2",
|
"redis": "^2.6.2",
|
||||||
"sockjs": "http://d2ettrnqo7v976.cloudfront.net/npm/sockjs-node/v0.3.15.14.tar.gz",
|
"sockjs": "http://d2ettrnqo7v976.cloudfront.net/npm/sockjs-node/v0.3.15.14.tar.gz",
|
||||||
"underscore": "^1.8.3"
|
"underscore": "^1.8.3"
|
||||||
|
|||||||
@ -81,37 +81,9 @@ exports.loadTable = function (tableId, callbackFunction) {
|
|||||||
var sqlCommand = "SELECT * FROM " + table + ";";
|
var sqlCommand = "SELECT * FROM " + table + ";";
|
||||||
baseConnector.sqlQuery(sqlCommand, callbackFunction);
|
baseConnector.sqlQuery(sqlCommand, callbackFunction);
|
||||||
};
|
};
|
||||||
exports.upsertInTable = function (tableId, toInsert, toUpdate, callbackFunction) {
|
|
||||||
var table = getTableById(tableId);
|
|
||||||
var sqlCommand = "INSERT INTO " + table + " VALUES (";
|
|
||||||
for (var i = 0, l = toInsert.length; i < l; ++i) {
|
|
||||||
sqlCommand += baseConnector.sqlEscape(toInsert[i]);
|
|
||||||
if (i !== l - 1)
|
|
||||||
sqlCommand += ",";
|
|
||||||
}
|
|
||||||
sqlCommand += ") ON DUPLICATE KEY UPDATE ";
|
|
||||||
for (var i = 0, l = toUpdate.length; i + 1 < l; i += 2) {
|
|
||||||
sqlCommand += toUpdate[i] + "=" + baseConnector.sqlEscape(toUpdate[i+1]);
|
|
||||||
if (i + 1 !== l - 1)
|
|
||||||
sqlCommand += ",";
|
|
||||||
}
|
|
||||||
sqlCommand += ";";
|
|
||||||
baseConnector.sqlQuery(sqlCommand, callbackFunction);
|
|
||||||
};
|
|
||||||
exports.upsertInTablePromise = function (tableId, toInsert, toUpdate) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
exports.upsertInTable(tableId, toInsert, toUpdate, function(error, result) {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
exports.insertCallback = function(id, href, baseUrl, callbackFunction) {
|
exports.insertCallback = function(id, href, baseUrl, callbackFunction) {
|
||||||
var sqlCommand = "INSERT IGNORE INTO " + tableCallbacks + " VALUES (" + baseConnector.sqlEscape(id) + "," +
|
var sqlCommand = "INSERT " + baseConnector.ignoreStr + " INTO " + tableCallbacks + " VALUES (" + baseConnector.sqlEscape(id) + "," +
|
||||||
baseConnector.sqlEscape(href) + "," + baseConnector.sqlEscape(baseUrl) + ");";
|
baseConnector.sqlEscape(href) + "," + baseConnector.sqlEscape(baseUrl) + ") " + baseConnector.doNothingStr + ";";
|
||||||
|
|
||||||
baseConnector.sqlQuery(sqlCommand, callbackFunction);
|
baseConnector.sqlQuery(sqlCommand, callbackFunction);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
/*
|
/*
|
||||||
@ -31,29 +31,110 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
var pg = require('pg');
|
var pg = require('pg');
|
||||||
|
var co = require('co');
|
||||||
|
var pgEscape = require('pg-escape');
|
||||||
|
var types = require('pg').types;
|
||||||
|
var sqlBase = require('./baseConnector');
|
||||||
var configSql = require('config').get('services.CoAuthoring.sql');
|
var configSql = require('config').get('services.CoAuthoring.sql');
|
||||||
var connectionString = 'postgres://' + configSql.get('dbUser') + ':' + configSql.get('dbPass') + '@' + configSql.get('dbHost') +
|
var pool = new pg.Pool({
|
||||||
(configSql.get('dbPort') ? (':' + configSql.get('dbPort')) : '') + '/' + configSql.get('dbName');
|
host: configSql.get('dbHost'),
|
||||||
|
port: configSql.get('dbPort'),
|
||||||
|
user: configSql.get('dbUser'),
|
||||||
|
password: configSql.get('dbPass'),
|
||||||
|
database: configSql.get('dbName'),
|
||||||
|
max: configSql.get('connectionlimit'),
|
||||||
|
min: 0,
|
||||||
|
ssl: false,
|
||||||
|
idleTimeoutMillis: 30000
|
||||||
|
});
|
||||||
|
//todo datetime timezone
|
||||||
|
types.setTypeParser(1114, function(stringValue) {
|
||||||
|
return new Date(stringValue + '+0000');
|
||||||
|
});
|
||||||
|
types.setTypeParser(1184, function(stringValue) {
|
||||||
|
return new Date(stringValue + '+0000');
|
||||||
|
});
|
||||||
|
|
||||||
var logger = require('./../../Common/sources/logger');
|
var logger = require('./../../Common/sources/logger');
|
||||||
|
|
||||||
exports.sqlQuery = function (sqlCommand, callbackFunction) {
|
exports.sqlQuery = function(sqlCommand, callbackFunction, opt_noModifyRes) {
|
||||||
pg.connect(connectionString, function (err, connection, done) {
|
co(function *() {
|
||||||
if(err) {
|
var client = null;
|
||||||
logger.error('pool.getConnection error: %s', err);
|
var result = null;
|
||||||
if (callbackFunction) callbackFunction(err, null);
|
var error = null;
|
||||||
return;
|
try {
|
||||||
}
|
client = yield pool.connect();
|
||||||
|
result = yield client.query(sqlCommand);
|
||||||
connection.query(sqlCommand, function (error, result) {
|
} catch (err) {
|
||||||
//call `done()` to release the client back to the pool
|
error = err;
|
||||||
done();
|
if (client) {
|
||||||
|
logger.error('sqlQuery error sqlCommand: %s:\r\n%s', sqlCommand.slice(0, 50), err.stack);
|
||||||
if (error) logger.error('sqlQuery: %s sqlCommand: %s', error.message, sqlCommand.slice(0, 50));
|
} else {
|
||||||
if (callbackFunction) callbackFunction(error, result ? result.rows : result);
|
logger.error('pool.getConnection error: %s', err);
|
||||||
});
|
}
|
||||||
});
|
} finally {
|
||||||
|
if (client) {
|
||||||
|
client.release();
|
||||||
|
}
|
||||||
|
if (callbackFunction) {
|
||||||
|
var output = result;
|
||||||
|
if (result && !opt_noModifyRes) {
|
||||||
|
if ('SELECT' === result.command) {
|
||||||
|
output = result.rows;
|
||||||
|
} else {
|
||||||
|
output = {affectedRows: result.rowCount};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callbackFunction(error, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.sqlEscape = function(value) {
|
||||||
|
//todo parameterized queries
|
||||||
|
return undefined !== value ? pgEscape.literal(value.toString()) : 'NULL';
|
||||||
|
};
|
||||||
|
exports.ignoreStr = '';
|
||||||
|
exports.doNothingStr = 'ON CONFLICT DO NOTHING';
|
||||||
|
|
||||||
|
function getUpsertString(task, opt_updateUserIndex) {
|
||||||
|
task.completeDefaults();
|
||||||
|
var dateNow = sqlBase.getDateTime(new Date());
|
||||||
|
var commandArg = [task.key, task.status, task.statusInfo, dateNow, task.title, task.userIndex, task.changeId];
|
||||||
|
var commandArgEsc = commandArg.map(function(curVal) {
|
||||||
|
return exports.sqlEscape(curVal)
|
||||||
|
});
|
||||||
|
//http://stackoverflow.com/questions/34762732/how-to-find-out-if-an-upsert-was-an-update-with-postgresql-9-5-upsert
|
||||||
|
var sql = "INSERT INTO task_result (id, status, status_info, last_open_date, title, user_index, change_id) SELECT " +
|
||||||
|
commandArgEsc.join(', ') +
|
||||||
|
" WHERE 'false' = set_config('myapp.isupdate', 'false', true) ON CONFLICT (id) DO UPDATE SET last_open_date = " +
|
||||||
|
sqlBase.baseConnector.sqlEscape(dateNow);
|
||||||
|
if (opt_updateUserIndex) {
|
||||||
|
sql += ', user_index = task_result.user_index + 1';
|
||||||
|
}
|
||||||
|
sql +=
|
||||||
|
" WHERE 'true' = set_config('myapp.isupdate', 'true', true) RETURNING current_setting('myapp.isupdate') as update";
|
||||||
|
if (opt_updateUserIndex) {
|
||||||
|
sql += ', user_index';
|
||||||
|
}
|
||||||
|
sql += ';';
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
exports.upsert = function(task, opt_updateUserIndex) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
var sqlCommand = getUpsertString(task, opt_updateUserIndex);
|
||||||
|
exports.sqlQuery(sqlCommand, function(error, result) {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
if (result && result.rows.length > 0) {
|
||||||
|
var first = result.rows[0];
|
||||||
|
result = {affectedRows: 0, insertId: 0};
|
||||||
|
result.affectedRows = 'true' == first.update ? 2 : 1;
|
||||||
|
result.insertId = opt_updateUserIndex ? first.user_index : 0;
|
||||||
|
}
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
exports.sqlEscape = function (value) {
|
|
||||||
return value.replace( /(\')/g, "\\'" );
|
|
||||||
};
|
|
||||||
@ -83,36 +83,8 @@ TaskResultData.prototype.completeDefaults = function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function getUpsertString(task, opt_updateUserIndex) {
|
|
||||||
task.completeDefaults();
|
|
||||||
var dateNow = sqlBase.getDateTime(new Date());
|
|
||||||
var commandArg = [task.key, task.status, task.statusInfo, dateNow, task.title, task.userIndex, task.changeId];
|
|
||||||
var commandArgEsc = commandArg.map(function(curVal) {
|
|
||||||
return sqlBase.baseConnector.sqlEscape(curVal)
|
|
||||||
});
|
|
||||||
var sql = 'INSERT INTO task_result ( id, status, status_info, last_open_date, title,' +
|
|
||||||
' user_index, change_id ) VALUES (' + commandArgEsc.join(', ') + ') ON DUPLICATE KEY UPDATE' +
|
|
||||||
' last_open_date = ' + sqlBase.baseConnector.sqlEscape(dateNow);
|
|
||||||
if (opt_updateUserIndex) {
|
|
||||||
//todo LAST_INSERT_ID in posgresql - RETURNING
|
|
||||||
sql += ', user_index = LAST_INSERT_ID(user_index + 1);';
|
|
||||||
} else {
|
|
||||||
sql += ';';
|
|
||||||
}
|
|
||||||
return sql;
|
|
||||||
}
|
|
||||||
|
|
||||||
function upsert(task, opt_updateUserIndex) {
|
function upsert(task, opt_updateUserIndex) {
|
||||||
return new Promise(function(resolve, reject) {
|
return sqlBase.baseConnector.upsert(task, opt_updateUserIndex);
|
||||||
var sqlCommand = getUpsertString(task, opt_updateUserIndex);
|
|
||||||
sqlBase.baseConnector.sqlQuery(sqlCommand, function(error, result) {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSelectString(docId) {
|
function getSelectString(docId) {
|
||||||
@ -281,7 +253,6 @@ exports.upsert = upsert;
|
|||||||
exports.select = select;
|
exports.select = select;
|
||||||
exports.update = update;
|
exports.update = update;
|
||||||
exports.updateIf = updateIf;
|
exports.updateIf = updateIf;
|
||||||
exports.addRandomKey = addRandomKey;
|
|
||||||
exports.addRandomKeyTask = addRandomKeyTask;
|
exports.addRandomKeyTask = addRandomKeyTask;
|
||||||
exports.remove = remove;
|
exports.remove = remove;
|
||||||
exports.getExpired = getExpired;
|
exports.getExpired = getExpired;
|
||||||
|
|||||||
52
schema/postgresql/createdb.sql
Normal file
52
schema/postgresql/createdb.sql
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
--
|
||||||
|
-- Create schema onlyoffice
|
||||||
|
--
|
||||||
|
|
||||||
|
-- CREATE DATABASE onlyoffice ENCODING = 'UTF8' CONNECTION LIMIT = -1;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Drop tables
|
||||||
|
--
|
||||||
|
DROP TABLE IF EXISTS "public"."doc_callbacks";
|
||||||
|
DROP TABLE IF EXISTS "public"."doc_changes";
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for doc_callbacks
|
||||||
|
-- ----------------------------
|
||||||
|
CREATE TABLE IF NOT EXISTS "public"."doc_callbacks" (
|
||||||
|
"id" varchar(255) COLLATE "default" NOT NULL,
|
||||||
|
"callback" text COLLATE "default" NOT NULL,
|
||||||
|
"baseurl" text COLLATE "default" NOT NULL,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
)
|
||||||
|
WITH (OIDS=FALSE);
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for doc_changes
|
||||||
|
-- ----------------------------
|
||||||
|
CREATE TABLE IF NOT EXISTS "public"."doc_changes" (
|
||||||
|
"id" varchar(255) COLLATE "default" NOT NULL,
|
||||||
|
"change_id" int8 NOT NULL,
|
||||||
|
"user_id" varchar(255) COLLATE "default" NOT NULL,
|
||||||
|
"user_id_original" varchar(255) COLLATE "default" NOT NULL,
|
||||||
|
"user_name" varchar(255) COLLATE "default" NOT NULL,
|
||||||
|
"change_data" text COLLATE "default" NOT NULL,
|
||||||
|
"change_date" timestamp without time zone NOT NULL,
|
||||||
|
PRIMARY KEY ("id", "change_id")
|
||||||
|
)
|
||||||
|
WITH (OIDS=FALSE);
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for task_result
|
||||||
|
-- ----------------------------
|
||||||
|
CREATE TABLE IF NOT EXISTS "public"."task_result" (
|
||||||
|
"id" varchar(255) COLLATE "default" NOT NULL,
|
||||||
|
"status" int2 NOT NULL,
|
||||||
|
"status_info" int8 NOT NULL,
|
||||||
|
"last_open_date" timestamp without time zone NOT NULL,
|
||||||
|
"title" varchar(255) COLLATE "default" NOT NULL,
|
||||||
|
"user_index" int8 NOT NULL DEFAULT 1,
|
||||||
|
"change_id" int8 NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
)
|
||||||
|
WITH (OIDS=FALSE);
|
||||||
1
schema/postgresql/removedb.sql
Normal file
1
schema/postgresql/removedb.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
DROP DATABASE IF EXISTS onlyoffice;
|
||||||
Reference in New Issue
Block a user