From 2a8bb2d60940760c6280d8cc06100cb9087194b5 Mon Sep 17 00:00:00 2001 From: Bob den Os <108393871+BobdenOs@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:03:17 +0100 Subject: [PATCH] fix: sqlite date string compatibility parsing only for valid dates (#410) fixes: #409 --- db-service/lib/cqn2sql.js | 4 ++-- sqlite/lib/SQLiteService.js | 7 ++++++- test/compliance/SELECT.test.js | 12 ++++++++++++ test/scenarios/bookshop/update.test.js | 12 ++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/db-service/lib/cqn2sql.js b/db-service/lib/cqn2sql.js index 48da9b538..082510b32 100644 --- a/db-service/lib/cqn2sql.js +++ b/db-service/lib/cqn2sql.js @@ -825,8 +825,8 @@ class CQN2SQLRenderer { case 'number': return `${val}` // REVISIT for HANA case 'object': if (val === null) return 'NULL' - if (val instanceof Date) return `'${val.toISOString()}'` - if (val instanceof Readable); // go on with default below + if (val instanceof Date) val = val.toJSON() // returns null if invalid + else if (val instanceof Readable); // go on with default below else if (Buffer.isBuffer(val)); // go on with default below else if (is_regexp(val)) val = val.source else val = JSON.stringify(val) diff --git a/sqlite/lib/SQLiteService.js b/sqlite/lib/SQLiteService.js index 6839dd14e..bdac04012 100644 --- a/sqlite/lib/SQLiteService.js +++ b/sqlite/lib/SQLiteService.js @@ -162,7 +162,12 @@ class SQLiteService extends SQLService { val(v) { if (Buffer.isBuffer(v.val)) v.val = v.val.toString('base64') // intercept DateTime values and convert to Date objects to compare ISO Strings - else if (/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[Z+-]/.test(v.val)) v.val = new Date(v.val) + else if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(.\d{1,9})?(Z|[+-]\d{2}(:?\d{2})?)$/.test(v.val)) { + const date = new Date(v.val) + if (!Number.isNaN(date.getTime())) { + v.val = date + } + } return super.val(v) } diff --git a/test/compliance/SELECT.test.js b/test/compliance/SELECT.test.js index 50dc53a2a..026e8ac47 100644 --- a/test/compliance/SELECT.test.js +++ b/test/compliance/SELECT.test.js @@ -221,6 +221,18 @@ describe('SELECT', () => { assert.strictEqual(res.length, 3, 'Ensure that all rows are coming back') }) + test('compare with DateTime column', async () => { + const entity = `basic.literals.dateTime` + const dateTime = '1970-02-02T10:09:34Z' + const timestamp = dateTime.slice(0,-1) + '.000Z' + await DELETE.from(entity) + await INSERT({ dateTime }).into(entity) + const dateTimeMatches = await SELECT('dateTime').from(entity).where(`dateTime = `, dateTime) + assert.strictEqual(dateTimeMatches.length, 1, 'Ensure that the dateTime column matches the dateTime value') + const timestampMatches = await SELECT('dateTime').from(entity).where(`dateTime = `, timestamp) + assert.strictEqual(timestampMatches.length, 1, 'Ensure that the dateTime column matches the timestamp value') + }) + test.skip('ref select', async () => { // Currently not possible as cqn4sql does not recognize where.ref.id: 'basic.projection.globals' as an external source const cqn = { diff --git a/test/scenarios/bookshop/update.test.js b/test/scenarios/bookshop/update.test.js index 28fdcd9ff..9afc0c55e 100644 --- a/test/scenarios/bookshop/update.test.js +++ b/test/scenarios/bookshop/update.test.js @@ -24,6 +24,18 @@ describe('Bookshop - Update', () => { expect(res.data.author_ID).to.be.eq(201) expect(res.data.descr).to.be.eq('UPDATED') }) + + test('Update Book (with timestamp)', async () => { + const descr = `"${new Date().toISOString()}"` + const res = await PUT( + '/admin/Books(201)', + { descr }, + admin, + ) + expect(res.status).to.be.eq(200) + expect(res.data.descr).to.be.eq(descr) + }) + test('Update array of', async () => { // create book const insert = INSERT.into('sap.capire.bookshop.Books').columns(['ID']).values([150])