-
Notifications
You must be signed in to change notification settings - Fork 78
/
builder.js
127 lines (105 loc) · 2.98 KB
/
builder.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
'use strict';
var _ = require('underscore');
var dialectsHash = {
base: require('./dialects/base'),
mssql: require('./dialects/mssql'),
postgresql: require('./dialects/postgresql'),
sqlite: require('./dialects/sqlite'),
mysql: require('./dialects/mysql')
};
var Builder = module.exports = function(options) {
this.configure(options);
};
Builder.prototype._reset = function() {
if (this.options.separatedValues) {
this._placeholderId = 1;
this._values = this.options.namedValues ? {} : [];
} else {
delete this._placeholderId;
delete this._values;
}
this._query = '';
};
Builder.prototype._getPlaceholder = function () {
var placeholder = '';
if (this.options.namedValues) placeholder += 'p';
if (this.options.indexedValues) placeholder += this._placeholderId++;
return placeholder;
};
Builder.prototype._wrapPlaceholder = function(name) {
return this.options.valuesPrefix + name;
};
Builder.prototype._pushValue = function(value) {
if (_.isUndefined(value) || _.isNull(value)) {
return 'null';
} else if (_.isNumber(value) || _.isBoolean(value)) {
return String(value);
} else if (_.isString(value) || _.isDate(value)) {
if (this.options.separatedValues) {
var placeholder = this._getPlaceholder();
if (this.options.namedValues) {
this._values[placeholder] = value;
} else {
this._values.push(value);
}
return this._wrapPlaceholder(placeholder);
} else {
if (_.isDate(value)) value = value.toISOString();
return '\'' + value + '\'';
}
} else {
throw new Error('Wrong value type "' + (typeof value) + '"');
}
};
Builder.prototype.configure = function(options) {
options = _.defaults({}, options, {
separatedValues: true,
namedValues: true,
valuesPrefix: '$',
dialect: 'base',
wrappedIdentifiers: true,
indexedValues: true
});
if (options.namedValues && !options.indexedValues) {
throw new Error(
'Option `indexedValues`: false is ' +
'not allowed together with option `namedValues`: true'
);
}
this.options = options;
this.setDialect(this.options.dialect);
this._reset();
};
Builder.prototype.build = function(params) {
var builder = this;
this._reset();
this._query = this.dialect.buildTemplate('query', {queryBody: params}) + ';';
if (this.options.separatedValues) {
return {
query: this._query,
values: this._values,
prefixValues: function() {
var values = {};
_(this.getValuesObject()).each(function(value, name) {
values[builder._wrapPlaceholder(name)] = value;
});
return values;
},
getValuesArray: function() {
return _.isArray(this.values) ? this.values : _(this.values).values();
},
getValuesObject: function() {
return _.isArray(this.values) ? _(_.range(1, this.values.length + 1)).object(this.values) :
this.values;
}
};
} else {
return {query: this._query};
}
};
Builder.prototype.setDialect = function(name) {
if (!dialectsHash[name]) {
throw new Error('Unknown dialect "' + name + '"');
}
this.dialect = new (dialectsHash[name])(this);
};