Skip to content

change-tracking can't handle non-ID named key fields and sends invalid query #212

@patricebender

Description

@patricebender
  1. cds init change-tracking-bug
  2. cd change-tracking-bug
  3. npm add @cap-js/change-tracking
  4. npm i
  5. touch db/schema.cds Add the following content to db/schema.cds:
namespace my.bookshop;

entity Books {
  key NOT_ID : Int16;
      @changelog
      title  : String;
}
  1. touch srv/api.cds Add the following content to srv/api.cds:
using { my.bookshop as shop } from '../db/schema';

Service CatalogService {
    entity Books as projection on shop.Books;
}
  1. touch test/CatalogService.http Add the following content to test/CatalogService.http:
@server=http://localhost:4004
@username=alice
@password=

### Books
# @name Books_POST
PUT {{server}}/odata/v4/catalog/Books(NOT_ID='42')
Content-Type: application/json
Authorization: Basic {{username}}:{{password}}

{
  "title": "title-4711"
}
  1. cds watch and then fire the request in test/CatalogService.http
  2. Observe the error:
[error] - 500 - Error: "ID" not found in the elements of "CatalogService.Books"
    at stepNotFoundInCombinedElements (/Users/patricebender/SAPDevelop/change-tracking-bug/node_modules/@cap-js/db-service/lib/infer/index.js:794:13)
    at /Users/patricebender/SAPDevelop/change-tracking-bug/node_modules/@cap-js/db-service/lib/infer/index.js:501:11
    at Array.forEach (<anonymous>)
    at inferArg (/Users/patricebender/SAPDevelop/change-tracking-bug/node_modules/@cap-js/db-service/lib/infer/index.js:441:13)
    at processToken (/Users/patricebender/SAPDevelop/change-tracking-bug/node_modules/@cap-js/db-service/lib/infer/index.js:307:11)
    at Array.forEach (<anonymous>)
    at walkTokenStream (/Users/patricebender/SAPDevelop/change-tracking-bug/node_modules/@cap-js/db-service/lib/infer/index.js:311:19)
    at inferQueryElements (/Users/patricebender/SAPDevelop/change-tracking-bug/node_modules/@cap-js/db-service/lib/infer/index.js:280:16)
    at infer (/Users/patricebender/SAPDevelop/change-tracking-bug/node_modules/@cap-js/db-service/lib/infer/index.js:71:22)
    at cqn4sql (/Users/patricebender/SAPDevelop/change-tracking-bug/node_modules/@cap-js/db-service/lib/cqn4sql.js:77:14) {
  code: ''
}
  1. The issue is that the change-tracking logic expects an ID field by default, but the entity uses a different key field name (NOT_ID). This results in the error when trying to process the request.

Here is the loc which generates the faulty query:

const getCurObjFromDbQuery = async function (entityName, queryVal, /**optional*/ queryKey='ID') {
  if (!queryVal) return {}
  // REVISIT: This always reads all elements -> should read required ones only!
  const obj = await SELECT.one.from(entityName).where({[queryKey]: queryVal})
  return obj || {}
}

→ this is the invalid query which is send to the db-service (which is rightfully rejected):

{
  "SELECT": {
    "one": true,
    "from": {
      "ref": [
        "CatalogService.Books"
      ]
    },
    "where": [
      {
        "ref": [
          "ID" // ❌ There is no ID in Books
        ]
      },
      "=",
      {
        "val": "undefined" // ❌ this is also broken
      }
    ],
    "expand": "root"
  }
}

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions