Error parsing STRUCT with JSON "keys" field #1774
Labels
api: spanner
Issues related to the googleapis/nodejs-spanner API.
priority: p2
Moderately-important priority. Fix may not be included in next release.
type: bug
Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Environment details
Mac OS Ventura 13.1
14.17.6
6.14.15
@google-cloud/spanner
version:6.7.0
Error
Steps to reproduce
The error occurs when the queried column either is or includes a
STRUCT
with a child field oftype: "JSON"
and aname
value equal to one of the JSArray
method names, e.g."keys"
.This condition is satisfied by a change-stream query that returns data change records. Change stream queries that don't return data change records are unaffected.
In my case I'm using
database.runStream()
to run the query.See also
The error case is reproduced by this test case in the issue-associated PR: https://github.com/googleapis/nodejs-spanner/pull/1775/files#diff-bd3702694080cbb1cc59ec4e3021374f22a2fd665617a80bd3c29630b9dbe7b7R675-R695.
Details
I'm hitting an error when running a change-stream query via the
database.runStream()
method:In the case where the query returns data change records, an error is thrown:
codec.js:321 – the initial source of the error – is part of the
decode()
function; this line specifically covers the decoding of JSON values [1]:Line 332 – the next level down in the stack – handles
STRUCT
parsing [2]:I added some logging to the file and found that the error occurs when parsing the data-change record
.mods
column..mods
is an array with the following format:A sample input/not-yet-decoded
.mods
value:decode()
with a STRUCT type use an object value, and not an array. Unsure why both cases are possible.)When we decode the first
.mods
array item, aSTRUCT
, we land at codec.js:331. The first field provided bytype.structType.fields
has{ name: "keys", type: "JSON" }
. We, at this point, have adecoded
value of:At codec.js:332 we should be passing over
decoded[name]
and usingdecoded[index]
, sincedecoded
is an array; however sincename == "keys"
andArray.prototype.keys
is a method,decoded[name]
registers as truthy:decoded.keys
is a function.We therefore pass the
Array.prototype.keys
function back intodecode()
withtype: "JSON"
, land at codec.js:321, andJSON.parse()
fails with a function as an argument.Solution
The apparent solution: when decoding a
STRUCT
, only preferdecoded[name]
whendecoded
is not an array:Or, in the src/ Typescript code:
Indeed when this change is made, the aforementioned query works correctly.
Footnotes
nodejs-spanner/src/codec.ts
Lines 390 to 400 in ba7029a
nodejs-spanner/src/codec.ts
Lines 411 to 420 in ba7029a
The text was updated successfully, but these errors were encountered: