Skip to content

Commit e268ebe

Browse files
author
Andrea Giammarchi
committed
Improved append(...) and nested statements
This MR addresses all concerns and optimizations reised in felixfbecker#30 and felixfbecker#44 * SQLStatement can be used as value * raw names can be passed via `'${'table_' + name}'` with `'` or `"` transform * `.append(...)` doesn't need a space at the beginning, it's handled automatically
1 parent 7be1d2a commit e268ebe

File tree

1 file changed

+34
-8
lines changed

1 file changed

+34
-8
lines changed

index.js

+34-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
'use strict'
22

3+
const lsp = str => (/^[\s\n\r]/.test(str) ? str : ' ' + str)
4+
const push = (str, val, statement, spaced) => {
5+
const { strings } = statement
6+
str[str.length - 1] += spaced ? lsp(strings[0]) : strings[0]
7+
str.push(...strings.slice(1))
8+
val.push(...(statement.values || statement.bind))
9+
}
10+
311
class SQLStatement {
412
/**
513
* @param {string[]} strings
@@ -25,20 +33,19 @@ class SQLStatement {
2533
* @returns {this}
2634
*/
2735
append(statement) {
36+
const { strings } = this
2837
if (statement instanceof SQLStatement) {
29-
this.strings[this.strings.length - 1] += statement.strings[0]
30-
this.strings.push.apply(this.strings, statement.strings.slice(1))
31-
const list = this.values || this.bind
32-
list.push.apply(list, statement.values)
38+
push(strings, this.values || this.bind, statement, true)
3339
} else {
34-
this.strings[this.strings.length - 1] += statement
40+
strings[strings.length - 1] += lsp(statement)
3541
}
3642
return this
3743
}
3844

3945
/**
4046
* Use a prepared statement with Sequelize.
41-
* Makes `query` return a query with `$n` syntax instead of `?` and switches the `values` key name to `bind`
47+
* Makes `query` return a query with `$n` syntax instead of `?`
48+
* and switches the `values` key name to `bind`
4249
* @param {boolean} [value=true] value If omitted, defaults to `true`
4350
* @returns this
4451
*/
@@ -79,8 +86,27 @@ Object.defineProperty(SQLStatement.prototype, 'sql', {
7986
* @param {...any} values
8087
* @returns {SQLStatement}
8188
*/
82-
function SQL(strings) {
83-
return new SQLStatement(strings.slice(0), Array.from(arguments).slice(1))
89+
function SQL(tpl, ...val) {
90+
const strings = [tpl[0]]
91+
const values = []
92+
for (let { length } = tpl, prev = tpl[0], j = 0, i = 1; i < length; i++) {
93+
const current = tpl[i]
94+
const value = val[i - 1]
95+
if (/^('|")/.test(current) && RegExp.$1 === prev.slice(-1)) {
96+
strings[j] = [strings[j].slice(0, -1), value, current.slice(1)].join('`')
97+
} else {
98+
if (value instanceof SQLStatement) {
99+
push(strings, values, value, false)
100+
j = strings.length - 1
101+
strings[j] += current
102+
} else {
103+
values.push(value)
104+
j = strings.push(current) - 1
105+
}
106+
prev = strings[j]
107+
}
108+
}
109+
return new SQLStatement(strings, values)
84110
}
85111

86112
module.exports = SQL

0 commit comments

Comments
 (0)