Niels Pardon created CALCITE-7648:
-------------------------------------

             Summary: Support unsigned shift amounts in the bitwise shift 
operators and functions
                 Key: CALCITE-7648
                 URL: https://issues.apache.org/jira/browse/CALCITE-7648
             Project: Calcite
          Issue Type: Improvement
            Reporter: Niels Pardon


The bitwise shift operators {{<<}} and {{>>}} and their function forms 
{{LEFTSHIFT}} and {{RIGHTSHIFT}} (added under CALCITE-7639, [PR 
5073|https://github.com/apache/calcite/pull/5073]) currently require the 
*second* operand -- the shift amount -- to be a *signed* integer type. An 
unsigned amount is rejected during validation:

{code:sql}
-- Cannot apply '>>' to arguments of type '<INTEGER> >> <INTEGER UNSIGNED>'
SELECT 8 >> CAST(2 AS INTEGER UNSIGNED);
SELECT RIGHTSHIFT(8, CAST(2 AS INTEGER UNSIGNED));
{code}

This is because {{SqlStdOperatorTable.SHIFT_OPERAND_TYPE_CHECKER}} only accepts 
{{SqlTypeFamily.INTEGER}} for the second operand, and the runtime 
{{SqlFunctions.leftShift}} / {{rightShift}} overloads take a signed {{long}}. 
The value being shifted (first operand) already accepts unsigned numeric types; 
only the shift amount does not, which is inconsistent.

h3. Suggested approach
(per review discussion on the CALCITE-7639 PR)
* Widen {{SHIFT_OPERAND_TYPE_CHECKER}} to also accept {{UNSIGNED_NUMERIC}} for 
the second operand.
* In {{RexImpTable}}, cast the unsigned amount to {{long}} in the generated 
enumerable code before calling the existing {{long}}-amount shift methods, so 
no new runtime overloads are needed.
* {{BIGINT UNSIGNED}} ({{ULong}}) needs special handling: a value with the high 
bit set exceeds {{Long.MAX_VALUE}}, so a naive cast to {{long}} yields a 
negative value that the shift code reads as "shift in the opposite direction". 
Decide and document how an out-of-{{long}}-range unsigned amount maps before 
the modulo normalization.

h3. Test coverage to add
Executing operator tests for {{a >> CAST(x AS UNSIGNED)}} / {{RIGHTSHIFT(a, 
CAST(x AS UNSIGNED))}} across {{TINYINT}} / {{SMALLINT}} / {{INTEGER}} / 
{{BIGINT UNSIGNED}} shift amounts, including a {{BIGINT UNSIGNED}} amount with 
the high bit set.

Follow-up to CALCITE-7639.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to