forked from bwestergard/node-postgres-named
-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.js
104 lines (58 loc) · 2.31 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
const uniq = require('lodash.uniq');
const map = require('lodash.map');
const difference = require('lodash.difference');
const intersection = require('lodash.intersection');
const reduce = require('lodash.reduce');
const isPlainObject = require('lodash.isplainobject');
const isString = require('lodash.isstring');
var tokenPattern = /\$[a-zA-Z]([a-zA-Z0-9_]*)\b/g;
function numericFromNamed(sql, parameters) {
var out = {};
var objTokens = Object.keys(parameters);
var sqlTokens = uniq(map(sql.match(tokenPattern), token => token.substring(1)));
var fillTokens = intersection(objTokens, sqlTokens).sort();
var fillValues = map(fillTokens, token => parameters[token]);
var unmatchedTokens = difference(sqlTokens, objTokens);
var missing = unmatchedTokens.join(', ');
var interpolatedSql = reduce(fillTokens, (partiallyInterpolated, token, index) => {
var replaceAllPattern = new RegExp(`\\$${fillTokens[index]}\\b`, 'g');
// PostGreSQL parameters are inexplicably 1-indexed.
return partiallyInterpolated.replace(replaceAllPattern, `$${index + 1}`);
}, sql);
if (unmatchedTokens.length) {
throw new Error(`Missing Parameters: ${missing}`);
}
out.sql = interpolatedSql;
out.values = fillValues;
return out;
}
function patch(client) {
var patchedQuery;
var originalQuery = client.query;
if (originalQuery.patched) return client;
originalQuery = originalQuery.bind(client);
// config, values, and callback
patchedQuery = (...args) => {
var cb;
var config;
var transformed;
// much prefer to check a whitelist then to check all possible
// blacklists like original repository...
if (isPlainObject(args[0]) && isPlainObject(args[0])) {
config = args[0];
transformed = numericFromNamed(config.text, config.values);
config.text = transformed.sql;
config.values = transformed.values;
}
if (isString(args[0]) && isPlainObject(args[1])) {
cb = (args.length === 3) ? args[2] : undefined;
transformed = numericFromNamed(args[0], args[1]);
return originalQuery(transformed.sql, transformed.values, cb);
}
return originalQuery(...args);
};
client.query = patchedQuery;
client.query.patched = true;
return client;
}
module.exports.patch = patch;