Skip to content

Commit

Permalink
refactor(postgres): use a custom type for big integers (graphile#328)
Browse files Browse the repository at this point in the history
* use custom string type for big integers

* use breaking case for bigint
  • Loading branch information
calebmer committed Feb 11, 2017
1 parent 6f4fea7 commit 5ac644e
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 28 deletions.
2 changes: 1 addition & 1 deletion examples/kitchen-sink/data.sql
Expand Up @@ -40,7 +40,7 @@ insert into a.foreign_key (person_id, compound_key_1, compound_key_2) values
insert into b.types values (
12,
50,
200,
467131188225,
15.2,
15.2,
true,
Expand Down
Expand Up @@ -633,7 +633,7 @@ Object {
},
"start": null,
},
"bigint": 50,
"bigint": "467131188225",
"boolean": false,
"compoundType": Object {
"a": 123,
Expand Down Expand Up @@ -666,8 +666,8 @@ Object {
"seconds": 1,
"years": 6,
},
"json": "{"x":1,"y":2,"z":3}",
"jsonb": "{"a":1,"b":2,"c":3}",
"json": "{\"x\":1,\"y\":2,\"z\":3}",
"jsonb": "{\"a\":1,\"b\":2,\"c\":3}",
"money": 5000,
"nestedCompoundType": Object {
"a": Object {
Expand Down Expand Up @@ -1677,7 +1677,7 @@ Object {
],
},
"jsonIdentityMutation": Object {
"json": "{"a":1,"b":2,"c":3}",
"json": "{\"a\":1,\"b\":2,\"c\":3}",
},
"mult1": Object {
"integer": 0,
Expand Down Expand Up @@ -2266,7 +2266,7 @@ Object {
"value": 20,
},
},
"bigint": 200,
"bigint": "467131188225",
"boolean": true,
"compoundType": Object {
"a": 1,
Expand All @@ -2278,8 +2278,8 @@ Object {
"domain": 5,
"domain2": 6,
"enum": "GREEN",
"json": "{"a":1,"b":2,"c":3,"d":{"e":4,"f":5,"g":[6,7,8,"x",false,null]}}",
"jsonb": "{"1":"a","2":"b","3":"c","4":{"5":"d","6":"e","7":["f","g","h",42,true,null]}}",
"json": "{\"a\":1,\"b\":2,\"c\":3,\"d\":{\"e\":4,\"f\":5,\"g\":[6,7,8,\"x\",false,null]}}",
"jsonb": "{\"1\":\"a\",\"2\":\"b\",\"3\":\"c\",\"4\":{\"5\":\"d\",\"6\":\"e\",\"7\":[\"f\",\"g\",\"h\",42,true,null]}}",
"money": 1000,
"nestedCompoundType": Object {
"a": Object {
Expand Down
@@ -1,5 +1,10 @@
exports[`test prints a schema with Relay 1 style ids 1`] = `
"type CompoundKey implements Node {
"# A signed eight-byte integer. The upper big integer values are greater then the
# max value for a JavaScript number. Therefore all big integers will be output as
# strings and not numbers.
scalar BigInt

type CompoundKey implements Node {
# A globally unique identifier. Can be used in various places throughout the system to identify this single value.
id: ID!
personId2: Int!
Expand Down Expand Up @@ -809,7 +814,7 @@ type Query implements Node {
# based pagination. May not be used with \`last\`.
offset: Int
): TableSetQueryConnection
typesQuery(a: Int!, b: Boolean!, c: String!, d: [Int]!, e: Json!, f: FloatRangeInput!): Boolean
typesQuery(a: BigInt!, b: Boolean!, c: String!, d: [Int]!, e: Json!, f: FloatRangeInput!): Boolean

# Reads and enables paginatation through a set of \`CompoundKey\`.
allCompoundKeys(
Expand Down Expand Up @@ -980,7 +985,7 @@ input TypesMutationInput {
# An arbitrary string value with no semantic meaning. Will be included in the
# payload verbatim. May be used to track mutations by the client.
clientMutationId: String
a: Int!
a: BigInt!
b: Boolean!
c: String!
d: [Int]!
Expand Down Expand Up @@ -1170,6 +1175,11 @@ type AuthenticatePayload {
query: Query
}

# A signed eight-byte integer. The upper big integer values are greater then the
# max value for a JavaScript number. Therefore all big integers will be output as
# strings and not numbers.
scalar BigInt

enum Color {
RED
GREEN
Expand Down Expand Up @@ -1699,7 +1709,7 @@ type Type implements Node {
nodeId: ID!
id: Int!
smallint: Int!
bigint: Int!
bigint: BigInt!
numeric: Float!
decimal: Float!
boolean: Boolean!
Expand Down Expand Up @@ -1734,7 +1744,7 @@ input TypeCondition {
smallint: Int

# Checks for equality with the object’s \`bigint\` field.
bigint: Int
bigint: BigInt

# Checks for equality with the object’s \`numeric\` field.
numeric: Float
Expand Down Expand Up @@ -1809,7 +1819,7 @@ input TypeCondition {
input TypeInput {
id: Int
smallint: Int!
bigint: Int!
bigint: BigInt!
numeric: Float!
decimal: Float!
boolean: Boolean!
Expand Down Expand Up @@ -1839,7 +1849,7 @@ input TypeInput {
input TypePatch {
id: Int
smallint: Int
bigint: Int
bigint: BigInt
numeric: Float
decimal: Float
boolean: Boolean
Expand Down Expand Up @@ -2222,6 +2232,11 @@ type AuthenticatePayload {
query: Query
}

# A signed eight-byte integer. The upper big integer values are greater then the
# max value for a JavaScript number. Therefore all big integers will be output as
# strings and not numbers.
scalar BigInt

enum Color {
RED
GREEN
Expand Down Expand Up @@ -4039,7 +4054,7 @@ type Query implements Node {
# based pagination. May not be used with \`last\`.
offset: Int
): TableSetQueryConnection
typesQuery(a: Int!, b: Boolean!, c: String!, d: [Int]!, e: Json!, f: FloatRangeInput!): Boolean
typesQuery(a: BigInt!, b: Boolean!, c: String!, d: [Int]!, e: Json!, f: FloatRangeInput!): Boolean

# Reads and enables paginatation through a set of \`ForeignKey\`.
allForeignKeys(
Expand Down Expand Up @@ -4583,7 +4598,7 @@ type Type implements Node {
nodeId: ID!
id: Int!
smallint: Int!
bigint: Int!
bigint: BigInt!
numeric: Float!
decimal: Float!
boolean: Boolean!
Expand Down Expand Up @@ -4618,7 +4633,7 @@ input TypeCondition {
smallint: Int

# Checks for equality with the object’s \`bigint\` field.
bigint: Int
bigint: BigInt

# Checks for equality with the object’s \`numeric\` field.
numeric: Float
Expand Down Expand Up @@ -4693,7 +4708,7 @@ input TypeCondition {
input TypeInput {
id: Int
smallint: Int!
bigint: Int!
bigint: BigInt!
numeric: Float!
decimal: Float!
boolean: Boolean!
Expand Down Expand Up @@ -4723,7 +4738,7 @@ input TypeInput {
input TypePatch {
id: Int
smallint: Int
bigint: Int
bigint: BigInt
numeric: Float
decimal: Float
boolean: Boolean
Expand Down Expand Up @@ -4778,7 +4793,7 @@ input TypesMutationInput {
# An arbitrary string value with no semantic meaning. Will be included in the
# payload verbatim. May be used to track mutations by the client.
clientMutationId: String
a: Int!
a: BigInt!
b: Boolean!
c: String!
d: [Int]!
Expand Down Expand Up @@ -5166,7 +5181,12 @@ scalar Uuid
`;

exports[`test prints a schema without default mutations 1`] = `
"type CompoundKey implements Node {
"# A signed eight-byte integer. The upper big integer values are greater then the
# max value for a JavaScript number. Therefore all big integers will be output as
# strings and not numbers.
scalar BigInt

type CompoundKey implements Node {
# A globally unique identifier. Can be used in various places throughout the system to identify this single value.
nodeId: ID!
personId2: Int!
Expand Down Expand Up @@ -5689,7 +5709,7 @@ type Query implements Node {
# based pagination. May not be used with \`last\`.
offset: Int
): TableSetQueryConnection
typesQuery(a: Int!, b: Boolean!, c: String!, d: [Int]!, e: Json!, f: FloatRangeInput!): Boolean
typesQuery(a: BigInt!, b: Boolean!, c: String!, d: [Int]!, e: Json!, f: FloatRangeInput!): Boolean

# Reads and enables paginatation through a set of \`CompoundKey\`.
allCompoundKeys(
Expand Down Expand Up @@ -5860,7 +5880,7 @@ input TypesMutationInput {
# An arbitrary string value with no semantic meaning. Will be included in the
# payload verbatim. May be used to track mutations by the client.
clientMutationId: String
a: Int!
a: BigInt!
b: Boolean!
c: String!
d: [Int]!
Expand Down
Expand Up @@ -3,7 +3,7 @@ mutation {
type: {
id: 201
smallint: 30
bigint: 50
bigint: "467131188225"
numeric: 15.2
decimal: 15.2
boolean: false
Expand Down
Expand Up @@ -8,7 +8,7 @@ mutation {
mult2(input: { arg0: 1, arg1: 1 }) { integer }
mult3(input: { arg0: 1, arg1: 2 }) { integer }
mult4(input: { arg0: 5, arg1: 2 }) { integer }
typesMutation(input: { a: 50, b: false, c: "xyz", d: [1, 2, 3], e: "{\"a\":1,\"b\":2,\"c\":3}", f: { start: { value: 1, inclusive: false }, end: { value: 5, inclusive: false } } }) { boolean }
typesMutation(input: { a: "50", b: false, c: "xyz", d: [1, 2, 3], e: "{\"a\":1,\"b\":2,\"c\":3}", f: { start: { value: 1, inclusive: false }, end: { value: 5, inclusive: false } } }) { boolean }
compoundTypeMutation(input: { object: { a: 419, b: "easy cheesy baked potatoes", c: RED, fooBar: 8 } }) { compoundType { a b c d fooBar } }
tableMutation(input: { id: 5 }) { post { nodeId id headline authorId } personByAuthorId { id name } postEdge { cursor node { id headline } } }
tableSetMutation(input: {}) { people { name } }
Expand Down
Expand Up @@ -3,7 +3,7 @@ query {
add2Query(a: 2, b: 2)
add3Query(arg1: 5)
add4Query(arg0: 1, b: 3)
typesQuery(a: 50, b: false, c: "xyz", d: [1, 2, 3], e: "{\"a\":1,\"b\":2,\"c\":3}", f: { start: { value: 1, inclusive: false }, end: { value: 5, inclusive: false } })
typesQuery(a: "50", b: false, c: "xyz", d: [1, 2, 3], e: "{\"a\":1,\"b\":2,\"c\":3}", f: { start: { value: 1, inclusive: false }, end: { value: 5, inclusive: false } })
compoundTypeQuery(object: { a: 419, b: "easy cheesy baked potatoes", c: RED, fooBar: 8 }) { a b c d fooBar }
tableQuery(id: 5) { nodeId id headline authorId }
tableSetQuery { edges { cursor node { name } } }
Expand Down
13 changes: 13 additions & 0 deletions src/postgres/inventory/type/custom/pgBigIntType.ts
@@ -0,0 +1,13 @@
import pgStringType from '../scalar/pgStringType'
import PgAliasType from '../PgAliasType'

const pgBigIntType = new PgAliasType({
name: 'big_int',
description:
'A signed eight-byte integer. The upper big integer values are greater then ' +
'the max value for a JavaScript number. Therefore all big integers will be ' +
'output as strings and not numbers.',
baseType: pgStringType,
})

export default pgBigIntType
3 changes: 2 additions & 1 deletion src/postgres/inventory/type/getTypeFromPgType.ts
Expand Up @@ -10,6 +10,7 @@ import pgIntegerType from './scalar/pgIntegerType'
import pgFloatType from './scalar/pgFloatType'
import pgStringType from './scalar/pgStringType'
import pgJsonType from './scalar/pgJsonType'
import pgBigIntType from './custom/pgBigIntType'
import pgUuidType from './custom/pgUuidType'
import pgDatetimeType from './custom/pgDatetimeType'
import pgDateType from './custom/pgDateType'
Expand All @@ -36,7 +37,7 @@ import PgListType from './PgListType'
* @private
*/
const pgTypeIdToType = new Map<string, PgType<mixed>>([
['20', pgIntegerType], // int8, bigint
['20', pgBigIntType], // int8, bigint
['21', pgIntegerType], // int2, smallint
['23', pgIntegerType], // int4, integer
['114', pgJsonType], // json
Expand Down
3 changes: 3 additions & 0 deletions src/postgres/inventory/type/scalar/pgStringType.ts
Expand Up @@ -7,6 +7,9 @@ const pgStringType: PgType<string> & AdapterType<string> = {
baseType: stringType,
isTypeOf: stringType.isTypeOf,
transformPgValueIntoValue: value => {
if (typeof value === 'number')
return value.toString(10)

if (!stringType.isTypeOf(value))
throw new Error(`Expected string. Not '${typeof value}'.`)

Expand Down

0 comments on commit 5ac644e

Please sign in to comment.