mihaibudiu commented on code in PR #5073:
URL: https://github.com/apache/calcite/pull/5073#discussion_r3546170936


##########
core/src/main/java/org/apache/calcite/sql/parser/SqlParserPos.java:
##########
@@ -264,6 +264,34 @@ public boolean startsAt(SqlParserPos pos) {
         && columnNumber == pos.columnNumber;
   }
 
+  /**
+   * Returns whether this position is immediately adjacent to another position;
+   * that is, one position ends exactly where the other begins, with no
+   * characters (such as whitespace) in between.
+   *
+   * <p>For example, the two {@code >} characters in {@code >>} are adjacent,

Review Comment:
   I would probably remove this part of the comment.



##########
core/src/main/codegen/templates/Parser.jj:
##########
@@ -8479,8 +8497,7 @@ SqlBinaryOperator BinaryRowOperator() :
     // so "a > > b" is not treated as a right shift; otherwise we fall through 
to
     // the single ">" (greater-than) alternative below.
 |   LOOKAHEAD({ getToken(1).kind == GT && getToken(2).kind == GT
-        && getToken(1).endLine == getToken(2).beginLine
-        && getToken(1).endColumn + 1 == getToken(2).beginColumn })
+        && pos(getToken(1)).adjacent(pos(getToken(2))) })

Review Comment:
   here you can use endsImmediatelyBefore, it's a bit more precise.
   This would make "adjacent" dead code. I am not sure that function is as 
useful.



##########
core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java:
##########
@@ -3914,6 +3914,148 @@ public static ULong leftShift(ULong x, int y) {
     return ULong.valueOf(val);
   }
 
+  /**
+   * Performs PostgresSQL-style bitwise shift on a 32-bit integer.
+   *
+   * @param x the integer value to shift
+   * @param y the shift amount (positive: right shift, negative: left shift)
+   * @return the shifted integer
+   */
+  public static int rightShift(int x, int y) {
+    int shift = ((y % 32) + 32) % 32; // normalize to 0~31

Review Comment:
   I would pull this into a helper positive_modulo function.



##########
core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java:
##########
@@ -3914,6 +3914,148 @@ public static ULong leftShift(ULong x, int y) {
     return ULong.valueOf(val);
   }
 
+  /**
+   * Performs PostgresSQL-style bitwise shift on a 32-bit integer.
+   *
+   * @param x the integer value to shift
+   * @param y the shift amount (positive: right shift, negative: left shift)
+   * @return the shifted integer
+   */
+  public static int rightShift(int x, int y) {
+    int shift = ((y % 32) + 32) % 32; // normalize to 0~31
+    return y >= 0 ? x >> shift : x << shift; // arithmetic right shift
+  }
+
+
+  // ----------------- long -----------------
+  /**
+   * Performs PostgresSQL-style bitwise shift on a 64-bit long value.
+   *
+   * @param x the long value to shift
+   * @param y the shift amount
+   * @return the shifted long value
+   */
+  public static long rightShift(long x, int y) {
+    int shift = ((y % 64) + 64) % 64; // normalize to 0~63
+    return y >= 0 ? x >> shift : x << shift;
+  }
+
+  /**
+   * Performs PostgresSQL-style bitwise shift on an int value with a long 
shift amount.
+   *
+   * @param x the int value to shift
+   * @param y the long shift amount
+   * @return the shifted value as long
+   */
+  public static long rightShift(int x, long y) {
+    int shift = (int) (((y % 32) + 32) % 32); // normalize to 0~31
+    return y >= 0 ? (long) x >> shift : (long) x << shift;
+  }
+
+  /**
+   * Performs PostgresSQL-style bitwise shift on a byte array.
+   * Positive shift: right shift.
+   * Negative shift: treated as positive shift with modulo arithmetic.
+   *
+   * @param bytes the input byte array
+   * @param y the shift amount in bits
+   * @return the shifted byte array
+   */
+  public static byte[] rightShift(byte[] bytes, int y) {
+    if (bytes.length == 0) {
+      return new byte[0];
+    }
+
+    int bitLen = bytes.length * 8;
+
+    // PostgreSQL behavior: always treat as right shift with modulo arithmetic
+    // Negative y becomes equivalent positive shift
+    int shift = ((y % bitLen) + bitLen) % bitLen;
+
+    if (shift == 0) {
+      return bytes.clone();
+    }
+
+    byte[] result = new byte[bytes.length];
+
+    // Always perform right shift (even for originally negative y)
+    int byteShift = shift / 8;
+    int bitShift = shift % 8;
+
+    for (int i = 0; i < bytes.length; i++) {
+      int srcIndex = i + byteShift;
+      int val = 0;
+
+      // Get the main byte
+      if (srcIndex < bytes.length) {
+        val = (bytes[srcIndex] & 0xFF) >>> bitShift;
+      }
+
+      // Get carry bits from next byte
+      if (srcIndex + 1 < bytes.length && bitShift != 0) {
+        val |= (bytes[srcIndex + 1] & 0xFF) << (8 - bitShift);
+      }
+
+      result[i] = (byte) val;
+    }
+    return result;
+  }
+
+  /**
+   * Performs PostgresSQL-style bitwise shift on ByteString.
+   *
+   * @param bytes the ByteString to shift
+   * @param y the shift amount in bits
+   * @return shifted ByteString
+   */
+  public static ByteString rightShift(ByteString bytes, int y) {
+    return new ByteString(rightShift(bytes.getBytes(), y));
+  }
+
+  /**
+   * Performs PostgresSQL-style bitwise shift on UByte.
+   * Overflow bits are masked to 8 bits.
+   */
+  public static UByte rightShift(UByte x, int y) {
+    int shift = ((y % 8) + 8) % 8;
+    int val = x.byteValue() & 0xFF;
+    val = (y >= 0) ? (val >> shift) & 0xFF : (val << shift) & 0xFF;
+    return UByte.valueOf((byte) val);
+  }
+
+  /**
+   * Performs PostgresSQL-style bitwise shift on UShort.
+   * Overflow bits are masked to 16 bits.
+   */
+  public static UShort rightShift(UShort x, int y) {
+    int shift = ((y % 16) + 16) % 16;
+    int val = x.shortValue() & 0xFFFF;
+    val = (y >= 0) ? (val >> shift) & 0xFFFF : (val << shift) & 0xFFFF;
+    return UShort.valueOf((short) val);
+  }
+
+  /**
+   * Performs PostgresSQL-style bitwise shift on UInteger.
+   * Overflow bits are masked to 32 bits.
+   */
+  public static UInteger rightShift(UInteger x, int y) {
+    int shift = ((y % 32) + 32) % 32;
+    long val = x.longValue() & 0xFFFFFFFFL;
+    val = (y >= 0) ? (val >> shift) & 0xFFFFFFFFL : (val << shift) & 
0xFFFFFFFFL;
+    return UInteger.valueOf(val);
+  }
+
+  /**
+   * Performs PostgresSQL-style bitwise shift on ULong.
+   * Overflow bits are masked to 64 bits (long shifts naturally truncate).
+   */
+  public static ULong rightShift(ULong x, int y) {

Review Comment:
   why don't you need versions with long y for these?



##########
core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java:
##########
@@ -3914,6 +3914,148 @@ public static ULong leftShift(ULong x, int y) {
     return ULong.valueOf(val);
   }
 
+  /**
+   * Performs PostgresSQL-style bitwise shift on a 32-bit integer.
+   *
+   * @param x the integer value to shift
+   * @param y the shift amount (positive: right shift, negative: left shift)
+   * @return the shifted integer
+   */
+  public static int rightShift(int x, int y) {
+    int shift = ((y % 32) + 32) % 32; // normalize to 0~31
+    return y >= 0 ? x >> shift : x << shift; // arithmetic right shift
+  }
+
+
+  // ----------------- long -----------------
+  /**
+   * Performs PostgresSQL-style bitwise shift on a 64-bit long value.
+   *
+   * @param x the long value to shift
+   * @param y the shift amount
+   * @return the shifted long value
+   */
+  public static long rightShift(long x, int y) {
+    int shift = ((y % 64) + 64) % 64; // normalize to 0~63
+    return y >= 0 ? x >> shift : x << shift;
+  }
+
+  /**
+   * Performs PostgresSQL-style bitwise shift on an int value with a long 
shift amount.
+   *
+   * @param x the int value to shift
+   * @param y the long shift amount
+   * @return the shifted value as long
+   */
+  public static long rightShift(int x, long y) {

Review Comment:
   you could only implement the long shift amount by casting any other type to 
long in the generated enumerable code.
   
   Is there a test with `a >> CAST(x AS UNSIGNED)`? If not, there should be.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to