This is an automated email from the ASF dual-hosted git repository.

xuzifu666 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new 05e410ff3e [CALCITE-7428] Support regexp function change regexp 
operator for Hive library
05e410ff3e is described below

commit 05e410ff3ebeb91d6d4f946a7a45087bf3571f95
Author: Terran <[email protected]>
AuthorDate: Wed Mar 4 11:07:57 2026 +0800

    [CALCITE-7428] Support regexp function change regexp operator for Hive 
library
---
 .../apache/calcite/sql/dialect/HiveSqlDialect.java |  3 ++
 .../calcite/sql/fun/SqlLibraryOperators.java       |  7 ++--
 .../apache/calcite/util/RelToSqlConverterUtil.java | 15 ++++++++
 .../calcite/rel/rel2sql/RelToSqlConverterTest.java | 41 ++++++++++++++++++++++
 site/_docs/reference.md                            |  2 +-
 .../org/apache/calcite/test/SqlOperatorTest.java   |  1 +
 6 files changed, 64 insertions(+), 5 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java 
b/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java
index db57e5affe..689ecc1ecf 100644
--- a/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java
@@ -129,6 +129,9 @@ public HiveSqlDialect(Context context) {
     case TRIM:
       RelToSqlConverterUtil.unparseHiveTrim(writer, call, leftPrec, rightPrec);
       break;
+    case RLIKE:
+      RelToSqlConverterUtil.unparseRegexp(writer, call, leftPrec, rightPrec);
+      break;
     default:
       super.unparseCall(writer, call, leftPrec, rightPrec);
     }
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
index 947223b682..2479a92ba2 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
@@ -705,11 +705,10 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding 
operatorBinding,
   public static final SqlFunction REGEXP_SUBSTR = 
REGEXP_EXTRACT.withName("REGEXP_SUBSTR");
 
   /** The "REGEXP(value, regexp)" function, equivalent to {@link #RLIKE}. */
-  @LibraryOperator(libraries = {SPARK})
+  @LibraryOperator(libraries = {SPARK, HIVE})
   public static final SqlFunction REGEXP =
-      SqlBasicFunction.create("REGEXP", ReturnTypes.BOOLEAN_NULLABLE,
-          OperandTypes.STRING_STRING,
-          SqlFunctionCategory.STRING);
+      SqlBasicFunction.create("REGEXP", SqlKind.RLIKE, 
ReturnTypes.BOOLEAN_NULLABLE,
+          OperandTypes.STRING_STRING);
 
   /** The "REGEXP_LIKE(value, regexp)" function, equivalent to {@link #RLIKE}. 
*/
   @LibraryOperator(libraries = {SPARK, MYSQL, POSTGRESQL, ORACLE})
diff --git 
a/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java 
b/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java
index 1f15adc7d6..db417179af 100644
--- a/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java
+++ b/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java
@@ -463,4 +463,19 @@ public ClickHouseSqlArrayTypeNameSpec(SqlTypeNameSpec 
elementTypeName,
       writer.endList(frame);
     }
   }
+
+  /**
+   * Unparses REGEXP function calls by converting from function call format
+   * (e.g., REGEXP(column, pattern)) to infix operator format (e.g., column 
REGEXP pattern).
+   */
+  public static void unparseRegexp(SqlWriter writer, SqlCall call, int 
leftPrec, int rightPrec) {
+    if ("REGEXP".equals(call.getOperator().getName())) {
+      final SqlWriter.Frame frame = 
writer.startList(SqlWriter.FrameTypeEnum.SIMPLE, "(", ")");
+      call.operand(0).unparse(writer, leftPrec, rightPrec);
+      writer.sep("REGEXP", true);
+      call.operand(1).unparse(writer, leftPrec, rightPrec);
+      writer.endList(frame);
+    }
+  }
+
 }
