Skip to content

Commit

Permalink
Improved append(...) and nested statements
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Andrea Giammarchi committed Mar 1, 2019
1 parent 7be1d2a commit e268ebe
Showing 1 changed file with 34 additions and 8 deletions.
42 changes: 34 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
'use strict'

const lsp = str => (/^[\s\n\r]/.test(str) ? str : ' ' + str)
const push = (str, val, statement, spaced) => {
const { strings } = statement
str[str.length - 1] += spaced ? lsp(strings[0]) : strings[0]
str.push(...strings.slice(1))
val.push(...(statement.values || statement.bind))
}

class SQLStatement {
/**
* @param {string[]} strings
Expand All @@ -25,20 +33,19 @@ class SQLStatement {
* @returns {this}
*/
append(statement) {
const { strings } = this
if (statement instanceof SQLStatement) {
this.strings[this.strings.length - 1] += statement.strings[0]
this.strings.push.apply(this.strings, statement.strings.slice(1))
const list = this.values || this.bind
list.push.apply(list, statement.values)
push(strings, this.values || this.bind, statement, true)
} else {
this.strings[this.strings.length - 1] += statement
strings[strings.length - 1] += lsp(statement)
}
return this
}

/**
* Use a prepared statement with Sequelize.
* Makes `query` return a query with `$n` syntax instead of `?` and switches the `values` key name to `bind`
* Makes `query` return a query with `$n` syntax instead of `?`
* and switches the `values` key name to `bind`
* @param {boolean} [value=true] value If omitted, defaults to `true`
* @returns this
*/
Expand Down Expand Up @@ -79,8 +86,27 @@ Object.defineProperty(SQLStatement.prototype, 'sql', {
* @param {...any} values
* @returns {SQLStatement}
*/
function SQL(strings) {
return new SQLStatement(strings.slice(0), Array.from(arguments).slice(1))
function SQL(tpl, ...val) {
const strings = [tpl[0]]
const values = []
for (let { length } = tpl, prev = tpl[0], j = 0, i = 1; i < length; i++) {
const current = tpl[i]
const value = val[i - 1]
if (/^('|")/.test(current) && RegExp.$1 === prev.slice(-1)) {
strings[j] = [strings[j].slice(0, -1), value, current.slice(1)].join('`')
} else {
if (value instanceof SQLStatement) {
push(strings, values, value, false)
j = strings.length - 1
strings[j] += current
} else {
values.push(value)
j = strings.push(current) - 1
}
prev = strings[j]
}
}
return new SQLStatement(strings, values)
}

module.exports = SQL
Expand Down

0 comments on commit e268ebe

Please sign in to comment.