@balena/abstract-sql-compiler
Advanced tools
Comparing version 9.0.3-build-bumps-sbvr-types-with-web-resource-aa97f14f560002592f9d270a6746423f38eaf5da-1 to 9.0.3-build-comparison-operator-precedence-simple-e31f8692d1137b8c87b633b7b827814402904047-1
@@ -7,5 +7,5 @@ # Change Log | ||
## 9.0.3 - 2023-05-17 | ||
## 9.0.3 - 2023-05-30 | ||
* Bumps sbvr types containing WebResource [Otávio Jacobi] | ||
* Wrap composite comparison operations with parenthesis when necessary [Thodoris Greasidis] | ||
@@ -12,0 +12,0 @@ ## 9.0.2 - 2023-05-16 |
@@ -251,4 +251,4 @@ "use strict"; | ||
(0, exports.checkArgs)(comparison, args, 2); | ||
const a = AnyValue((0, exports.getAbstractSqlQuery)(args, 0), indent); | ||
const b = AnyValue((0, exports.getAbstractSqlQuery)(args, 1), indent); | ||
const a = precedenceSafeOpValue(comparison, AnyValue, args, 0, indent); | ||
const b = precedenceSafeOpValue(comparison, AnyValue, args, 1, indent); | ||
return a + exports.comparisons[comparison] + b; | ||
@@ -323,10 +323,12 @@ }; | ||
]); | ||
const mathOpValue = (valueMatchFn, args, index, indent) => { | ||
const precedenceSafeOpValue = (parentNodeType, valueMatchFn, args, index, indent) => { | ||
const operandAbstractSql = (0, exports.getAbstractSqlQuery)(args, index); | ||
const numericValue = valueMatchFn(operandAbstractSql, indent); | ||
const valueExpr = valueMatchFn(operandAbstractSql, indent); | ||
const [childNodeType] = operandAbstractSql; | ||
if (mathOperatorNodeTypes.has(childNodeType)) { | ||
return `(${numericValue})`; | ||
if ((mathOperatorNodeTypes.has(parentNodeType) && | ||
mathOperatorNodeTypes.has(childNodeType)) || | ||
(parentNodeType in exports.comparisons && childNodeType in exports.comparisons)) { | ||
return `(${valueExpr})`; | ||
} | ||
return numericValue; | ||
return valueExpr; | ||
}; | ||
@@ -336,4 +338,4 @@ const MathOp = (type) => { | ||
(0, exports.checkArgs)(type, args, 2); | ||
const a = mathOpValue(NumericValue, args, 0, indent); | ||
const b = mathOpValue(NumericValue, args, 1, indent); | ||
const a = precedenceSafeOpValue(type, NumericValue, args, 0, indent); | ||
const b = precedenceSafeOpValue(type, NumericValue, args, 1, indent); | ||
return `${a} ${mathOps[type]} ${b}`; | ||
@@ -406,4 +408,4 @@ }; | ||
(0, exports.checkArgs)('AddDateNumber', args, 2); | ||
const a = mathOpValue(DateValue, args, 0, indent); | ||
const b = mathOpValue(NumericValue, args, 1, indent); | ||
const a = precedenceSafeOpValue('AddDateNumber', DateValue, args, 0, indent); | ||
const b = precedenceSafeOpValue('AddDateNumber', NumericValue, args, 1, indent); | ||
if (engine === "postgres") { | ||
@@ -421,4 +423,4 @@ return `${a} + ${b}`; | ||
(0, exports.checkArgs)('AddDateDuration', args, 2); | ||
const a = mathOpValue(DateValue, args, 0, indent); | ||
const b = mathOpValue(DurationValue, args, 1, indent); | ||
const a = precedenceSafeOpValue('AddDateDuration', DateValue, args, 0, indent); | ||
const b = precedenceSafeOpValue('AddDateDuration', DurationValue, args, 1, indent); | ||
if (engine === "postgres") { | ||
@@ -436,4 +438,4 @@ return `${a} + ${b}`; | ||
(0, exports.checkArgs)('SubtractDateDuration', args, 2); | ||
const a = mathOpValue(DateValue, args, 0, indent); | ||
const b = mathOpValue(DurationValue, args, 1, indent); | ||
const a = precedenceSafeOpValue('SubtractDateDuration', DateValue, args, 0, indent); | ||
const b = precedenceSafeOpValue('SubtractDateDuration', DurationValue, args, 1, indent); | ||
if (engine === "postgres") { | ||
@@ -451,4 +453,4 @@ return `${a} - ${b}`; | ||
(0, exports.checkArgs)('SubtractDateNumber', args, 2); | ||
const a = mathOpValue(DateValue, args, 0, indent); | ||
const b = mathOpValue(NumericValue, args, 1, indent); | ||
const a = precedenceSafeOpValue('SubtractDateNumber', DateValue, args, 0, indent); | ||
const b = precedenceSafeOpValue('SubtractDateNumber', NumericValue, args, 1, indent); | ||
if (engine === "postgres") { | ||
@@ -466,4 +468,4 @@ return `${a} - ${b}`; | ||
(0, exports.checkArgs)('SubtractDateDate', args, 2); | ||
const a = mathOpValue(DateValue, args, 0, indent); | ||
const b = mathOpValue(DateValue, args, 1, indent); | ||
const a = precedenceSafeOpValue('SubtractDateDate', DateValue, args, 0, indent); | ||
const b = precedenceSafeOpValue('SubtractDateDate', DateValue, args, 1, indent); | ||
if (engine === "postgres") { | ||
@@ -470,0 +472,0 @@ return `${a} - ${b}`; |
{ | ||
"name": "@balena/abstract-sql-compiler", | ||
"version": "9.0.3-build-bumps-sbvr-types-with-web-resource-aa97f14f560002592f9d270a6746423f38eaf5da-1", | ||
"version": "9.0.3-build-comparison-operator-precedence-simple-e31f8692d1137b8c87b633b7b827814402904047-1", | ||
"description": "A translator for abstract sql into sql.", | ||
@@ -19,3 +19,3 @@ "main": "out/AbstractSQLCompiler.js", | ||
"dependencies": { | ||
"@balena/sbvr-types": "5.1.0-build-web-resource-2-18a09938422881c4507118f81f2d5395e132e741-1", | ||
"@balena/sbvr-types": "^5.0.0", | ||
"lodash": "^4.17.21" | ||
@@ -65,4 +65,4 @@ }, | ||
"versionist": { | ||
"publishedAt": "2023-05-17T15:49:45.374Z" | ||
"publishedAt": "2023-05-30T08:53:06.439Z" | ||
} | ||
} |
@@ -318,4 +318,4 @@ import * as _ from 'lodash'; | ||
checkArgs(comparison, args, 2); | ||
const a = AnyValue(getAbstractSqlQuery(args, 0), indent); | ||
const b = AnyValue(getAbstractSqlQuery(args, 1), indent); | ||
const a = precedenceSafeOpValue(comparison, AnyValue, args, 0, indent); | ||
const b = precedenceSafeOpValue(comparison, AnyValue, args, 1, indent); | ||
return a + comparisons[comparison] + b; | ||
@@ -398,3 +398,4 @@ }; | ||
const mathOpValue = ( | ||
const precedenceSafeOpValue = ( | ||
parentNodeType: string, | ||
valueMatchFn: MetaMatchFn, | ||
@@ -406,8 +407,13 @@ args: AbstractSqlType[], | ||
const operandAbstractSql = getAbstractSqlQuery(args, index); | ||
const numericValue = valueMatchFn(operandAbstractSql, indent); | ||
const valueExpr = valueMatchFn(operandAbstractSql, indent); | ||
const [childNodeType] = operandAbstractSql; | ||
if (mathOperatorNodeTypes.has(childNodeType)) { | ||
return `(${numericValue})`; | ||
if ( | ||
(mathOperatorNodeTypes.has(parentNodeType) && | ||
mathOperatorNodeTypes.has(childNodeType)) || | ||
// We need parenthesis for chained boolean comparisons, otherwise PostgreSQL complains. | ||
(parentNodeType in comparisons && childNodeType in comparisons) | ||
) { | ||
return `(${valueExpr})`; | ||
} | ||
return numericValue; | ||
return valueExpr; | ||
}; | ||
@@ -418,4 +424,4 @@ | ||
checkArgs(type, args, 2); | ||
const a = mathOpValue(NumericValue, args, 0, indent); | ||
const b = mathOpValue(NumericValue, args, 1, indent); | ||
const a = precedenceSafeOpValue(type, NumericValue, args, 0, indent); | ||
const b = precedenceSafeOpValue(type, NumericValue, args, 1, indent); | ||
return `${a} ${mathOps[type]} ${b}`; | ||
@@ -489,4 +495,10 @@ }; | ||
checkArgs('AddDateNumber', args, 2); | ||
const a = mathOpValue(DateValue, args, 0, indent); | ||
const b = mathOpValue(NumericValue, args, 1, indent); | ||
const a = precedenceSafeOpValue('AddDateNumber', DateValue, args, 0, indent); | ||
const b = precedenceSafeOpValue( | ||
'AddDateNumber', | ||
NumericValue, | ||
args, | ||
1, | ||
indent, | ||
); | ||
@@ -504,4 +516,16 @@ if (engine === Engines.postgres) { | ||
checkArgs('AddDateDuration', args, 2); | ||
const a = mathOpValue(DateValue, args, 0, indent); | ||
const b = mathOpValue(DurationValue, args, 1, indent); | ||
const a = precedenceSafeOpValue( | ||
'AddDateDuration', | ||
DateValue, | ||
args, | ||
0, | ||
indent, | ||
); | ||
const b = precedenceSafeOpValue( | ||
'AddDateDuration', | ||
DurationValue, | ||
args, | ||
1, | ||
indent, | ||
); | ||
@@ -519,4 +543,16 @@ if (engine === Engines.postgres) { | ||
checkArgs('SubtractDateDuration', args, 2); | ||
const a = mathOpValue(DateValue, args, 0, indent); | ||
const b = mathOpValue(DurationValue, args, 1, indent); | ||
const a = precedenceSafeOpValue( | ||
'SubtractDateDuration', | ||
DateValue, | ||
args, | ||
0, | ||
indent, | ||
); | ||
const b = precedenceSafeOpValue( | ||
'SubtractDateDuration', | ||
DurationValue, | ||
args, | ||
1, | ||
indent, | ||
); | ||
@@ -534,4 +570,16 @@ if (engine === Engines.postgres) { | ||
checkArgs('SubtractDateNumber', args, 2); | ||
const a = mathOpValue(DateValue, args, 0, indent); | ||
const b = mathOpValue(NumericValue, args, 1, indent); | ||
const a = precedenceSafeOpValue( | ||
'SubtractDateNumber', | ||
DateValue, | ||
args, | ||
0, | ||
indent, | ||
); | ||
const b = precedenceSafeOpValue( | ||
'SubtractDateNumber', | ||
NumericValue, | ||
args, | ||
1, | ||
indent, | ||
); | ||
@@ -549,4 +597,16 @@ if (engine === Engines.postgres) { | ||
checkArgs('SubtractDateDate', args, 2); | ||
const a = mathOpValue(DateValue, args, 0, indent); | ||
const b = mathOpValue(DateValue, args, 1, indent); | ||
const a = precedenceSafeOpValue( | ||
'SubtractDateDate', | ||
DateValue, | ||
args, | ||
0, | ||
indent, | ||
); | ||
const b = precedenceSafeOpValue( | ||
'SubtractDateDate', | ||
DateValue, | ||
args, | ||
1, | ||
indent, | ||
); | ||
if (engine === Engines.postgres) { | ||
@@ -553,0 +613,0 @@ return `${a} - ${b}`; |
@@ -0,1 +1,2 @@ | ||
import { stripIndent } from 'common-tags'; | ||
import { AnyTypeNodes } from '../../src/AbstractSQLCompiler'; | ||
@@ -27,1 +28,131 @@ | ||
}); | ||
describe('Comparison Operator Precedence', () => { | ||
// Different precedence | ||
test( | ||
[ | ||
'SelectQuery', | ||
[ | ||
'Select', | ||
[ | ||
[ | ||
'Equals', | ||
['Boolean', true], | ||
['Equals', ['Boolean', true], ['Boolean', true]], | ||
], | ||
], | ||
], | ||
], | ||
(result, sqlEquals) => { | ||
it('should produce a valid Equals statement when the second operand is also an Equals', () => { | ||
sqlEquals(result.query, 'SELECT TRUE = (TRUE = TRUE)'); | ||
}); | ||
}, | ||
); | ||
test( | ||
[ | ||
'SelectQuery', | ||
[ | ||
'Select', | ||
[ | ||
[ | ||
'NotEquals', | ||
['Equals', ['Boolean', false], ['Boolean', false]], | ||
['Equals', ['Boolean', true], ['Boolean', true]], | ||
], | ||
], | ||
], | ||
], | ||
(result, sqlEquals) => { | ||
it('should produce a valid NotEquals statement when both operands are Equals comparisons', () => { | ||
sqlEquals(result.query, 'SELECT (FALSE = FALSE) != (TRUE = TRUE)'); | ||
}); | ||
}, | ||
); | ||
test( | ||
[ | ||
'SelectQuery', | ||
[ | ||
'Select', | ||
[ | ||
[ | ||
'NotEquals', | ||
['Add', ['Integer', 1], ['Add', ['Integer', 2], ['Integer', 3]]], | ||
['Add', ['Integer', 1], ['Integer', 0]], | ||
], | ||
], | ||
], | ||
], | ||
(result, sqlEquals) => { | ||
it('should produce a valid NotEquals statement when the operands are math expressions', () => { | ||
sqlEquals( | ||
result.query, | ||
stripIndent` | ||
SELECT 1 + (2 + 3) != 1 + 0 | ||
`, | ||
); | ||
}); | ||
}, | ||
); | ||
test( | ||
[ | ||
'SelectQuery', | ||
[ | ||
'Select', | ||
[ | ||
[ | ||
'And', | ||
[ | ||
'Or', | ||
['GreaterThan', ['Integer', 1], ['Integer', 0]], | ||
['LessThan', ['Integer', 1], ['Integer', 0]], | ||
], | ||
['GreaterThan', ['Integer', 1], ['Integer', 0]], | ||
], | ||
], | ||
], | ||
], | ||
(result, sqlEquals) => { | ||
it('should produce a valid And statement when the operands are composite boolean expressions', () => { | ||
sqlEquals( | ||
result.query, | ||
stripIndent` | ||
SELECT (1 > 0 | ||
OR 1 < 0) | ||
AND 1 > 0 | ||
`, | ||
); | ||
}); | ||
}, | ||
); | ||
test( | ||
[ | ||
'SelectQuery', | ||
[ | ||
'Select', | ||
[ | ||
[ | ||
'Between', | ||
['Add', ['Integer', 1], ['Integer', 0]], | ||
['Add', ['Integer', 1], ['Integer', 0]], | ||
['Add', ['Integer', 1], ['Integer', 0]], | ||
], | ||
], | ||
], | ||
], | ||
(result, sqlEquals) => { | ||
it('should produce a valid Between statement when the operands are math expressions', () => { | ||
sqlEquals( | ||
result.query, | ||
stripIndent` | ||
SELECT 1 + 0 BETWEEN 1 + 0 AND (1 + 0) | ||
`, | ||
); | ||
}); | ||
}, | ||
); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
832825
17928
+ Added@balena/sbvr-types@5.2.0(transitive)
- Removed@balena/sbvr-types@5.1.0-build-web-resource-2-18a09938422881c4507118f81f2d5395e132e741-1(transitive)
Updated@balena/sbvr-types@^5.0.0