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

jackietien pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 7eed3aac9b5 Fix substring logic proble And add function pi and e
7eed3aac9b5 is described below

commit 7eed3aac9b58815c626b4dd02bcd35ee7e782e5f
Author: Lin Xintao <[email protected]>
AuthorDate: Thu Aug 29 11:54:47 2024 +0800

    Fix substring logic proble And add function pi and e
---
 .../scalar/IoTDBScalarFunctionTableIT.java         | 88 ++++++++++++++++++++--
 .../scalar/IoTDBSubStringFunctionTableIT.java      | 51 +++++++------
 .../iotdb/relational/it/schema/IoTDBDeviceIT.java  |  2 +-
 .../relational/ColumnTransformerBuilder.java       | 39 +++++-----
 .../builtin/helper/SubStringFunctionHelper.java    |  2 +-
 .../relational/metadata/TableMetadataImpl.java     | 20 ++++-
 .../dag/column/leaf/LeafColumnTransformer.java     |  1 +
 .../unary/scalar/SubString2ColumnTransformer.java  | 11 +--
 .../unary/scalar/SubString3ColumnTransformer.java  | 28 +++++--
 ...former.java => SubStringColumnTransformer.java} | 32 +++++---
 .../unary/scalar/TableBuiltinScalarFunction.java   |  2 +
 .../scalar/SubStringFunctionColumnTransformer.java |  3 +-
 .../unary/scalar/SubStringFunctionTransformer.java |  2 +-
 13 files changed, 205 insertions(+), 76 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBScalarFunctionTableIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBScalarFunctionTableIT.java
index 2a7d157677f..d6eac7a6c63 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBScalarFunctionTableIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBScalarFunctionTableIT.java
@@ -322,6 +322,9 @@ public class IoTDBScalarFunctionTableIT {
         "INSERT INTO upperTable(Time,device_id,s1) values(3, 'd1', 'Abcdefg')",
         "INSERT INTO upperTable(Time,device_id,s9) values(2, 'd1', 'Test')",
         "INSERT INTO upperTable(Time,device_id,s9) values(3, 'd1', 'Abcdefg')",
+        // no args SQL
+        "create table NoArgTable(device_id STRING ID, s1 TEXT MEASUREMENT, s2 
INT32 MEASUREMENT, s3 INT64 MEASUREMENT, s4 FLOAT MEASUREMENT, s5 DOUBLE 
MEASUREMENT, s6 BOOLEAN MEASUREMENT, s7 DATE MEASUREMENT, s8 TIMESTAMP 
MEASUREMENT, s9 STRING MEASUREMENT, s10 BLOB MEASUREMENT)",
+        "INSERT INTO NoArgTable(Time,device_id,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10) 
values(1, 'd1', 'abcd', 0, 0, 0, 0, true, '2021-10-01', 1633046400000, 'abcd', 
X'abcd')",
         // dateBinSQL use s8 to calculate
         "create table dateBinTable(device_id STRING ID, s1 TEXT MEASUREMENT, 
s2 INT32 MEASUREMENT, s3 INT64 MEASUREMENT, s4 FLOAT MEASUREMENT, s5 DOUBLE 
MEASUREMENT, s6 BOOLEAN MEASUREMENT, s7 DATE MEASUREMENT, s8 TIMESTAMP 
MEASUREMENT, s9 STRING MEASUREMENT, s10 BLOB MEASUREMENT)",
         // 2024-01-01T00:00:00.000Z
@@ -490,11 +493,6 @@ public class IoTDBScalarFunctionTableIT {
         expectedResultLong,
         expectedResultFloat,
         expectedResultDouble);
-    String[] expectedAns =
-        new String[] {
-          "1970-01-01T00:00:00.001Z,1,0.0,1,0.0,1.0,0.0,1.0,0.0,",
-          
"1970-01-01T00:00:00.002Z,2,NaN,2,NaN,0.5,1.0471975511965979,0.5,1.0471975511965979,",
-        };
   }
 
   @Test
