This is an automated email from the ASF dual-hosted git repository.
duanzhengqiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new a43888aaa59 Extract expressions from special functions (#27545)
a43888aaa59 is described below
commit a43888aaa598abb0213a4464524db9b958456331
Author: ZhangCheng <[email protected]>
AuthorDate: Sat Jul 29 06:46:18 2023 +0800
Extract expressions from special functions (#27545)
* Extract expressions from special functions
* Extract expressions from special functions
* Extract expressions from special functions
* Extract expressions from special functions
* Extract expressions from special functions
* Extract expressions from special functions
* Extract expressions from special functions
* Extract expressions from special functions
* Extract expressions from special functions
* Extract expressions from special functions
---
.../visitor/statement/OracleStatementVisitor.java | 81 +++++++++++++++++++---
.../resources/case/dml/select-special-function.xml | 14 ++--
.../parser/src/main/resources/case/dml/select.xml | 74 +++++++++++++++++---
3 files changed, 146 insertions(+), 23 deletions(-)
diff --git
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
index 6d1b9f10c25..9bfd3841a35 100644
---
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
+++
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
@@ -25,7 +25,6 @@ import org.antlr.v4.runtime.tree.TerminalNode;
import
org.apache.shardingsphere.infra.database.core.metadata.database.enums.NullsOrderType;
import org.apache.shardingsphere.sql.parser.api.ASTNode;
import org.apache.shardingsphere.sql.parser.autogen.OracleStatementBaseVisitor;
-import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AggregationFunctionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.AnalyticFunctionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.BitExprContext;
@@ -42,7 +41,10 @@ import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DataTy
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DataTypeNameContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.DatetimeExprContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ExprContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ExtractFunctionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FeatureFunctionContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FirstOrLastValueFunctionContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FormatFunctionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FunctionCallContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.FunctionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.HexadecimalLiteralsContext;
@@ -70,6 +72,7 @@ import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.String
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.SynonymNameContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TableNameContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TableNamesContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TrimFunctionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.TypeNameContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.UnreservedWordContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.ViewNameContext;
@@ -78,6 +81,7 @@ import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlCol
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlExistsFunctionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlForestFunctionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlFunctionContext;
+import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlIsSchemaValidFunctionContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlNameSpaceStringAsIdentifierContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlNameSpacesClauseContext;
import
org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlParseFunctionContext;
@@ -105,7 +109,6 @@ import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.Expressi
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.IntervalDayToSecondExpression;
-import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.IntervalExpressionProjection;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.IntervalYearToMonthExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.NotExpression;
@@ -126,6 +129,7 @@ import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationDistinctProjectionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.AggregationProjectionSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.IntervalExpressionProjection;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.OrderBySegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ExpressionOrderByItemSegment;
@@ -149,6 +153,7 @@ import
org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.String
import
org.apache.shardingsphere.sql.parser.sql.common.value.parametermarker.ParameterMarkerValue;
import
org.apache.shardingsphere.sql.parser.sql.dialect.statement.oracle.dml.OracleSelectStatement;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
@@ -599,7 +604,13 @@ public abstract class OracleStatementVisitor extends
OracleStatementBaseVisitor<
String aggregationType = ctx.aggregationFunctionName().getText();
return AggregationType.isAggregationType(aggregationType)
? createAggregationSegment(ctx, aggregationType)
- : new FunctionSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(), aggregationType, getOriginalText(ctx));
+ : createAggregationFunctionSegment(ctx, aggregationType);
+ }
+
+ private FunctionSegment createAggregationFunctionSegment(final
AggregationFunctionContext ctx, final String aggregationType) {
+ FunctionSegment result = new
FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
aggregationType, getOriginalText(ctx));
+ result.getParameters().addAll(getExpressions(ctx.expr()));
+ return result;
}
private ASTNode createAggregationSegment(final AggregationFunctionContext
ctx, final String aggregationType) {
@@ -607,11 +618,11 @@ public abstract class OracleStatementVisitor extends
OracleStatementBaseVisitor<
if (null != ctx.DISTINCT()) {
AggregationDistinctProjectionSegment result =
new
AggregationDistinctProjectionSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(), type, getOriginalText(ctx),
getDistinctExpression(ctx));
- result.getParameters().addAll(getExpressions(ctx));
+ result.getParameters().addAll(getExpressions(ctx.expr()));
return result;
}
AggregationProjectionSegment result = new
AggregationProjectionSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(), type, getOriginalText(ctx));
- result.getParameters().addAll(getExpressions(ctx));
+ result.getParameters().addAll(getExpressions(ctx.expr()));
return result;
}
@@ -775,7 +786,7 @@ public abstract class OracleStatementVisitor extends
OracleStatementBaseVisitor<
}
@Override
- public ASTNode visitXmlIsSchemaValidFunction(final
OracleStatementParser.XmlIsSchemaValidFunctionContext ctx) {
+ public ASTNode visitXmlIsSchemaValidFunction(final
XmlIsSchemaValidFunctionContext ctx) {
FunctionSegment result = new
FunctionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(),
ctx.ISSCHEMAVALID().getText(), getOriginalText(ctx));
if (null != ctx.expr()) {
for (ExprContext each : ctx.expr()) {
@@ -785,8 +796,15 @@ public abstract class OracleStatementVisitor extends
OracleStatementBaseVisitor<
return result;
}
- private Collection<ExpressionSegment> getExpressions(final
AggregationFunctionContext ctx) {
- return null == ctx.expr() ? Collections.emptyList() :
ctx.expr().stream().map(each -> (ExpressionSegment)
visit(each)).collect(Collectors.toList());
+ private Collection<ExpressionSegment> getExpressions(final
List<ExprContext> exprList) {
+ if (null == exprList) {
+ return Collections.emptyList();
+ }
+ Collection<ExpressionSegment> result = new
ArrayList<>(exprList.size());
+ for (ExprContext each : exprList) {
+ result.add((ExpressionSegment) visit(each));
+ }
+ return result;
}
private String getDistinctExpression(final AggregationFunctionContext ctx)
{
@@ -805,10 +823,22 @@ public abstract class OracleStatementVisitor extends
OracleStatementBaseVisitor<
if (null != ctx.charFunction()) {
return visit(ctx.charFunction());
}
+ if (null != ctx.extractFunction()) {
+ return visit(ctx.extractFunction());
+ }
+ if (null != ctx.formatFunction()) {
+ return visit(ctx.formatFunction());
+ }
+ if (null != ctx.firstOrLastValueFunction()) {
+ return visit(ctx.firstOrLastValueFunction());
+ }
+ if (null != ctx.trimFunction()) {
+ return visit(ctx.trimFunction());
+ }
if (null != ctx.featureFunction()) {
return visit(ctx.featureFunction());
}
- return new FunctionSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(), ctx.getChild(0).getChild(0).getText(),
getOriginalText(ctx));
+ throw new IllegalStateException("SpecialFunctionContext must have
castFunction, charFunction, extractFunction, formatFunction,
firstOrLastValueFunction, trimFunction or featureFunction.");
}
@Override
@@ -833,7 +863,38 @@ public abstract class OracleStatementVisitor extends
OracleStatementBaseVisitor<
@Override
public final ASTNode visitCharFunction(final CharFunctionContext ctx) {
calculateParameterCount(ctx.expr());
- return new FunctionSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(), ctx.CHAR().getText(), getOriginalText(ctx));
+ FunctionSegment result = new
FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
ctx.CHAR().getText(), getOriginalText(ctx));
+ result.getParameters().addAll(getExpressions(ctx.expr()));
+ return result;
+ }
+
+ @Override
+ public ASTNode visitExtractFunction(final ExtractFunctionContext ctx) {
+ FunctionSegment result = new
FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
ctx.EXTRACT().getText(), getOriginalText(ctx));
+ result.getParameters().add((ExpressionSegment) visit(ctx.expr()));
+ return result;
+ }
+
+ @Override
+ public ASTNode visitFormatFunction(final FormatFunctionContext ctx) {
+ FunctionSegment result = new
FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
ctx.FORMAT().getText(), getOriginalText(ctx));
+ result.getParameters().addAll(getExpressions(ctx.expr()));
+ return result;
+ }
+
+ @Override
+ public ASTNode visitFirstOrLastValueFunction(final
FirstOrLastValueFunctionContext ctx) {
+ FunctionSegment result = new
FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
+ null == ctx.FIRST_VALUE() ? ctx.LAST_VALUE().getText() :
ctx.FIRST_VALUE().getText(), getOriginalText(ctx));
+ result.getParameters().add((ExpressionSegment) visit(ctx.expr()));
+ return result;
+ }
+
+ @Override
+ public ASTNode visitTrimFunction(final TrimFunctionContext ctx) {
+ FunctionSegment result = new
FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(),
ctx.TRIM().getText(), getOriginalText(ctx));
+ result.getParameters().add((ExpressionSegment) visit(ctx.expr()));
+ return result;
}
@Override
diff --git
a/test/it/parser/src/main/resources/case/dml/select-special-function.xml
b/test/it/parser/src/main/resources/case/dml/select-special-function.xml
index ea8e185be62..994c399707f 100644
--- a/test/it/parser/src/main/resources/case/dml/select-special-function.xml
+++ b/test/it/parser/src/main/resources/case/dml/select-special-function.xml
@@ -360,15 +360,21 @@
</select>
<select sql-case-id="select_extract_function_for_oracle">
- <projections start-index="7" stop-index="56">
- <expression-projection text="EXTRACT(YEAR FROM TIMESTAMP
'2001-02-16 20:38:40')" start-index="7" stop-index="56">
+ <projections start-index="7" stop-index="56" literal-start-index="7"
literal-stop-index="56">
+ <expression-projection text="EXTRACT(YEAR FROM TIMESTAMP
'2001-02-16 20:38:40')" start-index="7" stop-index="56" literal-start-index="7"
literal-stop-index="56">
+ <literalText>EXTRACT(YEAR FROM TIMESTAMP '2001-02-16
20:38:40')</literalText>
<expr>
- <function function-name="EXTRACT" start-index="7"
stop-index="56" text="EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40')" />
+ <function function-name="EXTRACT" text="EXTRACT(YEAR FROM
TIMESTAMP '2001-02-16 20:38:40')" start-index="7" stop-index="56"
literal-start-index="7" literal-stop-index="56">
+ <parameter>
+ <literal-expression value="2001-02-16 20:38:40"
start-index="25" stop-index="55" literal-start-index="25"
literal-stop-index="55" />
+ </parameter>
+ <literalText>EXTRACT(YEAR FROM TIMESTAMP '2001-02-16
20:38:40')</literalText>
+ </function>
</expr>
</expression-projection>
</projections>
<from>
- <simple-table name="DUAL" start-index="63" stop-index="66" />
+ <simple-table name="DUAL" start-index="63" stop-index="66"
literal-start-index="63" literal-stop-index="66" />
</from>
</select>
diff --git a/test/it/parser/src/main/resources/case/dml/select.xml
b/test/it/parser/src/main/resources/case/dml/select.xml
index bdafe84b87b..f8725aa57a3 100644
--- a/test/it/parser/src/main/resources/case/dml/select.xml
+++ b/test/it/parser/src/main/resources/case/dml/select.xml
@@ -5638,16 +5638,25 @@
</select>
<select sql-case-id="select_with_format_function">
- <from>
- <simple-table alias="wi" name="warehouse_info" start-index="66"
stop-index="82" literal-start-index="66" literal-stop-index="82"/>
- </from>
- <projections distinct-row="false" start-index="7" stop-index="59"
literal-start-index="7" literal-stop-index="59">
- <expression-projection text="wi.code.format(null,'PURE_IDENTITY')"
literal-text="wi.code.format(null,'PURE_IDENTITY')" alias="PURE_IDENTITY"
start-index="7" stop-index="59" literal-start-index="7" literal-stop-index="59">
- <expr >
- <function function-name="wi"
text="wi.code.format(null,'PURE_IDENTITY')"
literal-text="wi.code.format(null,'PURE_IDENTITY')" start-index="7"
stop-index="42" literal-start-index="7" literal-stop-index="42"/>
+ <projections start-index="7" stop-index="59" literal-start-index="7"
literal-stop-index="59">
+ <expression-projection text="wi.code.format(null,'PURE_IDENTITY')"
alias="PURE_IDENTITY" start-index="7" stop-index="59" literal-start-index="7"
literal-stop-index="59">
+ <literalText>wi.code.format(null,'PURE_IDENTITY')</literalText>
+ <expr>
+ <function function-name="format"
text="wi.code.format(null,'PURE_IDENTITY')" start-index="7" stop-index="42"
literal-start-index="7" literal-stop-index="42">
+ <parameter>
+ <literal-expression value="null" start-index="22"
stop-index="25" literal-start-index="22" literal-stop-index="25" />
+ </parameter>
+ <parameter>
+ <literal-expression value="PURE_IDENTITY"
start-index="27" stop-index="41" literal-start-index="27"
literal-stop-index="41" />
+ </parameter>
+
<literalText>wi.code.format(null,'PURE_IDENTITY')</literalText>
+ </function>
</expr>
</expression-projection>
</projections>
+ <from>
+ <simple-table alias="wi" name="warehouse_info" start-index="66"
stop-index="82" literal-start-index="66" literal-stop-index="82" />
+ </from>
</select>
<select sql-case-id="select_with_xml_is_schema_valid_function">
@@ -5673,15 +5682,22 @@
<select sql-case-id="select_with_last_value_function">
<projections start-index="7" stop-index="71" literal-start-index="7"
literal-stop-index="71">
<expression-projection text="LAST_VALUE(AGE IGNORE NULLS) OVER
(PARTITION BY AGE ORDER BY AGE)" start-index="7" stop-index="71"
literal-start-index="7" literal-stop-index="71">
+ <literalText>LAST_VALUE(AGE IGNORE NULLS) OVER (PARTITION BY
AGE ORDER BY AGE)</literalText>
<expr>
- <function function-name="LAST_VALUE" text="LAST_VALUE(AGE
IGNORE NULLS) OVER (PARTITION BY AGE ORDER BY AGE)" start-index="7"
stop-index="71" literal-start-index="7" literal-stop-index="71"/>
+ <function function-name="LAST_VALUE" text="LAST_VALUE(AGE
IGNORE NULLS) OVER (PARTITION BY AGE ORDER BY AGE)" start-index="7"
stop-index="71" literal-start-index="7" literal-stop-index="71">
+ <parameter>
+ <column name="AGE" start-index="18"
stop-index="20" literal-start-index="18" literal-stop-index="20" />
+ </parameter>
+ <literalText>LAST_VALUE(AGE IGNORE NULLS) OVER
(PARTITION BY AGE ORDER BY AGE)</literalText>
+ </function>
</expr>
</expression-projection>
</projections>
<from>
- <simple-table name="TEST" start-index="78" stop-index="81"
literal-start-index="78" literal-stop-index="81"/>
+ <simple-table name="TEST" start-index="78" stop-index="81"
literal-start-index="78" literal-stop-index="81" />
</from>
</select>
+
<select sql-case-id="select_with_connect_by_root">
<projections start-index="7" stop-index="41" literal-start-index="7"
literal-stop-index="41">
<column-projection alias="Manager" name="last_name"
start-index="23" stop-index="41" literal-start-index="23"
literal-stop-index="41"/>
@@ -5755,6 +5771,20 @@
<literalText>CORR(SYSDATE - hire_date, salary)</literalText>
<expr>
<function function-name="CORR" text="CORR(SYSDATE -
hire_date, salary)" start-index="20" stop-index="52" literal-start-index="20"
literal-stop-index="52">
+ <parameter>
+ <binary-operation-expression start-index="25"
stop-index="43" literal-start-index="25" literal-stop-index="43">
+ <left>
+ <column name="SYSDATE" start-index="25"
stop-index="31" literal-start-index="25" literal-stop-index="31" />
+ </left>
+ <operator>-</operator>
+ <right>
+ <column name="hire_date" start-index="35"
stop-index="43" literal-start-index="35" literal-stop-index="43" />
+ </right>
+ </binary-operation-expression>
+ </parameter>
+ <parameter>
+ <column name="salary" start-index="46"
stop-index="51" literal-start-index="46" literal-stop-index="51" />
+ </parameter>
<literalText>CORR(SYSDATE - hire_date,
salary)</literalText>
</function>
</expr>
@@ -5794,6 +5824,9 @@
<literalText>TRIM(' derby ')</literalText>
<expr>
<function function-name="TRIM" text="TRIM(' derby ')"
start-index="7" stop-index="22" literal-start-index="7" literal-stop-index="22">
+ <parameter>
+ <literal-expression value=" derby "
start-index="12" stop-index="21" literal-start-index="12"
literal-stop-index="21" />
+ </parameter>
<literalText>TRIM(' derby ')</literalText>
</function>
</expr>
@@ -5802,6 +5835,9 @@
<literalText>TRIM(BOTH ' ' FROM ' derby ')</literalText>
<expr>
<function function-name="TRIM" text="TRIM(BOTH ' ' FROM '
derby ')" start-index="25" stop-index="54" literal-start-index="25"
literal-stop-index="54">
+ <parameter>
+ <literal-expression value=" derby "
start-index="44" stop-index="53" literal-start-index="44"
literal-stop-index="53" />
+ </parameter>
<literalText>TRIM(BOTH ' ' FROM ' derby
')</literalText>
</function>
</expr>
@@ -5810,6 +5846,9 @@
<literalText>TRIM(TRAILING ' ' FROM ' derby ')</literalText>
<expr>
<function function-name="TRIM" text="TRIM(TRAILING ' '
FROM ' derby ')" start-index="57" stop-index="90" literal-start-index="57"
literal-stop-index="90">
+ <parameter>
+ <literal-expression value=" derby "
start-index="80" stop-index="89" literal-start-index="80"
literal-stop-index="89" />
+ </parameter>
<literalText>TRIM(TRAILING ' ' FROM ' derby
')</literalText>
</function>
</expr>
@@ -5818,6 +5857,9 @@
<literalText>TRIM(cast (null as char(1)) FROM ' derby
')</literalText>
<expr>
<function function-name="TRIM" text="TRIM(cast (null as
char(1)) FROM ' derby ')" start-index="93" stop-index="136"
literal-start-index="93" literal-stop-index="136">
+ <parameter>
+ <literal-expression value=" derby "
start-index="126" stop-index="135" literal-start-index="126"
literal-stop-index="135" />
+ </parameter>
<literalText>TRIM(cast (null as char(1)) FROM ' derby
')</literalText>
</function>
</expr>
@@ -5826,6 +5868,17 @@
<literalText>TRIM(' ' FROM cast(null as
varchar(30)))</literalText>
<expr>
<function function-name="TRIM" text="TRIM(' ' FROM
cast(null as varchar(30)))" start-index="139" stop-index="178"
literal-start-index="139" literal-stop-index="178">
+ <parameter>
+ <function function-name="cast" text="cast(null as
varchar(30))" start-index="153" stop-index="177" literal-start-index="153"
literal-stop-index="177">
+ <parameter>
+ <literal-expression value="null"
start-index="158" stop-index="161" literal-start-index="158"
literal-stop-index="161" />
+ </parameter>
+ <parameter>
+ <data-type value="varchar"
start-index="166" stop-index="176" />
+ </parameter>
+ <literalText>cast(null as
varchar(30))</literalText>
+ </function>
+ </parameter>
<literalText>TRIM(' ' FROM cast(null as
varchar(30)))</literalText>
</function>
</expr>
@@ -5834,6 +5887,9 @@
<literalText>TRIM('y' FROM ' derby')</literalText>
<expr>
<function function-name="TRIM" text="TRIM('y' FROM '
derby')" start-index="181" stop-index="203" literal-start-index="181"
literal-stop-index="203">
+ <parameter>
+ <literal-expression value=" derby"
start-index="195" stop-index="202" literal-start-index="195"
literal-stop-index="202" />
+ </parameter>
<literalText>TRIM('y' FROM ' derby')</literalText>
</function>
</expr>