Skip to content

Commit

Permalink
Treat postgres bigint as string by default
Browse files Browse the repository at this point in the history
  • Loading branch information
porsager committed Apr 7, 2020
1 parent 2e01c2b commit 4958e80
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 22 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -493,11 +493,19 @@ prexit(async () => {

`Number` in javascript is only able to represent 2<sup>53</sup>-1 safely which means that types in PostgreSQLs like `bigint` and `numeric` won't fit into `Number`.

Since Node.js v10.4 we can use [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) to match the PostgreSQL type `bigint`, so Postgres.js will use BigInt if running on v10.4 or later. For older versions `bigint` will be returned as a string.
Since Node.js v10.4 we can use [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) to match the PostgreSQL type `bigint` which is returned for eg. `count(*)`. Unfortunately it doesn't work with `JSON.stringify` out of the box, so Postgres.js will return it as a string.

There is currently no way to handle `numeric / decimal` in a native way in Javascript, so these and similar will be returned as `string`.
If you want to use `BigInt` you can add this custom type:

You can of course handle types like these using [custom types](#types) if you want to.
```js
const sql = postgres({
types: {
bigint: postgres.BigInt
}
})
```

There is currently no way to handle `numeric / decimal` in a native way in Javascript, so these and similar will be returned as `string`. You can also handle types like these using [custom types](#types) if you want to.

## The Connection Pool

Expand Down
8 changes: 7 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ function notTagged() {
Object.assign(Postgres, {
toPascal,
toCamel,
toKebab
toKebab,
BigInt: {
to: 20,
from: [20],
parse: x => BigInt(x), // eslint-disable-line
serialize: x => x.toString()
}
})

const originCache = new Map()
Expand Down
13 changes: 2 additions & 11 deletions lib/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const char = (acc, [k, v]) => (acc[k.charCodeAt(0)] = v, acc)
const entries = o => Object.keys(o).map(x => [x, o[x]])

// These were the fastest ways to do it in Node.js v12.11.1 (add tests to revise if this changes)
const types = module.exports.types = Object.assign({
const types = module.exports.types = {
string: {
to: 25,
from: null, // defaults to string
Expand Down Expand Up @@ -38,16 +38,7 @@ const types = module.exports.types = Object.assign({
serialize: x => '\\x' + x.toString('hex'),
parse: x => Buffer.from(x.slice(2), 'hex')
}
},
typeof BigInt === 'undefined' ? {} : {
bigint: {
to: 20,
from: [20],
parse: data => BigInt(data), // eslint-disable-line
serialize: bigint => bigint.toString()
}
}
)
}

const defaultHandlers = typeHandlers(types)

Expand Down
10 changes: 3 additions & 7 deletions tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ t('Transaction succeeds on caught savepoint', async() => {
await sql`insert into test values(3)`
})

return [typeof BigInt === 'undefined' ? '2' : 2n, (await sql`select count(1) from test`)[0].count, await sql`drop table test`]
return ['2', (await sql`select count(1) from test`)[0].count, await sql`drop table test`]
})

t('Savepoint returns Result', async() => {
Expand Down Expand Up @@ -875,8 +875,8 @@ t('Debug works', async() => {
return ['select 1', result]
})

t('bigint is returned as BigInt', async() => [
'bigint',
t('bigint is returned as String', async() => [
'string',
typeof (await sql`select 9223372036854777 as x`)[0].x
])

Expand All @@ -890,10 +890,6 @@ t('numeric is returned as string', async() => [
typeof (await sql`select 1.2 as x`)[0].x
])

function get() {
return sql`selec 1`
}

t('Async stack trace', async() => {
return [
parseInt(new Error().stack.split('\n')[1].split(':')[1]) + 1,
Expand Down

0 comments on commit 4958e80

Please sign in to comment.