Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions lib/pg.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import _sql = require('./sql')
import {
IPGQueryable,
IPGQueryConfig,
IPGQueryResult,
TemplateLiteralFunc
} from './utils'

type PGSql = TemplateLiteralFunc<IPGQueryConfig> & {
import { IPGQueryable, IPGQueryResult, Sql, TemplateLiteralFunc } from './utils'

type PGSql = Sql & {
query: <T extends IPGQueryResult>(
db: IPGQueryable<T>
) => TemplateLiteralFunc<Promise<T>>
Expand All @@ -17,6 +12,8 @@ type PGSql = TemplateLiteralFunc<IPGQueryConfig> & {

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

sql.raw = rawData => _sql.raw(rawData)

sql.query = db => (chains, ...expressions) =>
db.query(_sql(chains, ...expressions))

Expand Down
8 changes: 5 additions & 3 deletions lib/sql.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IPGQueryConfig, SqlContainer, TemplateLiteralFunc } from './utils'
import { IPGQueryConfig, Sql, SqlContainer } from './utils'

function sqlText(
count: number,
Expand Down Expand Up @@ -39,7 +39,9 @@ function sqlText(
}
}

const sql: TemplateLiteralFunc<IPGQueryConfig> = (chains, ...expressions) =>
sqlText(1, chains, expressions)
const sql: Sql = ((chains, ...expressions) =>
sqlText(1, chains, expressions)) as Sql

sql.raw = rawData => sqlText(1, [rawData], [])

export = sql
4 changes: 4 additions & 0 deletions lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export interface IPGQueryConfig {
values: any[]
}

export type Sql = TemplateLiteralFunc<IPGQueryConfig> & {
raw: (rawData: string) => IPGQueryConfig
}

export interface IPGQueryResult {
rowCount: number
rows: any[]
Expand Down
37 changes: 26 additions & 11 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ const query = sql`
and year <= ${yearRange[1]}
`

// query looks like this :
// query looks like this:
// {
// text: 'select * from books where author = $1 and year = $2',
// values: [1983, 1992]
// }
```

You can also use conditions :
You can also use conditions:

```js
const sql = require('@sequencework/sql')
Expand All @@ -60,13 +60,13 @@ const findBookByAuthor = author => sql`
}
`

// findBookByAuthor() looks like this :
// findBookByAuthor() looks like this:
// {
// text: 'select * from books',
// values: []
// }

// findBookByAuthor('steinbeck') looks like this :
// findBookByAuthor('steinbeck') looks like this:
// {
// text: 'select * from books where author = $1',
// values: ['steinbeck']
Expand All @@ -91,9 +91,18 @@ sql`
`
```

It's also possible to pass raw, unescaped data to your queries. For that, use `sql.raw`:

```js
const tableName = 'books'
const query = sql`select * from ${sql.raw(tableName)}`
```

💥 Please, be careful! Remember that the raw values won't be replaced by a placeholder and thus won't be escaped!

### Example with [node-postgres](https://github.com/brianc/node-postgres)

We start by creating a function :
We start by creating a function:

```js
// movies.js
Expand Down Expand Up @@ -124,7 +133,7 @@ const db = new Pool()
module.exports = db
```

Finally, we connect everything :
Finally, we connect everything:

```js
// main.js
Expand All @@ -140,7 +149,7 @@ const main = async () => {
main()
```

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

```js
const main = async () => {
Expand All @@ -165,21 +174,27 @@ const main = async () => {

#### Shorthand for postgres

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

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

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

// default pg result object : https://node-postgres.com/api/result
// sql.raw is also there
const booksTable = 'books'
const booksQuery = sql`select * from ${sql.raw(booksTable)}`

// default pg result object: https://node-postgres.com/api/result
const { rows, rowCount } = await sql.query(db)`select * from movies`

// helpers
const movies = await sql.many(db)`select * from movies`
const movie = await sql.one(db)`select * from movies where id = ${id}`
const nbMovie = await sql.count(db)`update from movies set name = ${name} where id = ${id}`
const nbMovie = await sql.count(
db
)`update from movies set name = ${name} where id = ${id}`
```

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

### More

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 :
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:

- nested `sql` tags
- ignore `undefined` expressions in `sql`
Expand Down
10 changes: 10 additions & 0 deletions test/pg.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,13 @@ test('sql.count should return rowCount', async () => {
const nbBooks = await sql.count(db)`select * from books where read = ${false}`
expect(nbBooks).toBe(sampleBooks.length)
})

test('sql.raw should work with pg shorthand', async () => {
const tableName = 'books'
const { rows, rowCount, oid } = await sql.query(db)`select * from ${sql.raw(
tableName
)} where read = ${false}`
expect(rows).toBe(sampleBooks)
expect(rowCount).toBe(sampleBooks.length)
expect(oid).toBe(1)
})
8 changes: 8 additions & 0 deletions test/sql.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,11 @@ test('json as query parameter', () => {
expect(query.values).toHaveLength(1)
expect(query.values[0]).toBe(jsonValue)
})

test('query with raw data', () => {
const tableName = 'books'
const query = sql`select * from ${sql.raw(tableName)} where read = ${false}`
expect(trimSpaces(query.text)).toBe('select * from books where read = $1')
expect(query.values).toHaveLength(1)
expect(query.values[0]).toBe(false)
})