var _ = require('lodash');

var tokenPattern = /\$[a-zA-Z]([a-zA-Z0-9_]*)\b/g;

function numericFromNamed(sql, parameters) {
  var fillableTokens = Object.keys(parameters);
  var matchedTokens = _.uniq(_.map(sql.match(tokenPattern), function (token) {
    return token.substring(1); // Remove leading dollar sign
  }));

  var fillTokens = _.intersection(fillableTokens, matchedTokens).sort();
  var fillValues = _.map(fillTokens, function (token) {
    return parameters[token];
  });

  var unmatchedTokens = _.difference(matchedTokens, fillableTokens);

  if (unmatchedTokens.length) {
    var missing = unmatchedTokens.join(", ");
    throw new Error("Missing Parameters: " + missing);
  }

  var interpolatedSql = _.reduce(fillTokens,
  function (partiallyInterpolated, token, index) {
    var replaceAllPattern = new RegExp('\\$' + fillTokens[index] + '\\b', "g");
    return partiallyInterpolated
      .replace(replaceAllPattern,
               '$' + (index+1)); // PostGreSQL parameters are inexplicably 1-indexed.
  }, sql);

  var out = {};
  out.sql = interpolatedSql;
  out.values = fillValues;

  return out;
}

function patch (client) {
  var originalQuery = client.query;
  originalQuery = originalQuery.bind(client);

  var patchedQuery = function(config, values, callback) {
    if (_.isPlainObject(values)) {
      var reparameterized = numericFromNamed(config, values);
      return originalQuery(reparameterized.sql, reparameterized.values, callback);
    } else {
      return originalQuery(config, values, callback);
    }
  };

  client.query = patchedQuery;
}

module.exports.patch = patch;

@@ -1180,16 +1180,64 @@
 t.query;
+%0A%0A  if (originalQuery.patched) return client;%0A  
 %0A  origi
@@ -1624,16 +1624,65 @@
 dQuery;%0A
+  client.query.patched = true;%0A%0A  return client;%0A
 %7D%0A%0Amodul

Check for existence of patched client -> prevents stack overflow