This is an automated email from the ASF dual-hosted git repository.
zclll pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new a076fea62af [feature](function) support MySQL dialect of function
substr and position (#55914)
a076fea62af is described below
commit a076fea62afd6f453bb914b7780be891849c7041
Author: admiring_xm <[email protected]>
AuthorDate: Wed Sep 24 15:55:53 2025 +0800
[feature](function) support MySQL dialect of function substr and position
(#55914)
support MySQL dialect of function substr(substring) and position
```sql
SUBSTRING(<str> FROM <pos> [FOR <len>])
SUBSTR(<str> FROM <pos> [FOR <len>])
```
```sql
POSITION ( <substr> IN <str> )
POSITION ( <substr>, <str> [, <pos>] )
```
---
be/src/vec/functions/function_string.cpp | 1 +
.../antlr4/org/apache/doris/nereids/DorisLexer.g4 | 3 +
.../antlr4/org/apache/doris/nereids/DorisParser.g4 | 6 +
.../doris/catalog/BuiltinScalarFunctions.java | 2 +-
.../doris/nereids/parser/LogicalPlanBuilder.java | 19 ++
.../doris/nereids/parser/NereidsParserTest.java | 126 +++++++++++++
.../data/nereids_function_p0/scalar_function/P.out | 174 ++++++++++++++++++
.../data/nereids_function_p0/scalar_function/S.out | 116 ++++++++++++
.../fold_constant_string_arithmatic.out | 202 +++++++++++++++++++++
.../nereids_function_p0/scalar_function/P.groovy | 12 ++
.../nereids_function_p0/scalar_function/S.groovy | 8 +
.../fold_constant_string_arithmatic.groovy | 110 +++++++++++
12 files changed, 778 insertions(+), 1 deletion(-)
diff --git a/be/src/vec/functions/function_string.cpp
b/be/src/vec/functions/function_string.cpp
index b81b4aff385..f991a56e950 100644
--- a/be/src/vec/functions/function_string.cpp
+++ b/be/src/vec/functions/function_string.cpp
@@ -1485,6 +1485,7 @@ void register_function_string(SimpleFunctionFactory&
factory) {
factory.register_alias(FunctionStringUTF8Length::name, "character_length");
factory.register_alias(FunctionStringDigestOneArg<SM3Sum>::name, "sm3");
factory.register_alias(FunctionStringDigestSHA1::name, "sha");
+ factory.register_alias(FunctionStringLocatePos::name, "position");
}
} // namespace doris::vectorized
diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
index df0b3d0234c..d4b3b1b09ce 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
@@ -413,6 +413,7 @@ PROCESS: 'PROCESS';
PLUGIN: 'PLUGIN';
PLUGINS: 'PLUGINS';
POLICY: 'POLICY';
+POSITION: 'POSITION';
PRECEDING: 'PRECEDING';
PREPARE: 'PREPARE';
PRIMARY: 'PRIMARY';
@@ -509,6 +510,8 @@ STREAM: 'STREAM';
STREAMING: 'STREAMING';
STRING: 'STRING';
STRUCT: 'STRUCT';
+SUBSTR: 'SUBSTR';
+SUBSTRING: 'SUBSTRING';
SUM: 'SUM';
SUPERUSER: 'SUPERUSER';
SWITCH: 'SWITCH';
diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
index e24bda7f98b..1441aced294 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
@@ -1601,6 +1601,9 @@ primaryExpression
(OVER windowSpec)?
#groupConcat
| TRIM LEFT_PAREN
((BOTH | LEADING | TRAILING) expression? | expression) FROM expression
RIGHT_PAREN #trim
+ | (SUBSTR | SUBSTRING) LEFT_PAREN
+ expression FROM expression (FOR expression)? RIGHT_PAREN
#substring
+ | POSITION LEFT_PAREN expression IN expression RIGHT_PAREN
#position
| functionCallExpression
#functionCall
| value=primaryExpression LEFT_BRACKET index=valueExpression RIGHT_BRACKET
#elementAt
| value=primaryExpression LEFT_BRACKET begin=valueExpression
@@ -2097,6 +2100,7 @@ nonReserved
| PLUGIN
| PLUGINS
| POLICY
+ | POSITION
| PRIVILEGES
| PROC
| PROCESS
@@ -2167,6 +2171,8 @@ nonReserved
| STREAMING
| STRING
| STRUCT
+ | SUBSTR
+ | SUBSTRING
| SUM
| TABLES
| TAG
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
index 6508fd4dbf2..78c79114f0d 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java
@@ -802,7 +802,7 @@ public class BuiltinScalarFunctions implements
FunctionHelper {
scalar(Crc32Internal.class, "crc32_internal"),
scalar(Like.class, "like"),
scalar(Ln.class, "ln", "dlog1"),
- scalar(Locate.class, "locate"),
+ scalar(Locate.class, "position", "locate"),
scalar(Log.class, "log"),
scalar(Log10.class, "log10"),
scalar(Log2.class, "log2"),
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
index 007738f4fac..c790a0a50c0 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
@@ -273,6 +273,7 @@ import
org.apache.doris.nereids.DorisParser.PartitionValueListContext;
import org.apache.doris.nereids.DorisParser.PartitionsDefContext;
import org.apache.doris.nereids.DorisParser.PauseMTMVContext;
import org.apache.doris.nereids.DorisParser.PlanTypeContext;
+import org.apache.doris.nereids.DorisParser.PositionContext;
import org.apache.doris.nereids.DorisParser.PredicateContext;
import org.apache.doris.nereids.DorisParser.PredicatedContext;
import org.apache.doris.nereids.DorisParser.PrimitiveDataTypeContext;
@@ -434,6 +435,7 @@ import
org.apache.doris.nereids.DorisParser.StringLiteralContext;
import org.apache.doris.nereids.DorisParser.StructLiteralContext;
import org.apache.doris.nereids.DorisParser.SubqueryContext;
import org.apache.doris.nereids.DorisParser.SubqueryExpressionContext;
+import org.apache.doris.nereids.DorisParser.SubstringContext;
import org.apache.doris.nereids.DorisParser.SupportedUnsetStatementContext;
import org.apache.doris.nereids.DorisParser.SwitchCatalogContext;
import org.apache.doris.nereids.DorisParser.SyncContext;
@@ -3099,6 +3101,23 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
});
}
+ @Override
+ public Object visitSubstring(SubstringContext ctx) {
+ return ParserUtils.withOrigin(ctx, () -> {
+ List<Expression> params = visit(ctx.expression(),
Expression.class);
+ String name = ctx.SUBSTR() != null ? "substr" : "substring";
+ return processUnboundFunction(ctx, null, name, false, params,
null, null);
+ });
+ }
+
+ @Override
+ public Object visitPosition(PositionContext ctx) {
+ return ParserUtils.withOrigin(ctx, () -> {
+ List<Expression> params = visit(ctx.expression(),
Expression.class);
+ return processUnboundFunction(ctx, null, "position", false,
params, null, null);
+ });
+ }
+
@Override
public Expression
visitFunctionCallExpression(DorisParser.FunctionCallExpressionContext ctx) {
return ParserUtils.withOrigin(ctx, () -> {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
index b104f34a8bb..fdcda7f1b74 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
@@ -31,6 +31,7 @@ import org.apache.doris.nereids.trees.expressions.Cast;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.OrderExpression;
import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral;
+import org.apache.doris.nereids.trees.expressions.literal.IntegerLikeLiteral;
import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral;
import org.apache.doris.nereids.trees.plans.DistributeType;
import org.apache.doris.nereids.trees.plans.JoinType;
@@ -996,6 +997,131 @@ public class NereidsParserTest extends ParserTestBase {
Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("trim(both '1')"));
}
+ @Test
+ public void testSubstring() {
+ NereidsParser parser = new NereidsParser();
+ String sql;
+ Expression e;
+ UnboundFunction unboundFunction;
+
+ sql = "substring('Sakila' FROM -4 FOR 2)";
+ e = parser.parseExpression(sql);
+ Assertions.assertInstanceOf(UnboundFunction.class, e);
+ unboundFunction = (UnboundFunction) e;
+ Assertions.assertEquals("substring", unboundFunction.getName());
+ Assertions.assertEquals(3, unboundFunction.arity());
+ Assertions.assertEquals("Sakila", ((StringLikeLiteral)
unboundFunction.child(0)).getStringValue());
+ Assertions.assertEquals(-4, ((IntegerLikeLiteral)
unboundFunction.child(1)).getIntValue());
+ Assertions.assertEquals(2, ((IntegerLikeLiteral)
unboundFunction.child(2)).getIntValue());
+
+ sql = "substring('Sakila', -5, 3)";
+ e = parser.parseExpression(sql);
+ Assertions.assertInstanceOf(UnboundFunction.class, e);
+ unboundFunction = (UnboundFunction) e;
+ Assertions.assertEquals("substring", unboundFunction.getName());
+ Assertions.assertEquals(3, unboundFunction.arity());
+ Assertions.assertEquals("Sakila", ((StringLikeLiteral)
unboundFunction.child(0)).getStringValue());
+ Assertions.assertEquals(-5, ((IntegerLikeLiteral)
unboundFunction.child(1)).getIntValue());
+ Assertions.assertEquals(3, ((IntegerLikeLiteral)
unboundFunction.child(2)).getIntValue());
+
+ sql = "substring('foobarbar' FROM 4)";
+ e = parser.parseExpression(sql);
+ Assertions.assertInstanceOf(UnboundFunction.class, e);
+ unboundFunction = (UnboundFunction) e;
+ Assertions.assertEquals("substring", unboundFunction.getName());
+ Assertions.assertEquals(2, unboundFunction.arity());
+ Assertions.assertEquals("foobarbar", ((StringLikeLiteral)
unboundFunction.child(0)).getStringValue());
+ Assertions.assertEquals(4, ((IntegerLikeLiteral)
unboundFunction.child(1)).getIntValue());
+
+ sql = "substring('Quadratically', 5)";
+ e = parser.parseExpression(sql);
+ Assertions.assertInstanceOf(UnboundFunction.class, e);
+ unboundFunction = (UnboundFunction) e;
+ Assertions.assertEquals("substring", unboundFunction.getName());
+ Assertions.assertEquals(2, unboundFunction.arity());
+ Assertions.assertEquals("Quadratically", ((StringLikeLiteral)
unboundFunction.child(0)).getStringValue());
+ Assertions.assertEquals(5, ((IntegerLikeLiteral)
unboundFunction.child(1)).getIntValue());
+
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("substring('Sakila' for 2)"));
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("substring('Sakila' from for)"));
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("substring('Sakila' from)"));
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("substring(from 1)"));
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("substring(for 1)"));
+ }
+
+ @Test
+ public void testSubstr() {
+ NereidsParser parser = new NereidsParser();
+ String sql;
+ Expression e;
+ UnboundFunction unboundFunction;
+
+ sql = "substr('Sakila' FROM -4 FOR 2)";
+ e = parser.parseExpression(sql);
+ Assertions.assertInstanceOf(UnboundFunction.class, e);
+ unboundFunction = (UnboundFunction) e;
+ Assertions.assertEquals("substr", unboundFunction.getName());
+ Assertions.assertEquals(3, unboundFunction.arity());
+ Assertions.assertEquals("Sakila", ((StringLikeLiteral)
unboundFunction.child(0)).getStringValue());
+ Assertions.assertEquals(-4, ((IntegerLikeLiteral)
unboundFunction.child(1)).getIntValue());
+ Assertions.assertEquals(2, ((IntegerLikeLiteral)
unboundFunction.child(2)).getIntValue());
+
+ sql = "substr('Sakila', -5, 3)";
+ e = parser.parseExpression(sql);
+ Assertions.assertInstanceOf(UnboundFunction.class, e);
+ unboundFunction = (UnboundFunction) e;
+ Assertions.assertEquals("substr", unboundFunction.getName());
+ Assertions.assertEquals(3, unboundFunction.arity());
+ Assertions.assertEquals("Sakila", ((StringLikeLiteral)
unboundFunction.child(0)).getStringValue());
+ Assertions.assertEquals(-5, ((IntegerLikeLiteral)
unboundFunction.child(1)).getIntValue());
+ Assertions.assertEquals(3, ((IntegerLikeLiteral)
unboundFunction.child(2)).getIntValue());
+
+ sql = "substr('foobarbar' FROM 4)";
+ e = parser.parseExpression(sql);
+ Assertions.assertInstanceOf(UnboundFunction.class, e);
+ unboundFunction = (UnboundFunction) e;
+ Assertions.assertEquals("substr", unboundFunction.getName());
+ Assertions.assertEquals(2, unboundFunction.arity());
+ Assertions.assertEquals("foobarbar", ((StringLikeLiteral)
unboundFunction.child(0)).getStringValue());
+ Assertions.assertEquals(4, ((IntegerLikeLiteral)
unboundFunction.child(1)).getIntValue());
+
+ sql = "substr('Quadratically', 5)";
+ e = parser.parseExpression(sql);
+ Assertions.assertInstanceOf(UnboundFunction.class, e);
+ unboundFunction = (UnboundFunction) e;
+ Assertions.assertEquals("substr", unboundFunction.getName());
+ Assertions.assertEquals(2, unboundFunction.arity());
+ Assertions.assertEquals("Quadratically", ((StringLikeLiteral)
unboundFunction.child(0)).getStringValue());
+ Assertions.assertEquals(5, ((IntegerLikeLiteral)
unboundFunction.child(1)).getIntValue());
+
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("substr('Sakila' for 2)"));
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("substr('Sakila' from for)"));
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("substr('Sakila' from)"));
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("substr(from 1)"));
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("substr(for 1)"));
+ }
+
+ @Test
+ public void testPositon() {
+ NereidsParser parser = new NereidsParser();
+ String sql;
+ Expression e;
+ UnboundFunction unboundFunction;
+
+ sql = "position('bar' in 'foobarbar')";
+ e = parser.parseExpression(sql);
+ Assertions.assertInstanceOf(UnboundFunction.class, e);
+ unboundFunction = (UnboundFunction) e;
+ Assertions.assertEquals("position", unboundFunction.getName());
+ Assertions.assertEquals(2, unboundFunction.arity());
+ Assertions.assertEquals("bar", ((StringLikeLiteral)
unboundFunction.child(0)).getStringValue());
+ Assertions.assertEquals("foobarbar", ((StringLikeLiteral)
unboundFunction.child(1)).getStringValue());
+
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("position('bar' in)"));
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("position(in 'foobarbar')"));
+ Assertions.assertThrowsExactly(ParseException.class, () ->
parser.parseExpression("position(in)"));
+ }
+
@Test
public void testNoBackSlashEscapes() {
testNoBackSlashEscapes("''", "", "");
diff --git a/regression-test/data/nereids_function_p0/scalar_function/P.out
b/regression-test/data/nereids_function_p0/scalar_function/P.out
index e69cf1f91d1..7fc20a43bda 100644
--- a/regression-test/data/nereids_function_p0/scalar_function/P.out
+++ b/regression-test/data/nereids_function_p0/scalar_function/P.out
@@ -60,6 +60,180 @@
0.0
0.0
+-- !sql_position_Varchar_Varchar_In --
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+-- !sql_position_Varchar_Varchar_notnull_In --
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+-- !sql_position_String_String_In --
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+-- !sql_position_String_String_notnull_In --
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+-- !sql_position_Varchar_Varchar --
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+-- !sql_position_Varchar_Varchar_notnull --
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+-- !sql_position_String_String --
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+-- !sql_position_String_String_notnull --
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+-- !sql_position_Varchar_Varchar_Integer --
+\N
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+
+-- !sql_position_Varchar_Varchar_Integer_notnull --
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+
+-- !sql_position_String_String_Integer --
+\N
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+
+-- !sql_position_String_String_Integer_notnull --
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+
-- !sql_positive_BigInt --
\N
1
diff --git a/regression-test/data/nereids_function_p0/scalar_function/S.out
b/regression-test/data/nereids_function_p0/scalar_function/S.out
index 15bd526cbab..b93aa93a0b1 100644
--- a/regression-test/data/nereids_function_p0/scalar_function/S.out
+++ b/regression-test/data/nereids_function_p0/scalar_function/S.out
@@ -2727,6 +2727,122 @@ g3
+-- !sql_substring_Varchar_Integer_From --
+\N
+varchar11
+char11
+r11
+
+archar12
+har12
+12
+
+rchar13
+ar13
+3
+
+
+-- !sql_substring_Varchar_Integer_notnull_From --
+varchar11
+char11
+r11
+
+archar12
+har12
+12
+
+rchar13
+ar13
+3
+
+
+-- !sql_substring_String_Integer_From --
+\N
+string1
+ing1
+1
+
+tring2
+ng2
+
+
+ring3
+g3
+
+
+
+-- !sql_substring_String_Integer_notnull_From --
+string1
+ing1
+1
+
+tring2
+ng2
+
+
+ring3
+g3
+
+
+
+-- !sql_substring_Varchar_Integer_Integer_From_For --
+\N
+v
+char
+r11
+
+ar
+har12
+12
+
+rch
+ar13
+3
+
+
+-- !sql_substring_Varchar_Integer_Integer_notnull_From_For --
+v
+char
+r11
+
+ar
+har12
+12
+
+rch
+ar13
+3
+
+
+-- !sql_substring_String_Integer_Integer_From_For --
+\N
+s
+ing1
+1
+
+tr
+ng2
+
+
+rin
+g3
+
+
+
+-- !sql_substring_String_Integer_Integer_notnull_From_For --
+s
+ing1
+1
+
+tr
+ng2
+
+
+rin
+g3
+
+
+
-- !sql_substring_index_Varchar_Varchar_Integer --
null
varchar11
diff --git
a/regression-test/data/nereids_p0/expression/fold_constant/fold_constant_string_arithmatic.out
b/regression-test/data/nereids_p0/expression/fold_constant/fold_constant_string_arithmatic.out
new file mode 100644
index 00000000000..047323ab910
--- /dev/null
+++
b/regression-test/data/nereids_p0/expression/fold_constant/fold_constant_string_arithmatic.out
@@ -0,0 +1,202 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !sql --
+5
+
+-- !sql --
+0
+
+-- !sql --
+4
+
+-- !sql --
+5
+
+-- !sql --
+1
+
+-- !sql --
+4
+
+-- !sql --
+0
+
+-- !sql --
+7
+
+-- !sql --
+0
+
+-- !sql --
+1
+
+-- !sql --
+0
+
+-- !sql --
+7
+
+-- !sql --
+0
+
+-- !sql --
+5
+
+-- !sql --
+5
+
+-- !sql --
+2
+
+-- !sql --
+1
+
+-- !sql --
+1
+
+-- !sql --
+1
+
+-- !sql --
+1
+
+-- !sql --
+1
+
+-- !sql --
+5
+
+-- !sql --
+0
+
+-- !sql --
+5
+
+-- !sql --
+0
+
+-- !sql --
+7
+
+-- !sql --
+9
+
+-- !sql --
+10
+
+-- !sql --
+1
+
+-- !sql --
+5
+
+-- !sql --
+0
+
+-- !sql --
+4
+
+-- !sql --
+5
+
+-- !sql --
+1
+
+-- !sql --
+4
+
+-- !sql --
+0
+
+-- !sql --
+7
+
+-- !sql --
+0
+
+-- !sql --
+1
+
+-- !sql --
+0
+
+-- !sql --
+7
+
+-- !sql --
+0
+
+-- !sql --
+5
+
+-- !sql --
+5
+
+-- !sql --
+0
+
+-- !sql --
+0
+
+-- !sql --
+5
+
+-- !sql --
+4
+
+-- !sql --
+1
+
+-- !sql --
+1
+
+-- !sql --
+0
+
+-- !sql --
+1
+
+-- !sql --
+5
+
+-- !sql --
+0
+
+-- !sql --
+1
+
+-- !sql --
+0
+
+-- !sql --
+0
+
+-- !sql --
+5
+
+-- !sql --
+0
+
+-- !sql --
+6
+
+-- !sql --
+0
+
+-- !sql --
+7
+
+-- !sql --
+9
+
+-- !sql --
+0
+
+-- !sql --
+1
+
+-- !sql --
+1
+
+-- !sql --
+0
+
diff --git
a/regression-test/suites/nereids_function_p0/scalar_function/P.groovy
b/regression-test/suites/nereids_function_p0/scalar_function/P.groovy
index 75611efb56c..e721fc4e579 100644
--- a/regression-test/suites/nereids_function_p0/scalar_function/P.groovy
+++ b/regression-test/suites/nereids_function_p0/scalar_function/P.groovy
@@ -32,6 +32,18 @@ suite("nereids_scalar_fn_P") {
qt_sql_pmod_BigInt_BigInt_notnull "select pmod(kbint, kbint) from
fn_test_not_nullable order by kbint, kbint"
qt_sql_pmod_Double_Double "select pmod(kdbl, kdbl) from fn_test order
by kdbl, kdbl"
qt_sql_pmod_Double_Double_notnull "select pmod(kdbl, kdbl) from
fn_test_not_nullable order by kdbl, kdbl"
+ qt_sql_position_Varchar_Varchar_In "select position(kvchrs1 in kvchrs1)
from fn_test order by kvchrs1, kvchrs1"
+ qt_sql_position_Varchar_Varchar_notnull_In "select position(kvchrs1 in
kvchrs1) from fn_test_not_nullable order by kvchrs1, kvchrs1"
+ qt_sql_position_String_String_In "select position(kstr in kstr) from
fn_test order by kstr, kstr"
+ qt_sql_position_String_String_notnull_In "select position(kstr in kstr)
from fn_test_not_nullable order by kstr, kstr"
+ qt_sql_position_Varchar_Varchar "select position(kvchrs1, kvchrs1) from
fn_test order by kvchrs1, kvchrs1"
+ qt_sql_position_Varchar_Varchar_notnull "select position(kvchrs1,
kvchrs1) from fn_test_not_nullable order by kvchrs1, kvchrs1"
+ qt_sql_position_String_String "select position(kstr, kstr) from fn_test
order by kstr, kstr"
+ qt_sql_position_String_String_notnull "select position(kstr, kstr) from
fn_test_not_nullable order by kstr, kstr"
+ qt_sql_position_Varchar_Varchar_Integer "select position(kvchrs1,
kvchrs1, kint) from fn_test order by kvchrs1, kvchrs1, kint"
+ qt_sql_position_Varchar_Varchar_Integer_notnull "select
position(kvchrs1, kvchrs1, kint) from fn_test_not_nullable order by kvchrs1,
kvchrs1, kint"
+ qt_sql_position_String_String_Integer "select position(kstr, kstr,
kint) from fn_test order by kstr, kstr, kint"
+ qt_sql_position_String_String_Integer_notnull "select position(kstr,
kstr, kint) from fn_test_not_nullable order by kstr, kstr, kint"
qt_sql_positive_BigInt "select positive(kbint) from fn_test order by
kbint"
qt_sql_positive_BigInt_notnull "select positive(kbint) from
fn_test_not_nullable order by kbint"
qt_sql_positive_Double "select positive(kdbl) from fn_test order by
kdbl"
diff --git
a/regression-test/suites/nereids_function_p0/scalar_function/S.groovy
b/regression-test/suites/nereids_function_p0/scalar_function/S.groovy
index 953c725d3c8..c3b8b179e70 100644
--- a/regression-test/suites/nereids_function_p0/scalar_function/S.groovy
+++ b/regression-test/suites/nereids_function_p0/scalar_function/S.groovy
@@ -255,6 +255,14 @@ suite("nereids_scalar_fn_S") {
qt_sql_substring_Varchar_Integer_Integer_notnull "select
substring(kvchrs1, kint, kint) from fn_test_not_nullable order by kvchrs1,
kint, kint"
qt_sql_substring_String_Integer_Integer "select substring(kstr, kint,
kint) from fn_test order by kstr, kint, kint"
qt_sql_substring_String_Integer_Integer_notnull "select substring(kstr,
kint, kint) from fn_test_not_nullable order by kstr, kint, kint"
+ qt_sql_substring_Varchar_Integer_From "select substring(kvchrs1 FROM
kint) from fn_test order by kvchrs1, kint"
+ qt_sql_substring_Varchar_Integer_notnull_From "select substring(kvchrs1
FROM kint) from fn_test_not_nullable order by kvchrs1, kint"
+ qt_sql_substring_String_Integer_From "select substring(kstr FROM kint)
from fn_test order by kstr, kint"
+ qt_sql_substring_String_Integer_notnull_From "select substring(kstr
FROM kint) from fn_test_not_nullable order by kstr, kint"
+ qt_sql_substring_Varchar_Integer_Integer_From_For "select
substring(kvchrs1 FROM kint FOR kint) from fn_test order by kvchrs1, kint, kint"
+ qt_sql_substring_Varchar_Integer_Integer_notnull_From_For "select
substring(kvchrs1 FROM kint FOR kint) from fn_test_not_nullable order by
kvchrs1, kint, kint"
+ qt_sql_substring_String_Integer_Integer_From_For "select substring(kstr
FROM kint FOR kint) from fn_test order by kstr, kint, kint"
+ qt_sql_substring_String_Integer_Integer_notnull_From_For "select
substring(kstr FROM kint FOR kint) from fn_test_not_nullable order by kstr,
kint, kint"
qt_sql_substring_index_Varchar_Varchar_Integer "select
substring_index(kvchrs1, ' ', 2) from fn_test order by kvchrs1"
qt_sql_substring_index_Varchar_Varchar_Integer_notnull "select
substring_index(kvchrs1, ' ', 2) from fn_test_not_nullable order by kvchrs1"
qt_sql_substring_index_String_String_Integer "select
substring_index(kstr, ' ', 2) from fn_test order by kstr"
diff --git
a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_string_arithmatic.groovy
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_string_arithmatic.groovy
index 68db295f66c..997ac3f9037 100644
---
a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_string_arithmatic.groovy
+++
b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_string_arithmatic.groovy
@@ -739,6 +739,75 @@ suite("fold_constant_string_arithmatic") {
// testFoldConst("select
PARSE_URL('http://user:[email protected]:8080/path/to/file?query=string#fragment',
'PORT')")
testFoldConst("select
PARSE_URL('http://user:[email protected]:8080/path/to/file?query=string#fragment',
'QUERY')")
+ // position
+ qt_sql "select position('北京' in '上海天津北京杭州')"
+ qt_sql "select position('上海天津北京杭州' in '北京')"
+ qt_sql "select position('bar' in 'foobarbar')"
+ qt_sql "select position(cast('北京' as string) in cast('上海天津北京杭州' as
string))"
+ qt_sql "select position(cast('' as string) in cast('foobar' as string))"
+ qt_sql "select position(cast('bar' as string) in cast('foobarbar' as
string))"
+ qt_sql "select position(cast('World' as string) in cast('Hello' as
string))"
+ qt_sql "select position(cast('World' as string) in cast('Hello World' as
string))"
+ qt_sql "select position(cast('xbar' as string) in cast('foobar' as
string))"
+ qt_sql "select position('' in 'foobar')"
+ qt_sql "select position('World' in 'Hello')"
+ qt_sql "select position('World' in 'Hello World')"
+ qt_sql "select position('xbar' in 'foobar')"
+ qt_sql "select position('北京' in '上海天津北京杭州')"
+ qt_sql "select position('2' in ' 123 ')"
+ qt_sql "select position('bc' in 'abcbcbc')"
+ qt_sql "select position('a' in 'a')"
+ qt_sql "select position('' in '')"
+ qt_sql "select position('abc' in 'abcd')"
+ qt_sql "select position('' in 'hello')"
+ qt_sql "select position('' in '哈哈😊😂🤣🤣😄')"
+ qt_sql "select position('🤣🤣' in '哈哈😊😂🤣🤣😄')"
+ qt_sql "select position('🤣🤣🤣' in '哈哈😊😂🤣🤣😄')"
+ qt_sql "select position('🤣' in '哈哈😊😂🤣🤣😄')"
+ qt_sql "select position('😅' in '哈哈😊😂🤣🤣😄')"
+ qt_sql "select position('안녕' in '哈哈こんにち안녕하세')"
+ qt_sql "select position('하세' in '哈哈こんにち안녕하세')"
+ qt_sql "select position('세' in '哈哈こんにち안녕하세')"
+ qt_sql "select position('' in '你好世界')"
+ qt_sql "select position('北京', '上海天津北京杭州')"
+ qt_sql "select position('上海天津北京杭州', '北京')"
+ qt_sql "select position('bar', 'foobarbar')"
+ qt_sql "select position(cast('北京' as string), cast('上海天津北京杭州' as string))"
+ qt_sql "select position(cast('' as string), cast('foobar' as string))"
+ qt_sql "select position(cast('bar' as string), cast('foobarbar' as
string))"
+ qt_sql "select position(cast('World' as string), cast('Hello' as string))"
+ qt_sql "select position(cast('World' as string), cast('Hello World' as
string))"
+ qt_sql "select position(cast('xbar' as string), cast('foobar' as string))"
+ qt_sql "select position('', 'foobar')"
+ qt_sql "select position('World', 'Hello')"
+ qt_sql "select position('World', 'Hello World')"
+ qt_sql "select position('xbar', 'foobar')"
+ qt_sql "select position('北京', '上海天津北京杭州', 4)"
+ qt_sql "select position('北京', '上海天津北京杭州', 5)"
+ qt_sql "select position('北京', '上海天津北京杭州', -4)"
+ qt_sql "select position('北京', '上海天津北京杭州', -5)"
+ qt_sql "select position('2', ' 123 ', 1)"
+ qt_sql "select position('bc', 'abcbcbc', 4)"
+ qt_sql "select position('a', 'a')"
+ qt_sql "select position('', '')"
+ qt_sql "select position('', '', 2)"
+ qt_sql "select position('abc', 'abcd')"
+ qt_sql "select position('', 'hello', 5)"
+ qt_sql "select position('', 'hello', 6)"
+ qt_sql "select position('', '哈哈😊😂🤣🤣😄')"
+ qt_sql "select position('', '哈哈😊😂🤣🤣😄', 26)"
+ qt_sql "select position('', '哈哈😊😂🤣🤣😄', 27)"
+ qt_sql "select position('🤣🤣', '哈哈😊😂🤣🤣😄', 5)"
+ qt_sql "select position('🤣🤣🤣', '哈哈😊😂🤣🤣😄', 5)"
+ qt_sql "select position('🤣', '哈哈😊😂🤣🤣😄', 6)"
+ qt_sql "select position('😅', '哈哈😊😂🤣🤣😄', 6)"
+ qt_sql "select position('안녕', '哈哈こんにち안녕하세', 6)"
+ qt_sql "select position('하세', '哈哈こんにち안녕하세', 9)"
+ qt_sql "select position('세', '哈哈こんにち안녕하세', 11)"
+ qt_sql "select position('', '', 1)"
+ qt_sql "select position('', '你好世界', 1)"
+ qt_sql "select position('', '你好世界', 5)"
+
// repeat
testFoldConst("select repeat('a', 0)")
testFoldConst("select repeat('a', -1)")
@@ -1198,6 +1267,20 @@ suite("fold_constant_string_arithmatic") {
testFoldConst("select substr('abcdef',-3)")
testFoldConst("select substr('abcdef',3)")
testFoldConst("select substr('',3)")
+ testFoldConst("select substr('a' FROM 0 FOR 1)")
+ testFoldConst("select substr('a' FROM -1 FOR 1)")
+ testFoldConst("select substr('a' FROM 1 FOR 1)")
+ testFoldConst("select substr('a' FROM -2 FOR 1)")
+ testFoldConst("select substr('a' FROM 2 FOR 1)")
+ testFoldConst("select substr('a' FROM -3 FOR 1)")
+ testFoldConst("select substr('a' FROM 3 FOR 1)")
+ testFoldConst("select substr('abcdef' FROM -3 FOR -1)")
+ testFoldConst("select substr('abcdef' FROM 3 FOR -1)")
+ testFoldConst("select substr('' FROM 3 FOR -1)")
+ testFoldConst("select substr('abcdef' FROM 3 FOR 10)")
+ testFoldConst("select substr('abcdef' FROM -3)")
+ testFoldConst("select substr('abcdef' FROM 3)")
+ testFoldConst("select substr('' FROM 3)")
// substring
testFoldConst("select substring('1', 1, 1)")
@@ -1227,6 +1310,33 @@ suite("fold_constant_string_arithmatic") {
testFoldConst("select substring('abcdef',-3)")
testFoldConst("select substring('abcdef',3)")
testFoldConst("select substring('',3)")
+ testFoldConst("select substring('1' FROM 1 FOR 1)")
+ testFoldConst("select substring('abc1' FROM -2)")
+ testFoldConst("select substring('abc1' FROM 2)")
+ testFoldConst("select substring('abc1' FROM 5)")
+ testFoldConst("select substring('abc1def' FROM 2 FOR 2)")
+ testFoldConst("select substring('abcdef' FROM 10 FOR 1)")
+ testFoldConst("select substring('abcdef' FROM -3 FOR -1)")
+ testFoldConst("select substring('abcdef' FROM 3 FOR -1)")
+ testFoldConst("select substring(cast('1' as string) FROM 1 FOR 1)")
+ testFoldConst("select substring(CAST('abc1' AS STRING) FROM -2)")
+ testFoldConst("select substring(CAST('abc1' AS STRING) FROM 2)")
+ testFoldConst("select substring(CAST('abc1' AS STRING) FROM 5)")
+ testFoldConst("select substring(CAST('abc1def' AS STRING) FROM 2 FOR 2)")
+ testFoldConst("select substring(CAST('abcdef' AS STRING) FROM 10 FOR 1)")
+ testFoldConst("select substring(CAST('abcdef' AS STRING) FROM -3 FOR -1)")
+ testFoldConst("select substring(CAST('abcdef' AS STRING) FROM 3 FOR -1)")
+ testFoldConst("select substring(cast('Hello' as string) FROM 1 FOR 10)")
+ testFoldConst("select substring(cast('Hello World' as string) FROM -1 FOR
5)")
+ testFoldConst("select substring(cast('Hello World' as string) FROM 1 FOR
5)")
+ testFoldConst("select substring('Hello' FROM 1 FOR 10)")
+ testFoldConst("select substring('Hello World' FROM -1 FOR 5)")
+ testFoldConst("select substring('Hello World' FROM 1 FOR 5)")
+ testFoldConst("select substring('' FROM 1 FOR 5)")
+ testFoldConst("select substring('Hello World' FROM 1 FOR 50)")
+ testFoldConst("select substring('abcdef' FROM -3)")
+ testFoldConst("select substring('abcdef' FROM 3)")
+ testFoldConst("select substring('' FROM 3)")
// substring_index
testFoldConst("select substring_index('a,b,c', ',', 2)")
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]