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));