Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(hana): Ensure xpr with logical operator to only contain comparisons #452

Merged
merged 3 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions hana/lib/HANAService.js
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,9 @@ class HANAService extends SQLService {
}

where(xpr) {
return this.xpr({ xpr: [...xpr, 'THEN'] }).slice(0, -4)
xpr = { xpr }
const suffix = this.is_comparator(xpr) ? '' : ' = TRUE'
return `${this.xpr(xpr)}${suffix}`
}

having(xpr) {
Expand All @@ -673,6 +675,7 @@ class HANAService extends SQLService {
*/
}

let endWithCompare = false
if (!_internal) {
for (let i = 0; i < xpr.length; i++) {
let x = xpr[i]
Expand All @@ -683,6 +686,7 @@ class HANAService extends SQLService {
// HANA does not support comparators in all clauses (e.g. SELECT 1>0 FROM DUMMY)
// HANA does not have an 'IS' or 'IS NOT' operator
if (x in compareOperators) {
endWithCompare = true
const left = xpr[i - 1]
const right = xpr[i + 1]
const ifNull = compareOperators[x]
Expand Down Expand Up @@ -725,16 +729,25 @@ class HANAService extends SQLService {
for (let i = 0; i < xpr.length; ++i) {
const x = xpr[i]
if (typeof x === 'string') {
const up = x.toUpperCase()
if (up in logicOperators) {
// Force current expression to end with a comparison
endWithCompare = true
}
if (endWithCompare && (up in caseOperators || up === ')')) {
endWithCompare = false
}
sql.push(this.operator(x, i, xpr))
} else if (x.xpr) sql.push(`(${this.xpr(x, caseSuffix)})`)
// default
else sql.push(this.expr(x))
}

// HANA does not allow WHERE TRUE so when the expression is only a single entry "= TRUE" is appended
if (caseSuffix && (
xpr.length === 1 || xpr.at(-1) === '')) {
sql.push(caseSuffix)
if (endWithCompare) {
const suffix = this.operator('OR', xpr.length, xpr).slice(0, -3)
if (suffix) {
sql.push(suffix)
}
}

return `${sql.join(' ')}`
Expand Down Expand Up @@ -765,13 +778,14 @@ class HANAService extends SQLService {
* @returns
*/
is_comparator({ xpr }, start) {
const local = start != null
for (let i = start ?? xpr.length; i > -1; i--) {
const cur = xpr[i]
if (cur == null) continue
if (typeof cur === 'string') {
const up = cur.toUpperCase()
// When a compare operator is found the expression is a comparison
if (up in compareOperators) return true
if (up in compareOperators || (!local && up in logicOperators)) return true
// When a case operator is found it is the start of the expression
if (up in caseOperators) break
continue
Expand Down
8 changes: 8 additions & 0 deletions test/scenarios/bookshop/read.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ describe('Bookshop - Read', () => {
expect(res4[1].title).to.be.eq('dracula')
})

test('Filter Books(multiple functions)', async () => {
const res = await GET(
`/admin/Books?$filter=contains(descr,'Edgar') or contains(descr,'Autobiography')`,
admin,
)
expect(res.data.value.length).to.be.eq(3)
})

test.skip('Insert Booky', async () => {
const res = await POST(
'/admin/Booky',
Expand Down