You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The byte[] shift added for LEFTSHIFT treats binary as little-endian and
modulo-wraps the amount, which is inconsistent with the big-endian
CAST(INT AS BINARY) from CALCITE-7368. Rather than cement that behaviour
in a new operator, restrict >> and RIGHTSHIFT to integer/unsigned operands
and reject BINARY/VARBINARY at validation. Binary shift semantics are
tracked separately in CALCITE-7651; binary left shift is left as released.
- Split the shared shift operand type checker: keep BINARY for <</LEFTSHIFT,
add a non-binary checker for >>/RIGHTSHIFT.
- Remove the unused rightShift(byte[])/rightShift(ByteString) overloads.
- Replace the binary/VARBINARY right-shift tests with checkFails that pin
the rejection; keep the integer/unsigned coverage.
- Update the RIGHTSHIFT reference docs accordingly.
Copy file name to clipboardExpand all lines: site/_docs/reference.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2974,7 +2974,7 @@ In the following:
2974
2974
| * | BITOR(value1, value2) | Returns the bitwise OR of *value1* and *value2*. *value1* and *value2* must both be integer or binary values. Binary values must be of the same length.
2975
2975
| * | BITXOR(value1, value2) | Returns the bitwise XOR of *value1* and *value2*. *value1* and *value2* must both be integer or binary values. Binary values must be of the same length.
2976
2976
| * | LEFTSHIFT(value1, value2) | Returns the result of left-shifting *value1* by *value2* bits. *value1* can be integer, unsigned integer, or binary. For binary, the result has the same length as *value1*. The shift amount *value2* is normalized using modulo arithmetic based on the bit width of *value1* (for example, modulo 32 for `INTEGER` and modulo 64 for `BIGINT`); for binary types it is modulo (8 × N), where N is the actual length in bytes of the *value1* value — for a variable-length `VARBINARY` value this is the length of the value itself, not its declared maximum. For integer and unsigned types the sign of *value2* selects the direction: a non-negative amount shifts left and a negative amount shifts right by the normalized magnitude (for example, `LEFTSHIFT(1, -2)` returns `0`, a right shift by 30, and `LEFTSHIFT(8, -1)` returns `0`). For binary the shift is always to the left; a negative *value2* is simply folded into the range [0, 8 × N) by the same modulo.
2977
-
| * | RIGHTSHIFT(value1, value2) | Returns the result of right-shifting *value1* by *value2* bits. For signed integers the shift is arithmetic (the sign bit is preserved). *value1* can be integer, unsigned integer, or binary. For binary, the result has the same length as *value1*. The shift amount *value2* is normalized using modulo arithmetic based on the bit width of *value1* (for example, modulo 32 for `INTEGER` and modulo 64 for `BIGINT`); for binary types it is modulo (8 × N), where N is the actual length in bytes of the *value1* value — for a variable-length `VARBINARY` value this is the length of the value itself, not its declared maximum. For integer and unsigned types the sign of *value2* selects the direction: a non-negative amount shifts right and a negative amount shifts left by the normalized magnitude (for example, `RIGHTSHIFT(1024, 2)` returns `256`, `RIGHTSHIFT(-20, 2)` returns `-5`, and `RIGHTSHIFT(1, -2)` returns `1073741824`, a left shift by 30). For binary the shift is always to the right; a negative *value2* is simply folded into the range [0, 8 × N) by the same modulo.
2977
+
| * | RIGHTSHIFT(value1, value2) | Returns the result of right-shifting *value1* by *value2* bits. For signed integers the shift is arithmetic (the sign bit is preserved). *value1* can be integer or unsigned integer (binary right shift is not yet supported). The shift amount *value2* is normalized using modulo arithmetic based on the bit width of *value1* (for example, modulo 32 for `INTEGER` and modulo 64 for `BIGINT`). The sign of *value2* selects the direction: a non-negative amount shifts right and a negative amount shifts left by the normalized magnitude (for example, `RIGHTSHIFT(1024, 2)` returns `256`, `RIGHTSHIFT(-20, 2)` returns `-5`, and `RIGHTSHIFT(1, -2)` returns `1073741824`, a left shift by 30).
2978
2978
| * | BITNOT(value) | Returns the bitwise NOT of *value*. *value* must be either an integer type or a binary value.
2979
2979
| f | BITAND_AGG(value) | Equivalent to `BIT_AND(value)`
2980
2980
| f | BITOR_AGG(value) | Equivalent to `BIT_OR(value)`
f.checkScalar("RIGHTSHIFT(0, 32)", "0", "INTEGER NOT NULL");
17348
17327
f.checkScalar("RIGHTSHIFT(0, 100)", "0", "INTEGER NOT NULL");
17349
17328
17350
-
// === Binary types ===
17351
-
// A binary literal such as X'FF' already has type BINARY(1) (X'FFFF' is
17352
-
// BINARY(2), and so on), so no cast is needed to exercise the BINARY path.
17353
-
f.checkScalar("RIGHTSHIFT(X'FF', 1)", "7f", "BINARY(1) NOT NULL");
17354
-
f.checkScalar("RIGHTSHIFT(X'F0', 4)", "0f", "BINARY(1) NOT NULL");
17355
-
f.checkScalar("RIGHTSHIFT(X'08', 3)", "01", "BINARY(1) NOT NULL");
17356
-
f.checkScalar("RIGHTSHIFT(X'00', 5)", "00", "BINARY(1) NOT NULL");
17357
-
17358
-
f.checkScalar("RIGHTSHIFT(X'FFFF', 1)", "ff7f", "BINARY(2) NOT NULL");
17359
-
f.checkScalar("RIGHTSHIFT(X'1234', 4)", "4103", "BINARY(2) NOT NULL");
17360
-
f.checkScalar("RIGHTSHIFT(X'1234', 8)", "3400", "BINARY(2) NOT NULL");
17361
-
f.checkScalar("RIGHTSHIFT(X'FF', 8)", "ff", "BINARY(1) NOT NULL");
17362
-
f.checkScalar("RIGHTSHIFT(X'FFFF', 16)", "ffff", "BINARY(2) NOT NULL");
17363
-
17364
-
f.checkScalar("RIGHTSHIFT(X'ABCD', 0)", "abcd", "BINARY(2) NOT NULL");
17365
-
f.checkScalar("RIGHTSHIFT(X'123456', 4)", "416305", "BINARY(3) NOT NULL");
17366
-
f.checkScalar("RIGHTSHIFT(X'0001', 1)", "8000", "BINARY(2) NOT NULL");
17367
-
f.checkScalar("RIGHTSHIFT(X'8000', 1)", "4000", "BINARY(2) NOT NULL");
17368
-
f.checkScalar("RIGHTSHIFT(X'F0', -4)", "0f", "BINARY(1) NOT NULL");
17369
-
17370
-
// === VARBINARY types ===
17371
-
// For variable-length binary the shift width is 8 * the actual value
17372
-
// length, so the modulo used to normalize the amount tracks the value.
17373
-
f.checkScalar("RIGHTSHIFT(CAST(X'FF' AS VARBINARY), 1)", "7f",
17374
-
"VARBINARY NOT NULL");
17375
-
f.checkScalar("RIGHTSHIFT(CAST(X'F0' AS VARBINARY), 4)", "0f",
17376
-
"VARBINARY NOT NULL");
17377
-
f.checkScalar("RIGHTSHIFT(CAST(X'FFFF' AS VARBINARY), 1)", "ff7f",
17378
-
"VARBINARY NOT NULL");
17379
-
f.checkScalar("RIGHTSHIFT(CAST(X'123456' AS VARBINARY), 4)", "416305",
17380
-
"VARBINARY NOT NULL");
17381
-
// 8 % (8 * 1) = 0 leaves the 1-byte value unchanged, while 8 % (8 * 2) = 8
17382
-
// shifts the 2-byte value by a whole byte: the width follows the value.
17383
-
f.checkScalar("RIGHTSHIFT(CAST(X'FF' AS VARBINARY), 8)", "ff",
17384
-
"VARBINARY NOT NULL");
17385
-
f.checkScalar("RIGHTSHIFT(CAST(X'FFFF' AS VARBINARY), 8)", "ff00",
17386
-
"VARBINARY NOT NULL");
17387
-
f.checkScalar("RIGHTSHIFT(CAST(X'F0' AS VARBINARY), -4)", "0f",
17388
-
"VARBINARY NOT NULL");
17329
+
// === Binary operands are not supported ===
17330
+
// Unlike LEFTSHIFT, binary right shift is intentionally rejected until the
17331
+
// endianness of bitwise shifts on binary is settled (see [CALCITE-7651]).
17332
+
// A binary literal such as X'FF' already has type BINARY(1).
17333
+
f.checkFails("^RIGHTSHIFT(X'FF', 1)^",
17334
+
"Cannot apply 'RIGHTSHIFT' to arguments of type 'RIGHTSHIFT\\(<BINARY\\(1\\)>, <INTEGER>\\)'\\. Supported form\\(s\\): 'RIGHTSHIFT\\(<INTEGER>, <INTEGER>\\)'\\n'RIGHTSHIFT\\(<UNSIGNED_NUMERIC>, <INTEGER>\\)'",
17335
+
false);
17336
+
f.checkFails("^RIGHTSHIFT(CAST(X'FF' AS VARBINARY), 1)^",
17337
+
"Cannot apply 'RIGHTSHIFT' to arguments of type 'RIGHTSHIFT\\(<VARBINARY>, <INTEGER>\\)'\\. Supported form\\(s\\): 'RIGHTSHIFT\\(<INTEGER>, <INTEGER>\\)'\\n'RIGHTSHIFT\\(<UNSIGNED_NUMERIC>, <INTEGER>\\)'",
17338
+
false);
17339
+
17389
17340
// === Invalid types ===
17390
17341
f.checkFails("^RIGHTSHIFT(1.2, 2)^",
17391
-
"Cannot apply 'RIGHTSHIFT' to arguments of type 'RIGHTSHIFT\\(<DECIMAL\\(2, 1\\)>, <INTEGER>\\)'\\. Supported form\\(s\\): 'RIGHTSHIFT\\(<INTEGER>, <INTEGER>\\)'\\n'RIGHTSHIFT\\(<BINARY>, <INTEGER>\\)'\\n'RIGHTSHIFT\\(<UNSIGNED_NUMERIC>, <INTEGER>\\)'",
17342
+
"Cannot apply 'RIGHTSHIFT' to arguments of type 'RIGHTSHIFT\\(<DECIMAL\\(2, 1\\)>, <INTEGER>\\)'\\. Supported form\\(s\\): 'RIGHTSHIFT\\(<INTEGER>, <INTEGER>\\)'\\n'RIGHTSHIFT\\(<UNSIGNED_NUMERIC>, <INTEGER>\\)'",
17392
17343
false);
17393
17344
// A BIGINT shift amount is accepted, but an unsigned shift amount is not:
17394
17345
// the second argument must be a signed integer type.
17395
17346
f.checkScalar("RIGHTSHIFT(8, CAST(2 AS BIGINT))", "2", "INTEGER NOT NULL");
17396
17347
f.checkFails("^RIGHTSHIFT(8, CAST(2 AS INTEGER UNSIGNED))^",
17397
-
"Cannot apply 'RIGHTSHIFT' to arguments of type 'RIGHTSHIFT\\(<INTEGER>, <INTEGER UNSIGNED>\\)'\\. Supported form\\(s\\): 'RIGHTSHIFT\\(<INTEGER>, <INTEGER>\\)'\\n'RIGHTSHIFT\\(<BINARY>, <INTEGER>\\)'\\n'RIGHTSHIFT\\(<UNSIGNED_NUMERIC>, <INTEGER>\\)'",
17348
+
"Cannot apply 'RIGHTSHIFT' to arguments of type 'RIGHTSHIFT\\(<INTEGER>, <INTEGER UNSIGNED>\\)'\\. Supported form\\(s\\): 'RIGHTSHIFT\\(<INTEGER>, <INTEGER>\\)'\\n'RIGHTSHIFT\\(<UNSIGNED_NUMERIC>, <INTEGER>\\)'",
0 commit comments