www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

commit 643376769adac3de2531db6e56eabb60846eadaf
parent 2d619ff561c2aed4cbcc76a9c5c9fda01a34c108
Author: Dan Stillman <dstillman@zotero.org>
Date:   Sun, 17 May 2009 07:52:05 +0000

Automatically hard-code NULL bound parameters (e.g., convert "WHERE foo=?" to "WHERE foo IS NULL" and "SET foo=?" to "SET foo=NULL")


Diffstat:
Mchrome/content/zotero/xpcom/db.js | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 68 insertions(+), 12 deletions(-)

diff --git a/chrome/content/zotero/xpcom/db.js b/chrome/content/zotero/xpcom/db.js @@ -213,6 +213,65 @@ Zotero.DBConnection.prototype.columnQuery = function (sql,params) { Zotero.DBConnection.prototype.getStatement = function (sql, params, checkParams) { var db = this._getDBConnection(); + // First, determine the type of query using first word + var matches = sql.match(/^[^\s\(]*/); + queryMethod = matches[0].toLowerCase(); + + if (params) { + // If single scalar value or single non-array object, wrap in an array + if (typeof params != 'object' || params === null || + (params && typeof params == 'object' && !params.length)) { + var params = [params]; + } + + // Since we might make changes, only work on a copy of the array + var params = params.concat(); + + // Replace NULL bound parameters with hard-coded NULLs + var nullRE = /\s*=?\s*\?/g; + // Reset lastIndex, since regexp isn't recompiled dynamically + nullRE.lastIndex = 0; + var lastNullParamIndex = -1; + for (var i=0; i<params.length; i++) { + if (typeof params[i] != 'object' || params[i] !== null) { + continue; + } + + // Find index of this parameter, skipping previous ones + do { + var matches = nullRE.exec(sql); + lastNullParamIndex++; + } + while (lastNullParamIndex < i); + lastNullParamIndex = i; + + if (matches[0].indexOf('=') == -1) { + // mozStorage supports null bound parameters in value lists (e.g., "(?,?)") natively + continue; + //var repl = 'NULL'; + } + else if (queryMethod == 'select') { + var repl = ' IS NULL'; + } + else { + var repl = '=NULL'; + } + + var subpos = matches.index; + var sublen = matches[0].length; + sql = sql.substring(0, subpos) + repl + sql.substr(subpos + sublen); + + //Zotero.debug("Hard-coding null bound parameter " + i); + + params.splice(i, 1); + i--; + continue; + } + if (!params.length) { + params = undefined; + } + } + try { this._debug(sql,5); var statement = db.createStatement(sql); @@ -226,12 +285,6 @@ Zotero.DBConnection.prototype.getStatement = function (sql, params, checkParams) var numParams = statement.parameterCount; if (params) { - // If single scalar value or single non-array object, wrap in an array - if (typeof params != 'object' || params === null || - (params && typeof params == 'object' && !params.length)) { - params = [params]; - } - if (checkParams) { if (numParams == 0) { throw ("Parameters provided for query without placeholders"); @@ -243,6 +296,14 @@ Zotero.DBConnection.prototype.getStatement = function (sql, params, checkParams) } for (var i=0; i<params.length; i++) { + if (params[i] === undefined) { + Zotero.debug(params); + var msg = 'Parameter ' + i + ' is undefined in Zotero.DB.getStatement() [QUERY: ' + sql + ']'; + Zotero.debug(msg); + Components.utils.reportError(msg); + throw (msg); + } + // Integer if (params[i]!==null && typeof params[i]['int'] != 'undefined') { var type = 'int'; @@ -253,10 +314,6 @@ Zotero.DBConnection.prototype.getStatement = function (sql, params, checkParams) var type = 'string'; var value = params[i]['string']; } - // Null - else if (params[i]!==null && typeof params[i]['null'] != 'undefined') { - var type = 'null'; - } // Automatic (trust the JS type) else { switch (typeof params[i]) { @@ -316,8 +373,7 @@ Zotero.DBConnection.prototype.getStatement = function (sql, params, checkParams) break; case 'null': - this._debug('Binding parameter ' + (i+1) - + ' of type NULL', 5); + this._debug('Binding parameter ' + (i+1) + ' of type NULL', 5); statement.bindNullParameter(i); break; }