Skip to content

"malformed range literal" when tstzrange used as part of a key in an eager load #1630

@chudley

Description

@chudley

I'm trying to upgrade my project from 1.6.11 to 2.0.8 but am having trouble with objection seemingly wanting to handle a node-pg-range/tstzrange value in an eager load before it's passed down to node-pg. I've also seen this as early as 2.0.0-alpha.1 while trying to debug.

Here's a contrived example, including a description of the relationships. Running objection 1.6.11, my example prints the following and returns the results that I intended (last couple of relevant lines):

...
{
  method: 'select',
  options: {},
  timeout: false,
  cancelOnTimeout: false,
  bindings: [
    'c73a99a9-a73c-4189-b407-c84db0f34263',
    PGRange {
      begin: 2019-12-23T22:13:37.786Z,
      end: null,
      bounds: '[)'
    }
  ],
  __knexQueryUid: '00115cd8-779c-45bc-9cd3-c706700264a2',
  sql: 'select "bookings".* from "bookings" where ("bookings"."house_id", "bookings"."duration") in ((?, ?))'
}
{
  method: 'select',
  options: {},
  timeout: false,
  cancelOnTimeout: false,
  bindings: [ 'de85970b-2039-48f5-8fb2-563a420cc99c' ],
  __knexQueryUid: 'f085a437-f656-4293-a169-20f6c099ce3c',
  sql: 'select "rooms".* from "rooms" where "rooms"."id" in (?)'
}
[
  House {
    id: 'c73a99a9-a73c-4189-b407-c84db0f34263',
    duration: PGRange {
      begin: 2019-12-23T22:13:37.786Z,
      end: null,
      bounds: '[)'
    },
    booking: Booking {
      id: '4d26b31d-376b-4898-b737-d6500aa66c62',
      room_id: 'de85970b-2039-48f5-8fb2-563a420cc99c',
      house_id: 'c73a99a9-a73c-4189-b407-c84db0f34263',
      person_id: '6f89899e-73f1-472c-a08f-9fd6763e3771',
      duration: [PGRange],
      room: [Room]
    }
  }
]

However, under 2.0.8 I get the following:

...
{
  method: 'select',
  options: {},
  timeout: false,
  cancelOnTimeout: false,
  bindings: [
    'e70b2e31-9fc1-4f21-aa71-88221e87d1b9',
    '[Mon Dec 23 2019 22:18:58 GMT+0000 (Greenwich Mean Time),)'
  ],
  __knexQueryUid: '679918e6-95b9-4ee4-b4e7-68026a42f3d6',
  sql: 'select "bookings".* from "bookings" where ("bookings"."house_id", "bookings"."duration") in ((?, ?))'
}
DataError: select "bookings".* from "bookings" where ("bookings"."house_id", "bookings"."duration") in (($1, $2)) - malformed range literal: "[Mon Dec 23 2019 22:18:58 GMT+0000 (Greenwich Mean Time),)"
    at wrapError (/Users/richard/projects/tstzrange-repro/node_modules/db-errors/lib/dbErrors.js:19:14)
    at handleExecuteError (/Users/richard/projects/tstzrange-repro/node_modules/objection/lib/queryBuilder/QueryBuilder.js:1494:32)
    at QueryBuilder.execute (/Users/richard/projects/tstzrange-repro/node_modules/objection/lib/queryBuilder/QueryBuilder.js:685:13) {
  name: 'DataError',
  nativeError: error: malformed range literal: "[Mon Dec 23 2019 22:18:58 GMT+0000 (Greenwich Mean Time),)"
      at Connection.parseE (/Users/richard/projects/tstzrange-repro/node_modules/pg/lib/connection.js:604:13)
      at Connection.parseMessage (/Users/richard/projects/tstzrange-repro/node_modules/pg/lib/connection.js:403:19)
      at Socket.<anonymous> (/Users/richard/projects/tstzrange-repro/node_modules/pg/lib/connection.js:123:22)
      at Socket.emit (events.js:210:5)
      at addChunk (_stream_readable.js:326:12)
      at readableAddChunk (_stream_readable.js:301:11)
      at Socket.Readable.push (_stream_readable.js:235:10)
      at TCP.onStreamRead (internal/stream_base_commons.js:182:23) {
    name: 'error',
    length: 180,
    severity: 'ERROR',
    code: '22P02',
    detail: 'Missing comma after lower bound.',
    hint: undefined,
    position: undefined,
    internalPosition: undefined,
    internalQuery: undefined,
    where: undefined,
    schema: undefined,
    table: undefined,
    column: undefined,
    dataType: undefined,
    constraint: undefined,
    file: 'rangetypes.c',
    line: '2041',
    routine: 'range_parse'
  },
  client: 'postgres'
}

I can see that the "bindings" of the latter example has some form of stringify'd representation of my PGRange, as opposed to the PGRange itself. The only way I've found to get that particular form is to JSON.stringify the start property of the PGRange, perhaps hinting that objection is trying to somehow handle this object itself where it wasn't previously doing so.

I hope that's enough information. I've tried digging myself but it's taking me a long time. I've taken a look around the docs and the migration guide but nothing jumps out. Is there something I've missed in the migration which means I should now be handling this type of eager loading or relationship differently?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions