Skip to content

Commit 8d75cab

Browse files
authored
Merge 8aa8073 into 7e1ffd4
2 parents 7e1ffd4 + 8aa8073 commit 8d75cab

File tree

5 files changed

+41
-4
lines changed

5 files changed

+41
-4
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6060
- CLI no longer terminates on user errors in submitted PartiQL (when printing out the AST with !!)
6161
and no longer prints out stack traces upon user errors.
6262

63+
- Constrained Decimal matching logic.
64+
6365
### Removed
6466
- The deprecated `IonValue` property in `ExprValue` interface is now removed.
6567
- Removed partiql-extensions to partiql-cli `org.partiql.cli.functions`

partiql-lang/src/main/kotlin/org/partiql/lang/eval/visitors/PartiqlAstSanityValidator.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ class PartiqlAstSanityValidator : PartiqlAst.Visitor() {
6868

6969
private fun validateDecimalOrNumericType(scale: LongPrimitive?, precision: LongPrimitive?, metas: MetaContainer) {
7070
if (scale != null && precision != null && compileOptions.typedOpBehavior == TypedOpBehavior.HONOR_PARAMETERS) {
71+
if (precision.value <= 0L) {
72+
err(
73+
"Precision ${precision.value} should be a positive integer",
74+
errorCode = ErrorCode.SEMANTIC_INVALID_DECIMAL_ARGUMENTS,
75+
errorContext = errorContextFrom(metas),
76+
internal = false
77+
)
78+
}
7179
if (scale.value !in 0..precision.value) {
7280
err(
7381
"Scale ${scale.value} should be between 0 and precision ${precision.value}",

partiql-lang/src/test/kotlin/org/partiql/lang/eval/CastTestBase.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,10 @@ abstract class CastTestBase : EvaluatorTestBase() {
12501250
listOf(
12511251
case("1", ErrorCode.SEMANTIC_INVALID_DECIMAL_ARGUMENTS)
12521252
).types(ExprValueType.DECIMAL.typeAliases().map { "$it(2,4)" }),
1253+
// DECIMAL(0, 0) is a compilation failure in this mode because we should not allow precision to be zero
1254+
listOf(
1255+
case("1", ErrorCode.SEMANTIC_INVALID_DECIMAL_ARGUMENTS)
1256+
).types(ExprValueType.DECIMAL.typeAliases().map { "$it(0,0)" }),
12531257
// VARCHAR(4) should truncate to size <= 4
12541258
listOf(
12551259
// from string types

partiql-lang/src/test/kotlin/org/partiql/lang/eval/EvaluatingCompilerIsTests.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,20 @@ class EvaluatingCompilerIsTests : EvaluatorTestBase() {
460460
expectedIsDecimalHonorParamsResult = "TRUE"
461461
),
462462

463+
// Equal Precision and scale
464+
isDecimalTypeTestCase(
465+
sql = "0.001 is DECIMAL(3,3)",
466+
expectedLegacyResult = "TRUE",
467+
expectedIsDecimalHonorParamsResult = "TRUE"
468+
),
469+
470+
// Equal Precision and scale
471+
isDecimalTypeTestCase(
472+
sql = "1.000 is DECIMAL(4,3)",
473+
expectedLegacyResult = "TRUE",
474+
expectedIsDecimalHonorParamsResult = "TRUE"
475+
),
476+
463477
// less precision and scale
464478
isDecimalTypeTestCase(
465479
sql = "123.456 IS DECIMAL(2, 2)",

partiql-types/src/main/kotlin/org/partiql/types/StaticType.kt

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package org.partiql.types
66

77
import java.math.BigDecimal
8+
import java.math.RoundingMode
89

910
/**
1011
* Represents static types available in the language and ways to extends them to create new types.
@@ -300,11 +301,19 @@ data class DecimalType(
300301

301302
data class Constrained(val precision: Int, val scale: Int = 0) : PrecisionScaleConstraint() {
302303
override fun matches(d: BigDecimal): Boolean {
303-
val dv = d.stripTrailingZeros()
304-
305-
val integerDigits = dv.precision() - dv.scale()
304+
// check scale
305+
val decimalPoint = if (d.scale() >= 0) d.scale() else 0
306+
if (decimalPoint > scale) {
307+
return false
308+
}
309+
// check integer part
310+
val integerPart = d.setScale(0, RoundingMode.DOWN)
311+
val integerLength = if (integerPart.signum() != 0) integerPart.precision() - integerPart.scale() else 0
312+
// PartiQL precision semantics -> the maximum number of total digit (left of decimal place + right of decimal place)
313+
// PartiQL scale semantics -> the total number of digit after the decimal point.
306314
val expectedIntegerDigits = precision - scale
307-
return integerDigits <= expectedIntegerDigits && dv.scale() <= scale
315+
316+
return expectedIntegerDigits >= integerLength
308317
}
309318
}
310319
}

0 commit comments

Comments
 (0)