diff --git 
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java 
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
index 2deca5f9d8..f2a5b4b383 100644
--- 
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
+++ 
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
@@ -11948,4 +11948,45 @@ public Sql schema(CalciteAssert.SchemaSpec schemaSpec) 
{
             + "FROM (VALUES (1.0E-310)) AS \"t\" (\"EXPR$0\")");
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7428";>[CALCITE-7428]
+   * Support regexp function change regexp operator for Hive library</a>. */
+  @Test void testRegexpWithHive() {
+    final String query = "select \"brand_name\"\n"
+        + "from \"product\" where REGEXP(\"brand_name\",'[a-zA-Z]') ";
+    final String expectedHive = "SELECT `brand_name`\nFROM "
+        + "`foodmart`.`product`\nWHERE (`brand_name` REGEXP '[a-zA-Z]')";
+    final String expectedSpark = "SELECT `brand_name`\nFROM 
`foodmart`.`product`\n"
+        + "WHERE REGEXP(`brand_name`, '[a-zA-Z]')";
+    sql(query).withLibrary(SqlLibrary.HIVE).withHive().ok(expectedHive);
+    sql(query).withLibrary(SqlLibrary.SPARK).withSpark().ok(expectedSpark);
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7428";>[CALCITE-7428]
+   * Support regexp function change regexp operator for Hive library</a>. */
+  @Test void testRegexpWithHiveIsNotNull() {
+    final String query = "select \"brand_name\"\n"
+        + "from \"product\" where REGEXP(\"brand_name\",'[a-zA-Z]') is not 
null ";
+    final String expectedHive = "SELECT `brand_name`\nFROM "
+        + "`foodmart`.`product`\nWHERE (`brand_name` REGEXP '[a-zA-Z]') IS NOT 
NULL";
+    final String expectedSpark = "SELECT `brand_name`\nFROM 
`foodmart`.`product`\n"
+        + "WHERE REGEXP(`brand_name`, '[a-zA-Z]') IS NOT NULL";
+    sql(query).withLibrary(SqlLibrary.HIVE).withHive().ok(expectedHive);
+    sql(query).withLibrary(SqlLibrary.SPARK).withSpark().ok(expectedSpark);
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7428";>[CALCITE-7428]
+   * Support regexp function change regexp operator for Hive library</a>. */
+  @Test void testSelectRegexpWithHiveIsNotNull() {
+    final String query = "select REGEXP(\"brand_name\",'[a-zA-Z]') is not null 
\n"
+        + "from \"product\"";
+    final String expectedHive = "SELECT (`brand_name` REGEXP '[a-zA-Z]') IS 
NOT NULL\n"
+        + "FROM `foodmart`.`product`";
+    final String expectedSpark = "SELECT REGEXP(`brand_name`, '[a-zA-Z]') IS 
NOT NULL\n"
+        + "FROM `foodmart`.`product`";
+    sql(query).withLibrary(SqlLibrary.HIVE).withHive().ok(expectedHive);
+    sql(query).withLibrary(SqlLibrary.SPARK).withSpark().ok(expectedSpark);
+  }
 }
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index e1ea8e7206..ee3d2d739f 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -3004,7 +3004,7 @@ ### Dialect-specific Operators
 | b s | POW(numeric1, numeric2)                      | Returns *numeric1* 
raised to the power *numeric2*
 | b c h q m o f s p r | POWER(numeric1, numeric2) | Returns *numeric1* raised 
to the power of *numeric2*
 | p r | RANDOM()                                     | Generates a random 
double between 0 and 1 inclusive
-| s | REGEXP(string, regexp)                         | Equivalent to `string1 
RLIKE string2`
+| s h | REGEXP(string, regexp)                         | Equivalent to 
`string1 RLIKE string2`
 | b | REGEXP_CONTAINS(string, regexp)                | Returns whether 
*string* is a partial match for the *regexp*
 | b | REGEXP_EXTRACT(string, regexp [, position [, occurrence]]) | Returns the 
substring in *string* that matches the *regexp*, starting search at *position* 
(default 1), and until locating the nth *occurrence* (default 1). Returns NULL 
if there is no match
 | b | REGEXP_EXTRACT_ALL(string, regexp)             | Returns an array of all 
substrings in *string* that matches the *regexp*. Returns an empty array if 
there is no match
diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java 
b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
index 41b45d3c76..b6731f9e63 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -4232,6 +4232,7 @@ void checkIsNull(SqlOperatorFixture f, SqlOperator 
operator) {
     checkRlikeFunc(f, SqlLibrary.HIVE, SqlLibraryOperators.RLIKE);
     checkRlikeFunc(f, SqlLibrary.SPARK, SqlLibraryOperators.RLIKE);
     checkRlikeFunc(f, SqlLibrary.SPARK, SqlLibraryOperators.REGEXP);
+    checkRlikeFunc(f, SqlLibrary.HIVE, SqlLibraryOperators.REGEXP);
     checkRlikeFunc(f, SqlLibrary.MYSQL, SqlLibraryOperators.RLIKE);
     checkNotRlikeFunc(f.withLibrary(SqlLibrary.HIVE));
     checkNotRlikeFunc(f.withLibrary(SqlLibrary.SPARK));

Reply via email to