diff --git a/__tests__/__snapshots__/resolvers.test.js.snap b/__tests__/__snapshots__/resolvers.test.js.snap index 16b5f4b..3163981 100644 --- a/__tests__/__snapshots__/resolvers.test.js.snap +++ b/__tests__/__snapshots__/resolvers.test.js.snap @@ -246,13 +246,41 @@ exports[`rds resolvers toJsonObject 1`] = ` [ [ { + "IS ACTIVE": true, "ISBN-13": "978-1948132817", "author": "Mark Twain", + "blob_value": "aGVsbG8=", + "id": 12345, + "tags": [ + "a", + "b", + ], "title": "Adventures of Huckleberry Finn", }, { + "IS ACTIVE": false, "ISBN-13": "978-1948132275", "author": "Jack London", + "blob_value": "d29ybGQ=", + "id": 67890, + "optional_double": 12.34, + "tags": [ + [ + true, + false, + ], + [ + 1.234, + ], + [ + 1, + 2, + ], + [ + "a", + "b", + ], + ], "title": "The Call of the Wild", }, ], diff --git a/__tests__/resolvers.test.js b/__tests__/resolvers.test.js index 1eb5ee2..907f79f 100644 --- a/__tests__/resolvers.test.js +++ b/__tests__/resolvers.test.js @@ -242,6 +242,9 @@ describe("rds resolvers", () => { "numberOfRecordsUpdated": 0, "records": [ [ + { + "longValue": 12345 + }, { "stringValue": "Mark Twain" }, @@ -250,9 +253,18 @@ describe("rds resolvers", () => { }, { "stringValue": "978-1948132817" - } + }, + { + "isNull": true + }, + { "arrayValue": { "stringValues": ["a", "b"] } }, + { "booleanValue": true }, + { "blobValue": Buffer.from("hello").toString("base64") } ], [ + { + "longValue": 67890 + }, { "stringValue": "Jack London" }, @@ -261,10 +273,39 @@ describe("rds resolvers", () => { }, { "stringValue": "978-1948132275" - } + }, + { + "doubleValue": 12.34, + }, + { "arrayValue": { + "arrayValues": [ + { "booleanValues": [true, false] }, + { "doubleValues": [1.234] }, + { "longValues": [1, 2] }, + { "stringValues": ["a", "b"] }, + ], + }, + }, + { "booleanValue": false }, + { "blobValue": Buffer.from("world").toString("base64") }, ] ], "columnMetadata": [ + { + "type": 4, + "typeName": "serial", + "label": "id", + "schemaName": "", + "tableName": "Books", + "isAutoIncrement": true, + "isSigned": true, + "isCurrency": false, + "isCaseSensitive": false, + "nullable": 0, + "precision": 10, + "scale": 0, + "arrayBaseColumnType": 0 + }, { "isSigned": false, "isCurrency": false, @@ -312,7 +353,20 @@ describe("rds resolvers", () => { "nullable": 0, "arrayBaseColumnType": 0, "name": "ISBN-13" - } + }, + { + "name": "optional_double", + }, + { + "name": "tags", + }, + { + "name": "is_active", + "label": "IS ACTIVE", + }, + { + "name": "blob_value", + }, ] } ] diff --git a/rds/index.js b/rds/index.js index fa91fc3..e452757 100644 --- a/rds/index.js +++ b/rds/index.js @@ -1,3 +1,31 @@ +/** + * Extract the value from the field given a row from sqlStatementResults. + * + * See https://docs.aws.amazon.com/rdsdataservice/latest/APIReference/API_Field.html. + */ +function extractFieldValue(field) { + // Handle isNull. + if (field.isNull === true) { + return null; + } + + // Handle arrayValue. + if ('arrayValue' in field) { + const { arrayValue } = field; + + // Handle arrayValues. + if (arrayValue.arrayValues) { + return arrayValue.arrayValues.map(field => extractFieldValue(field)); + } + + // Handle stringValues, doubleValues, longValues and booleanValues. + return Object.values(arrayValue)[0] ?? []; + } + + // Handle stringValue, doubleValue, longValue, booleanValue and blobValue. + return Object.values(field)[0]; +} + export function toJsonObject(inputStr) { // on AWS inputStr is always a string, but on LocalStack the input may be an object. let input; @@ -20,12 +48,15 @@ export function toJsonObject(inputStr) { } for (const colNo in record) { - - // TODO: what if the column is not a string? - const { stringValue } = record[colNo]; - const { label } = columnMetadata[colNo]; - - row[label] = stringValue; + // Use label if available, otherwise use name. + const metadata = columnMetadata[colNo]; + const colName = metadata.label ?? metadata.name; + + // Extract the value from the field. + const value = extractFieldValue(record[colNo]); + if (value !== null) { + row[colName] = value; + } } statement.push(row);