Skip to content

Commit 2e51600

Browse files
samogotkoistya
authored andcommitted
Add support of sql-template-strings, v3.0.0 (#66)
1 parent e3a1406 commit 2e51600

9 files changed

Lines changed: 969 additions & 1008 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
### [v3.0.0]
6+
> 2018-08-22
7+
8+
- Add support for ES6 tagged template strings ([#66](https://github.com/kriasoft/node-sqlite/pull/66))
9+
510
### [v2.9.3]
611
> 2018-08-22
712

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,22 @@ app.get('/post/:id', async (req, res, next) => {
5757
app.listen(port);
5858
```
5959

60+
### ES6 tagged template strings
61+
62+
This module is compatible with [sql-template-strings](https://www.npmjs.com/package/sql-template-strings).
63+
64+
```js
65+
import SQL from 'sql-template-strings';
66+
import sqlite from 'sqlite';
67+
68+
const db = await sqlite.open('./database.sqlite');
69+
70+
const book = 'harry potter';
71+
const author = 'J. K. Rowling';
72+
73+
const data = await db.all(SQL`SELECT author FROM books WHERE name = ${book} AND author = ${author}`);
74+
```
75+
6076
### Cached DB Driver
6177

6278
If you want to enable the [database object cache](https://github.com/mapbox/node-sqlite3/wiki/Caching)
@@ -156,6 +172,7 @@ main();
156172

157173
* [Using SQLite with Node.js for Rapid Prototyping](https://medium.com/@tarkus/node-js-and-sqlite-for-rapid-prototyping-bc9cf1f26f10) on Medium.com
158174
* [SQLite Documentation](https://www.sqlite.org/docs.html), e.g. [SQL Syntax](https://www.sqlite.org/lang.html), [Data Types](https://www.sqlite.org/datatype3.html) etc. on SQLite.org
175+
* ES6 tagged [sql-template-strings](https://www.npmjs.com/package/sql-template-strings).
159176

160177

161178
### Related Projects

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"private": true,
33
"name": "sqlite",
4-
"version": "2.9.3",
4+
"version": "3.0.0",
55
"description": "SQLite client for Node.js applications with SQL-based migrations API",
66
"repository": "kriasoft/node-sqlite",
77
"author": "Kriasoft <hello@kriasoft.com> (https://www.kriasoft.com)",
@@ -68,6 +68,9 @@
6868
"rollup": "^0.41.4",
6969
"rollup-plugin-babel": "^2.7.1"
7070
},
71+
"optionalDependencies": {
72+
"sql-template-strings": "^2.2.2"
73+
},
7174
"scripts": {
7275
"lint": "eslint src test tools",
7376
"test": "node tools/build && mocha",

src/Database.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import path from 'path';
1212
// eslint-disable-next-line no-unused-vars,import/no-unresolved,import/extensions
1313
import sqlite3 from 'sqlite3'; // import sqlite3 for jsdoc type information only
1414
import Statement from './Statement';
15-
import prepareParams from './utils';
15+
import { resolveTemplateStringObject } from './utils';
1616

1717
class Database {
1818
/**
@@ -50,8 +50,8 @@ class Database {
5050
this.driver.on(eventName, listener);
5151
}
5252

53-
run(sql) {
54-
const params = prepareParams(arguments, { offset: 1 });
53+
run() {
54+
const { sql, params } = resolveTemplateStringObject(arguments);
5555
const Promise = this.Promise;
5656
return new Promise((resolve, reject) => {
5757
this.driver.run(sql, params, function runExecResult(err) {
@@ -67,8 +67,8 @@ class Database {
6767
});
6868
}
6969

70-
get(sql) {
71-
const params = prepareParams(arguments, { offset: 1 });
70+
get() {
71+
const { sql, params } = resolveTemplateStringObject(arguments);
7272
return new this.Promise((resolve, reject) => {
7373
this.driver.get(sql, params, (err, row) => {
7474
if (err) {
@@ -80,8 +80,8 @@ class Database {
8080
});
8181
}
8282

83-
all(sql) {
84-
const params = prepareParams(arguments, { offset: 1 });
83+
all() {
84+
const { sql, params } = resolveTemplateStringObject(arguments);
8585
return new this.Promise((resolve, reject) => {
8686
this.driver.all(sql, params, (err, rows) => {
8787
if (err) {
@@ -108,8 +108,8 @@ class Database {
108108
});
109109
}
110110

111-
each(sql) {
112-
const params = prepareParams(arguments, { offset: 1, excludeLastArg: true });
111+
each() {
112+
const { sql, params } = resolveTemplateStringObject(arguments, { excludeLastArg: true });
113113
const callback = arguments[arguments.length - 1];
114114
return new this.Promise((resolve, reject) => {
115115
this.driver.each(sql, params, callback, (err, rowsCount = 0) => {
@@ -122,8 +122,8 @@ class Database {
122122
});
123123
}
124124

125-
prepare(sql) {
126-
const params = prepareParams(arguments, { offset: 1 });
125+
prepare() {
126+
const { sql, params } = resolveTemplateStringObject(arguments);
127127
return new this.Promise((resolve, reject) => {
128128
const stmt = this.driver.prepare(sql, params, (err) => {
129129
if (err) {

src/Statement.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* LICENSE.txt file in the root directory of this source tree.
88
*/
99

10-
import prepareParams from './utils';
10+
import { prepareParams } from './utils';
1111

1212
class Statement {
1313

src/main.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { SQLStatement } from "sql-template-strings";
2+
13
declare module 'sqlite' {
24
export interface Statement {
35
readonly sql: string;
@@ -35,26 +37,33 @@ declare module 'sqlite' {
3537

3638
run(sql: string): Promise<Statement>;
3739
run(sql: string, ...params: any[]): Promise<Statement>;
40+
run(sql: SQLStatement): Promise<Statement>;
3841

3942
get(sql: string): Promise<any>;
4043
get(sql: string, ...params: any[]): Promise<any>;
44+
get(sql: SQLStatement): Promise<any>;
4145

4246
get<T>(sql: string): Promise<T>;
4347
get<T>(sql: string, ...params: any[]): Promise<T>;
48+
get<T>(sql: SQLStatement): Promise<T>;
4449

4550
all(sql: string): Promise<any[]>;
4651
all(sql: string, ...params: any[]): Promise<any[]>;
52+
all(sql: SQLStatement): Promise<any[]>;
4753

4854
all<T>(sql: string): Promise<T[]>;
4955
all<T>(sql: string, ...params: any[]): Promise<T[]>;
56+
all<T>(sql: SQLStatement): Promise<T[]>;
5057

5158
exec(sql: string): Promise<Database>;
5259

5360
each(sql: string, callback?: (err: Error, row: any) => void): Promise<number>;
5461
each(sql: string, ...params: any[]): Promise<number>;
62+
each(sql: SQLStatement, callback?: (err: Error, row: any) => void): Promise<number>;
5563

5664
prepare(sql: string): Promise<Statement>;
5765
prepare(sql: string, ...params: any[]): Promise<Statement>;
66+
prepare(sql: SQLStatement): Promise<Statement>;
5867

5968
configure(option: "busyTimeout", value: number): void;
6069
configure(option: string, value: any): void;

src/utils.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,24 @@
55
* LICENSE.txt file in the root directory of this source tree.
66
*/
77

8-
function prepareParams(args, { offset = 0, excludeLastArg = false } = {}) {
8+
export function prepareParams(args, { offset = 0, excludeLastArg = false } = {}) {
99
const hasOneParam = (args.length === (offset + 1 + (excludeLastArg ? 1 : 0)));
1010
if (hasOneParam) {
1111
return args[offset];
1212
}
1313
return Array.prototype.slice.call(args, offset, args.length - (excludeLastArg ? 1 : 0));
1414
}
1515

16-
export default prepareParams;
16+
export function resolveTemplateStringObject(args, { offset = 0, excludeLastArg = false } = {}) {
17+
const hasOneParam = (args.length === (offset + 1 + (excludeLastArg ? 1 : 0)));
18+
if (hasOneParam && typeof args[offset] === 'object') {
19+
return {
20+
sql: args[offset].sql,
21+
params: args[offset].values,
22+
};
23+
}
24+
return {
25+
sql: args[offset],
26+
params: prepareParams(args, { offset: offset + 1, excludeLastArg }),
27+
};
28+
}

test/spec.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
const db = require('../build/main');
1111
const expect = require('chai').expect;
12+
const SQL = require('sql-template-strings');
1213

1314
// enable the sqlite cached database or not
1415
const cache = [false, true];
@@ -150,6 +151,37 @@ it('Should handle BLOBs', (done) => {
150151
p.then(done, done);
151152
});
152153

154+
it('Should work with sql-template-strings', (done) => {
155+
let p = db.open(':memory:');
156+
const value1 = 'test';
157+
const value2 = 'foo';
158+
p = p.then(() => db.exec('CREATE TABLE tbl (col TEXT)'));
159+
p = p.then(() => db.run(SQL`INSERT INTO tbl VALUES (${value1})`));
160+
p = p.then(() => db.get(SQL`SELECT col FROM tbl`).then((result) => {
161+
expect(result).to.be.deep.equal({ col: value1 });
162+
}));
163+
p = p.then(() => db.all(SQL`SELECT col FROM tbl`).then((result) => {
164+
expect(result).to.be.deep.equal([{ col: value1 }]);
165+
}));
166+
p = p.then(() => db.all(SQL`SELECT * FROM tbl WHERE col = ${value1}`).then((result) => {
167+
expect(result).to.have.length(1);
168+
}));
169+
p = p.then(() => db.prepare(SQL`UPDATE tbl SET col = ${value2} WHERE col = ${value1}`)).then(s => s.run().then((stmt) => {
170+
// Cannot use deep equals because stmt is a Statement instance
171+
expect(stmt.lastID).to.equal(1);
172+
expect(stmt.changes).to.equal(1);
173+
expect(stmt.sql).to.equal('UPDATE tbl SET col = ? WHERE col = ?');
174+
return stmt.finalize();
175+
}));
176+
p = p.then(() => db.each(SQL`SELECT col FROM tbl`, (err, result) => {
177+
expect(result).to.be.deep.equal({ col: value2 });
178+
}).then((rowsCount) => {
179+
expect(rowsCount).to.equal(1);
180+
}));
181+
p = p.then(() => db.close());
182+
p.then(done, done);
183+
});
184+
153185
it('Should migrate the database', (done) => {
154186
let p = db.open(':memory:');
155187
p = p.then(() => db.migrate());

0 commit comments

Comments
 (0)