Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treat integers longer than 32 bit as floats. #6082

Merged
merged 4 commits into from
Jun 25, 2018
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
24 changes: 20 additions & 4 deletions packages/gatsby/src/schema/__tests__/data-tree-utils-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,34 +176,50 @@ describe(`Gatsby data tree utils`, () => {
it(`prefers float when multiple number types`, () => {
let example

// nodes starting with integer
// nodes starting with 32-bit integer ("big" ints are float)
example = getExampleValues({ nodes: [{ number: 5 }, { number: 2.5 }] })
expect(example.number).toBeDefined()
expect(example.number).toEqual(2.5)
example = getExampleValues({ nodes: [{ number: 5 }, { number: 3000000000 }] })
expect(example.number).toBeDefined()
expect(example.number).toEqual(3000000000)

// with node not containing number field
example = getExampleValues({ nodes: [{ number: 5 }, {}, { number: 2.5 }] })
expect(example.number).toBeDefined()
expect(example.number).toEqual(2.5)

// nodes starting with float
// nodes starting with float ("big" ints are float)
example = getExampleValues({ nodes: [{ number: 2.5 }, { number: 5 }] })
expect(example.number).toBeDefined()
expect(example.number).toEqual(2.5)
example = getExampleValues({ nodes: [{ number: 3000000000 }, { number: 5 }] })
expect(example.number).toBeDefined()
expect(example.number).toEqual(3000000000)

// array of numbers - starting with integer
// array of numbers - starting with float
example = getExampleValues({ nodes: [{ numbers: [2.5, 5] }] })
expect(example.numbers).toBeDefined()
expect(Array.isArray(example.numbers)).toBe(true)
expect(example.numbers.length).toBe(1)
expect(example.numbers[0]).toBe(2.5)
example = getExampleValues({ nodes: [{ numbers: [3000000000, 5] }] })
expect(example.numbers).toBeDefined()
expect(Array.isArray(example.numbers)).toBe(true)
expect(example.numbers.length).toBe(1)
expect(example.numbers[0]).toBe(3000000000)

// array of numbers - starting with float
// array of numbers - starting with 32-bit integer
example = getExampleValues({ nodes: [{ numbers: [5, 2.5] }] })
expect(example.numbers).toBeDefined()
expect(Array.isArray(example.numbers)).toBe(true)
expect(example.numbers.length).toBe(1)
expect(example.numbers[0]).toBe(2.5)
example = getExampleValues({ nodes: [{ numbers: [5, 3000000000] }] })
expect(example.numbers).toBeDefined()
expect(Array.isArray(example.numbers)).toBe(true)
expect(example.numbers.length).toBe(1)
expect(example.numbers[0]).toBe(3000000000)
})

it(`handles mix of date strings and date objects`, () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,21 @@ describe(`GraphQL Input args`, () => {
expect(Object.keys(fields.foo.type.getFields())).toHaveLength(2)
})

it(`infers number types`, () => {
const fields = inferInputObjectStructureFromNodes({
nodes: [
{
int32: 42,
float: 2.5,
longint: 3000000000,
},
],
}).inferredFields
expect(fields.int32.type.name.endsWith(`Integer`)).toBe(true)
expect(fields.float.type.name.endsWith(`Float`)).toBe(true)
expect(fields.longint.type.name.endsWith(`Float`)).toBe(true)
})

it(`handles eq operator`, async () => {
let result = await queryResult(
nodes,
Expand Down
29 changes: 29 additions & 0 deletions packages/gatsby/src/schema/__tests__/infer-graphql-type-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,20 @@ describe(`GraphQL type inferance`, () => {
)
})

it(`doesn't throw errors at ints longer than 32-bit`, async () => {
const result = await queryResult(
[
{
longint: 3000000000,
},
],
`
longint
`
)
expect(result.errors).toBeUndefined()
})

it(`prefers float when multiple number types`, async () => {
let result = await queryResult(
[{ number: 1.1 }, { number: 1 }],
Expand Down Expand Up @@ -199,6 +213,21 @@ describe(`GraphQL type inferance`, () => {
expect(Object.keys(fields.foo.type.getFields())).toHaveLength(4)
})

it(`infers number types`, () => {
const fields = inferObjectStructureFromNodes({
nodes: [
{
int32: 42,
float: 2.5,
longint: 3000000000,
},
],
})
expect(fields.int32.type.name).toEqual(`Int`)
expect(fields.float.type.name).toEqual(`Float`)
expect(fields.longint.type.name).toEqual(`Float`)
})

it(`Handle invalid graphql field names`, async () => {
let result = await queryResult(
nodes,
Expand Down
3 changes: 2 additions & 1 deletion packages/gatsby/src/schema/data-tree-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const invariant = require(`invariant`)
const createKey = require(`./create-key`)
const { typeConflictReporter } = require(`./type-conflict-reporter`)
const DateType = require(`./types/type-date`)
const is32BitInteger = require(`../utils/is-32-bit-integer`)

import type { TypeEntry } from "./type-conflict-reporter"

Expand Down Expand Up @@ -118,7 +119,7 @@ const getExampleScalarFromArray = values =>
values,
(value, nextValue) => {
// Prefer floats over ints as they're more specific.
if (nextValue && _.isNumber(nextValue) && !_.isInteger(nextValue)) {
if (nextValue && _.isNumber(nextValue) && !is32BitInteger(nextValue)) {
return nextValue
} else if (value === null) {
return nextValue
Expand Down
5 changes: 3 additions & 2 deletions packages/gatsby/src/schema/infer-graphql-input-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const {

const { findLinkedNode } = require(`./infer-graphql-type`)
const { getNodes } = require(`../redux`)
const is32BitInteger = require(`../utils/is-32-bit-integer`)

import type {
GraphQLInputFieldConfig,
Expand Down Expand Up @@ -76,7 +77,7 @@ function inferGraphQLInputFields({
let headType = typeOf(headValue)

if (headType === `number`)
headType = _.isInteger(headValue) ? `int` : `float`
headType = is32BitInteger(headValue) ? `int` : `float`

// Determine type for in operator.
let inType
Expand Down Expand Up @@ -165,7 +166,7 @@ function inferGraphQLInputFields({
}
}
case `number`: {
if (value % 1 === 0) {
if (is32BitInteger(value)) {
return {
type: new GraphQLInputObjectType({
name: createTypeName(`${prefix}QueryInteger`),
Expand Down
3 changes: 2 additions & 1 deletion packages/gatsby/src/schema/infer-graphql-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const createKey = require(`./create-key`)
const { getExampleValues, isEmptyObjectOrArray } = require(`./data-tree-utils`)
const DateType = require(`./types/type-date`)
const FileType = require(`./types/type-file`)
const is32BitInteger = require(`../utils/is-32-bit-integer`)

import type { GraphQLOutputType } from "graphql"
import type {
Expand Down Expand Up @@ -117,7 +118,7 @@ function inferGraphQLType({
}),
}
case `number`:
return _.isInteger(exampleValue)
return is32BitInteger(exampleValue)
? { type: GraphQLInt }
: { type: GraphQLFloat }
default:
Expand Down
21 changes: 21 additions & 0 deletions packages/gatsby/src/utils/__tests__/is-32-bit-integer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const is32BitInteger = require(`../is-32-bit-integer.js`)

const MAX_INT = 2147483647
const MIN_INT = -2147483648

describe(`is32BitInteger`, () => {
it(`works with all kind of values`, () => {
expect(is32BitInteger(MAX_INT)).toBe(true)
expect(is32BitInteger(MIN_INT)).toBe(true)
expect(is32BitInteger(MAX_INT + 1)).toBe(false)
expect(is32BitInteger(MIN_INT - 1)).toBe(false)
expect(is32BitInteger(2.4)).toBe(false)
expect(is32BitInteger(`42`)).toBe(false)
expect(is32BitInteger({})).toBe(false)
expect(is32BitInteger([1])).toBe(false)
expect(is32BitInteger(true)).toBe(false)
expect(is32BitInteger(false)).toBe(false)
expect(is32BitInteger(undefined)).toBe(false)
expect(is32BitInteger(null)).toBe(false)
})
})
3 changes: 3 additions & 0 deletions packages/gatsby/src/utils/is-32-bit-integer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = function(x) {
return (x | 0) === x
}