From 6d47a94fe9a2c8b88f5b8d0d20084ee7da8eef4b Mon Sep 17 00:00:00 2001 From: calzoneman Date: Wed, 21 Aug 2013 16:09:28 -0500 Subject: [PATCH] Fix db key issue for bans - run node update.js 2013-08-21-banfix --- database.js | 11 +++++---- update.js | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/database.js b/database.js index 1c3a62f4..971b4bdb 100644 --- a/database.js +++ b/database.js @@ -366,7 +366,7 @@ Database.prototype.registerChannel = function (name, owner, callback) { "`ip` VARCHAR(15) NOT NULL,", "`name` VARCHAR(32) NOT NULL,", "`banner` VARCHAR(32) NOT NULL,", - "PRIMARY KEY (`ip`))", + "PRIMARY KEY (`ip`, `name`))", "ENGINE = MyISAM ", "CHARACTER SET utf8;"].join(""); @@ -570,10 +570,10 @@ Database.prototype.addToLibrary = function (channame, media, callback) { return; } - // use INSERT IGNORE to prevent errors from adding duplicates - var query = "INSERT IGNORE INTO `chan_" + channame + "_library` " + + var query = "INSERT INTO `chan_" + channame + "_library` " + "(id, title, seconds, type) " + - "VALUES (?, ?, ?, ?)"; + "VALUES (?, ?, ?, ?) " + + "ON DUPLICATE KEY UPDATE id=id"; var params = [ media.id, media.title, @@ -648,7 +648,8 @@ Database.prototype.addChannelBan = function (channame, ip, name, banBy, } var query = "INSERT INTO `chan_" + channame + "_bans`" + - "(ip, name, banner) VALUES (?, ?, ?)"; + "(ip, name, banner) VALUES (?, ?, ?) " + + "ON DUPLICATE KEY UPDATE ip=ip"; self.query(query, [ip, name, banBy], callback); }; diff --git a/update.js b/update.js index 94491af0..513132ae 100644 --- a/update.js +++ b/update.js @@ -2,7 +2,8 @@ var Config = require("./config.js"); var Database = require("./database.js"); var updates = { - "2013-08-20-utf8fix": fixDBUnicode + "2013-08-20-utf8fix": fixDBUnicode, + "2013-08-21-banfix": fixChannelBanKey }; var x = {}; @@ -23,6 +24,25 @@ Config.load(x, "cfg.json", function () { fn(db); }); +/* + 2013-08-20 + + This function iterates over tables in the database and converts the + encoding on each to UTF-8. + + Furthermore, it does the following to convert channel libraries in + a way such that UTF-8 titles stored in other encodings (e.g. latin1) + are preserved as UTF-8: + 1. Change the `title` column to BLOB (unencoded) + 2. Change the table character set to utf8 + 3. Change the `title` column to VARCHAR(255) CHARACTER SET utf8 + + This corrects an encoding issue that was exposed when switching to + node-mysql. mysql-libmysqlclient ignored database encoding and assumed + the data was UTF-8. + +*/ + function fixDBUnicode(db) { db.query("SHOW TABLES", function (err, res) { if(err) { @@ -110,3 +130,51 @@ function fixDBUnicode(db) { }, 1000); }); } + +/* + 2013-08-21 + + This function iterates over channel ban tables and corrects the + PRIMARY KEY. Previously, the table was defined with PRIMARY KEY (ip), + but in reality, (ip, name) should be pairwise unique. + + This corrects the issue where only one name ban can exist in the table + because of the `ip` field "*" being unique. + +*/ + +function fixChannelBanKey(db) { + db.query("SHOW TABLES", function (err, res) { + if(err) { + console.log("SEVERE: SHOW TABLES failed"); + return; + } + + var count = res.length; + res.forEach(function (r) { + var k = Object.keys(r)[0]; + + if(!r[k].match(/^chan_[\w-_]{1,30}_bans$/)) { + count--; + return; + } + + db.query("ALTER TABLE `" + r[k] + "` DROP PRIMARY KEY, ADD PRIMARY KEY (ip, name)", function (err, res) { + count--; + if(err) { + console.log("FAILED: " + r[k]); + return; + } + + console.log("Fixed " + r[k]); + }); + }); + + setInterval(function () { + if(count == 0) { + console.log("Done"); + process.exit(0); + } + }, 1000); + }); +}