Skip to content

Commit f0da079

Browse files
committed
[CALCITE-7360] The meaning of negation for unsigned numbers is not defined
Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
1 parent 6548b0e commit f0da079

File tree

4 files changed

+37
-2
lines changed

4 files changed

+37
-2
lines changed

core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
10231023
80,
10241024
ReturnTypes.ARG0,
10251025
InferTypes.RETURN_TYPE,
1026-
OperandTypes.NUMERIC_OR_INTERVAL);
1026+
OperandTypes.SIGNED_OR_INTERVAL);
10271027

10281028
/**
10291029
* Checked version of prefix arithmetic minus operator, '<code>-</code>'.

core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,10 +402,15 @@ public static SqlOperandTypeChecker variadic(
402402
public static final SqlSingleOperandTypeChecker INTEGER =
403403
family(SqlTypeFamily.INTEGER);
404404

405+
public static final SqlSingleOperandTypeChecker SIGNED =
406+
family(SqlTypeFamily.INTEGER)
407+
.or(family(SqlTypeFamily.APPROXIMATE_NUMERIC))
408+
// Note: cannot use family(DECIMAL), because UNSIGNED can be implicitly cast to DECIMAL
409+
.or(typeName(SqlTypeName.DECIMAL));
410+
405411
public static final SqlSingleOperandTypeChecker UNSIGNED_NUMERIC_UNSIGNED_NUMERIC =
406412
family(SqlTypeFamily.UNSIGNED_NUMERIC, SqlTypeFamily.UNSIGNED_NUMERIC);
407413

408-
409414
public static final SqlSingleOperandTypeChecker INTEGER_INTEGER =
410415
family(SqlTypeFamily.INTEGER, SqlTypeFamily.INTEGER);
411416

@@ -1297,6 +1302,9 @@ public static SqlSingleOperandTypeChecker same(int operandCount,
12971302
public static final SqlSingleOperandTypeChecker NUMERIC_OR_INTERVAL =
12981303
NUMERIC.or(INTERVAL);
12991304

1305+
public static final SqlSingleOperandTypeChecker SIGNED_OR_INTERVAL =
1306+
SIGNED.or(INTERVAL);
1307+
13001308
public static final SqlSingleOperandTypeChecker NUMERIC_OR_STRING =
13011309
NUMERIC.or(STRING);
13021310

core/src/test/resources/sql/unsigned.iq

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ EXPR$0
2424
6
2525
!ok
2626

27+
SELECT -CAST(200 AS INT UNSIGNED);
28+
java.sql.SQLException: Error while executing SQL "SELECT -CAST(200 AS INT UNSIGNED)": From line 1, column 8 to line 1, column 33: Cannot apply '-' to arguments of type '-<INTEGER UNSIGNED>'. Supported form(s): '-<INTEGER>'
29+
30+
!error
31+
2732
SELECT CAST(200 AS INT UNSIGNED) - 100;
2833
EXPR$0
2934
100

testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16745,6 +16745,28 @@ private static void checkLogicalOrFunc(SqlOperatorFixture f) {
1674516745
f.checkNull("CAST(NULL AS INTEGER UNSIGNED) ^^ CAST(NULL AS INTEGER UNSIGNED)");
1674616746
}
1674716747

16748+
@Test void testUnsignedArithmetic() {
16749+
final SqlOperatorFixture f = fixture();
16750+
// Test case for [CALCITE-7360] The meaning of negation for unsigned numbers is not defined
16751+
f.checkFails("^-CAST (100 AS INT UNSIGNED)^",
16752+
"Cannot apply '-' to arguments of type '-<INTEGER UNSIGNED>'\\. "
16753+
+ "Supported form\\(s\\): '-<INTEGER>'\\n"
16754+
+ "'-<APPROXIMATE_NUMERIC>'\\n"
16755+
+ "-\\(DECIMAL\\)\\n"
16756+
+ "'-<DATETIME_INTERVAL>'", false);
16757+
f.checkScalar("CAST(2 AS INT UNSIGNED)", "2", "INTEGER UNSIGNED NOT NULL");
16758+
f.checkScalar("CAST(2 AS INT UNSIGNED) + CAST(2 AS INT UNSIGNED)", "4",
16759+
"INTEGER UNSIGNED NOT NULL");
16760+
f.checkScalar("CAST(2 AS INT UNSIGNED) + CAST(2 AS TINYINT UNSIGNED)", "4",
16761+
"INTEGER UNSIGNED NOT NULL");
16762+
f.checkScalar("CAST(2 AS INT UNSIGNED) + 2", "4", "INTEGER UNSIGNED NOT NULL");
16763+
f.checkScalar("CAST(2 AS INT UNSIGNED) - 2", "0", "INTEGER UNSIGNED NOT NULL");
16764+
f.checkScalar("CAST(2 AS INT UNSIGNED) - CAST(2 AS TINYINT UNSIGNED)", "0",
16765+
"INTEGER UNSIGNED NOT NULL");
16766+
f.checkScalar("CAST(2 AS INT UNSIGNED) * 2", "4", "INTEGER UNSIGNED NOT NULL");
16767+
f.checkScalar("CAST(2 AS INT UNSIGNED) / 2", "1", "INTEGER UNSIGNED NOT NULL");
16768+
}
16769+
1674816770
/**
1674916771
* Test cases for
1675016772
* <a href="https://issues.apache.org/jira/browse/CALCITE-7109">[CALCITE-7109]

0 commit comments

Comments
 (0)