Homelab, Linux, JS & ABAP (~˘▾˘)~
 

[CAP] CQL Expand two levels deep

I’ve already made a post about expanding compositions or associations (see here), but this time I had to extend two levels deep.

My entity structure looked something to this:

entity Header: cuid, managed {
    Items           : Composition of many Header.Items
                          on Items.purgeRun = $self;
}

entity Header.Items : cuid, managed {
    file            : Association to Files @mandatory @assert.target;
    header: Association to Header;
}

entity Files : cuid, managed {          
    content         : LargeBinary @Core.MediaType: mediaType  @Core.ContentDisposition.Filename: fileName  @Core.ContentDisposition.Type: 'inline';
    mediaType       : String      @Core.IsMediaType: true;
    fileName        : String      @mandatory;
    size            : Integer;
}   

It is possible to query all data in a single HTTP call using $expand twice.

### Header + Items + File
GET {{server}}/odata/v4/service/MainEntity/{{ID}}
?$expand=Items($expand=file)
Authorization: Basic {{username}} {{password}}

However, if you want to fetch the same data using CQL, the following query is required:

        const data = await SELECT(Header, ID)
            .columns(h => {
                h('*')
                h.Items(i => {
                    i('*')
                    i.file(f => f('*'))
                })
            })

This syntax is really hard to remember…

[CAP] CQL Expand Composition / Deep read

In the documentation they always use a star in string literals like this o => o.`*` to select all fields, but when running this it always failed. However, after some tests I found that this format works with brackets o => o.('*')

https://cap.cloud.sap/docs/guides/providing-services/#–-deep-read

entity myEntity: cuid, managed {
    field1          : String;
    comp            : Composition of one myComposition;
}
 
aspect myComposition: cuid, managed {
    myCompField: String;
}
        const result = await SELECT.from(myEntity)
            .columns(e => {
                e('*')
                e.comp(c => c.myCompField) //expand composition, but only select 'myCompField'
            })

Update 14.09.2023: is now fixed (#)

[CAP] CQL Deep Update

A Composition of one can be updated via the Parent Entity, like we would do it, when dealing with an Association to one.

entity myEntity: cuid, managed {
    field1          : String;
    comp            : Composition of one myComposition;
}

aspect myComposition: cuid, managed {
    myCompField: String;
}
            const { myEntity } = srv.entities
            const EntityComposition = srv.entities['myEntity.myComposition'] // composition

            srv.after('CREATE', EntityComposition , async (comp, req) => {
                await UPDATE(myEntity, comp.ID)
                    .set({
                      comp : [{ myCompField: 'test' }]
                    })
            })

A Composition of many must be updated via the actual Composition Entity.

entity myEntity: cuid, managed {
    field1          : String;
    comp            : Composition to many myComposition;
}

aspect myComposition: cuid, managed {
    myCompField: String;
}
    const EntityComposition = srv.entities['myEntity.myComposition'] // composition

    srv.after('CREATE', EntityComposition , async (comp, req) => {
        await UPDATE(EntityComposition, { up__ID: comp.up__ID, ID: comp.ID }).set({ myCompField: 'test' })
    })