korlov42 commented on code in PR #6996:
URL: https://github.com/apache/ignite-3/pull/6996#discussion_r2541556649
##########
modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/IgniteSqlFunctions.java:
##########
@@ -761,4 +761,196 @@ private static long divide(long p, long q, RoundingMode
mode) {
return increment ? div + signum : div;
}
+
+ /**
+ * Computes the next lexicographically greater string by incrementing the
rightmost character that is not at its maximum value.
+ *
+ * <p>This method is primarily used in conjunction with {@link
#findPrefix(String, String)} to create upper bounds for efficient
+ * range scans. Given a prefix extracted from a LIKE pattern, this method
produces the smallest string that is lexicographically greater
+ * than the prefix, enabling queries like {@code WHERE key >= prefix AND
key < nextGreaterPrefix}.
+ *
+ * <p>If all characters are at maximum value ({@value
Character#MAX_VALUE}), the method returns {@code null} because no greater string
+ * exists within the Unicode character space.
+ *
+ * <p>Basic examples:
+ * <pre>
+ * nextGreaterPrefix("abc") → "abd"
+ * nextGreaterPrefix("test") → "tesu"
+ * nextGreaterPrefix("user") → "uses"
+ * nextGreaterPrefix("a") → "b"
+ * nextGreaterPrefix("z") → "{"
+ * nextGreaterPrefix("9") → ":"
+ * </pre>
+ *
+ * <p>Examples with maximum values:
+ * <pre>
+ * nextGreaterPrefix("abc\uFFFF") → "abd" (skip max char,
increment 'c')
+ * nextGreaterPrefix("a\uFFFF\uFFFF") → "b" (skip two max chars,
increment 'a')
+ * nextGreaterPrefix("test\uFFFF") → "tesu" (skip max char,
increment 't')
+ * nextGreaterPrefix("\uFFFF") → null (cannot increment)
+ * nextGreaterPrefix("\uFFFF\uFFFF") → null (all chars at max)
+ * </pre>
+ *
+ * <p>Edge cases:
+ * <pre>
+ * nextGreaterPrefix(null) → null (null input)
+ * nextGreaterPrefix("") → null (empty string, no
chars to increment)
+ * nextGreaterPrefix("abc\uFFFF\uFFFF") → "abd" (truncates all
trailing max values)
+ * </pre>
+ *
+ * <p>Properties:
+ * <ul>
+ * <li>The result is always the <em>smallest</em> string greater than
the input</li>
+ * <li>For any valid input {@code s}, {@code
nextGreaterPrefix(s).compareTo(s) > 0}</li>
+ * <li>The result may be shorter than the input (trailing max-value
chars are removed)</li>
+ * <li>Trailing {@code \uFFFF} characters are effectively truncated</li>
+ * </ul>
+ *
+ * @param prefix The string to increment. If {@code null}, returns {@code
null}.
+ * @return A next lexicographically greater string, or {@code null} if the
input is {@code null}, empty, or consists entirely of
+ * maximum-value characters ({@code \uFFFF}). The returned string
is guaranteed to be the smallest string greater than the
+ * input.
+ */
+ public static @Nullable String nextGreaterPrefix(@Nullable String prefix) {
+ if (prefix == null) {
+ return null;
+ }
+
+ // Try to increment characters from right to left
+ for (int i = prefix.length() - 1; i >= 0; i--) {
+ char c = prefix.charAt(i);
+
+ // Check if we can increment this character
+ if (c < Character.MAX_VALUE) {
+ // Increment and return
+ return prefix.substring(0, i) + ((char) (c + 1));
+ }
+
+ // This character is already max, continue to previous character
+ }
+
+ // All characters are at maximum value
+ return null; // Given prefix is the greatest.
+ }
+
+ /**
+ * Extracts the literal prefix from a SQL LIKE pattern by identifying all
characters before the first unescaped wildcard.
+ *
+ * <p>This method processes SQL LIKE patterns containing wildcards ({@code
%} for any sequence, {@code _} for single character) and
+ * returns the constant prefix that can be used for optimized range scans.
+ *
+ * <p>When an escape character is provided, it allows wildcards to be
treated as literal characters. The escape character itself can
+ * also be escaped to include it literally in the prefix.
+ *
+ * <p>Examples without escape character:
+ * <pre>
+ * findPrefix("user%", null) → "user"
+ * findPrefix("admin_123", null) → "admin"
+ * findPrefix("test", null) → "test"
+ * findPrefix("%anything", null) → ""
Review Comment:
this case is similar to this one: `* findPrefix("admin_123", null) →
"admin"`. Updated the javadoc
--
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]