Skip to content

Commit a688b21

Browse files
committed
Handle case when SQLStatement passed as parameter.
Closes felixfbecker#30.
1 parent 7d38214 commit a688b21

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

index.js

+30-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,36 @@ class SQLStatement {
77
* @param {any[]} values
88
*/
99
constructor(strings, values) {
10-
this.strings = strings
11-
this.values = values
10+
if (values.length === 0) {
11+
this.strings = strings
12+
this.values = values
13+
} else {
14+
this.strings = []
15+
this.values = []
16+
let prevOpened = false
17+
const valuesLength = values.length
18+
for (let i = 0; i < valuesLength; i++) {
19+
if (prevOpened) {
20+
this.strings[this.strings.length - 1] += strings[i]
21+
prevOpened = false
22+
} else {
23+
this.strings.push(strings[i])
24+
}
25+
const value = values[i]
26+
if (value instanceof SQLStatement) {
27+
this.append(value)
28+
prevOpened = true
29+
} else {
30+
this.values.push(value)
31+
}
32+
}
33+
if (prevOpened) {
34+
this.strings[this.strings.length - 1] += strings[valuesLength]
35+
prevOpened = false
36+
} else {
37+
this.strings.push(strings[valuesLength])
38+
}
39+
}
1240
}
1341

1442
/** Returns the SQL Statement for Sequelize */

test/unit.js

+39
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,45 @@ describe('SQL', () => {
7777
})
7878
})
7979

80+
describe('pass nested SQLStatement instances', () => {
81+
it('should not handle nested SQLStatement as parameter', () => {
82+
const nested = SQL`table_name`
83+
const statement = SQL`SELECT * FROM ${nested}`
84+
assert.equal(statement.sql, 'SELECT * FROM table_name')
85+
assert.equal(statement.text, 'SELECT * FROM table_name')
86+
assert.deepEqual(statement.values, [])
87+
})
88+
89+
it('should merge SQLStatement instances parameters', () => {
90+
const nested = SQL`SELECT id FROM table2 WHERE key = ${'value'}`
91+
const statement = SQL`SELECT * FROM table1 WHERE id IN (${nested})`
92+
assert.equal(statement.sql, 'SELECT * FROM table1 WHERE id IN (SELECT id FROM table2 WHERE key = ?)')
93+
assert.equal(statement.text, 'SELECT * FROM table1 WHERE id IN (SELECT id FROM table2 WHERE key = $1)')
94+
assert.deepEqual(statement.values, ['value'])
95+
})
96+
97+
it('should merge SQLStatement instances parameters, 3 nested statements test', () => {
98+
const s1 = SQL`SELECT id FROM table WHERE key=${'value1'}`
99+
const s2 = SQL`SELECT id FROM table2 WHERE key=${'value0'} AND key2 IN (${s1})`
100+
const s3 = SQL`SELECT id FROM table3 WHERE key=${'value2'} AND key3 IN (${s2})`
101+
assert.equal(
102+
s3.sql,
103+
'SELECT id FROM table3 WHERE key=? AND key3 IN (SELECT id FROM table2 WHERE key=? AND key2 IN (SELECT id FROM table WHERE key=?))'
104+
)
105+
assert.equal(
106+
s3.text,
107+
'SELECT id FROM table3 WHERE key=$1 AND key3 IN (SELECT id FROM table2 WHERE key=$2 AND key2 IN (SELECT id FROM table WHERE key=$3))'
108+
)
109+
assert.deepEqual(s3.values, ['value2', 'value0', 'value1'])
110+
})
111+
112+
it('should not handle nested SQLStatement as parameter, if passed first', () => {
113+
const statement = SQL`${SQL`SELECT`} * FROM table`
114+
assert.equal(statement.sql, 'SELECT * FROM table')
115+
assert.deepEqual(statement.values, [])
116+
})
117+
})
118+
80119
describe('setName()', () => {
81120

82121
it('should set the name and return this', () => {

0 commit comments

Comments
 (0)