@@ -2681,6 +2679,86 @@ public class IoTDBScalarFunctionTableIT {
         DATABASE_NAME);
   }
 
+  private void testOneRowDoubleResult(
+      String sql, String[] expectedHeader, String database, Double[] 
expectedResult) {
+    try (Connection connection =
+        EnvFactory.getEnv()
+            .getConnection(
+                SessionConfig.DEFAULT_USER,
+                SessionConfig.DEFAULT_PASSWORD,
+                BaseEnv.TABLE_SQL_DIALECT)) {
+      connection.setClientInfo("time_zone", "+00:00");
+      try (Statement statement = connection.createStatement()) {
+        statement.execute("use " + database);
+        try (ResultSet resultSet = statement.executeQuery(sql)) {
+          ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+          for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+            assertEquals(expectedHeader[i - 1], 
resultSetMetaData.getColumnName(i));
+          }
+          assertEquals(expectedHeader.length, 
resultSetMetaData.getColumnCount());
+          resultSet.next();
+          assertEquals(expectedResult[0], 
Double.parseDouble(resultSet.getString(1)), 0.00001);
+          assertEquals(expectedResult[1], 
Double.parseDouble(resultSet.getString(2)), 0.00001);
+        }
+      }
+    } catch (SQLException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
+
+  @Test
+  public void piTestNormal() {
+    String[] expectedHeader = new String[] {"time", "_col1", "_col2", "_col3", 
"_col4"};
+    Double[] expectedResultInt = new Double[] {Math.PI};
+    Double[] expectedResultLong = new Double[] {Math.PI};
+    Double[] expectedResultFloat = new Double[] {Math.PI};
+    Double[] expectedResultDouble = new Double[] {Math.PI};
+    testDoubleResult(
+        "select time, s2 + pi(), s3 + pi(), s4 + pi(), s5 + pi() from 
NoArgTable",
+        expectedHeader,
+        DATABASE_NAME,
+        expectedResultInt,
+        expectedResultLong,
+        expectedResultFloat,
+        expectedResultDouble);
+  }
+
+  @Test
+  public void piTestFail() {
+    // case 1: more than one argument
+    tableAssertTestFail(
+        "select s2,pi(s2) from NoArgTable",
+        TSStatusCode.SEMANTIC_ERROR.getStatusCode() + ": Scalar function pi 
accepts no argument.",
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void eTestNormal() {
+    String[] expectedHeader = new String[] {"time", "_col1", "_col2", "_col3", 
"_col4"};
+    Double[] expectedResultInt = new Double[] {Math.E};
+    Double[] expectedResultLong = new Double[] {Math.E};
+    Double[] expectedResultFloat = new Double[] {Math.E};
+    Double[] expectedResultDouble = new Double[] {Math.E};
+    testDoubleResult(
+        "select time, s2 + e(), s3 + e(), s4 + e(), s5 + e() from NoArgTable",
+        expectedHeader,
+        DATABASE_NAME,
+        expectedResultInt,
+        expectedResultLong,
+        expectedResultFloat,
+        expectedResultDouble);
+  }
+
+  @Test
+  public void eTestFail() {
+    // case 1: more than one argument
+    tableAssertTestFail(
+        "select s1,e(s1) from NoArgTable",
+        TSStatusCode.SEMANTIC_ERROR.getStatusCode() + ": Scalar function e 
accepts no argument.",
+        DATABASE_NAME);
+  }
+
   @Test
   public void dateBinTestNormal() {
     String[] expectedHeader = new String[] {"time", "s1", "s8", "_col3"};
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBSubStringFunctionTableIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBSubStringFunctionTableIT.java
index 1ea049ebfd7..f938e7ffc37 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBSubStringFunctionTableIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBSubStringFunctionTableIT.java
@@ -49,11 +49,13 @@ public class IoTDBSubStringFunctionTableIT {
         "CREATE DATABASE " + DATABASE_NAME,
         "use " + DATABASE_NAME,
         "create table table1(device_id STRING ID, s1 TEXT MEASUREMENT, s2 
INT32 MEASUREMENT, s3 INT64 MEASUREMENT, s4 FLOAT MEASUREMENT, s5 DOUBLE 
MEASUREMENT, s6 BOOLEAN MEASUREMENT, s7 DATE MEASUREMENT, s8 TIMESTAMP 
MEASUREMENT, s9 STRING MEASUREMENT, s10 BLOB MEASUREMENT)",
-        "INSERT INTO table1(Time,device_id,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10) 
values(1, 'd1', 'abcd', 1, 1, 1, 1, true, '2021-10-01', 1633046400000, 'abcd', 
X'abcd')",
+        "INSERT INTO table1(Time,device_id,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10) 
values(1, 'd1', 'abcd', -1, 3, 1, 1, true, '2021-10-01', 1633046400000, 'abcd', 
X'abcd')",
         "INSERT INTO table1(Time,device_id,s1) values(2, 'd1', 'test')",
         "INSERT INTO table1(Time,device_id,s1) values(3, 'd1', 'abcdefg')",
         "INSERT INTO table1(Time,device_id,s9) values(2, 'd1', 'test')",
         "INSERT INTO table1(Time,device_id,s9) values(3, 'd1', 'abcdefg')",
+        "INSERT INTO table1(Time,device_id,s2,s3) values(2, 'd1', -1, 10)",
+        "INSERT INTO table1(Time,device_id,s2,s3) values(3, 'd1', 2, 3)",
         "flush"
       };
 
@@ -83,44 +85,45 @@ public class IoTDBSubStringFunctionTableIT {
   @Test
   public void testNewTransformer() {
     // Normal
-    String[] expectedHeader = new String[] {"time", "s1", "_col2", "_col3"};
+    String[] expectedHeader = new String[] {"time", "s1", "_col2", "_col3", 
"s9", "_col5", "_col6"};
     String[] retArray =
         new String[] {
-          "1970-01-01T00:00:00.001Z,abcd,abcd,abc,",
-          "1970-01-01T00:00:00.002Z,test,test,tes,",
-          "1970-01-01T00:00:00.003Z,abcdefg,abcdefg,abc,",
+          "1970-01-01T00:00:00.001Z,abcd,abcd,abc,abcd,abcd,abc,",
+          "1970-01-01T00:00:00.002Z,test,test,tes,test,test,tes,",
+          "1970-01-01T00:00:00.003Z,abcdefg,abcdefg,abc,abcdefg,abcdefg,abc,",
         };
     tableResultSetEqualTest(
-        "select time,s1,SUBSTRING(s1 FROM 1),SUBSTRING(s1 FROM 1 FOR 3) from 
table1",
+        "select time,s1,SUBSTRING(s1 FROM 1),SUBSTRING(s1 FROM 1 FOR 
3),s9,SUBSTRING(s9 from 1),SUBSTRING(s9 from 1 for 3) from table1",
         expectedHeader,
         retArray,
         DATABASE_NAME);
 
-    // Param 1 greater than input series length
+    // 2 column
+    expectedHeader = new String[] {"time", "s1", "s9", "s2", "_col4", "_col5"};
     retArray =
         new String[] {
-          "1970-01-01T00:00:00.001Z,abcd,,,",
-          "1970-01-01T00:00:00.002Z,test,,,",
-          "1970-01-01T00:00:00.003Z,abcdefg,,,",
+          "1970-01-01T00:00:00.001Z,abcd,abcd,-1,abcd,abcd,",
+          "1970-01-01T00:00:00.002Z,test,test,-1,test,test,",
+          "1970-01-01T00:00:00.003Z,abcdefg,abcdefg,2,bcdefg,bcdefg,",
         };
     tableResultSetEqualTest(
-        "select time,s1,SUBSTRING(s1 from 11),SUBSTRING(s1 from 11 for 13) 
from table1",
+        "select time,s1,s9,s2,SUBSTRING(s1 from s2),SUBSTRING(s1 from s2) from 
table1",
         expectedHeader,
         retArray,
         DATABASE_NAME);
 
-    // Normal
-    expectedHeader = new String[] {"time", "s9", "_col2", "_col3"};
-    String[] retArray2 =
+    // 3 column
+    expectedHeader = new String[] {"time", "s1", "s9", "s2", "s3", "_col5", 
"_col6"};
+    retArray =
         new String[] {
-          "1970-01-01T00:00:00.001Z,abcd,abcd,abc,",
-          "1970-01-01T00:00:00.002Z,test,test,tes,",
-          "1970-01-01T00:00:00.003Z,abcdefg,abcdefg,abc,",
+          "1970-01-01T00:00:00.001Z,abcd,abcd,-1,3,a,a,",
+          "1970-01-01T00:00:00.002Z,test,test,-1,10,test,test,",
+          "1970-01-01T00:00:00.003Z,abcdefg,abcdefg,2,3,bcd,bcd,",
         };
     tableResultSetEqualTest(
-        "select time,s9,SUBSTRING(s9 from 1),SUBSTRING(s9 from 1 for 3) from 
table1",
+        "select time,s1,s9,s2,s3,SUBSTRING(s1 from s2 for s3),SUBSTRING(s1 
from s2 for s3) from table1",
         expectedHeader,
-        retArray2,
+        retArray,
         DATABASE_NAME);
   }
 
@@ -206,14 +209,14 @@ public class IoTDBSubStringFunctionTableIT {
     tableAssertTestFail(
         "select SUBSTRING(s1 FROM 1 FOR -10) from table1",
         TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode()
-            + ": Argument exception,the scalar function [SUBSTRING] 
beginPosition and length must be greater than 0",
+            + ": Argument exception,the scalar function substring length must 
not be less than 0",
         DATABASE_NAME);
 
-    // Negative characters begin
+    // big characters begin
     tableAssertTestFail(
-        "select SUBSTRING(s1 FROM -1 FOR 10) from table1",
-        TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode()
-            + ": Argument exception,the scalar function [SUBSTRING] 
beginPosition and length must be greater than 0",
+        "select SUBSTRING(s1 FROM 100 FOR 1) from table1",
+        TSStatusCode.SEMANTIC_ERROR.getStatusCode()
+            + ": Argument exception,the scalar function substring 
beginPosition must not be greater than the string length",
         DATABASE_NAME);
   }
 }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceIT.java
index d2c4aab2be9..63cb87ff350 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceIT.java
@@ -114,7 +114,7 @@ public class IoTDBDeviceIT {
           Collections.singleton("1,"));
       TestUtils.assertResultSetEqual(
           statement.executeQuery(
-              "count devices from table0 where substring(region_id, 
cast(plant_id as int32), 1) < plant_id"),
+              "count devices from table0 where substring(region_id, 
cast((cast(plant_id as int32) - 4) as int32 ) , 1) < plant_id"),
           "count(devices),",
           Collections.singleton("1,"));
       // Test get from cache
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
index bdaa1f2ea1c..ba8f3898229 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
@@ -137,7 +137,7 @@ import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.St
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.StrposColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubString2ColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubString3ColumnTransformer;
-import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubStringFunctionColumnTransformer;
+import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubStringColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.TableBuiltinScalarFunction;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.TanColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.TanhColumnTransformer;
@@ -612,22 +612,22 @@ public class ColumnTransformerBuilder
       if (children.size() == 2) {
         if (isStringLiteral(children.get(1))) {
           return new ReplaceFunctionColumnTransformer(
-              first.getType(), first, ((StringLiteral) 
children.get(1)).getValue(), "");
+              STRING, first, ((StringLiteral) children.get(1)).getValue(), "");
         } else {
           return new Replace2ColumnTransformer(
-              first.getType(), first, this.process(children.get(1), context));
+              STRING, first, this.process(children.get(1), context));
         }
       } else {
         // size == 3
         if (isStringLiteral(children.get(1)) && 
isStringLiteral(children.get(2))) {
           return new ReplaceFunctionColumnTransformer(
-              first.getType(),
+              STRING,
               first,
               ((StringLiteral) children.get(1)).getValue(),
               ((StringLiteral) children.get(2)).getValue());
         } else {
           return new Replace3ColumnTransformer(
-              first.getType(),
+              STRING,
               first,
               this.process(children.get(1), context),
               this.process(children.get(2), context));
@@ -640,29 +640,20 @@ public class ColumnTransformerBuilder
       if (children.size() == 2) {
         if (isLongLiteral(children.get(1))) {
           int startIndex = (int) ((LongLiteral) 
children.get(1)).getParsedValue();
-          if (startIndex <= 0) {
-            throw new SemanticException(
-                "Argument exception,the scalar function [SUBSTRING] 
beginPosition and length must be greater than 0");
-          }
-          return new SubStringFunctionColumnTransformer(
-              first.getType(), first, startIndex, Integer.MAX_VALUE);
+          return new SubStringColumnTransformer(STRING, first, startIndex, 
Integer.MAX_VALUE);
         } else {
           return new SubString2ColumnTransformer(
-              first.getType(), first, this.process(children.get(1), context));
+              STRING, first, this.process(children.get(1), context));
         }
       } else {
         // size == 3
         if (isLongLiteral(children.get(1)) && isLongLiteral(children.get(2))) {
           int startIndex = (int) ((LongLiteral) 
children.get(1)).getParsedValue();
           int length = (int) ((LongLiteral) children.get(2)).getParsedValue();
-          if (startIndex <= 0 || length <= 0) {
-            throw new SemanticException(
-                "Argument exception,the scalar function [SUBSTRING] 
beginPosition and length must be greater than 0");
-          }
-          return new SubStringFunctionColumnTransformer(first.getType(), 
first, startIndex, length);
+          return new SubStringColumnTransformer(STRING, first, startIndex, 
length);
         } else {
           return new SubString3ColumnTransformer(
-              first.getType(),
+              STRING,
               first,
               this.process(children.get(1), context),
               this.process(children.get(2), context));
@@ -907,6 +898,18 @@ public class ColumnTransformerBuilder
       if (children.size() == 1) {
         return new SqrtColumnTransformer(DOUBLE, first);
       }
+    } else if 
(TableBuiltinScalarFunction.PI.getFunctionName().equalsIgnoreCase(functionName))
 {
+      ConstantColumnTransformer piColumnTransformer =
+          new ConstantColumnTransformer(
+              DOUBLE, new DoubleColumn(1, Optional.empty(), new double[] 
{Math.PI}));
+      context.leafList.add(piColumnTransformer);
+      return piColumnTransformer;
+    } else if 
(TableBuiltinScalarFunction.E.getFunctionName().equalsIgnoreCase(functionName)) 
{
+      ConstantColumnTransformer eColumnTransformer =
+          new ConstantColumnTransformer(
+              DOUBLE, new DoubleColumn(1, Optional.empty(), new double[] 
{Math.E}));
+      context.leafList.add(eColumnTransformer);
+      return eColumnTransformer;
     } else if (TableBuiltinScalarFunction.DATE_BIN
         .getFunctionName()
         .equalsIgnoreCase(functionName)) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/multi/builtin/helper/SubStringFunctionHelper.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/multi/builtin/helper/SubStringFunctionHelper.java
index 561805cc5a2..7d9490ac759 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/multi/builtin/helper/SubStringFunctionHelper.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/multi/builtin/helper/SubStringFunctionHelper.java
@@ -24,8 +24,8 @@ import 
org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression;
 import 
org.apache.iotdb.db.queryengine.plan.expression.multi.builtin.BuiltInScalarFunctionHelper;
 import org.apache.iotdb.db.queryengine.transformation.api.LayerReader;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
-import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubStringFunctionColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.transformer.Transformer;
+import 
org.apache.iotdb.db.queryengine.transformation.dag.transformer.unary.scalar.SubStringFunctionColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.transformer.unary.scalar.SubStringFunctionTransformer;
 
 import org.apache.tsfile.enums.TSDataType;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
index 1f7cadb111e..04b03e12dce 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
@@ -177,7 +177,7 @@ public class TableMetadataImpl implements Metadata {
                 + functionName.toLowerCase(Locale.ENGLISH)
                 + " only supports text or string data type.");
       }
-      return argumentTypes.get(0);
+      return STRING;
     } else if (TableBuiltinScalarFunction.SUBSTRING
         .getFunctionName()
         .equalsIgnoreCase(functionName)) {
@@ -193,7 +193,7 @@ public class TableMetadataImpl implements Metadata {
                 + functionName.toLowerCase(Locale.ENGLISH)
                 + " only accepts two or three arguments and first must be text 
or string data type, second and third must be numeric data types [INT32, 
INT64]");
       }
-      return argumentTypes.get(0);
+      return STRING;
     } else if 
(TableBuiltinScalarFunction.LENGTH.getFunctionName().equalsIgnoreCase(functionName))
 {
       if (!(argumentTypes.size() == 1 && isCharType(argumentTypes.get(0)))) {
         throw new SemanticException(
@@ -456,6 +456,22 @@ public class TableMetadataImpl implements Metadata {
                 + " only accepts one argument and it must be Double, Float, 
Int32 or Int64 data type.");
       }
       return DOUBLE;
+    } else if 
(TableBuiltinScalarFunction.PI.getFunctionName().equalsIgnoreCase(functionName))
 {
+      if (!(argumentTypes.isEmpty())) {
+        throw new SemanticException(
+            "Scalar function "
+                + functionName.toLowerCase(Locale.ENGLISH)
+                + " accepts no argument.");
+      }
+      return DOUBLE;
+    } else if 
(TableBuiltinScalarFunction.E.getFunctionName().equalsIgnoreCase(functionName)) 
{
+      if (!(argumentTypes.isEmpty())) {
+        throw new SemanticException(
+            "Scalar function "
+                + functionName.toLowerCase(Locale.ENGLISH)
+                + " accepts no argument.");
+      }
+      return DOUBLE;
     } else if (TableBuiltinScalarFunction.DATE_BIN
         .getFunctionName()
         .equalsIgnoreCase(functionName)) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/leaf/LeafColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/leaf/LeafColumnTransformer.java
index b09811e963d..6f4f704e1bd 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/leaf/LeafColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/leaf/LeafColumnTransformer.java
@@ -31,6 +31,7 @@ public abstract class LeafColumnTransformer extends 
ColumnTransformer {
 
   @Override
   public void evaluate() {
+    System.out.println("test");
     // do nothing
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString2ColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString2ColumnTransformer.java
index fc85b6f54a9..2f5ae44000d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString2ColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString2ColumnTransformer.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar;
 
+import org.apache.iotdb.db.exception.sql.SemanticException;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.binary.BinaryColumnTransformer;
 
@@ -28,8 +29,6 @@ import org.apache.tsfile.common.conf.TSFileConfig;
 import org.apache.tsfile.read.common.type.Type;
 import org.apache.tsfile.utils.BytesUtils;
 
-import static 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubStringFunctionColumnTransformer.EMPTY_STRING;
-
 public class SubString2ColumnTransformer extends BinaryColumnTransformer {
   public SubString2ColumnTransformer(
       Type returnType, ColumnTransformer leftTransformer, ColumnTransformer 
rightTransformer) {
@@ -49,10 +48,12 @@ public class SubString2ColumnTransformer extends 
BinaryColumnTransformer {
       if (!leftColumn.isNull(i) && !rightColumn.isNull(i)) {
         String currentValue = 
leftColumn.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET);
         int beginPosition = rightType.getInt(rightColumn, i);
-        if (beginPosition >= currentValue.length()) {
-          currentValue = EMPTY_STRING;
+        if (beginPosition > currentValue.length()) {
+          throw new SemanticException(
+              "Argument exception,the scalar function substring beginPosition 
must not be greater than the string length");
         } else {
-          currentValue = currentValue.substring(beginPosition);
+          int maxMin = Math.max(1, beginPosition);
+          currentValue = currentValue.substring(maxMin - 1);
         }
         builder.writeBinary(BytesUtils.valueOf(currentValue));
       } else {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString3ColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString3ColumnTransformer.java
index c9a3ae1a3fe..10f48451a44 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString3ColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString3ColumnTransformer.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar;
 
+import org.apache.iotdb.db.exception.sql.SemanticException;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.ternary.TernaryColumnTransformer;
 
@@ -28,7 +29,7 @@ import org.apache.tsfile.common.conf.TSFileConfig;
 import org.apache.tsfile.read.common.type.Type;
 import org.apache.tsfile.utils.BytesUtils;
 
-import static 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubStringFunctionColumnTransformer.EMPTY_STRING;
+import static 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubStringColumnTransformer.EMPTY_STRING;
 
 public class SubString3ColumnTransformer extends TernaryColumnTransformer {
   public SubString3ColumnTransformer(
@@ -59,14 +60,27 @@ public class SubString3ColumnTransformer extends 
TernaryColumnTransformer {
         String currentValue =
             firstType.getBinary(firstColumn, 
i).getStringValue(TSFileConfig.STRING_CHARSET);
         int beginPosition = secondType.getInt(secondColumn, i);
-        int endPosition = thirdType.getInt(thirdColumn, i);
-        if (beginPosition >= currentValue.length() || endPosition < 0) {
-          currentValue = EMPTY_STRING;
+        int length = thirdType.getInt(thirdColumn, i);
+        int endPosition;
+        if (length < 0) {
+          throw new SemanticException(
+              "Argument exception,the scalar function substring length must 
not be less than 0");
+        }
+        if (beginPosition > Integer.MAX_VALUE - length) {
+          endPosition = Integer.MAX_VALUE;
+        } else {
+          endPosition = beginPosition + length - 1;
+        }
+        if (beginPosition > currentValue.length()) {
+          throw new SemanticException(
+              "Argument exception,the scalar function substring beginPosition 
must not be greater than the string length");
         } else {
-          if (endPosition >= currentValue.length()) {
-            currentValue = currentValue.substring(beginPosition);
+          int maxMin = Math.max(1, beginPosition);
+          int minMax = Math.min(currentValue.length(), endPosition);
+          if (maxMin > minMax) {
+            currentValue = EMPTY_STRING;
           } else {
-            currentValue = currentValue.substring(beginPosition, endPosition);
+            currentValue = currentValue.substring(maxMin - 1, minMax);
           }
         }
         builder.writeBinary(BytesUtils.valueOf(currentValue));
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubStringFunctionColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubStringColumnTransformer.java
similarity index 64%
copy from 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubStringFunctionColumnTransformer.java
copy to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubStringColumnTransformer.java
index 0b567d799b6..25b47e5025c 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubStringFunctionColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubStringColumnTransformer.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar;
 
+import org.apache.iotdb.db.exception.sql.SemanticException;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.UnaryColumnTransformer;
 
@@ -28,18 +29,26 @@ import org.apache.tsfile.common.conf.TSFileConfig;
 import org.apache.tsfile.read.common.type.Type;
 import org.apache.tsfile.utils.BytesUtils;
 
-public class SubStringFunctionColumnTransformer extends UnaryColumnTransformer 
{
+public class SubStringColumnTransformer extends UnaryColumnTransformer {
 
   private final int beginPosition;
   private final int endPosition;
   public static final String EMPTY_STRING = "";
 
-  public SubStringFunctionColumnTransformer(
+  public SubStringColumnTransformer(
       Type returnType, ColumnTransformer childColumnTransformer, int 
beginPosition, int length) {
     super(returnType, childColumnTransformer);
-    this.endPosition =
-        (length == Integer.MAX_VALUE ? Integer.MAX_VALUE : beginPosition + 
length - 1);
-    this.beginPosition = beginPosition > 0 ? beginPosition - 1 : 0;
+    if (length < 0) {
+      throw new SemanticException(
+          "Argument exception,the scalar function substring length must not be 
less than 0");
+    }
+    // case which is two args or the result of the beginPosition add length is 
over
+    if (length == Integer.MAX_VALUE || beginPosition > Integer.MAX_VALUE - 
length) {
+      this.endPosition = Integer.MAX_VALUE;
+    } else {
+      this.endPosition = beginPosition + length - 1;
+    }
+    this.beginPosition = beginPosition;
   }
 
   @Override
@@ -47,13 +56,16 @@ public class SubStringFunctionColumnTransformer extends 
UnaryColumnTransformer {
     for (int i = 0, n = column.getPositionCount(); i < n; i++) {
       if (!column.isNull(i)) {
         String currentValue = 
column.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET);
-        if (beginPosition >= currentValue.length() || endPosition < 0) {
-          currentValue = EMPTY_STRING;
+        if (beginPosition > currentValue.length()) {
+          throw new SemanticException(
+              "Argument exception,the scalar function substring beginPosition 
must not be greater than the string length");
         } else {
-          if (endPosition >= currentValue.length()) {
-            currentValue = currentValue.substring(beginPosition);
+          int maxMin = Math.max(1, beginPosition);
+          int minMax = Math.min(currentValue.length(), endPosition);
+          if (maxMin > minMax) {
+            currentValue = EMPTY_STRING;
           } else {
-            currentValue = currentValue.substring(beginPosition, endPosition);
+            currentValue = currentValue.substring(maxMin - 1, minMax);
           }
         }
         columnBuilder.writeBinary(BytesUtils.valueOf(currentValue));
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/TableBuiltinScalarFunction.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/TableBuiltinScalarFunction.java
index 52bd6cd7c0e..c58182a3f27 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/TableBuiltinScalarFunction.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/TableBuiltinScalarFunction.java
@@ -56,6 +56,8 @@ public enum TableBuiltinScalarFunction {
   LN("ln"),
   LOG10("log10"),
   SQRT("sqrt"),
+  PI("pi"),
+  E("e"),
   DATE_BIN("date_bin"),
   ;
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubStringFunctionColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/transformer/unary/scalar/SubStringFunctionColumnTransformer.java
similarity index 96%
rename from 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubStringFunctionColumnTransformer.java
rename to 
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/transformer/unary/scalar/SubStringFunctionColumnTransformer.java
index 0b567d799b6..74a4ed73fe4 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubStringFunctionColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/transformer/unary/scalar/SubStringFunctionColumnTransformer.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar;
+package 
org.apache.iotdb.db.queryengine.transformation.dag.transformer.unary.scalar;
 
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.UnaryColumnTransformer;
@@ -29,7 +29,6 @@ import org.apache.tsfile.read.common.type.Type;
 import org.apache.tsfile.utils.BytesUtils;
 
 public class SubStringFunctionColumnTransformer extends UnaryColumnTransformer 
{
-
   private final int beginPosition;
   private final int endPosition;
   public static final String EMPTY_STRING = "";
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/transformer/unary/scalar/SubStringFunctionTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/transformer/unary/scalar/SubStringFunctionTransformer.java
index 3952d442c78..71312657ce4 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/transformer/unary/scalar/SubStringFunctionTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/transformer/unary/scalar/SubStringFunctionTransformer.java
@@ -30,7 +30,7 @@ import org.apache.tsfile.utils.Binary;
 import org.apache.tsfile.utils.BytesUtils;
 import org.apache.tsfile.write.UnSupportedDataTypeException;
 
-import static 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubStringFunctionColumnTransformer.EMPTY_STRING;
+import static 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubStringColumnTransformer.EMPTY_STRING;
 
 public class SubStringFunctionTransformer extends UnaryTransformer {
   private int beginPosition;


Reply via email to