UNPKG

quizzer

Version:

Quizzer is a webserver for collaborative writing lab support. Based on a _fail early, fail often? approach to written language, the tool is particularly suited to second-language learners. The workflow (essay - error - quiz - exam) treats mistakes as an o

901 lines (896 loc) 47.2 kB
(function () { var upgraderClass = function (db,fromVersion,toVersion) { this.fromVersion = fromVersion; this.toVersion = toVersion; this.db = db; }; upgraderClass.prototype.run = function (callback) { var db = this.db; var pos = this.fromVersion-1; console.log("Upgrading schema from version " + this.fromVersion + " to version " + this.toVersion); var toVersion = this.toVersion; var steps = [ function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'CREATE TEMP TABLE oldAdmin AS SELECT * FROM admin;' + 'DROP TABLE admin;' + 'CREATE TABLE admin (adminID INTEGER PRIMARY KEY,name TEXT, adminKey TEXT, role INTEGER, interval INTEGER);' + 'CREATE UNIQUE INDEX admin_name_idx ON admin(name);' + 'CREATE UNIQUE INDEX admin_key_idx ON admin(adminKey);' + 'INSERT INTO admin (name,adminKey,role,interval) SELECT name,adminID AS adminKey,role,interval FROM oldAdmin;' + 'ALTER TABLE comments ADD COLUMN commenterID INTEGER;' + 'CREATE TEMP TABLE newComments AS SELECT c.commentID,c.classID,c.quizNumber,c.questionNumber,c.choice,c.commentTextID,a.adminID AS commenterID FROM comments AS c JOIN admin AS a ON a.name=c.commenter;' + 'DROP TABLE comments;' + 'CREATE TABLE comments (' + 'commentID INT PRIMARY KEY,' + 'classID INT,' + 'quizNumber INT,' + 'questionNumber INT,' + 'choice INT,' + 'commentTextID INT,' + 'commenterID INT' + ');' + 'INSERT INTO comments SELECT * FROM newComments;' + 'CREATE UNIQUE INDEX comments_idx ON comments(classID,quizNumber,questionNumber,choice,commenterID);' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'ALTER TABLE quizzes ADD COLUMN examName TEXT;' + 'ALTER TABLE quizzes ADD COLUMN examDate TEXT;' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'ALTER TABLE admin ADD COLUMN email TEXT;' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'ALTER TABLE memberships ADD COLUMN last_mail_date DATE;' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'CREATE TABLE IF NOT EXISTS showing (showID INTEGER PRIMARY KEY, adminID INTEGER, classID INTEGER, studentID INTEGER);' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'CREATE UNIQUE INDEX IF NOT EXISTS showing_idx ON showing(adminID,classID,studentID);' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'CREATE TEMP TABLE newAnswers AS SELECT a.answerID,q.questionID,a.studentID,a.choice FROM answers AS a JOIN questions AS q ON q.classID=a.classID AND q.quizNumber=a.quizNumber AND q.questionNumber=a.questionNumber;' + 'DROP INDEX answers_idx;' + 'DROP TABLE answers;' + 'CREATE TABLE answers AS SELECT * FROM newAnswers;' + 'CREATE UNIQUE INDEX answers_idx ON answers(questionID,studentID,choice);' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ // Clean up a potential mess of duplicate answer entries, in preparation // for turning on foreign key constraints db.exec( 'CREATE TEMP TABLE newAnswers AS SELECT * FROM answers;' + 'DROP TABLE answers;' + 'CREATE TABLE answers(' + 'answerID INTEGER PRIMARY KEY AUTOINCREMENT,' + 'questionID INTEGER,' + 'studentID INTEGER,' + 'choice INTEGER' + ');' + 'INSERT INTO answers SELECT * FROM newAnswers WHERE answerID IS NOT NULL;' + 'INSERT INTO answers (questionID,studentID,choice) SELECT questionID,studentID,choice FROM newAnswers WHERE answerID IS NULL;' + 'DROP TABLE newAnswers;' + 'CREATE UNIQUE INDEX answers_idx ON answers(questionID,studentID,choice);' + 'CREATE TEMP TABLE uniqueAnswerIDs AS ' + 'SELECT a.answerID FROM answers AS a ' + 'JOIN answers AS aa ON aa.questionID=a.questionID AND aa.studentID=a.studentID AND (' + 'NOT a.answerID=aa.answerID ' + 'OR a.answerID IS NULL' + ') ' + 'LEFT JOIN questions AS q ON q.questionID=a.questionID ' + 'GROUP BY a.questionID,a.answerID ' + 'ORDER BY q.classID,q.quizNumber,q.questionNumber,a.answerID DESC;' + 'DELETE FROM answers WHERE answerID IN (' + 'SELECT a.answerID FROM answers AS a ' + 'JOIN answers AS aa ON aa.questionID=a.questionID ' + 'AND aa.studentID=a.studentID ' + 'AND (' + 'NOT a.answerID=aa.answerID ' + 'OR a.answerID IS NULL' + ')' + ') ' + 'AND answerID NOT IN (select answerID FROM uniqueAnswerIDs);' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'CREATE TEMP TABLE newAnswers AS SELECT * FROM answers;' + 'DROP TABLE answers;' + 'CREATE TABLE answers(' + 'answerID INTEGER PRIMARY KEY AUTOINCREMENT,' + 'questionID INTEGER,' + 'studentID INTEGER,' + 'choice INTEGER,' + 'UNIQUE(questionID,studentID,choice)' + 'FOREIGN KEY (questionID) REFERENCES questions(questionID)' + ');' + 'INSERT INTO answers SELECT * FROM newAnswers;' + 'DROP TABLE newAnswers;' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'PRAGMA foreign_keys = OFF;' + 'CREATE TEMP TABLE newMemberships AS SELECT * FROM memberships;' + 'DROP TABLE memberships;' + '' + 'CREATE TEMP TABLE newShowing AS SELECT * FROM showing;' + 'DROP TABLE showing;' + '' + 'CREATE TEMP TABLE newAnswers AS SELECT * FROM answers;' + 'DROP TABLE answers;' + '' + 'CREATE TEMP TABLE newQuestions AS SELECT *,quizID FROM questions AS qui JOIN quizzes AS que ON que.classID=qui.classID AND que.quizNumber=qui.quizNumber;' + 'DROP TABLE questions;' + '' + '' + 'CREATE TEMP TABLE newChoices (choiceID INTEGER PRIMARY KEY,questionID INTEGER,choice INTEGER,stringID INTEGER,classID INTEGER,quizNumber INTEGER,questionNumber INTEGER);' + 'INSERT INTO newChoices (questionID,choice,stringID,classID,quizNumber,questionNumber) SELECT questionID,0,qOneID,classID,quizNumber,questionNumber FROM newQuestions;' + 'INSERT INTO newChoices (questionID,choice,stringID,classID,quizNumber,questionNumber) SELECT questionID,1,qTwoID,classID,quizNumber,questionNumber FROM newQuestions;' + 'INSERT INTO newChoices (questionID,choice,stringID,classID,quizNumber,questionNumber) SELECT questionID,2,qThreeID,classID,quizNumber,questionNumber FROM newQuestions;' + 'INSERT INTO newChoices (questionID,choice,stringID,classID,quizNumber,questionNumber) SELECT questionID,3,qFourID,classID,quizNumber,questionNumber FROM newQuestions;' + '' + 'CREATE TEMP TABLE newQuizzes AS SELECT * FROM quizzes;' + 'DROP TABLE quizzes;' + '' + 'ALTER TABLE comments ADD COLUMN choiceID INTEGER;' + 'INSERT OR REPLACE INTO comments SELECT commentID,c.classID,c.quizNumber,c.questionNumber,c.choice,c.commentTextID,c.commenterID,nc.choiceID FROM comments AS c JOIN newChoices AS nc ON nc.classID=c.classID AND nc.quizNumber=c.quizNumber AND nc.questionNumber=c.questionNumber AND nc.choice=c.choice;' + 'CREATE TABLE newComments AS SELECT * FROM comments;' + 'DROP TABLE comments;' + '' + 'CREATE TABLE memberships (membershipID INTEGER PRIMARY KEY,classID INTEGER,studentID INTEGER,studentKey TEXT NOT NULL,last_mail_date DATE,UNIQUE (studentID,classID),FOREIGN KEY (studentID) REFERENCES students(studentID),FOREIGN KEY (classID) REFERENCES classes(classID));' + 'INSERT INTO memberships SELECT * FROM newMemberships;' + 'CREATE TABLE showing (showID INTEGER PRIMARY KEY,adminID INTEGER,classID INTEGER,studentID INTEGER,UNIQUE (adminID,classID,studentID),FOREIGN KEY (adminID) REFERENCES admin(adminID),FOREIGN KEY (classID) REFERENCES classes(classID),FOREIGN KEY (studentID) REFERENCES students(studentID));' + 'INSERT INTO showing SELECT * FROM newShowing;' + '' + 'CREATE TABLE quizzes (quizID INTEGER PRIMARY KEY,classID INTEGER,quizNumber INTEGER,sent BOOLEAN,examName TEXT,examDate TEXT,UNIQUE (classID,quizNumber),FOREIGN KEY (classID) REFERENCES classes(classID));' + 'INSERT INTO quizzes SELECT * FROM newQuizzes;' + '' + 'CREATE TABLE questions (questionID INTEGER PRIMARY KEY,quizID INTEGER,questionNumber INTEGER,correct INTEGER,stringID INTEGER,UNIQUE (quizID,questionNumber),FOREIGN KEY (quizID) REFERENCES quizzes(quizID),FOREIGN KEY (stringID) REFERENCES strings(stringID));' + 'INSERT INTO questions SELECT questionID,quizID,questionNumber,correct,rubricID AS stringID FROM newQuestions;' + '' + 'CREATE TABLE answers(answerID INTEGER PRIMARY KEY AUTOINCREMENT,questionID INTEGER,studentID INTEGER,choice INTEGER,FOREIGN KEY (questionID) REFERENCES questions(questionID));' + 'INSERT INTO answers SELECT * FROM newAnswers;' + '' + 'CREATE TABLE choices (choiceID INTEGER PRIMARY KEY,questionID INTEGER,choice INTEGER,stringID INTEGER,UNIQUE (questionID,choice),FOREIGN KEY (questionID) REFERENCES questions(questionID),FOREIGN KEY (stringID) REFERENCES strings(stringID));' + 'INSERT INTO choices (choiceID,questionID,choice,stringID) SELECT choiceID,questionID,choice,stringID FROM newChoices;' + '' + 'CREATE TABLE comments (commentID INTEGER PRIMARY KEY,choiceID INTEGER,adminID INTEGER,stringID INTEGER,UNIQUE (choiceID,stringID),FOREIGN KEY (choiceID) REFERENCES choices(choiceID),FOREIGN KEY (adminID) REFERENCES admin(adminID),FOREIGN KEY (stringID) REFERENCES strings(stringID));' + 'INSERT INTO comments (choiceID,adminID,stringID) SELECT choiceID,commenterID AS adminID,commentTextID AS stringID FROM newComments;' + '' + 'CREATE TABLE ruleStrings (ruleStringID INTEGER PRIMARY KEY,string TEXT NOT NULL,UNIQUE (string));' + 'CREATE TABLE rules (ruleID INTEGER PRIMARY KEY,ruleStringID INTEGER,FOREIGN KEY (ruleStringID) REFERENCES ruleStrings(ruleStringID));' + 'CREATE TABLE rulesToChoices (ruleToChoiceID INTEGER PRIMARY KEY,choiceID INTEGER,ruleID INTEGER,UNIQUE (choiceID,ruleID),FOREIGN KEY (choiceID) REFERENCES choices(choiceID),FOREIGN KEY (ruleID) REFERENCES rules(ruleID));' + '' + 'DELETE FROM quizzes ' + 'WHERE quizID IN (' + 'SELECT quizID ' + 'FROM quizzes ' + 'LEFT JOIN classes AS x using(classID) ' + 'WHERE x.classID IS NULL' + ');' + '' + 'DELETE FROM comments ' + 'WHERE commentID IN (' + 'SELECT commentID ' + 'FROM comments ' + 'LEFT JOIN choices AS x using(choiceID) ' + 'WHERE x.choiceID IS NULL' + ');' + '' + 'DROP TABLE newShowing;' + 'DROP TABLE newMemberships;' + 'DROP TABLE newAnswers;' + 'DROP TABLE newQuizzes;' + 'DROP TABLE newComments;' + 'DROP TABLE newChoices;' + 'DROP TABLE newQuestions;' + 'PRAGMA foreign_keys = ON;' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'CREATE TEMP TABLE newRules AS SELECT * FROM rules;' + 'DROP TABLE rules;' + 'CREATE TABLE rules (' + 'ruleID INTEGER PRIMARY KEY,' + 'ruleStringID INTEGER,' + 'active BOOLEAN,' + 'FOREIGN KEY (ruleStringID) REFERENCES ruleStrings(ruleStringID)' + ');' + 'INSERT INTO rules SELECT ruleID,ruleStringID,1 FROM newRules;' + 'DROP TABLE newRules;' + 'CREATE TABLE ruleTranslations (' + 'ruleTranslationID INTEGER PRIMARY KEY,' + 'ruleID NOT NULL,' + 'string TEXT NOT NULL,' + 'lang TEXT NOT NULL,' + 'UNIQUE (string),' + 'UNIQUE (ruleID,lang),' + 'FOREIGN KEY (ruleID) REFERENCES rules(ruleID)' + ');' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'CREATE TEMP TABLE newRules AS SELECT * FROM rules;' + 'DROP TABLE rules;' + 'CREATE TABLE rules (' + 'ruleID INTEGER PRIMARY KEY,' + 'ruleStringID INTEGER,' + 'adminID INTEGER,' + 'FOREIGN KEY (adminID) REFERENCES admin(adminID),' + 'FOREIGN KEY (ruleStringID) REFERENCES ruleStrings(ruleStringID)' + ');' + 'INSERT INTO rules SELECT ruleID,ruleStringID,1 FROM newRules;' + 'DROP TABLE newRules;' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('PRAGMA foreign_keys = OFF;',function(err) { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); }); function performUpgrade (){ db.exec( 'CREATE TABLE adminLanguages (' + 'adminLanguageID INTEGER PRIMARY KEY,' + 'adminID INTEGER,' + 'lang TEXT,' + 'UNIQUE(adminID,lang),' + 'FOREIGN KEY (adminID) REFERENCES admin(adminID),' + 'FOREIGN KEY (lang) REFERENCES languages(lang)' + ');' + 'CREATE TABLE quizAnswers (' + 'quizAnswerID INTEGER PRIMARY KEY,' + 'quizID INTEGER,' + 'studentID INTEGER,' + 'submissionDate DATE,' + 'UNIQUE(quizID,studentID),' + 'FOREIGN KEY (quizID) REFERENCES quizzes(quizID),' + 'FOREIGN KEY (studentID) REFERENCES students(studentID)' + ');' + 'CREATE TABLE languages (' + 'lang TEXT PRIMARY KEY,' + 'langName TEXT' + ');' + "INSERT INTO languages VALUES ('en','English');" + "INSERT INTO languages VALUES ('zh-CN','Chinese (cn)');" + "INSERT INTO languages VALUES ('zh-TW','Chinese (tw)');" + "INSERT INTO languages VALUES ('fr','French');" + "INSERT INTO languages VALUES ('id','Indonesian');" + "INSERT INTO languages VALUES ('it','Italian');" + "INSERT INTO languages VALUES ('ja','Japanese');" + "INSERT INTO languages VALUES ('km','Khmer');" + "INSERT INTO languages VALUES ('kr','Korean');" + "INSERT INTO languages VALUES ('la','Laotian');" + "INSERT INTO languages VALUES ('mn','Mongolian');" + "INSERT INTO languages VALUES ('my','Myanmar');" + "INSERT INTO languages VALUES ('pl','Polish');" + "INSERT INTO languages VALUES ('ru','Russian');" + "INSERT INTO languages VALUES ('th','Thai');" + "INSERT INTO languages VALUES ('uz','Uzbek');" + "INSERT INTO languages VALUES ('vn','Vietnamese');" + "INSERT INTO languages VALUES ('bn','Bengali');" + "INSERT INTO languages VALUES ('tr','Turkish');" + "CREATE TABLE ruleTranslationEdits (" + "ruleTranslationEditID INTEGER PRIMARY KEY," + "ruleTranslationID INTEGER NOT NULL," + "studentID INTEGER," + "editDate DATE," + "FOREIGN KEY (ruleTranslationID) REFERENCES ruleTranslations(ruleTranslationID)," + "FOREIGN KEY (studentID) REFERENCES students(studentID)" + ");" + 'CREATE TEMP TABLE newRuleTranslations AS SELECT * FROM ruleTranslations;' + 'DROP TABLE ruleTranslations;' + 'CREATE TABLE ruleTranslations (' + 'ruleTranslationID INTEGER PRIMARY KEY,' + 'ruleID NOT NULL,' + 'string TEXT,' + 'lang TEXT NOT NULL,' + 'UNIQUE (string),' + 'UNIQUE (ruleID,lang),' + 'FOREIGN KEY (ruleID) REFERENCES rules(ruleID)' + ');' + 'INSERT INTO ruleTranslations SELECT * FROM newRuleTranslations;' + 'DROP TABLE newRuleTranslations;' + 'CREATE TABLE ruleGroups (' + 'ruleGroupID INTEGER PRIMARY KEY,' + 'name TEXT NOT NULL,' + 'UNIQUE(name)' + ');' + 'INSERT INTO ruleGroups VALUES (NULL,\'Academic Writing\');' + 'CREATE TEMP TABLE newClasses AS SELECT * FROM classes;' + 'DROP TABLE classes;' + 'CREATE TABLE classes (' + 'classID INTEGER PRIMARY KEY,' + 'ruleGroupID INTEGER,' + 'name TEXT,' + 'FOREIGN KEY (ruleGroupID) REFERENCES ruleGroups(ruleGroupID)' + ');' + 'INSERT INTO classes ' + 'SELECT classID,ruleGroupID,newClasses.name ' + 'FROM newClasses JOIN ruleGroups;' + 'DROP TABLE newClasses;' + 'CREATE TEMP TABLE newRules AS SELECT * FROM rules;' + 'DROP TABLE rules;' + 'CREATE TABLE rules (' + 'ruleID INTEGER PRIMARY KEY,' + 'ruleGroupID INTEGER,' + 'ruleStringID INTEGER,' + 'adminID INTEGER,' + 'FOREIGN KEY (ruleGroupID) REFERENCES ruleGroups(ruleGroupID),' + 'FOREIGN KEY (ruleStringID) REFERENCES ruleStrings(ruleStringID),' + 'FOREIGN KEY (adminID) REFERENCES admin(adminID)' + ');' + 'INSERT INTO rules ' + 'SELECT ruleID,ruleGroupID,ruleStringID,adminID ' + 'FROM newRules ' + 'JOIN ruleGroups;' + 'DROP TABLE newRules;' + 'DROP TABLE IF EXISTS newComments;' ,function(err){ reportStep(1,err); extractRules(); }); }; var rulesCount = 0; var lst = []; // Extract rules from existing comments function extractRules() { var sql = 'SELECT adminID,string FROM comments JOIN strings USING(stringID);'; db.all(sql,function(err,rows){ reportStep(2,err); for (var i=0,ilen=rows.length;i<ilen;i+=1) { var row = rows[i]; // Check whether the comment text contains one or more rules var tlst = row.string.split('\n\n'); for (var j=tlst.length-1;j>-1;j+=-1) { var m = tlst[j].match(/^>>>(.*)/); if (m) { var rule = m[1].replace(/^\s+/,'').replace(/\s+$/,''); lst.push({adminID:row.adminID,ruleText:rule}); //console.log("confirm: "+lst[lst.length-1].ruleText+ ', type='+typeof lst[lst.length-1].ruleText+" LEN="+lst.length); } } } rulesCount = lst.length; checkRuleStrings(lst,0,lst.length); }); }; function checkRuleStrings(lst,pos,limit) { if (pos === limit) { setVersion(); return; } //console.log("checkRuleStrings()"); var sql = 'SELECT ruleStringID FROM ruleStrings WHERE string=?'; var ruleText = lst[pos].ruleText; db.get(sql,[ruleText],function(err,row){ if (err) {throw 'Error in upgrades/checkRuleString(): '+err}; if (row && row.ruleStringID) { lst[pos].ruleStringID = row.ruleStringID; checkRule(lst,pos,limit); } else { addRuleString(lst,pos,limit); } }); }; function addRuleString (lst,pos,limit) { //console.log(" addRuleString()"); var ruleText = lst[pos].ruleText; var sql = 'INSERT INTO ruleStrings VALUES (NULL,?)'; db.run(sql,[ruleText],function(err){ if (err) {throw 'Error in upgrades/addRuleString(): '+err+" -- "+ ruleText}; lst[pos].ruleStringID = this.lastID; checkRule(lst,pos,limit); }); }; function checkRule(lst,pos,limit) { //console.log(" checkRule()"); var adminID = lst[pos].adminID; var ruleStringID = lst[pos].ruleStringID; var sql = 'SELECT ruleID FROM rules WHERE adminID=? AND ruleStringID=?'; db.get(sql,[adminID,ruleStringID],function(err,row){ if (err) {throw 'Error in upgrades/checkRule()'}; if (row && row.ruleID) { rulesCount += -1; if (!rulesCount) { setVersion(); } else { // Go back and do the next //console.log("rulesCount: "+rulesCount); pos += 1; checkRuleStrings(lst,pos,limit); } } else { addRule(lst,pos,limit); } }); }; function addRule(lst,pos,limit) { //console.log(" addRule()"); var ruleStringID = lst[pos].ruleStringID; var adminID = lst[pos].adminID; var sql = 'INSERT INTO rules VALUES (NULL,1,?,?)'; db.run(sql,[ruleStringID,adminID],function(err){ if (err) {throw 'Error in upgrades/addRule(): '+err}; rulesCount += -1; if (!rulesCount) { setVersion(); } else { // Go back and run the next pos += 1; checkRuleStrings(lst,pos,limit); } }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(3,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ db.run('PRAGMA foreign_keys = ON;',function(err){ reportStep(4,err); nextStep(); }); }); } }, function () { db.run('PRAGMA foreign_keys = OFF;',function(err) { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); }); function performUpgrade (){ db.exec( 'CREATE TEMP TABLE newRuleTranslationEdits AS SELECT * FROM ruleTranslationEdits;' + 'DROP TABLE ruleTranslationEdits;' + 'CREATE TEMP TABLE newRuleTranslations AS SELECT * FROM ruleTranslations;' + 'DROP TABLE ruleTranslations;' + 'CREATE TABLE ruleTranslations (' + 'ruleTranslationID INTEGER PRIMARY KEY,' + 'ruleID NOT NULL,' + 'string TEXT,' + 'lang TEXT NOT NULL,' + 'UNIQUE (ruleID,lang),' + 'FOREIGN KEY (ruleID) REFERENCES rules(ruleID)' + ');' + 'INSERT INTO ruleTranslations SELECT * FROM newRuleTranslations;' + 'CREATE TABLE ruleTranslationEdits (' + 'ruleTranslationEditID INTEGER PRIMARY KEY,' + 'ruleTranslationID INTEGER NOT NULL,' + 'studentID INTEGER,' + 'editDate DATE,' + 'FOREIGN KEY (ruleTranslationID) REFERENCES ruleTranslations(ruleTranslationID),' + 'FOREIGN KEY (studentID) REFERENCES students(studentID)' + ');' + 'INSERT INTO ruleTranslationEdits SELECT * FROM newRuleTranslationEdits;' + 'DROP TABLE newRuleTranslations;' + 'DROP TABLE newRuleTranslationEdits;' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ db.run('PRAGMA foreign_keys = ON;',function(err){ reportStep(3,err); nextStep(); }); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'DROP TABLE ruleTranslationEdits;' + 'CREATE TABLE ruleTranslationEdits (' + 'ruleTranslationEditID INTEGER PRIMARY KEY,' + 'ruleTranslationID INTEGER NOT NULL,' + 'studentID INTEGER,' + 'adminID INTEGER,' + 'editDate DATE,' + 'FOREIGN KEY (ruleTranslationID) REFERENCES ruleTranslations(ruleTranslationID),' + ' FOREIGN KEY (studentID) REFERENCES students(studentID)' + ');' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( "INSERT INTO languages VALUES ('de','German');" + "INSERT INTO languages VALUES ('pt-BR','Portuguese (br)');" ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( "ALTER TABLE memberships ADD COLUMN last_key_date DATE;" ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } }, function () { db.run('BEGIN TRANSACTION',function(err){ reportStep(0,err); performUpgrade(); }); function performUpgrade (){ db.exec( 'UPDATE memberships SET last_key_date=DATE("now") WHERE last_key_date IS NULL AND studentKey IS NOT NULL;' ,function(err){ reportStep(1,err); setVersion(); }); }; function setVersion () { db.run('UPDATE version SET version=? WHERE schema=?',[(pos+2),'quizzer'],function(err){ reportStep(2,err); closeTransaction(); }); } function closeTransaction () { db.run('END TRANSACTION',function(err){ reportStep(3,err); nextStep(); }); } } ]; function reportStep(opno,err) { if (err) throw 'Upgrade error at step pos=' + pos + '(' + opno + '): ' + err; if (!opno) { console.log("* Migrating version " + (pos+1) + " schema to version " + (pos+2)); } }; function nextStep() { pos += 1; if (pos === steps.length) { callback(); } else { steps[pos](); } }; steps[pos](); }; exports.upgraderClass = upgraderClass; })();