aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.luacheckrc4
-rw-r--r--net/dns.lua11
-rw-r--r--plugins/mod_storage_sql2.lua56
-rwxr-xr-xprosodyctl3
-rw-r--r--util/sql.lua35
5 files changed, 82 insertions, 27 deletions
diff --git a/.luacheckrc b/.luacheckrc
index 3f147806..7ebc7af4 100644
--- a/.luacheckrc
+++ b/.luacheckrc
@@ -6,3 +6,7 @@ module = true
unused_secondaries = false
codes = true
ignore = { "411/err", "421/err", "411/ok", "421/ok" }
+
+files["plugins/"] = {
+ ignore = { "122/module" };
+}
diff --git a/net/dns.lua b/net/dns.lua
index 037f3ec6..992f3986 100644
--- a/net/dns.lua
+++ b/net/dns.lua
@@ -213,15 +213,6 @@ function cache_metatable.__tostring(cache)
end
-function resolver:new() -- - - - - - - - - - - - - - - - - - - - - resolver
- local r = { active = {}, cache = {}, unsorted = {} };
- setmetatable(r, resolver);
- setmetatable(r.cache, cache_metatable);
- setmetatable(r.unsorted, { __mode = 'kv' });
- return r;
-end
-
-
-- packet layer -------------------------------------------------- packet layer
@@ -1054,8 +1045,6 @@ end
function dns.resolver () -- - - - - - - - - - - - - - - - - - - - - resolver
- -- this function seems to be redundant with resolver.new ()
-
local r = { active = {}, cache = {}, unsorted = {}, wanted = {}, best_server = 1 };
setmetatable (r, resolver);
setmetatable (r.cache, cache_metatable);
diff --git a/plugins/mod_storage_sql2.lua b/plugins/mod_storage_sql2.lua
index 1702108c..adf9f9b6 100644
--- a/plugins/mod_storage_sql2.lua
+++ b/plugins/mod_storage_sql2.lua
@@ -13,8 +13,8 @@ local function is_stanza(x) return getmetatable(x) == stanza_mt; end
local noop = function() end
local unpack = unpack
local function iterator(result)
- return function(result)
- local row = result();
+ return function(result_)
+ local row = result_();
if row ~= nil then
return unpack(row);
end
@@ -385,7 +385,8 @@ local function upgrade_table(params, apply_changes)
end
-- COMPAT w/pre-0.10: Upgrade table to UTF-8 if not already
- local check_encoding_query = "SELECT `COLUMN_NAME`,`COLUMN_TYPE` FROM `information_schema`.`columns` WHERE `TABLE_NAME`='prosody' AND ( `CHARACTER_SET_NAME`!='utf8' OR `COLLATION_NAME`!='utf8_bin' );";
+ local check_encoding_query = "SELECT `COLUMN_NAME`,`COLUMN_TYPE`,`TABLE_NAME` FROM `information_schema`.`columns` WHERE `TABLE_NAME` LIKE 'prosody%%' AND ( `CHARACTER_SET_NAME`!='%s' OR `COLLATION_NAME`!='%s_bin' );";
+ check_encoding_query = check_encoding_query:format(engine.charset, engine.charset);
success,err = engine:transaction(function()
local result = engine:execute(check_encoding_query);
local n_bad_columns = result:rowcount();
@@ -393,12 +394,13 @@ local function upgrade_table(params, apply_changes)
changes = true;
if apply_changes then
module:log("warn", "Found %d columns in prosody table requiring encoding change, updating now...", n_bad_columns);
- local fix_column_query1 = "ALTER TABLE `prosody` CHANGE `%s` `%s` BLOB;";
- local fix_column_query2 = "ALTER TABLE `prosody` CHANGE `%s` `%s` %s CHARACTER SET 'utf8' COLLATE 'utf8_bin';";
+ local fix_column_query1 = "ALTER TABLE `%s` CHANGE `%s` `%s` BLOB;";
+ local fix_column_query2 = "ALTER TABLE `%s` CHANGE `%s` `%s` %s CHARACTER SET '%s' COLLATE '%s_bin';";
for row in result:rows() do
- local column_name, column_type = unpack(row);
- engine:execute(fix_column_query1:format(column_name, column_name));
- engine:execute(fix_column_query2:format(column_name, column_name, column_type));
+ local column_name, column_type, table_name = unpack(row);
+ module:log("debug", "Fixing column %s in table %s", column_name, table_name);
+ engine:execute(fix_column_query1:format(table_name, column_name, column_name));
+ engine:execute(fix_column_query2:format(table_name, column_name, column_name, column_type, engine.charset, engine.charset));
end
module:log("info", "Database encoding upgrade complete!");
end
@@ -410,6 +412,7 @@ local function upgrade_table(params, apply_changes)
return false;
end
end
+ return changes;
end
local function normalize_params(params)
@@ -429,8 +432,8 @@ function module.load()
-- FIXME: we should check in information_schema, etc.
create_table();
-- Check whether the table needs upgrading
- if not upgrade_table(params, true) then
- module:log("error", "Old database format detected, and upgrade failed");
+ if upgrade_table(params, false) then
+ module:log("error", "Old database format detected. Please run: prosodyctl mod_%s upgrade", module.name);
return false, "database upgrade needed";
end
end
@@ -438,3 +441,36 @@ function module.load()
module:provides("storage", driver);
end
+
+function module.command(arg)
+ local config = require "core.configmanager";
+ local prosodyctl = require "util.prosodyctl";
+ local command = table.remove(arg, 1);
+ if command == "upgrade" then
+ -- We need to find every unique dburi in the config
+ local uris = {};
+ for host in pairs(prosody.hosts) do
+ local params = config.get(host, "sql") or default_params;
+ uris[sql.db2uri(params)] = params;
+ end
+ print("We will check and upgrade the following databases:\n");
+ for _, params in pairs(uris) do
+ print("", "["..params.driver.."] "..params.database..(params.host and " on "..params.host or ""));
+ end
+ print("");
+ print("Ensure you have working backups of the above databases before continuing! ");
+ if not prosodyctl.show_yesno("Continue with the database upgrade? [yN]") then
+ print("Ok, no upgrade. But you do have backups, don't you? ...don't you?? :-)");
+ return;
+ end
+ -- Upgrade each one
+ for _, params in pairs(uris) do
+ print("Checking "..params.database.."...");
+ engine = sql:create_engine(params);
+ upgrade_table(params, true);
+ end
+ print("All done!");
+ else
+ print("Unknown command: "..command);
+ end
+end
diff --git a/prosodyctl b/prosodyctl
index 6c4b148a..a67f3dbd 100755
--- a/prosodyctl
+++ b/prosodyctl
@@ -841,7 +841,8 @@ function commands.check(arg)
});
local known_global_options = set.new({
"pidfile", "log", "plugin_paths", "prosody_user", "prosody_group", "daemonize",
- "umask", "prosodyctl_timeout", "use_ipv6", "use_libevent", "network_settings"
+ "umask", "prosodyctl_timeout", "use_ipv6", "use_libevent", "network_settings",
+ "network_backend", "http_default_host",
});
local config = config.getconfig();
-- Check that we have any global options (caused by putting a host at the top)
diff --git a/util/sql.lua b/util/sql.lua
index 92032f43..f934bbdf 100644
--- a/util/sql.lua
+++ b/util/sql.lua
@@ -101,6 +101,7 @@ function engine:connect()
local params = self.params;
assert(params.driver, "no driver")
+ log("debug", "Connecting to [%s] %s...", params.driver, params.database);
local dbh, err = DBI.Connect(
params.driver, params.database,
params.username, params.password,
@@ -110,8 +111,14 @@ function engine:connect()
dbh:autocommit(false); -- don't commit automatically
self.conn = dbh;
self.prepared = {};
- self:set_encoding();
- self:onconnect();
+ local ok, err = self:set_encoding();
+ if not ok then
+ return ok, err;
+ end
+ local ok, err = self:onconnect();
+ if ok == false then
+ return ok, err;
+ end
return true;
end
function engine:onconnect()
@@ -242,7 +249,7 @@ function engine:_create_table(table)
if self.params.driver == "PostgreSQL" then
sql = sql:gsub("`", "\"");
elseif self.params.driver == "MySQL" then
- sql = sql:gsub(";$", " CHARACTER SET 'utf8' COLLATE 'utf8_bin';");
+ sql = sql:gsub(";$", (" CHARACTER SET '%s' COLLATE '%s_bin';"):format(self.charset, self.charset));
end
local success,err = self:execute(sql);
if not success then return success,err; end
@@ -265,15 +272,33 @@ function engine:set_encoding() -- to UTF-8
local set_names_query = "SET NAMES '%s';"
local charset = "utf8";
if driver == "MySQL" then
- set_names_query = set_names_query:gsub(";$", " COLLATE 'utf8_bin';");
local ok, charsets = self:transaction(function()
return self:select"SELECT `CHARACTER_SET_NAME` FROM `information_schema`.`CHARACTER_SETS` WHERE `CHARACTER_SET_NAME` LIKE 'utf8%' ORDER BY MAXLEN DESC LIMIT 1;";
end);
local row = ok and charsets();
charset = row and row[1] or charset;
+ set_names_query = set_names_query:gsub(";$", (" COLLATE '%s';"):format(charset.."_bin"));
end
self.charset = charset;
- return self:transaction(function() return self:execute(set_names_query:format(charset)); end);
+ log("debug", "Using encoding '%s' for database connection", charset);
+ local ok, err = self:transaction(function() return self:execute(set_names_query:format(charset)); end);
+ if not ok then
+ return ok, err;
+ end
+
+ if driver == "MySQL" then
+ local ok, actual_charset = self:transaction(function ()
+ return self:select"SHOW SESSION VARIABLES LIKE 'character_set_client'";
+ end);
+ for row in actual_charset do
+ if row[2] ~= charset then
+ log("error", "MySQL %s is actually %q (expected %q)", row[1], row[2], charset);
+ return false, "Failed to set connection encoding";
+ end
+ end
+ end
+
+ return true;
end
local engine_mt = { __index = engine };