Skip to content

Commit b952735

Browse files
authored
Fix rds.toJsonObject method only supporting string values (#122)
Currently, the `toJsonObject` method from `rds` only supports `{ stringValue: string }`, but other value types can appear in payloads, such as `{ longValue: number }`, `{ doubleValue: number }`, etc. See https://docs.aws.amazon.com/rdsdataservice/latest/APIReference/API_Field.html for more information. This PR changes `toJsonObject` so it extracts the values properly. It also uses the row label if available, and the row name as a fallback.
1 parent 630f6a7 commit b952735

File tree

3 files changed

+122
-9
lines changed

3 files changed

+122
-9
lines changed

__tests__/__snapshots__/resolvers.test.js.snap

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,13 +246,41 @@ exports[`rds resolvers toJsonObject 1`] = `
246246
[
247247
[
248248
{
249+
"IS ACTIVE": true,
249250
"ISBN-13": "978-1948132817",
250251
"author": "Mark Twain",
252+
"blob_value": "aGVsbG8=",
253+
"id": 12345,
254+
"tags": [
255+
"a",
256+
"b",
257+
],
251258
"title": "Adventures of Huckleberry Finn",
252259
},
253260
{
261+
"IS ACTIVE": false,
254262
"ISBN-13": "978-1948132275",
255263
"author": "Jack London",
264+
"blob_value": "d29ybGQ=",
265+
"id": 67890,
266+
"optional_double": 12.34,
267+
"tags": [
268+
[
269+
true,
270+
false,
271+
],
272+
[
273+
1.234,
274+
],
275+
[
276+
1,
277+
2,
278+
],
279+
[
280+
"a",
281+
"b",
282+
],
283+
],
256284
"title": "The Call of the Wild",
257285
},
258286
],

__tests__/resolvers.test.js

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ describe("rds resolvers", () => {
242242
"numberOfRecordsUpdated": 0,
243243
"records": [
244244
[
245+
{
246+
"longValue": 12345
247+
},
245248
{
246249
"stringValue": "Mark Twain"
247250
},
@@ -250,9 +253,18 @@ describe("rds resolvers", () => {
250253
},
251254
{
252255
"stringValue": "978-1948132817"
253-
}
256+
},
257+
{
258+
"isNull": true
259+
},
260+
{ "arrayValue": { "stringValues": ["a", "b"] } },
261+
{ "booleanValue": true },
262+
{ "blobValue": Buffer.from("hello").toString("base64") }
254263
],
255264
[
265+
{
266+
"longValue": 67890
267+
},
256268
{
257269
"stringValue": "Jack London"
258270
},
@@ -261,10 +273,39 @@ describe("rds resolvers", () => {
261273
},
262274
{
263275
"stringValue": "978-1948132275"
264-
}
276+
},
277+
{
278+
"doubleValue": 12.34,
279+
},
280+
{ "arrayValue": {
281+
"arrayValues": [
282+
{ "booleanValues": [true, false] },
283+
{ "doubleValues": [1.234] },
284+
{ "longValues": [1, 2] },
285+
{ "stringValues": ["a", "b"] },
286+
],
287+
},
288+
},
289+
{ "booleanValue": false },
290+
{ "blobValue": Buffer.from("world").toString("base64") },
265291
]
266292
],
267293
"columnMetadata": [
294+
{
295+
"type": 4,
296+
"typeName": "serial",
297+
"label": "id",
298+
"schemaName": "",
299+
"tableName": "Books",
300+
"isAutoIncrement": true,
301+
"isSigned": true,
302+
"isCurrency": false,
303+
"isCaseSensitive": false,
304+
"nullable": 0,
305+
"precision": 10,
306+
"scale": 0,
307+
"arrayBaseColumnType": 0
308+
},
268309
{
269310
"isSigned": false,
270311
"isCurrency": false,
@@ -312,7 +353,20 @@ describe("rds resolvers", () => {
312353
"nullable": 0,
313354
"arrayBaseColumnType": 0,
314355
"name": "ISBN-13"
315-
}
356+
},
357+
{
358+
"name": "optional_double",
359+
},
360+
{
361+
"name": "tags",
362+
},
363+
{
364+
"name": "is_active",
365+
"label": "IS ACTIVE",
366+
},
367+
{
368+
"name": "blob_value",
369+
},
316370
]
317371
}
318372
]

rds/index.js

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,31 @@
1+
/**
2+
* Extract the value from the field given a row from sqlStatementResults.
3+
*
4+
* See https://docs.aws.amazon.com/rdsdataservice/latest/APIReference/API_Field.html.
5+
*/
6+
function extractFieldValue(field) {
7+
// Handle isNull.
8+
if (field.isNull === true) {
9+
return null;
10+
}
11+
12+
// Handle arrayValue.
13+
if ('arrayValue' in field) {
14+
const { arrayValue } = field;
15+
16+
// Handle arrayValues.
17+
if (arrayValue.arrayValues) {
18+
return arrayValue.arrayValues.map(field => extractFieldValue(field));
19+
}
20+
21+
// Handle stringValues, doubleValues, longValues and booleanValues.
22+
return Object.values(arrayValue)[0] ?? [];
23+
}
24+
25+
// Handle stringValue, doubleValue, longValue, booleanValue and blobValue.
26+
return Object.values(field)[0];
27+
}
28+
129
export function toJsonObject(inputStr) {
230
// on AWS inputStr is always a string, but on LocalStack the input may be an object.
331
let input;
@@ -20,12 +48,15 @@ export function toJsonObject(inputStr) {
2048
}
2149

2250
for (const colNo in record) {
23-
24-
// TODO: what if the column is not a string?
25-
const { stringValue } = record[colNo];
26-
const { label } = columnMetadata[colNo];
27-
28-
row[label] = stringValue;
51+
// Use label if available, otherwise use name.
52+
const metadata = columnMetadata[colNo];
53+
const colName = metadata.label ?? metadata.name;
54+
55+
// Extract the value from the field.
56+
const value = extractFieldValue(record[colNo]);
57+
if (value !== null) {
58+
row[colName] = value;
59+
}
2960
}
3061

3162
statement.push(row);

0 commit comments

Comments
 (0)