forked from nearform/sql
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SQL.js
135 lines (106 loc) · 3.07 KB
/
SQL.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
128
129
130
131
132
133
134
135
'use strict'
const inspect = Symbol.for('nodejs.util.inspect.custom')
class SqlStatement {
constructor (strings, values) {
if (values.some(value => value === undefined)) {
throw new Error('SQL`...` strings cannot take `undefined` as values as this can generate invalid sql.')
}
this.strings = strings
this.values = values
}
glue (pieces, separator) {
const result = { strings: [], values: [] }
let carryover
for (let i = 0; i < pieces.length; i++) {
let strings = Array.from(pieces[i].strings)
if (typeof carryover === 'string') {
strings[0] = carryover + separator + strings[0]
carryover = null
}
if (strings.length > pieces[i].values.length) {
carryover = strings.splice(-1)[0]
}
result.strings = result.strings.concat(strings)
result.values = result.values.concat(pieces[i].values)
}
if (typeof carryover === 'string') {
result.strings.push(carryover)
}
if (result.strings.length === result.values.length) {
result.strings.push('')
}
result.strings[result.strings.length - 1] += ' '
return new SqlStatement(
result.strings,
result.values
)
}
generateString (type) {
let text = this.strings[0]
for (var i = 1; i < this.strings.length; i++) {
let delimiter = '?'
if (type === 'pg') {
delimiter = '$' + i
}
text += delimiter + this.strings[i]
}
return text
.replace(/\s+$/mg, ' ')
.replace(/^\s+|\s+$/mg, '')
}
get debug () {
let text = this.strings[0]
let data
for (var i = 1; i < this.strings.length; i++) {
data = this.values[i - 1]
typeof data === 'string' ? text += "'" + data + "'" : text += data
text += this.strings[i]
}
return text
.replace(/\s+$/mg, ' ')
.replace(/^\s+|\s+$/mg, '')
}
[inspect] () {
return `SQL << ${this.debug} >>`
}
get text () {
return this.generateString('pg')
}
get sql () {
return this.generateString('mysql')
}
append (statement, options) {
if (!statement) {
return this
}
if (!(statement instanceof SqlStatement)) {
throw new Error('"append" accepts only template string prefixed with SQL (SQL`...`)')
}
if (options && options.unsafe === true) {
const text = statement.strings.reduce((acc, string, i) => {
acc = `${acc}${string}${statement.values[i] ? statement.values[i] : ''}`
return acc
}, '')
const strings = this.strings.slice(0)
strings[this.strings.length - 1] += text
this.strings = strings
return this
}
const last = this.strings[this.strings.length - 1]
const [first, ...rest] = statement.strings
this.strings = [
...this.strings.slice(0, -1),
last + first,
...rest
]
this.values.push.apply(this.values, statement.values)
return this
}
}
function SQL (strings, ...values) {
return new SqlStatement(strings, values)
}
SQL.glue = SqlStatement.prototype.glue
module.exports = SQL
module.exports.SQL = SQL
module.exports.default = SQL