Skip to content

Commit fc325ee

Browse files
committed
Cross reference the cast matrix against openGauss pg_cast.h to confirm numeric_int4 dtoi4 ftoi4 bpchar and namein OIDs match PostgreSQL exactly while explicitly calling out the openGauss only bool to numeric and numeric to bool cast entries 6433 6434 that the evaluator deliberately treats as conservative narrowing since aligning with PostgreSQL rejection means routing falls through to broadcast on openGauss rather than picking the casted 0 or 1 value
1 parent 148a12f commit fc325ee

2 files changed

Lines changed: 23 additions & 6 deletions

File tree

features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/PostgreSQLCastEvaluator.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,19 @@
5151
* {@code bool::numeric}, {@code numeric::bool}, {@code float8::bool}, {@code '1.5'::int4} (PG raises
5252
* {@code invalid input syntax for type integer}).</p>
5353
*
54-
* <p>openGauss inherits its {@code pg_cast} catalog from PostgreSQL 9.2 and keeps the same {@code numeric_int4} /
55-
* {@code dtoi4} / {@code ftoi4} / {@code bpchar} / {@code namein} cast functions, so the cell-by-cell behavior
56-
* verified here against PostgreSQL 16 also describes the openGauss path. The evaluator is invoked only when the
57-
* parser produces a {@code TypeCastExpression}, which is emitted exclusively by the PostgreSQL and openGauss
58-
* visitors; MySQL / Oracle / SQL Server {@code CAST(...)} syntax becomes a {@code FunctionSegment} and bypasses
59-
* this evaluator entirely, so there is no cross-dialect contamination risk.</p>
54+
* <p>openGauss forks the {@code pg_cast} catalog from PostgreSQL 9.2 (see
55+
* {@code src/include/catalog/pg_cast.h} in {@code opengauss-mirror/openGauss-server}) and keeps the same OID-bound
56+
* {@code numeric_int4} / {@code dtoi4} / {@code ftoi4} / {@code bpchar} / {@code namein} cast functions, so the
57+
* integer / numeric / float / text / name behavior verified here against PostgreSQL 16 carries through unchanged.
58+
* The one substantive divergence is the {@code bool ↔ numeric} pair: openGauss adds explicit cast functions
59+
* {@code 6433} ({@code bool → numeric}) and {@code 6434} ({@code numeric → bool}) that PostgreSQL does not have, and
60+
* this evaluator stays aligned with PostgreSQL by returning {@link Optional#empty()} for both, which on openGauss is
61+
* a conservative narrowing: routing falls through to broadcast where openGauss could otherwise route by the casted
62+
* 0 / 1 value. Implementing openGauss-aware optimization for those two cells is deferred and noted explicitly here.</p>
63+
*
64+
* <p>The evaluator is invoked only when the parser produces a {@code TypeCastExpression}, which is emitted
65+
* exclusively by the PostgreSQL and openGauss visitors; MySQL / Oracle / SQL Server {@code CAST(...)} syntax becomes
66+
* a {@code FunctionSegment} and bypasses this evaluator entirely, so there is no cross-dialect contamination risk.</p>
6067
*/
6168
@NoArgsConstructor(access = AccessLevel.PRIVATE)
6269
public final class PostgreSQLCastEvaluator {

features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/route/engine/condition/engine/PostgreSQLCastEvaluatorTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,16 @@ void assertBooleanToBoolean() {
411411
assertThat(PostgreSQLCastEvaluator.evaluate(Boolean.TRUE, "bool").orElseThrow(AssertionError::new), is(Boolean.TRUE));
412412
}
413413

414+
@Test
415+
void assertBoolToNumericIsConservativeOnOpenGaussWhichWouldAcceptThisCast() {
416+
assertFalse(PostgreSQLCastEvaluator.evaluate(Boolean.TRUE, "numeric").isPresent());
417+
}
418+
419+
@Test
420+
void assertNumericToBoolIsConservativeOnOpenGaussWhichWouldAcceptThisCast() {
421+
assertFalse(PostgreSQLCastEvaluator.evaluate(new BigDecimal("1"), "bool").isPresent());
422+
}
423+
414424
@Test
415425
void assertBooleanTrueToName() {
416426
assertThat(PostgreSQLCastEvaluator.evaluate(Boolean.TRUE, "name").orElseThrow(AssertionError::new), is("t"));

0 commit comments

Comments
 (0)