From ab31577ba980e38ecb4624bb605061cdf2ba6a33 Mon Sep 17 00:00:00 2001 From: I560824 Date: Tue, 10 Sep 2024 17:57:34 +0800 Subject: [PATCH 1/2] Redundant changelog entries for decimal fields on HANA DB --- lib/change-log.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/lib/change-log.js b/lib/change-log.js index 4342ab5..17d6651 100644 --- a/lib/change-log.js +++ b/lib/change-log.js @@ -18,6 +18,25 @@ const { localizeLogFields } = require("./localization") const isRoot = "change-tracking-isRootEntity" +function formatDecimal(str, scale) { + if (typeof str === "number" && !isNaN(str)) { + str = String(str); + } else return str; + + if (scale > 0) { + let parts = str.split("."); + let decimalPart = parts[1] || ""; + + while (decimalPart.length < scale) { + decimalPart += "0"; + } + + return `${parts[0]}.${decimalPart}`; + } + + return str; +} + const _getRootEntityPathVals = function (txContext, entity, entityKey) { const serviceEntityPathVals = [] const entityIDs = _getEntityIDs(txContext.params) @@ -316,6 +335,28 @@ function _trackedChanges4 (srv, target, diff) { const eleParentKeys = element.parent.keys if (from === to) return + /** + * + * HANA driver always filling up the defined decimal places with zeros, + * need to skip the change log if the value is not changed. + * Example: + * entity Books : cuid { + * price : Decimal(11, 4); + * } + * When price is updated from 3000.0000 to 3000, + * the change log should not be created. + */ + if ( + row._op === "update" && + element.type === "cds.Decimal" && + cds.db.kind === "hana" && + typeof to === "number" + ) { + const scaleNum = element.scale || 0; + if (from === formatDecimal(to, scaleNum)) + return; + } + /** * * For the Inline entity such as Items, From 70cfa9a8ef501273d5fe9e9ac1a707b9c22bf6fd Mon Sep 17 00:00:00 2001 From: I560824 Date: Wed, 11 Sep 2024 18:17:22 +0800 Subject: [PATCH 2/2] add UT --- .../db/data/sap.capire.bookshop-Books.csv | 4 ++-- tests/bookshop/db/schema.cds | 2 +- tests/integration/fiori-draft-enabled.test.js | 18 ++++++++++++++++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/tests/bookshop/db/data/sap.capire.bookshop-Books.csv b/tests/bookshop/db/data/sap.capire.bookshop-Books.csv index 3793518..dcb94f4 100644 --- a/tests/bookshop/db/data/sap.capire.bookshop-Books.csv +++ b/tests/bookshop/db/data/sap.capire.bookshop-Books.csv @@ -1,6 +1,6 @@ ID;title;descr;isUsed;author_ID;stock;price;genre_ID;bookStore_ID -9d703c23-54a8-4eff-81c1-cdce6b8376b1;Wuthering Heights;"Wuthering Heights, Emily Brontë's only novel, was published in 1847 under the pseudonym ""Ellis Bell"". It was written between October 1845 and June 1846. Wuthering Heights and Anne Brontë's Agnes Grey were accepted by publisher Thomas Newby before the success of their sister Charlotte's novel Jane Eyre. After Emily's death, Charlotte edited the manuscript of Wuthering Heights and arranged for the edited version to be published as a posthumous second edition in 1850.";true;d4d4a1b3-5b83-4814-8a20-f039af6f0387;12;11.11;11;64625905-c234-4d0d-9bc1-283ee8946770 +9d703c23-54a8-4eff-81c1-cdce6b8376b1;Wuthering Heights;"Wuthering Heights, Emily Brontë's only novel, was published in 1847 under the pseudonym ""Ellis Bell"". It was written between October 1845 and June 1846. Wuthering Heights and Anne Brontë's Agnes Grey were accepted by publisher Thomas Newby before the success of their sister Charlotte's novel Jane Eyre. After Emily's death, Charlotte edited the manuscript of Wuthering Heights and arranged for the edited version to be published as a posthumous second edition in 1850.";true;d4d4a1b3-5b83-4814-8a20-f039af6f0387;12;3000.0000;11;64625905-c234-4d0d-9bc1-283ee8946770 676059d4-8851-47f1-b558-3bdc461bf7d5;Jane Eyre;"Jane Eyre /ɛər/ (originally published as Jane Eyre: An Autobiography) is a novel by English writer Charlotte Brontë, published under the pen name ""Currer Bell"", on 16 October 1847, by Smith, Elder & Co. of London. The first American edition was published the following year by Harper & Brothers of New York. Primarily a bildungsroman, Jane Eyre follows the experiences of its eponymous heroine, including her growth to adulthood and her love for Mr. Rochester, the brooding master of Thornfield Hall. The novel revolutionised prose fiction in that the focus on Jane's moral and spiritual development is told through an intimate, first-person narrative, where actions and events are coloured by a psychological intensity. The book contains elements of social criticism, with a strong sense of Christian morality at its core and is considered by many to be ahead of its time because of Jane's individualistic character and how the novel approaches the topics of class, sexuality, religion and feminism.";true;47f97f40-4f41-488a-b10b-a5725e762d5e;11;12.34;11;5ab2a87b-3a56-4d97-a697-7af72334a384 42bc7997-f6ce-4ae9-8a64-ee5e02ef1087;The Raven;"""The Raven"" is a narrative poem by American writer Edgar Allan Poe. First published in January 1845, the poem is often noted for its musicality, stylized language, and supernatural atmosphere. It tells of a talking raven's mysterious visit to a distraught lover, tracing the man's slow fall into madness. The lover, often identified as being a student, is lamenting the loss of his love, Lenore. Sitting on a bust of Pallas, the raven seems to further distress the protagonist with its constant repetition of the word ""Nevermore"". The poem makes use of folk, mythological, religious, and classical references.";true;5c30d395-db0a-4095-bd7e-d4de34646607;333;13.13;16;5ab2a87b-3a56-4d97-a697-7af72334a384 9297e4ea-396e-47a4-8815-cd4622dea8b1;Eleonora;"""Eleonora"" is a short story by Edgar Allan Poe, first published in 1842 in Philadelphia in the literary annual The Gift. It is often regarded as somewhat autobiographical and has a relatively ""happy"" ending.";true;5c30d395-db0a-4095-bd7e-d4de34646607;555;14;16;8aaed432-8336-4b0d-be7e-3ef1ce7f13ea -574c8add-0ee3-4175-ab62-ca09a92c723c;Catweazle;Catweazle is a British fantasy television series, starring Geoffrey Bayldon in the title role, and created by Richard Carpenter for London Weekend Television. The first series, produced and directed by Quentin Lawrence, was screened in the UK on ITV in 1970. The second series, directed by David Reid and David Lane, was shown in 1971. Each series had thirteen episodes, most but not all written by Carpenter, who also published two books based on the scripts.;true;a45da28a-7f55-4b53-8a63-48b61132d1b9;22;15;13;8aaed432-8336-4b0d-be7e-3ef1ce7f13ea \ No newline at end of file +574c8add-0ee3-4175-ab62-ca09a92c723c;Catweazle;Catweazle is a British fantasy television series, starring Geoffrey Bayldon in the title role, and created by Richard Carpenter for London Weekend Television. The first series, produced and directed by Quentin Lawrence, was screened in the UK on ITV in 1970. The second series, directed by David Reid and David Lane, was shown in 1971. Each series had thirteen episodes, most but not all written by Carpenter, who also published two books based on the scripts.;true;a45da28a-7f55-4b53-8a63-48b61132d1b9;22;15;13;8aaed432-8336-4b0d-be7e-3ef1ce7f13ea diff --git a/tests/bookshop/db/schema.cds b/tests/bookshop/db/schema.cds index 30daa98..ddb4a03 100644 --- a/tests/bookshop/db/schema.cds +++ b/tests/bookshop/db/schema.cds @@ -126,7 +126,7 @@ entity Books : managed, cuid { @title : '{i18n>books.genre}' genre : Association to Genres; stock : Integer; - price : Decimal; + price : Decimal(11, 4); isUsed : Boolean; image : LargeBinary @Core.MediaType : 'image/png'; @title : '{i18n>books.bookType}' diff --git a/tests/integration/fiori-draft-enabled.test.js b/tests/integration/fiori-draft-enabled.test.js index 17d5dfe..16eb191 100644 --- a/tests/integration/fiori-draft-enabled.test.js +++ b/tests/integration/fiori-draft-enabled.test.js @@ -169,11 +169,14 @@ describe("change log integration test", () => { }); it("2.2 Child entity update - should log basic data type changes (ERP4SMEPREPWORKAPPPLAT-32 ERP4SMEPREPWORKAPPPLAT-613)", async () => { + cds.services.AdminService.entities.Books.elements.price["@changelog"] = true; + const action = PATCH.bind({}, `/odata/v4/admin/Books(ID=9d703c23-54a8-4eff-81c1-cdce6b8376b1,IsActiveEntity=false)`, { title: "new title", author_ID: "47f97f40-4f41-488a-b10b-a5725e762d5e", genre_ID: 16, - isUsed: false + isUsed: false, + price: 3000 }); await utils.apiAction("admin", "BookStores", "64625905-c234-4d0d-9bc1-283ee8946770", "AdminService", action); const bookChanges = await adminService.run( @@ -262,6 +265,17 @@ describe("change log integration test", () => { expect(isUsedChange.valueChangedFrom).to.equal("true"); expect(isUsedChange.valueChangedTo).to.equal("false"); + // The current price is 3000.0000, and update operation via OData service is price: 3000. In this case, a changelog should not be generated. + const priceChanges = await adminService.run( + SELECT.from(ChangeView).where({ + entity: "sap.capire.bookshop.Books", + attribute: "price", + }) + ); + + expect(priceChanges.length).to.equal(0); + + delete cds.services.AdminService.entities.Books.elements.price["@changelog"]; }); it("2.3 Child entity delete - should log basic data type changes (ERP4SMEPREPWORKAPPPLAT-32 ERP4SMEPREPWORKAPPPLAT-613)", async () => { @@ -522,7 +536,7 @@ describe("change log integration test", () => { expect(titleChanges.length).to.equal(1); const titleChange = titleChanges[0]; - expect(titleChange.objectID).to.equal("11.11, new title, 12"); + expect(titleChange.objectID).to.equal("3000, new title, 12"); cds.services.AdminService.entities.Books["@changelog"] = [ { "=": "title" },