Skip to content

Commit 4aa29c7

Browse files
yannvgnlucleray
authored andcommitted
add sql.raw (#12)
* add sql.raw * update readme
1 parent 17ada3c commit 4aa29c7

File tree

6 files changed

+58
-22
lines changed

6 files changed

+58
-22
lines changed

lib/pg.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import _sql = require('./sql')
2-
import {
3-
IPGQueryable,
4-
IPGQueryConfig,
5-
IPGQueryResult,
6-
TemplateLiteralFunc
7-
} from './utils'
8-
9-
type PGSql = TemplateLiteralFunc<IPGQueryConfig> & {
2+
import { IPGQueryable, IPGQueryResult, Sql, TemplateLiteralFunc } from './utils'
3+
4+
type PGSql = Sql & {
105
query: <T extends IPGQueryResult>(
116
db: IPGQueryable<T>
127
) => TemplateLiteralFunc<Promise<T>>
@@ -17,6 +12,8 @@ type PGSql = TemplateLiteralFunc<IPGQueryConfig> & {
1712

1813
const sql = ((chains, ...expressions) => _sql(chains, ...expressions)) as PGSql
1914

15+
sql.raw = rawData => _sql.raw(rawData)
16+
2017
sql.query = db => (chains, ...expressions) =>
2118
db.query(_sql(chains, ...expressions))
2219

lib/sql.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { IPGQueryConfig, SqlContainer, TemplateLiteralFunc } from './utils'
1+
import { IPGQueryConfig, Sql, SqlContainer } from './utils'
22

33
function sqlText(
44
count: number,
@@ -39,7 +39,9 @@ function sqlText(
3939
}
4040
}
4141

42-
const sql: TemplateLiteralFunc<IPGQueryConfig> = (chains, ...expressions) =>
43-
sqlText(1, chains, expressions)
42+
const sql: Sql = ((chains, ...expressions) =>
43+
sqlText(1, chains, expressions)) as Sql
44+
45+
sql.raw = rawData => sqlText(1, [rawData], [])
4446

4547
export = sql

lib/utils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ export interface IPGQueryConfig {
2424
values: any[]
2525
}
2626

27+
export type Sql = TemplateLiteralFunc<IPGQueryConfig> & {
28+
raw: (rawData: string) => IPGQueryConfig
29+
}
30+
2731
export interface IPGQueryResult {
2832
rowCount: number
2933
rows: any[]

readme.md

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ const query = sql`
4040
and year <= ${yearRange[1]}
4141
`
4242

43-
// query looks like this :
43+
// query looks like this:
4444
// {
4545
// text: 'select * from books where author = $1 and year = $2',
4646
// values: [1983, 1992]
4747
// }
4848
```
4949

50-
You can also use conditions :
50+
You can also use conditions:
5151

5252
```js
5353
const sql = require('@sequencework/sql')
@@ -60,13 +60,13 @@ const findBookByAuthor = author => sql`
6060
}
6161
`
6262

63-
// findBookByAuthor() looks like this :
63+
// findBookByAuthor() looks like this:
6464
// {
6565
// text: 'select * from books',
6666
// values: []
6767
// }
6868

69-
// findBookByAuthor('steinbeck') looks like this :
69+
// findBookByAuthor('steinbeck') looks like this:
7070
// {
7171
// text: 'select * from books where author = $1',
7272
// values: ['steinbeck']
@@ -91,9 +91,18 @@ sql`
9191
`
9292
```
9393

94+
It's also possible to pass raw, unescaped data to your queries. For that, use `sql.raw`:
95+
96+
```js
97+
const tableName = 'books'
98+
const query = sql`select * from ${sql.raw(tableName)}`
99+
```
100+
101+
💥 Please, be careful! Remember that the raw values won't be replaced by a placeholder and thus won't be escaped!
102+
94103
### Example with [node-postgres](https://github.com/brianc/node-postgres)
95104

96-
We start by creating a function :
105+
We start by creating a function:
97106

98107
```js
99108
// movies.js
@@ -124,7 +133,7 @@ const db = new Pool()
124133
module.exports = db
125134
```
126135

127-
Finally, we connect everything :
136+
Finally, we connect everything:
128137

129138
```js
130139
// main.js
@@ -140,7 +149,7 @@ const main = async () => {
140149
main()
141150
```
142151

143-
We can even create a **transaction** (useless in this example, but it's just to show that our previous function is reusable) :
152+
We can even create a **transaction** (useless in this example, but it's just to show that our previous function is reusable):
144153

145154
```js
146155
const main = async () => {
@@ -165,21 +174,27 @@ const main = async () => {
165174

166175
#### Shorthand for postgres
167176

168-
Since we ❤️ [node-postgres](https://github.com/brianc/node-postgres) so much, we created shorthands and helpers for it :
177+
Since we ❤️ [node-postgres](https://github.com/brianc/node-postgres) so much, we created shorthands and helpers for it:
169178

170179
```js
171180
const sql = require('@sequencework/sql/pg') // ⚠️ we import @sequencework/sql/pg
172181

173182
// main export stays the same
174183
const query = sql`select * from movies where id = ${id}`
175184

176-
// default pg result object : https://node-postgres.com/api/result
185+
// sql.raw is also there
186+
const booksTable = 'books'
187+
const booksQuery = sql`select * from ${sql.raw(booksTable)}`
188+
189+
// default pg result object: https://node-postgres.com/api/result
177190
const { rows, rowCount } = await sql.query(db)`select * from movies`
178191

179192
// helpers
180193
const movies = await sql.many(db)`select * from movies`
181194
const movie = await sql.one(db)`select * from movies where id = ${id}`
182-
const nbMovie = await sql.count(db)`update from movies set name = ${name} where id = ${id}`
195+
const nbMovie = await sql.count(
196+
db
197+
)`update from movies set name = ${name} where id = ${id}`
183198
```
184199

185200
You can then rewrite the previous `listMoviesByYear` function in a much more concise way 😎
@@ -214,7 +229,7 @@ const query = sql`
214229

215230
### More
216231

217-
This package is inspired by the great [sql-template-strings](https://github.com/felixfbecker/node-sql-template-strings). Some interesting features that we were missing :
232+
This package is inspired by the great [sql-template-strings](https://github.com/felixfbecker/node-sql-template-strings). Some interesting features that we were missing:
218233

219234
- nested `sql` tags
220235
- ignore `undefined` expressions in `sql`

test/pg.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,13 @@ test('sql.count should return rowCount', async () => {
4646
const nbBooks = await sql.count(db)`select * from books where read = ${false}`
4747
expect(nbBooks).toBe(sampleBooks.length)
4848
})
49+
50+
test('sql.raw should work with pg shorthand', async () => {
51+
const tableName = 'books'
52+
const { rows, rowCount, oid } = await sql.query(db)`select * from ${sql.raw(
53+
tableName
54+
)} where read = ${false}`
55+
expect(rows).toBe(sampleBooks)
56+
expect(rowCount).toBe(sampleBooks.length)
57+
expect(oid).toBe(1)
58+
})

test/sql.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,11 @@ test('json as query parameter', () => {
102102
expect(query.values).toHaveLength(1)
103103
expect(query.values[0]).toBe(jsonValue)
104104
})
105+
106+
test('query with raw data', () => {
107+
const tableName = 'books'
108+
const query = sql`select * from ${sql.raw(tableName)} where read = ${false}`
109+
expect(trimSpaces(query.text)).toBe('select * from books where read = $1')
110+
expect(query.values).toHaveLength(1)
111+
expect(query.values[0]).toBe(false)
112+
})

0 commit comments

Comments
 (0)