@sap/cds
Version:
SAP Cloud Application Programming Model - CDS for Node.js
106 lines (90 loc) • 3.25 kB
JavaScript
const { where2obj } = require('./cqn')
const { deepCopy } = require('./copy')
const { foreignKeyPropagations } = require('./foreignKeyPropagations')
function _mergeWhere(base, additional) {
if (additional?.length) {
// copy where else query will be modified
const whereCopy = deepCopy(additional)
if (base.length > 0) base.push('and')
base.push(...whereCopy)
}
return base
}
function _modifyWhereWithNavigations(where, newWhere, entityKey, targetKey) {
_mergeWhere(newWhere, where)
_renameOnUp(newWhere, entityKey, targetKey)
}
function _buildWhereForNavigations(ref, newWhere, model, target) {
const currentRef = ref[0]
const nextRef = ref[1]
if (nextRef) {
const csnEntity = target || model.definitions[currentRef.id || currentRef]
const navigationElement = csnEntity && csnEntity.elements[nextRef.id || nextRef]
if (!navigationElement || !navigationElement.on) return
const nextKeys = foreignKeyPropagations(navigationElement)
// only add where once in _modifyWhereWithNavigations
let whereAdded = false
for (const key of nextKeys) {
const targetKeyElement = navigationElement._target.elements[key.childElement.name]
if (targetKeyElement && (targetKeyElement.isAssociation || targetKeyElement._foreignKey4)) {
_modifyWhereWithNavigations(
!whereAdded && currentRef.where,
newWhere,
key.childElement.name,
key.parentElement.name
)
whereAdded = true
}
}
_buildWhereForNavigations(ref.slice(1), newWhere, model, navigationElement._target)
}
}
function _renameOnUp(newWhere, entityKey, targetKey) {
let renamed = false
newWhere.forEach(element => {
if (element.xpr && element.xpr.length) {
renamed = _renameOnUp(element.xpr, entityKey, targetKey) || renamed
}
if (element.ref && element.ref[0] === targetKey) {
element.ref = [entityKey]
renamed = true
}
})
return renamed
}
function _getWhereFromInsert(query, model) {
const where = []
if (query.INSERT.into.ref && query.INSERT.into.ref.length > 1) {
_buildWhereForNavigations(query.INSERT.into.ref, where, model)
}
return where
}
function _getWhereFromUpdate(query, model) {
if (query.UPDATE.entity.ref && query.UPDATE.entity.ref.length > 1) {
const where = []
_buildWhereForNavigations(query.UPDATE.entity.ref, where, model)
return where
}
const where = query.UPDATE.where || []
if (query.UPDATE.entity.ref?.length === 1 && query.UPDATE.entity.ref[0].where)
return _mergeWhere(where.length ? [...query.UPDATE.entity.ref[0].where] : query.UPDATE.entity.ref[0].where, where)
return where
}
// params: data, req, service/tx
function enrichDataWithKeysFromWhere(data, { query, target }, { model }) {
if (!query) return
if (query.INSERT) {
const where = _getWhereFromInsert(query, model)
if (!where?.length) return
if (!Array.isArray(data)) data = [data]
for (const d of data) Object.assign(d, where2obj(where, target))
} else if (query.UPDATE) {
const where = _getWhereFromUpdate(query, model)
if (!where?.length) return
where2obj(where, target, data)
}
}
module.exports = {
where2obj,
enrichDataWithKeysFromWhere
}