This is an automated email from the ASF dual-hosted git repository.
zhangliang 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 065fe17c51f Refactor `shardingsphere-infra-expr` to expose the use of
Row Value Expressions SPI (#28340)
065fe17c51f is described below
commit 065fe17c51f39614ccba11383fed772f381a2d78
Author: Ling Hengqian <[email protected]>
AuthorDate: Sat Sep 23 21:03:29 2023 +0800
Refactor `shardingsphere-infra-expr` to expose the use of Row Value
Expressions SPI (#28340)
* Refactor `shardingsphere-infra-expr` to expose the use of SPI
* Add doc for Row Value Expressions SPI
---
docs/document/content/dev-manual/sharding.cn.md | 17 +++
docs/document/content/dev-manual/sharding.en.md | 17 +++
docs/document/content/faq/_index.cn.md | 2 +-
docs/document/content/faq/_index.en.md | 3 +-
.../content/features/sharding/concept.cn.md | 7 ++
.../content/features/sharding/concept.en.md | 9 ++
.../common-config/builtin-algorithm/expr.cn.md | 64 ++++++++++
.../common-config/builtin-algorithm/expr.en.md | 66 ++++++++++
.../common-config/builtin-algorithm/sharding.cn.md | 2 +-
.../common-config/builtin-algorithm/sharding.en.md | 3 +-
.../startup/graalvm-native-image.cn.md | 7 +-
.../startup/graalvm-native-image.en.md | 12 +-
...ReadwriteSplittingRuleConfigurationChecker.java | 4 +-
.../rule/ReadwriteSplittingRule.java | 6 +-
.../sharding/hint/HintInlineShardingAlgorithm.java | 4 +-
.../inline/ComplexInlineShardingAlgorithm.java | 4 +-
.../sharding/inline/InlineShardingAlgorithm.java | 4 +-
.../shardingsphere/sharding/rule/ShardingRule.java | 4 +-
.../shardingsphere/sharding/rule/TableRule.java | 4 +-
.../checker/ShardingTableRuleStatementChecker.java | 10 +-
.../sharding/CoreHintShardingAlgorithmFixture.java | 4 +-
infra/expr/core/pom.xml | 7 +-
.../expr/core/InlineExpressionParserFactory.java | 36 +++++-
.../core/InlineExpressionParserFactoryTest.java | 49 +++++---
.../CustomInlineExpressionParserFixture.java | 63 ++++++++++
...ingsphere.infra.expr.spi.InlineExpressionParser | 2 +-
infra/expr/espresso/pom.xml | 12 ++
.../espresso/EspressoInlineExpressionParser.java | 42 +++++--
.../EspressoInlineExpressionParserTest.java | 43 +++++--
infra/expr/{hotsopt => groovy}/pom.xml | 8 +-
.../expr/groovy/GroovyInlineExpressionParser.java} | 54 ++++++--
...ingsphere.infra.expr.spi.InlineExpressionParser | 2 +-
.../groovy/GroovyInlineExpressionParserTest.java | 139 +++++++++++++++++++++
.../hotsopt/HotspotInlineExpressionParserTest.java | 120 ------------------
infra/expr/pom.xml | 4 +-
infra/expr/purelist/pom.xml | 6 +-
.../purelist/PureListInlineExpressionParser.java | 22 ++--
.../PureListInlineExpressionParserTest.java | 28 ++++-
.../infra/expr/spi/InlineExpressionParser.java | 24 ++--
pom.xml | 8 --
.../ShardingRuleConfigurationImportChecker.java | 4 +-
.../test/e2e/cases/dataset/DataSet.java | 2 +-
.../engine/composer/BatchE2EContainerComposer.java | 2 +-
.../test/e2e/engine/type/DDLE2EIT.java | 2 +-
.../test/e2e/engine/type/dml/BaseDMLE2EIT.java | 2 +-
.../test/e2e/env/DataSetEnvironmentManager.java | 2 +-
46 files changed, 679 insertions(+), 257 deletions(-)
diff --git a/docs/document/content/dev-manual/sharding.cn.md
b/docs/document/content/dev-manual/sharding.cn.md
index dfac191b287..e419ccafd2b 100644
--- a/docs/document/content/dev-manual/sharding.cn.md
+++ b/docs/document/content/dev-manual/sharding.cn.md
@@ -79,3 +79,20 @@ chapter = true
|--------------------------|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| DatabaseTimestampService | 从数据库中获取当前时间进行路由 |
[`org.apache.shardingsphere.timeservice.type.database.DatabaseTimestampService`](https://github.com/apache/shardingsphere/blob/master/kernel/time-service/type/database/src/main/java/org/apache/shardingsphere/timeservice/type/database/DatabaseTimestampService.java)
|
| SystemTimestampService | 从应用系统时间中获取当前时间进行路由 |
[`org.apache.shardingsphere.timeservice.type.system.SystemTimestampService`](https://github.com/apache/shardingsphere/blob/master/kernel/time-service/type/system/src/main/java/org/apache/shardingsphere/timeservice/type/system/SystemTimestampService.java)
|
+
+## InlineExpressionParser
+
+### 全限定类名
+
+`org.apache.shardingsphere.infra.expr.core.InlineExpressionParser`
+
+### 定义
+
+解析行表达式
+
+### 已知实现
+
+| *配置标识* | *详细说明* | *全限定类名*
|
+|----------|-------------------|--------------------------------------------------------------------------------|
+| GROOVY | 使用 Groovy 语法的行表达式 |
`org.apache.shardingsphere.infra.expr.groovy.GroovyInlineExpressionParser` |
+| PURELIST | 使用标准列表的行表达式 |
`org.apache.shardingsphere.infra.expr.purelist.PureListInlineExpressionParser` |
diff --git a/docs/document/content/dev-manual/sharding.en.md
b/docs/document/content/dev-manual/sharding.en.md
index aeadbfae502..0463e27c40c 100644
--- a/docs/document/content/dev-manual/sharding.en.md
+++ b/docs/document/content/dev-manual/sharding.en.md
@@ -79,3 +79,20 @@ Obtain the current date for routing definition
|--------------------------|--------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| DatabaseTimestampService | Get the current time from the database for
routing |
[`org.apache.shardingsphere.timeservice.type.database.DatabaseTimestampService`](https://github.com/apache/shardingsphere/blob/master/kernel/time-service/type/database/src/main/java/org/apache/shardingsphere/timeservice/type/database/DatabaseTimestampService.java)
|
| SystemTimestampService | Get the current time from the application system
for routing |
[`org.apache.shardingsphere.timeservice.type.system.SystemTimestampService`](https://github.com/apache/shardingsphere/blob/master/kernel/time-service/type/system/src/main/java/org/apache/shardingsphere/timeservice/type/system/SystemTimestampService.java)
|
+
+## InlineExpressionParser
+
+### Fully-qualified class name
+
+`org.apache.shardingsphere.infra.expr.core.InlineExpressionParser`
+
+### Definition
+
+Row Value Expressions definition
+
+### Implementation classes
+
+| *Configuration Type* | *Description* |
*Fully-qualified class name* |
+|----------------------|---------------------------------------------------|--------------------------------------------------------------------------------|
+| GROOVY | Row Value Expressions that uses the Groovy syntax |
`org.apache.shardingsphere.infra.expr.groovy.GroovyInlineExpressionParser` |
+| PURELIST | Row Value Expressions that uses a standard list |
`org.apache.shardingsphere.infra.expr.purelist.PureListInlineExpressionParser` |
diff --git a/docs/document/content/faq/_index.cn.md
b/docs/document/content/faq/_index.cn.md
index d5e3865a03a..3797a58860e 100644
--- a/docs/document/content/faq/_index.cn.md
+++ b/docs/document/content/faq/_index.cn.md
@@ -122,7 +122,7 @@ DROP DATABASE sharding_db;
回答:
-行表达式标识符可以使用 `${...}` 或 `$->{...}`,但前者与 Spring 本身的属性文件占位符冲突,因此在 Spring
环境中使用行表达式标识符建议使用 `$->{...}`。
+使用 `InlineExpressionParser` SPI 的默认实现的行表达式标识符可以使用 `${...}` 或 `$->{...}`,但前者与
Spring 本身的属性文件占位符冲突,因此在 Spring 环境中使用行表达式标识符建议使用 `$->{...}`。
### [分片] inline 表达式返回结果为何出现浮点数?
diff --git a/docs/document/content/faq/_index.en.md
b/docs/document/content/faq/_index.en.md
index f6e7d01b238..1bcf0ffbbf3 100644
--- a/docs/document/content/faq/_index.en.md
+++ b/docs/document/content/faq/_index.en.md
@@ -130,7 +130,8 @@ Answer:
Answer:
-`${...}` or `$->{...}` can be used in inline expression identifiers, but the
former one clashes with place holders in Spring property files, so `$->{...}`
is recommended to be used in Spring as inline expression identifiers.
+`${...}` or `$->{...}` can be used in inline expression identifiers using the
default implementation of the
+`InlineExpressionParser` SPI, but the former one clashes with place holders in
Spring property files, so `$->{...}` is recommended to be used in Spring as
inline expression identifiers.
### [Sharding] Why does float number appear in the return result of inline
expression?
diff --git a/docs/document/content/features/sharding/concept.cn.md
b/docs/document/content/features/sharding/concept.cn.md
index 66cc22c6a80..194dd2ab7bb 100644
--- a/docs/document/content/features/sharding/concept.cn.md
+++ b/docs/document/content/features/sharding/concept.cn.md
@@ -159,6 +159,13 @@ db0.t_order0, db0.t_order1, db1.t_order2, db1.t_order3,
db1.t_order4
对于常见的分片算法,使用 Java 代码实现并不有助于配置的统一管理。 通过行表达式书写分片算法,可以有效地将规则配置一同存放,更加易于浏览与存储。
+行表达式作为字符串由两部分组成,分别是字符串开头的对应 SPI 实现的 Type Name 部分和表达式部分。 以
`<GROOVY>t_order_${1..3}` 为例,字符
+串`<GROOVY>` 部分的子字符串 `GROOVY` 为此行表达式使用的对应 SPI 实现的 Type Name,其被 `<>`
符号包裹来识别。而字符串 `t_order_${1..3}`
+为此行表达式的表达式部分。当行表达式不指定 Type Name 时,例如 `t_order_${1..3}`,行表示式默认将使用
`InlineExpressionParser` SPI 的
+`GROOVY` 实现来解析表达式。
+
+以下部分介绍 `GROOVY` 实现的语法规则。
+
行表达式的使用非常直观,只需要在配置中使用 `${ expression }` 或 `$->{ expression }` 标识行表达式即可。
目前支持数据节点和分片算法这两个部分的配置。 行表达式的内容使用的是 Groovy 的语法,Groovy 能够支持的所有操作,行表达式均能够支持。 例如:
`${begin..end}` 表示范围区间
diff --git a/docs/document/content/features/sharding/concept.en.md
b/docs/document/content/features/sharding/concept.en.md
index e5da2668f3d..b72ad2219bb 100644
--- a/docs/document/content/features/sharding/concept.en.md
+++ b/docs/document/content/features/sharding/concept.en.md
@@ -159,6 +159,15 @@ Row expressions are designed to address the two main
issues of configuration sim
For the common sharding algorithm, using Java code implementation does not
help to manage the configuration uniformly. But by writing the sharding
algorithm through line expressions, the rule configuration can be effectively
stored together, which is easier to browse and store.
+A Row Value Expressions consists of two parts as a string, the Type Name part
of the corresponding SPI implementation at the beginning of the string and the
expression part.
+
+Take `<GROOVY>t_order_${1..3}` as sample, the `GROOVY` substring in the part
of the `<GROOVY>` string is the Type Name used by the corresponding SPI
implementation for this Row Value Expressions, which is identified by the `<>`
symbol.
+And the `t_order_${1..3}` string is the expression part of this Row Value
Expressions. When a Row Value Expressions does
+not specify a Type Name, such as `t_order_${1..3}`, the Row Value Expressions
defaults to parse expressions by `GROOVY` implementation for
`InlineExpressionParser` SPI.
+
+The following sections describe the syntax rules for the `GROOVY`
implementation.
+
+
Row expressions are very intuitive, just use `${ expression }` or `$->{
expression }` in the configuration to identify the row expressions. Data nodes
and sharding algorithms are currently supported. The content of row expressions
uses Groovy syntax, and all operations supported by Groovy are supported by row
expressions. For example:
`${begin..end}` denotes the range interval
diff --git
a/docs/document/content/user-manual/common-config/builtin-algorithm/expr.cn.md
b/docs/document/content/user-manual/common-config/builtin-algorithm/expr.cn.md
new file mode 100644
index 00000000000..c55718e6b57
--- /dev/null
+++
b/docs/document/content/user-manual/common-config/builtin-algorithm/expr.cn.md
@@ -0,0 +1,64 @@
++++
+title = "行表达式"
+weight = 7
++++
+
+## 使用 Groovy 语法的行表达式
+
+类型:GROOVY
+
+可配置属性:
+
+无
+
+## 使用标准列表的行表达式
+
+类型:PURELIST
+
+可配置属性:
+
+无
+
+## 操作步骤
+
+使用需要使用 `行表达式` 的属性时, 如在 `数据分片` 功能中, 在 `actualDataNodes` 属性下指明特定的 SPI 实现的 Type
Name 即可。
+
+若 `行表达式` 不指明 SPI 的 Type Name,默认将使用 `GROOVY` 的 SPI 实现。
+
+## 配置示例
+
+```yaml
+rules:
+- !SHARDING
+ tables:
+ t_order:
+ actualDataNodes: <PURELIST>ds_0.t_order_0, ds_0.t_order_1,
ds_1.t_order_0, ds_1.t_order_1
+ tableStrategy:
+ standard:
+ shardingColumn: order_id
+ shardingAlgorithmName: t_order_inline
+ keyGenerateStrategy:
+ column: order_id
+ keyGeneratorName: snowflake
+ defaultDatabaseStrategy:
+ standard:
+ shardingColumn: user_id
+ shardingAlgorithmName: database_inline
+ shardingAlgorithms:
+ database_inline:
+ type: INLINE
+ props:
+ algorithm-expression: <GROOVY>ds_${user_id % 2}
+ t_order_inline:
+ type: INLINE
+ props:
+ algorithm-expression: <GROOVY>t_order_${order_id % 2}
+ keyGenerators:
+ snowflake:
+ type: SNOWFLAKE
+```
+
+## 相关参考
+
+- [核心概念](/docs/document/content/features/sharding/concept.cn.md)
+- [数据分片](/docs/document/content/dev-manual/sharding.cn.md)
diff --git
a/docs/document/content/user-manual/common-config/builtin-algorithm/expr.en.md
b/docs/document/content/user-manual/common-config/builtin-algorithm/expr.en.md
new file mode 100644
index 00000000000..216ce754d39
--- /dev/null
+++
b/docs/document/content/user-manual/common-config/builtin-algorithm/expr.en.md
@@ -0,0 +1,66 @@
++++
+title = "Row Value Expressions"
+weight = 7
++++
+
+## Row Value Expressions that uses the Groovy syntax
+
+Type: GROOVY
+
+Attributes:
+
+None
+
+## Row Value Expressions that uses a standard list
+
+Type: PURELIST
+
+Attributes:
+
+None
+
+## Procedure
+
+When using attributes that require the use of `Row Value Expressions`, such as
in the `data sharding` feature, it is
+sufficient to indicate the Type Name of the specific SPI implementation under
the `actualDataNodes` attribute.
+
+If the `Row Value Expressions` does not indicate the Type Name of the SPI, the
SPI implementation of `GROOVY` will be
+used by default.
+
+## Sample
+
+```yaml
+rules:
+- !SHARDING
+ tables:
+ t_order:
+ actualDataNodes: <PURELIST>ds_0.t_order_0, ds_0.t_order_1,
ds_1.t_order_0, ds_1.t_order_1
+ tableStrategy:
+ standard:
+ shardingColumn: order_id
+ shardingAlgorithmName: t_order_inline
+ keyGenerateStrategy:
+ column: order_id
+ keyGeneratorName: snowflake
+ defaultDatabaseStrategy:
+ standard:
+ shardingColumn: user_id
+ shardingAlgorithmName: database_inline
+ shardingAlgorithms:
+ database_inline:
+ type: INLINE
+ props:
+ algorithm-expression: <GROOVY>ds_${user_id % 2}
+ t_order_inline:
+ type: INLINE
+ props:
+ algorithm-expression: <GROOVY>t_order_${order_id % 2}
+ keyGenerators:
+ snowflake:
+ type: SNOWFLAKE
+```
+
+## Related References
+
+- [Core Concept](/docs/document/content/features/sharding/concept.en.md)
+- [Data Sharding](/docs/document/content/dev-manual/sharding.en.md)
diff --git
a/docs/document/content/user-manual/common-config/builtin-algorithm/sharding.cn.md
b/docs/document/content/user-manual/common-config/builtin-algorithm/sharding.cn.md
index ba4a751c8ad..0cd29976d13 100644
---
a/docs/document/content/user-manual/common-config/builtin-algorithm/sharding.cn.md
+++
b/docs/document/content/user-manual/common-config/builtin-algorithm/sharding.cn.md
@@ -73,7 +73,7 @@ Apache ShardingSphere 内置的标准分片算法实现类包括:
#### 行表达式分片算法
-使用 Groovy 的表达式,提供对 SQL 语句中的 `=` 和 `IN` 的分片操作支持,只支持单分片键。
+使用 `InlineExpressionParser` SPI 的默认实现的 Groovy 的表达式,提供对 SQL 语句中的 `=` 和 `IN`
的分片操作支持,只支持单分片键。
对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的 Java 代码开发,如: `t_user_$->{u_id % 8}` 表示 `t_user`
表根据 `u_id` 模 8,而分成 8 张表,表名称为 `t_user_0` 到 `t_user_7`。
详情请参见[行表达式](/cn/dev-manual/sharding/#implementation-classes)。
diff --git
a/docs/document/content/user-manual/common-config/builtin-algorithm/sharding.en.md
b/docs/document/content/user-manual/common-config/builtin-algorithm/sharding.en.md
index 7ba7d66d793..4c1e7bae245 100644
---
a/docs/document/content/user-manual/common-config/builtin-algorithm/sharding.en.md
+++
b/docs/document/content/user-manual/common-config/builtin-algorithm/sharding.en.md
@@ -75,7 +75,8 @@ Apache ShardingSphere built-in standard sharding algorithm
are:
#### Inline Sharding Algorithm
-With Groovy expressions, `InlineShardingStrategy` provides single-key support
for the sharding operation of `=` and `IN` in SQL.
+With Groovy expressions that uses the default implementation of the
`InlineExpressionParser` SPI,
+`InlineShardingStrategy` provides single-key support for the sharding
operation of `=` and `IN` in SQL.
Simple sharding algorithms can be used through a simple configuration to avoid
laborious Java code developments.
For example, `t_user_$->{u_id % 8}` means table t_user is divided into 8
tables according to u_id, with table names from `t_user_0` to `t_user_7`.
Please refer to [Inline
Expression](/en/dev-manual/sharding/#implementation-classes) for more details.
diff --git
a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md
b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md
index 973e550be69..501f9f99d00 100644
---
a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md
+++
b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md
@@ -37,9 +37,10 @@ services:
-
`org.apache.shardingsphere.sharding.algorithm.sharding.inline.ComplexInlineShardingAlgorithm`
-
`org.apache.shardingsphere.sharding.algorithm.sharding.hint.HintInlineShardingAlgorithm`
-- 当前阶段,GraalVM Native Image 形态的 ShardingSphere Proxy 不支持使用带 Groovy
- 语法的 `行表达式`, 这首先导致 `数据分片` 功能的`actualDataNodes`属性只能使用纯列表来配置, 例如
`ds_0.t_order_0, ds_0.t_order_1`
- 或 `ds_0.t_user_0, ds_15.t_user_1023`。此问题在
https://github.com/oracle/graal/issues/5522 追踪。
+- 当前阶段,GraalVM Native Image 形态的 ShardingSphere Proxy 不支持使用
`InlineExpressionParser` SPI 的默认实现的 `行表达式`,
+ 这首先导致 `数据分片` 功能的`actualDataNodes` 属性只能使用其他 `InlineExpressionParser` SPI
的实现来配置, 例如使用
+ `InlineExpressionParser` SPI 实现为 `PURELIST` 的 `行表达式`, 即
`<PURELIST>ds_0.t_order_0, ds_0.t_order_1`
+ 或 `<PURELIST>ds_0.t_user_0, ds_15.t_user_1023`。
- 本节假定处于 Linux(amd64,aarch64), MacOS(amd64)或 Windows(amd64)环境。
如果你位于 MacOS(aarch64/M1) 环境,你需要关注尚未关闭的
https://github.com/oracle/graal/issues/2666 。
diff --git
a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md
b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md
index 993d9dcd482..fe0d38acfa8 100644
---
a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md
+++
b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md
@@ -42,16 +42,18 @@ services:
-
`org.apache.shardingsphere.sharding.algorithm.sharding.inline.ComplexInlineShardingAlgorithm`
-
`org.apache.shardingsphere.sharding.algorithm.sharding.hint.HintInlineShardingAlgorithm`
-- At this stage, ShardingSphere Proxy in the form of GraalVM Native Image does
not support the use
- of `Row Value Expressions` with Groovy syntax, which first results in the
`actualDataNodes` property of the `Sharding`
- feature being only configurable using a pure list, such as `ds_0.t_order_0,
ds_0.t_order_1`
- or `ds_0.t_user_0, ds_15.t_user_1023`. This issue is tracked in
https://github.com/oracle/graal/issues/5522 .
+- At this stage, ShardingSphere Proxy in the form of GraalVM Native Image does
not support `row expressions` using the
+ default implementation of the `InlineExpressionParser` SPI.
+ This first results in the `actualDataNodes` property of the `data sharding`
feature that can only be configured using
+ other implementations of the `InlineExpressionParser` SPI, for example using
`PURELIST` implemented
+ `InlineExpressionParser` SPI for `row expression`, i.e.
`<PURELIST>ds_0.t_order_0, ds_0.t_order_1`
+ or `<PURELIST>ds_0.t_user_0, ds_15.t_user_1023`.
- This section assumes a Linux (amd64, aarch64), MacOS (amd64) or Windows
(amd64) environment.
If you are on MacOS (aarch64/M1) environment, you need to follow
https://github.com/oracle/graal/issues/2666 which is
not closed yet.
-- 'org.apache.shardingsphere:shardingsphere-cluster-mode-repository-etcd' is
affected by
+- `org.apache.shardingsphere:shardingsphere-cluster-mode-repository-etcd` is
affected by
https://github.com/micronaut-projects/micronaut-gcp/issues/532 and cannot be
used.
## Premise
diff --git
a/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/checker/ReadwriteSplittingRuleConfigurationChecker.java
b/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/checker/ReadwriteSplittingRuleConfigurationChecker.java
index ed9fb2a2a9b..984a472bb09 100644
---
a/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/checker/ReadwriteSplittingRuleConfigurationChecker.java
+++
b/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/checker/ReadwriteSplittingRuleConfigurationChecker.java
@@ -79,7 +79,7 @@ public final class ReadwriteSplittingRuleConfigurationChecker
implements RuleCon
private void checkWriteDataSourceNames(final String databaseName, final
Map<String, DataSource> dataSourceMap, final Collection<String>
addedWriteDataSourceNames,
final
ReadwriteSplittingDataSourceRuleConfiguration config, final
Collection<ShardingSphereRule> rules) {
- for (String each :
InlineExpressionParserFactory.newInstance().splitAndEvaluate(config.getWriteDataSourceName()))
{
+ for (String each :
InlineExpressionParserFactory.newInstance(config.getWriteDataSourceName()).splitAndEvaluate())
{
ShardingSpherePreconditions.checkState(dataSourceMap.containsKey(each) ||
containsInOtherRules(each, rules),
() -> new
DataSourceNameExistedException(String.format("Write data source name `%s` not
in database `%s`.", each, databaseName)));
ShardingSpherePreconditions.checkState(addedWriteDataSourceNames.add(each),
@@ -97,7 +97,7 @@ public final class ReadwriteSplittingRuleConfigurationChecker
implements RuleCon
}
private void checkReadeDataSourceNames(final String databaseName, final
Map<String, DataSource> dataSourceMap, final Collection<String>
addedReadDataSourceNames, final String readDataSourceName) {
- for (String each :
InlineExpressionParserFactory.newInstance().splitAndEvaluate(readDataSourceName))
{
+ for (String each :
InlineExpressionParserFactory.newInstance(readDataSourceName).splitAndEvaluate())
{
ShardingSpherePreconditions.checkState(dataSourceMap.containsKey(each),
() -> new
DataSourceNameExistedException(String.format("Read data source name `%s` not in
database `%s`.", each, databaseName)));
ShardingSpherePreconditions.checkState(addedReadDataSourceNames.add(each),
diff --git
a/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/rule/ReadwriteSplittingRule.java
b/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/rule/ReadwriteSplittingRule.java
index db9bad0d737..68ec5cb4267 100644
---
a/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/rule/ReadwriteSplittingRule.java
+++
b/features/readwrite-splitting/core/src/main/java/org/apache/shardingsphere/readwritesplitting/rule/ReadwriteSplittingRule.java
@@ -103,10 +103,10 @@ public final class ReadwriteSplittingRule implements
DatabaseRule, DataSourceCon
private Map<String, ReadwriteSplittingDataSourceRule>
createStaticDataSourceRules(final ReadwriteSplittingDataSourceRuleConfiguration
config,
final ReadQueryLoadBalanceAlgorithm loadBalanceAlgorithm) {
- List<String> inlineReadwriteDataSourceNames =
InlineExpressionParserFactory.newInstance().splitAndEvaluate(config.getName());
- List<String> inlineWriteDatasourceNames =
InlineExpressionParserFactory.newInstance().splitAndEvaluate(config.getWriteDataSourceName());
+ List<String> inlineReadwriteDataSourceNames =
InlineExpressionParserFactory.newInstance(config.getName()).splitAndEvaluate();
+ List<String> inlineWriteDatasourceNames =
InlineExpressionParserFactory.newInstance(config.getWriteDataSourceName()).splitAndEvaluate();
List<List<String>> inlineReadDatasourceNames =
config.getReadDataSourceNames().stream()
- .map(each ->
InlineExpressionParserFactory.newInstance().splitAndEvaluate(each)).collect(Collectors.toList());
+ .map(each ->
InlineExpressionParserFactory.newInstance(each).splitAndEvaluate()).collect(Collectors.toList());
ShardingSpherePreconditions.checkState(inlineWriteDatasourceNames.size() ==
inlineReadwriteDataSourceNames.size(),
() -> new
InvalidInlineExpressionDataSourceNameException("Inline expression write data
source names size error."));
inlineReadDatasourceNames.forEach(each ->
ShardingSpherePreconditions.checkState(each.size() ==
inlineReadwriteDataSourceNames.size(),
diff --git
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/hint/HintInlineShardingAlgorithm.java
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/hint/HintInlineShardingAlgorithm.java
index 1d0ba06f067..1f52b6980fa 100644
---
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/hint/HintInlineShardingAlgorithm.java
+++
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/hint/HintInlineShardingAlgorithm.java
@@ -51,7 +51,7 @@ public final class HintInlineShardingAlgorithm implements
HintShardingAlgorithm<
private String getAlgorithmExpression(final Properties props) {
String algorithmExpression =
props.getProperty(ALGORITHM_EXPRESSION_KEY, DEFAULT_ALGORITHM_EXPRESSION);
ShardingSpherePreconditions.checkNotNull(algorithmExpression, () ->
new ShardingAlgorithmInitializationException(getType(), "Inline sharding
algorithm expression can not be null."));
- return
InlineExpressionParserFactory.newInstance().handlePlaceHolder(algorithmExpression.trim());
+ return
InlineExpressionParserFactory.newInstance(algorithmExpression.trim()).handlePlaceHolder();
}
@Override
@@ -67,7 +67,7 @@ public final class HintInlineShardingAlgorithm implements
HintShardingAlgorithm<
}
private Closure<?> createClosure() {
- Closure<?> result =
InlineExpressionParserFactory.newInstance().evaluateClosure(algorithmExpression).rehydrate(new
Expando(), null, null);
+ Closure<?> result =
InlineExpressionParserFactory.newInstance(algorithmExpression).evaluateClosure().rehydrate(new
Expando(), null, null);
result.setResolveStrategy(Closure.DELEGATE_ONLY);
return result;
}
diff --git
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/inline/ComplexInlineShardingAlgorithm.java
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/inline/ComplexInlineShardingAlgorithm.java
index e9d81087cc6..22042132704 100644
---
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/inline/ComplexInlineShardingAlgorithm.java
+++
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/inline/ComplexInlineShardingAlgorithm.java
@@ -67,7 +67,7 @@ public final class ComplexInlineShardingAlgorithm implements
ComplexKeysSharding
String algorithmExpression =
props.getProperty(ALGORITHM_EXPRESSION_KEY);
ShardingSpherePreconditions.checkState(!Strings.isNullOrEmpty(algorithmExpression),
() -> new ShardingAlgorithmInitializationException(getType(),
"Inline sharding algorithm expression can not be null."));
- return
InlineExpressionParserFactory.newInstance().handlePlaceHolder(algorithmExpression.trim());
+ return
InlineExpressionParserFactory.newInstance(algorithmExpression.trim()).handlePlaceHolder();
}
private Collection<String> getShardingColumns(final Properties props) {
@@ -132,7 +132,7 @@ public final class ComplexInlineShardingAlgorithm
implements ComplexKeysSharding
}
private Closure<?> createClosure() {
- Closure<?> result =
InlineExpressionParserFactory.newInstance().evaluateClosure(algorithmExpression).rehydrate(new
Expando(), null, null);
+ Closure<?> result =
InlineExpressionParserFactory.newInstance(algorithmExpression).evaluateClosure().rehydrate(new
Expando(), null, null);
result.setResolveStrategy(Closure.DELEGATE_ONLY);
return result;
}
diff --git
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/inline/InlineShardingAlgorithm.java
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/inline/InlineShardingAlgorithm.java
index 593b1a02663..84c1ba83c87 100644
---
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/inline/InlineShardingAlgorithm.java
+++
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/inline/InlineShardingAlgorithm.java
@@ -58,7 +58,7 @@ public final class InlineShardingAlgorithm implements
StandardShardingAlgorithm<
String expression = props.getProperty(ALGORITHM_EXPRESSION_KEY);
ShardingSpherePreconditions.checkState(!Strings.isNullOrEmpty(expression),
() -> new ShardingAlgorithmInitializationException(getType(),
"Inline sharding algorithm expression cannot be null or empty"));
- return
InlineExpressionParserFactory.newInstance().handlePlaceHolder(expression.trim());
+ return
InlineExpressionParserFactory.newInstance(expression.trim()).handlePlaceHolder();
}
private boolean isAllowRangeQuery(final Properties props) {
@@ -83,7 +83,7 @@ public final class InlineShardingAlgorithm implements
StandardShardingAlgorithm<
}
private Closure<?> createClosure() {
- Closure<?> result =
InlineExpressionParserFactory.newInstance().evaluateClosure(algorithmExpression).rehydrate(new
Expando(), null, null);
+ Closure<?> result =
InlineExpressionParserFactory.newInstance(algorithmExpression).evaluateClosure().rehydrate(new
Expando(), null, null);
result.setResolveStrategy(Closure.DELEGATE_ONLY);
return result;
}
diff --git
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/rule/ShardingRule.java
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/rule/ShardingRule.java
index 17d9d126e79..cd35c79d082 100644
---
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/rule/ShardingRule.java
+++
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/rule/ShardingRule.java
@@ -197,12 +197,12 @@ public final class ShardingRule implements DatabaseRule,
DataNodeContainedRule,
}
private Collection<String> getDataSourceNames(final
ShardingAutoTableRuleConfiguration shardingAutoTableRuleConfig) {
- List<String> actualDataSources =
InlineExpressionParserFactory.newInstance().splitAndEvaluate(shardingAutoTableRuleConfig.getActualDataSources());
+ List<String> actualDataSources =
InlineExpressionParserFactory.newInstance(shardingAutoTableRuleConfig.getActualDataSources()).splitAndEvaluate();
return new HashSet<>(actualDataSources);
}
private Collection<String> getDataSourceNames(final
ShardingTableRuleConfiguration shardingTableRuleConfig) {
- List<String> actualDataNodes =
InlineExpressionParserFactory.newInstance().splitAndEvaluate(shardingTableRuleConfig.getActualDataNodes());
+ List<String> actualDataNodes =
InlineExpressionParserFactory.newInstance(shardingTableRuleConfig.getActualDataNodes()).splitAndEvaluate();
return actualDataNodes.stream().map(each -> new
DataNode(each).getDataSourceName()).collect(Collectors.toList());
}
diff --git
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/rule/TableRule.java
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/rule/TableRule.java
index ea7c5af15c8..429ad42d83e 100644
---
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/rule/TableRule.java
+++
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/rule/TableRule.java
@@ -106,7 +106,7 @@ public final class TableRule {
public TableRule(final ShardingTableRuleConfiguration tableRuleConfig,
final Collection<String> dataSourceNames, final String
defaultGenerateKeyColumn) {
logicTable = tableRuleConfig.getLogicTable();
- List<String> dataNodes =
InlineExpressionParserFactory.newInstance().splitAndEvaluate(tableRuleConfig.getActualDataNodes());
+ List<String> dataNodes =
InlineExpressionParserFactory.newInstance(tableRuleConfig.getActualDataNodes()).splitAndEvaluate();
dataNodeIndexMap = new HashMap<>(dataNodes.size(), 1F);
actualDataNodes = isEmptyDataNodes(dataNodes) ?
generateDataNodes(tableRuleConfig.getLogicTable(), dataSourceNames) :
generateDataNodes(dataNodes, dataSourceNames);
actualTables = getActualTables();
@@ -158,7 +158,7 @@ public final class TableRule {
return new LinkedList<>();
}
List<String> dataSources =
Strings.isNullOrEmpty(tableRuleConfig.getActualDataSources()) ? new
LinkedList<>(dataSourceNames)
- :
InlineExpressionParserFactory.newInstance().splitAndEvaluate(tableRuleConfig.getActualDataSources());
+ :
InlineExpressionParserFactory.newInstance(tableRuleConfig.getActualDataSources()).splitAndEvaluate();
return
DataNodeUtils.getFormatDataNodes(shardingAlgorithm.getAutoTablesAmount(),
logicTable, dataSources);
}
diff --git
a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/checker/ShardingTableRuleStatementChecker.java
b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/checker/ShardingTableRuleStatementChecker.java
index cfefac1e9c4..70abf9cdee3 100644
---
a/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/checker/ShardingTableRuleStatementChecker.java
+++
b/features/sharding/distsql/handler/src/main/java/org/apache/shardingsphere/sharding/distsql/handler/checker/ShardingTableRuleStatementChecker.java
@@ -179,13 +179,13 @@ public final class ShardingTableRuleStatementChecker {
}
Collection<String> result = new LinkedHashSet<>();
tableRuleConfigs.forEach(each ->
result.addAll(getDataSourceNames(each)));
- autoTableRuleConfigs.forEach(each ->
result.addAll(InlineExpressionParserFactory.newInstance().splitAndEvaluate(each.getActualDataSources())));
+ autoTableRuleConfigs.forEach(each ->
result.addAll(InlineExpressionParserFactory.newInstance(each.getActualDataSources()).splitAndEvaluate()));
return result;
}
private static Collection<String> getDataSourceNames(final
ShardingTableRuleConfiguration shardingTableRuleConfig) {
- return InlineExpressionParserFactory.newInstance()
-
.splitAndEvaluate(shardingTableRuleConfig.getActualDataNodes()).stream().map(each
-> new DataNode(each).getDataSourceName()).collect(Collectors.toList());
+ return
InlineExpressionParserFactory.newInstance(shardingTableRuleConfig.getActualDataNodes())
+ .splitAndEvaluate().stream().map(each -> new
DataNode(each).getDataSourceName()).collect(Collectors.toList());
}
private static Collection<String> getDataSourceNames(final
Collection<String> actualDataNodes) {
@@ -316,7 +316,7 @@ public final class ShardingTableRuleStatementChecker {
Collection<String> result = new LinkedHashSet<>();
result.addAll(config.getAutoTables().stream().map(ShardingAutoTableRuleConfiguration::getActualDataSources)
.map(each ->
Splitter.on(",").trimResults().splitToList(each)).flatMap(Collection::stream).collect(Collectors.toSet()));
- result.addAll(config.getTables().stream().map(each ->
InlineExpressionParserFactory.newInstance().splitAndEvaluate(each.getActualDataNodes()))
+ result.addAll(config.getTables().stream().map(each ->
InlineExpressionParserFactory.newInstance(each.getActualDataNodes()).splitAndEvaluate())
.flatMap(Collection::stream).distinct().map(each -> new
DataNode(each).getDataSourceName()).collect(Collectors.toSet()));
return result;
}
@@ -327,7 +327,7 @@ public final class ShardingTableRuleStatementChecker {
}
private static Collection<String> parseDateSource(final String dateSource)
{
- return
InlineExpressionParserFactory.newInstance().splitAndEvaluate(dateSource);
+ return
InlineExpressionParserFactory.newInstance(dateSource).splitAndEvaluate();
}
private static Collection<String> getLogicDataSources(final
ShardingSphereDatabase database) {
diff --git
a/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/fixture/sharding/CoreHintShardingAlgorithmFixture.java
b/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/fixture/sharding/CoreHintShardingAlgorithmFixture.java
index 40c8865786d..671a4b1d946 100644
---
a/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/fixture/sharding/CoreHintShardingAlgorithmFixture.java
+++
b/features/sharding/distsql/handler/src/test/java/org/apache/shardingsphere/sharding/distsql/fixture/sharding/CoreHintShardingAlgorithmFixture.java
@@ -46,7 +46,7 @@ public final class CoreHintShardingAlgorithmFixture
implements HintShardingAlgor
private String getAlgorithmExpression(final Properties props) {
String algorithmExpression =
props.getProperty(ALGORITHM_EXPRESSION_KEY, DEFAULT_ALGORITHM_EXPRESSION);
Preconditions.checkNotNull(algorithmExpression, "Inline sharding
algorithm expression can not be null.");
- return
InlineExpressionParserFactory.newInstance().handlePlaceHolder(algorithmExpression.trim());
+ return
InlineExpressionParserFactory.newInstance(algorithmExpression.trim()).handlePlaceHolder();
}
@Override
@@ -61,7 +61,7 @@ public final class CoreHintShardingAlgorithmFixture
implements HintShardingAlgor
}
private Closure<?> createClosure() {
- Closure<?> result =
InlineExpressionParserFactory.newInstance().evaluateClosure(algorithmExpression).rehydrate(new
Expando(), null, null);
+ Closure<?> result =
InlineExpressionParserFactory.newInstance(algorithmExpression).evaluateClosure().rehydrate(new
Expando(), null, null);
result.setResolveStrategy(Closure.DELEGATE_ONLY);
return result;
}
diff --git a/infra/expr/core/pom.xml b/infra/expr/core/pom.xml
index 84f274b57cf..a5fafdeba9e 100644
--- a/infra/expr/core/pom.xml
+++ b/infra/expr/core/pom.xml
@@ -34,7 +34,7 @@
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
- <artifactId>shardingsphere-infra-expr-hotsopt</artifactId>
+ <artifactId>shardingsphere-infra-expr-groovy</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
@@ -49,10 +49,5 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
-
- <dependency>
- <groupId>org.apache.groovy</groupId>
- <artifactId>groovy</artifactId>
- </dependency>
</dependencies>
</project>
diff --git
a/infra/expr/core/src/main/java/org/apache/shardingsphere/infra/expr/core/InlineExpressionParserFactory.java
b/infra/expr/core/src/main/java/org/apache/shardingsphere/infra/expr/core/InlineExpressionParserFactory.java
index 11a03cd4948..97dd60b3c76 100644
---
a/infra/expr/core/src/main/java/org/apache/shardingsphere/infra/expr/core/InlineExpressionParserFactory.java
+++
b/infra/expr/core/src/main/java/org/apache/shardingsphere/infra/expr/core/InlineExpressionParserFactory.java
@@ -22,21 +22,45 @@ import lombok.NoArgsConstructor;
import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import java.util.Properties;
+
/**
* Inline expression parser factory.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class InlineExpressionParserFactory {
- // workaround for
https://junit.org/junit5/docs/5.10.0/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/EnabledInNativeImage.html
- private static final boolean IS_SUBSTRATE_VM =
"runtime".equals(System.getProperty("org.graalvm.nativeimage.imagecode"));
+ private static final String TYPE_NAME_BEGIN_SYMBOL = "<";
+
+ private static final String TYPE_NAME_END_SYMBOL = ">";
/**
- * Create new instance of inline expression parser.
- *
+ * Create new instance of inline expression parser by inlineExpression.
+ * And for compatibility reasons, inlineExpression allows to be null.
+ *
+ * @param inlineExpression inline expression
* @return created instance
*/
- public static InlineExpressionParser newInstance() {
- return TypedSPILoader.getService(InlineExpressionParser.class,
IS_SUBSTRATE_VM ? "PURELIST" : "HOTSPOT");
+ public static InlineExpressionParser newInstance(final String
inlineExpression) {
+ Properties props = new Properties();
+ if (null == inlineExpression) {
+ return TypedSPILoader.getService(InlineExpressionParser.class,
"GROOVY", props);
+ }
+ if (!inlineExpression.startsWith(TYPE_NAME_BEGIN_SYMBOL)) {
+ props.setProperty(InlineExpressionParser.INLINE_EXPRESSION_KEY,
inlineExpression);
+ return TypedSPILoader.getService(InlineExpressionParser.class,
"GROOVY", props);
+ }
+ Integer typeBeginIndex =
inlineExpression.indexOf(TYPE_NAME_BEGIN_SYMBOL);
+ Integer typeEndIndex = inlineExpression.indexOf(TYPE_NAME_END_SYMBOL);
+ props.setProperty(InlineExpressionParser.INLINE_EXPRESSION_KEY,
removeTypeNameInExpr(inlineExpression, typeBeginIndex, typeEndIndex));
+ return TypedSPILoader.getService(InlineExpressionParser.class,
getTypeName(inlineExpression, typeBeginIndex, typeEndIndex), props);
+ }
+
+ private static String getTypeName(final String inlineExpression, final
Integer beginIndex, final Integer endIndex) {
+ return beginIndex.equals(-1) || endIndex.equals(-1) ? "GROOVY" :
inlineExpression.substring(beginIndex + 1, endIndex);
+ }
+
+ private static String removeTypeNameInExpr(final String inlineExpression,
final Integer beginIndex, final Integer endIndex) {
+ return inlineExpression.substring(0, beginIndex) +
inlineExpression.substring(endIndex + 1);
}
}
diff --git
a/infra/expr/core/src/test/java/org/apache/shardingsphere/infra/expr/core/InlineExpressionParserFactoryTest.java
b/infra/expr/core/src/test/java/org/apache/shardingsphere/infra/expr/core/InlineExpressionParserFactoryTest.java
index 931e47f3150..4ade13127fe 100644
---
a/infra/expr/core/src/test/java/org/apache/shardingsphere/infra/expr/core/InlineExpressionParserFactoryTest.java
+++
b/infra/expr/core/src/test/java/org/apache/shardingsphere/infra/expr/core/InlineExpressionParserFactoryTest.java
@@ -17,34 +17,49 @@
package org.apache.shardingsphere.infra.expr.core;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
+import
org.apache.shardingsphere.infra.spi.exception.ServiceProviderNotFoundException;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledInNativeImage;
+
+import java.util.Arrays;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
class InlineExpressionParserFactoryTest {
- private String originalImageCode;
-
- @BeforeEach
- public void setUp() {
- originalImageCode =
System.getProperty("org.graalvm.nativeimage.imagecode");
+ @Test
+ @DisabledInNativeImage
+ void assertNewInstance() {
+ assertThat(InlineExpressionParserFactory.newInstance("t_order_0,
t_order_1").getType(), is("GROOVY"));
+ assertThat(InlineExpressionParserFactory.newInstance("t_order_0,
t_order_1").handlePlaceHolder(), is("t_order_0, t_order_1"));
+
assertThat(InlineExpressionParserFactory.newInstance("<GROOVY>t_order_0,
t_order_1").getType(), is("GROOVY"));
+
assertThat(InlineExpressionParserFactory.newInstance("<GROOVY>t_order_0,
t_order_1").handlePlaceHolder(), is("t_order_0, t_order_1"));
+
assertThat(InlineExpressionParserFactory.newInstance("<PURELIST>t_order_0,
t_order_1").getType(), is("PURELIST"));
+
assertThat(InlineExpressionParserFactory.newInstance("<PURELIST>t_order_0,
t_order_1").handlePlaceHolder(), is("t_order_0, t_order_1"));
}
- @AfterEach
- public void tearDown() {
- if (null != originalImageCode) {
- System.setProperty("org.graalvm.nativeimage.imagecode",
originalImageCode);
- } else {
- System.clearProperty("org.graalvm.nativeimage.imagecode");
- }
+ @Test
+ void assertUndefinedInstance() {
+ assertThrows(ServiceProviderNotFoundException.class,
+ () ->
InlineExpressionParserFactory.newInstance("<UNDEFINED>t_order_0,
t_order_1").getType());
}
@Test
- void assertNewInstance() {
- System.setProperty("org.graalvm.nativeimage.imagecode", "");
- assertThat(InlineExpressionParserFactory.newInstance().getType(),
is("HOTSPOT"));
+ void assertFixtureInstance() {
+
assertThat(InlineExpressionParserFactory.newInstance("<CUSTOM.FIXTURE>spring").splitAndEvaluate(),
+ is(Arrays.asList("t_order_2023_03", "t_order_2023_04",
"t_order_2023_05")));
+
assertThat(InlineExpressionParserFactory.newInstance("<CUSTOM.FIXTURE>summer").splitAndEvaluate(),
+ is(Arrays.asList("t_order_2023_06", "t_order_2023_07",
"t_order_2023_08")));
+
assertThat(InlineExpressionParserFactory.newInstance("<CUSTOM.FIXTURE>autumn").splitAndEvaluate(),
+ is(Arrays.asList("t_order_2023_09", "t_order_2023_10",
"t_order_2023_11")));
+
assertThat(InlineExpressionParserFactory.newInstance("<CUSTOM.FIXTURE>winter").splitAndEvaluate(),
+ is(Arrays.asList("t_order_2023_12", "t_order_2024_01",
"t_order_2024_02")));
+
assertThat(InlineExpressionParserFactory.newInstance("<CUSTOM.FIXTURE>").splitAndEvaluate(),
+ is(Arrays.asList("t_order_2023_03", "t_order_2023_04",
"t_order_2023_05",
+ "t_order_2023_06", "t_order_2023_07",
"t_order_2023_08",
+ "t_order_2023_09", "t_order_2023_10",
"t_order_2023_11",
+ "t_order_2023_12", "t_order_2024_01",
"t_order_2024_02")));
}
}
diff --git
a/infra/expr/core/src/test/java/org/apache/shardingsphere/infra/expr/core/fixture/CustomInlineExpressionParserFixture.java
b/infra/expr/core/src/test/java/org/apache/shardingsphere/infra/expr/core/fixture/CustomInlineExpressionParserFixture.java
new file mode 100644
index 00000000000..3f0f8d5a59d
--- /dev/null
+++
b/infra/expr/core/src/test/java/org/apache/shardingsphere/infra/expr/core/fixture/CustomInlineExpressionParserFixture.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.infra.expr.core.fixture;
+
+import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+public final class CustomInlineExpressionParserFixture implements
InlineExpressionParser {
+
+ private String inlineExpression;
+
+ @Override
+ public void init(final Properties props) {
+ this.inlineExpression = props.getProperty(INLINE_EXPRESSION_KEY);
+ }
+
+ @Override
+ public String handlePlaceHolder() {
+ return inlineExpression;
+ }
+
+ @Override
+ public List<String> splitAndEvaluate() {
+ switch (inlineExpression) {
+ case "spring":
+ return Arrays.asList("t_order_2023_03", "t_order_2023_04",
"t_order_2023_05");
+ case "summer":
+ return Arrays.asList("t_order_2023_06", "t_order_2023_07",
"t_order_2023_08");
+ case "autumn":
+ return Arrays.asList("t_order_2023_09", "t_order_2023_10",
"t_order_2023_11");
+ case "winter":
+ return Arrays.asList("t_order_2023_12", "t_order_2024_01",
"t_order_2024_02");
+ default:
+ return Arrays.asList("t_order_2023_03", "t_order_2023_04",
"t_order_2023_05",
+ "t_order_2023_06", "t_order_2023_07",
"t_order_2023_08",
+ "t_order_2023_09", "t_order_2023_10",
"t_order_2023_11",
+ "t_order_2023_12", "t_order_2024_01",
"t_order_2024_02");
+ }
+ }
+
+ @Override
+ public Object getType() {
+ return "CUSTOM.FIXTURE";
+ }
+}
diff --git
a/infra/expr/hotsopt/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
b/infra/expr/core/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
similarity index 90%
copy from
infra/expr/hotsopt/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
copy to
infra/expr/core/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
index 48cf905c9a5..2af948cb146 100644
---
a/infra/expr/hotsopt/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
+++
b/infra/expr/core/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
@@ -15,4 +15,4 @@
# limitations under the License.
#
-org.apache.shardingsphere.infra.expr.hotsopt.HotspotInlineExpressionParser
+org.apache.shardingsphere.infra.expr.core.fixture.CustomInlineExpressionParserFixture
diff --git a/infra/expr/espresso/pom.xml b/infra/expr/espresso/pom.xml
index 653fe6e1653..df7c6fc1cfb 100644
--- a/infra/expr/espresso/pom.xml
+++ b/infra/expr/espresso/pom.xml
@@ -26,6 +26,10 @@
<artifactId>shardingsphere-infra-expr-espresso</artifactId>
<name>${project.artifactId}</name>
+ <properties>
+ <truffle-api.version>21.2.0</truffle-api.version>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
@@ -46,6 +50,14 @@
<dependency>
<groupId>org.graalvm.truffle</groupId>
<artifactId>truffle-api</artifactId>
+ <version>${truffle-api.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-test-util</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
</dependency>
</dependencies>
diff --git
a/infra/expr/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParser.java
b/infra/expr/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParser.java
index bfe5201bb08..8e9b33fc3ad 100644
---
a/infra/expr/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParser.java
+++
b/infra/expr/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParser.java
@@ -19,7 +19,6 @@ package org.apache.shardingsphere.infra.expr.espresso;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
-import groovy.lang.Closure;
import groovy.lang.GroovyShell;
import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
import org.graalvm.polyglot.Context;
@@ -32,6 +31,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
@@ -44,31 +44,53 @@ public final class EspressoInlineExpressionParser
implements InlineExpressionPar
private static final char SPLITTER = ',';
+ private String inlineExpression;
+
static {
URL resource =
Thread.currentThread().getContextClassLoader().getResource("espresso-need-libs");
String dir = null == resource ? null : resource.getPath();
JAVA_CLASSPATH = dir + File.separator + "groovy.jar";
}
+ /**
+ * Initialize SPI.
+ *
+ * @param props A Properties instance that carries inlineExpression.
+ * And for compatibility reasons, inlineExpression allows to
be null.
+ */
@Override
- public String handlePlaceHolder(final String inlineExpression) {
- return inlineExpression.contains("$->{") ?
inlineExpression.replaceAll("\\$->\\{", "\\$\\{") : inlineExpression;
+ public void init(final Properties props) {
+ this.inlineExpression = props.getProperty(INLINE_EXPRESSION_KEY);
}
@Override
- public List<String> splitAndEvaluate(final String inlineExpression) {
- try (Context context = createContext()) {
- return Strings.isNullOrEmpty(inlineExpression) ?
Collections.emptyList() : flatten(evaluate(split(inlineExpression), context));
- }
+ public String handlePlaceHolder() {
+ return handlePlaceHolder(inlineExpression);
+ }
+
+ /**
+ * Replace all inline expression placeholders.
+ *
+ * @param inlineExpression inline expression with {@code $->}
+ * @return result inline expression with {@code $}
+ */
+ private String handlePlaceHolder(final String inlineExpression) {
+ return inlineExpression.contains("$->{") ?
inlineExpression.replaceAll("\\$->\\{", "\\$\\{") : inlineExpression;
}
@Override
- public Closure<?> evaluateClosure(final String inlineExpression) {
- throw new UnsupportedOperationException("GraalVM Truffle's Espresso
implementation cannot return an instance of `groovy.lang.Closure` to the Host
JVM.");
+ public List<String> splitAndEvaluate() {
+ try (Context context = createContext()) {
+ return Strings.isNullOrEmpty(inlineExpression) ?
Collections.emptyList() :
flatten(evaluate(split(handlePlaceHolder(inlineExpression)), context));
+ }
}
+ /**
+ * TODO <a href="https://github.com/oracle/graal/issues/4555">espressoHome
not defined</a> not yet closed.
+ *
+ * @return the Truffle Context Instance.
+ */
private Context createContext() {
- // TODO https://github.com/oracle/graal/issues/4555 not yet closed
return Context.newBuilder()
.allowAllAccess(true)
.option("java.Properties.org.graalvm.home",
System.getenv("JAVA_HOME"))
diff --git
a/infra/expr/espresso/src/test/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParserTest.java
b/infra/expr/espresso/src/test/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParserTest.java
index 3f7999f5e4c..ca6deb1c66e 100644
---
a/infra/expr/espresso/src/test/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParserTest.java
+++
b/infra/expr/espresso/src/test/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParserTest.java
@@ -17,6 +17,9 @@
package org.apache.shardingsphere.infra.expr.espresso;
+import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.test.util.PropertiesBuilder;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
@@ -24,6 +27,7 @@ import org.junit.jupiter.api.condition.EnabledInNativeImage;
import java.util.Collections;
import java.util.List;
+import java.util.Properties;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
@@ -35,62 +39,71 @@ class EspressoInlineExpressionParserTest {
@Test
void assertEvaluateForExpressionIsNull() {
- List<String> expected = new
EspressoInlineExpressionParser().splitAndEvaluate(null);
+ InlineExpressionParser parser =
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO", new
Properties());
+ List<String> expected = parser.splitAndEvaluate();
assertThat(expected, is(Collections.<String>emptyList()));
}
@Test
void assertEvaluateForSimpleString() {
- List<String> expected = new
EspressoInlineExpressionParser().splitAndEvaluate(" t_order_0, t_order_1 ");
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, "
t_order_0, t_order_1 "))).splitAndEvaluate();
assertThat(expected.size(), is(2));
assertThat(expected, hasItems("t_order_0", "t_order_1"));
}
@Test
void assertEvaluateForNull() {
- List<String> expected = new
EspressoInlineExpressionParser().splitAndEvaluate("t_order_${null}");
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_order_${null}"))).splitAndEvaluate();
assertThat(expected.size(), is(1));
assertThat(expected, hasItems("t_order_"));
}
@Test
void assertEvaluateForLiteral() {
- List<String> expected = new
EspressoInlineExpressionParser().splitAndEvaluate("t_order_${'xx'}");
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_order_${'xx'}"))).splitAndEvaluate();
assertThat(expected.size(), is(1));
assertThat(expected, hasItems("t_order_xx"));
}
@Test
void assertEvaluateForArray() {
- List<String> expected = new
EspressoInlineExpressionParser().splitAndEvaluate("t_order_${[0, 1,
2]},t_order_item_${[0, 2]}");
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_order_${[0, 1, 2]},t_order_item_${[0, 2]}"))).splitAndEvaluate();
assertThat(expected.size(), is(5));
assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2",
"t_order_item_0", "t_order_item_2"));
}
@Test
void assertEvaluateForRange() {
- List<String> expected = new
EspressoInlineExpressionParser().splitAndEvaluate("t_order_${0..2},t_order_item_${0..1}");
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_order_${0..2},t_order_item_${0..1}"))).splitAndEvaluate();
assertThat(expected.size(), is(5));
assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2",
"t_order_item_0", "t_order_item_1"));
}
@Test
void assertEvaluateForComplex() {
- List<String> expected = new
EspressoInlineExpressionParser().splitAndEvaluate("t_${['new','old']}_order_${1..2},
t_config");
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_${['new','old']}_order_${1..2}, t_config"))).splitAndEvaluate();
assertThat(expected.size(), is(5));
assertThat(expected, hasItems("t_new_order_1", "t_new_order_2",
"t_old_order_1", "t_old_order_2", "t_config"));
}
@Test
void assertEvaluateForCalculate() {
- List<String> expected = new
EspressoInlineExpressionParser().splitAndEvaluate("t_${[\"new${1+2}\",'old']}_order_${1..2}");
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_${[\"new${1+2}\",'old']}_order_${1..2}"))).splitAndEvaluate();
assertThat(expected.size(), is(4));
assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2",
"t_old_order_1", "t_old_order_2"));
}
@Test
void assertEvaluateForExpressionPlaceHolder() {
- List<String> expected = new
EspressoInlineExpressionParser().splitAndEvaluate("t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}");
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}"))).splitAndEvaluate();
assertThat(expected.size(), is(4));
assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2",
"t_old_order_1", "t_old_order_2"));
}
@@ -107,15 +120,18 @@ class EspressoInlineExpressionParserTest {
expression.append(",");
}
}
- List<String> expected = new
EspressoInlineExpressionParser().splitAndEvaluate(expression.toString());
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
expression.toString()))).splitAndEvaluate();
assertThat(expected.size(), is(1024));
assertThat(expected, hasItems("ds_0.t_user_0", "ds_15.t_user_1023"));
}
@Test
void assertHandlePlaceHolder() {
- assertThat(new
EspressoInlineExpressionParser().handlePlaceHolder("t_$->{[\"new$->{1+2}\"]}"),
is("t_${[\"new${1+2}\"]}"));
- assertThat(new
EspressoInlineExpressionParser().handlePlaceHolder("t_${[\"new$->{1+2}\"]}"),
is("t_${[\"new${1+2}\"]}"));
+ assertThat(TypedSPILoader.getService(InlineExpressionParser.class,
"ESPRESSO", PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_$->{[\"new$->{1+2}\"]}"))).handlePlaceHolder(), is("t_${[\"new${1+2}\"]}"));
+ assertThat(TypedSPILoader.getService(InlineExpressionParser.class,
"ESPRESSO", PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_${[\"new$->{1+2}\"]}"))).handlePlaceHolder(), is("t_${[\"new${1+2}\"]}"));
}
/*
@@ -125,6 +141,7 @@ class EspressoInlineExpressionParserTest {
@Test
@Disabled("See java doc")
void assertEvaluateClosure() {
- assertThat(new
EspressoInlineExpressionParser().evaluateClosure("${1+2}").call().toString(),
is("3"));
+ assertThat(TypedSPILoader.getService(InlineExpressionParser.class,
"ESPRESSO", PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"${1+2}"))).evaluateClosure().call().toString(), is("3"));
}
}
diff --git a/infra/expr/hotsopt/pom.xml b/infra/expr/groovy/pom.xml
similarity index 86%
rename from infra/expr/hotsopt/pom.xml
rename to infra/expr/groovy/pom.xml
index 2fa03655f3b..cbc18ed0bed 100644
--- a/infra/expr/hotsopt/pom.xml
+++ b/infra/expr/groovy/pom.xml
@@ -23,7 +23,7 @@
<artifactId>shardingsphere-infra-expr</artifactId>
<version>5.4.1-SNAPSHOT</version>
</parent>
- <artifactId>shardingsphere-infra-expr-hotsopt</artifactId>
+ <artifactId>shardingsphere-infra-expr-groovy</artifactId>
<name>${project.artifactId}</name>
<dependencies>
@@ -34,8 +34,10 @@
</dependency>
<dependency>
- <groupId>org.apache.groovy</groupId>
- <artifactId>groovy</artifactId>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-test-util</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
</dependency>
</dependencies>
</project>
diff --git
a/infra/expr/hotsopt/src/main/java/org/apache/shardingsphere/infra/expr/hotsopt/HotspotInlineExpressionParser.java
b/infra/expr/groovy/src/main/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParser.java
similarity index 78%
rename from
infra/expr/hotsopt/src/main/java/org/apache/shardingsphere/infra/expr/hotsopt/HotspotInlineExpressionParser.java
rename to
infra/expr/groovy/src/main/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParser.java
index 1ec58bb940c..27411402be0 100644
---
a/infra/expr/hotsopt/src/main/java/org/apache/shardingsphere/infra/expr/hotsopt/HotspotInlineExpressionParser.java
+++
b/infra/expr/groovy/src/main/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParser.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.infra.expr.hotsopt;
+package org.apache.shardingsphere.infra.expr.groovy;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
@@ -31,34 +31,70 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
- * Hotspot inline expression parser.
+ * Groovy inline expression parser.
*/
-public final class HotspotInlineExpressionParser implements
InlineExpressionParser {
+public final class GroovyInlineExpressionParser implements
InlineExpressionParser {
private static final char SPLITTER = ',';
+ private static final String INLINE_EXPRESSION_KEY = "inlineExpression";
+
private static final Map<String, Script> SCRIPTS = new
ConcurrentHashMap<>();
private static final GroovyShell SHELL = new GroovyShell();
+ private String inlineExpression;
+
+ /**
+ * Initialize SPI.
+ *
+ * @param props A Properties instance that carries inlineExpression.
+ * And for compatibility reasons, inlineExpression allows to
be null.
+ */
@Override
- public String handlePlaceHolder(final String inlineExpression) {
+ public void init(final Properties props) {
+ this.inlineExpression = props.getProperty(INLINE_EXPRESSION_KEY);
+ }
+
+ @Override
+ public String handlePlaceHolder() {
+ return handlePlaceHolder(inlineExpression);
+ }
+
+ /**
+ * Replace all inline expression placeholders.
+ *
+ * @param inlineExpression inline expression with {@code $->}
+ * @return result inline expression with {@code $}
+ */
+ private String handlePlaceHolder(final String inlineExpression) {
return inlineExpression.contains("$->{") ?
inlineExpression.replaceAll("\\$->\\{", "\\$\\{") : inlineExpression;
}
+ /**
+ * Split and Evaluate inline expression. This function will replace all
inline expression placeholders.
+ *
+ * @return result inline expression with {@code $}
+ */
@Override
- public List<String> splitAndEvaluate(final String inlineExpression) {
- return Strings.isNullOrEmpty(inlineExpression) ?
Collections.emptyList() : flatten(evaluate(split(inlineExpression)));
+ public List<String> splitAndEvaluate() {
+ return Strings.isNullOrEmpty(inlineExpression) ?
Collections.emptyList() :
flatten(evaluate(split(handlePlaceHolder(inlineExpression))));
}
+ /**
+ * Turn inline expression into Groovy Closure. This function will replace
all inline expression placeholders.
+ *
+ * @return The result of the Groovy Closure pattern.
+ */
@Override
- public Closure<?> evaluateClosure(final String inlineExpression) {
- return (Closure<?>) evaluate("{it -> \"" + inlineExpression + "\"}");
+ public Closure<?> evaluateClosure() {
+ return (Closure<?>) evaluate("{it -> \"" +
handlePlaceHolder(inlineExpression) + "\"}");
}
private List<Object> evaluate(final List<String> inlineExpressions) {
@@ -178,7 +214,7 @@ public final class HotspotInlineExpressionParser implements
InlineExpressionPars
@Override
public String getType() {
- return "HOTSPOT";
+ return "GROOVY";
}
@Override
diff --git
a/infra/expr/hotsopt/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
b/infra/expr/groovy/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
similarity index 91%
rename from
infra/expr/hotsopt/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
rename to
infra/expr/groovy/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
index 48cf905c9a5..1eab5f0f7be 100644
---
a/infra/expr/hotsopt/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
+++
b/infra/expr/groovy/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser
@@ -15,4 +15,4 @@
# limitations under the License.
#
-org.apache.shardingsphere.infra.expr.hotsopt.HotspotInlineExpressionParser
+org.apache.shardingsphere.infra.expr.groovy.GroovyInlineExpressionParser
diff --git
a/infra/expr/groovy/src/test/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParserTest.java
b/infra/expr/groovy/src/test/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParserTest.java
new file mode 100644
index 00000000000..b2a2940720f
--- /dev/null
+++
b/infra/expr/groovy/src/test/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParserTest.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.infra.expr.groovy;
+
+import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.test.util.PropertiesBuilder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledInNativeImage;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+@DisabledInNativeImage
+class GroovyInlineExpressionParserTest {
+
+ @Test
+ void assertEvaluateForExpressionIsNull() {
+ InlineExpressionParser parser =
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY", new
Properties());
+ List<String> expected = parser.splitAndEvaluate();
+ assertThat(expected, is(Collections.<String>emptyList()));
+ }
+
+ @Test
+ void assertEvaluateForSimpleString() {
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, "
t_order_0, t_order_1 "))).splitAndEvaluate();
+ assertThat(expected.size(), is(2));
+ assertThat(expected, hasItems("t_order_0", "t_order_1"));
+ }
+
+ @Test
+ void assertEvaluateForNull() {
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_order_${null}"))).splitAndEvaluate();
+ assertThat(expected.size(), is(1));
+ assertThat(expected, hasItems("t_order_"));
+ }
+
+ @Test
+ void assertEvaluateForLiteral() {
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_order_${'xx'}"))).splitAndEvaluate();
+ assertThat(expected.size(), is(1));
+ assertThat(expected, hasItems("t_order_xx"));
+ }
+
+ @Test
+ void assertEvaluateForArray() {
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_order_${[0, 1, 2]},t_order_item_${[0, 2]}"))).splitAndEvaluate();
+ assertThat(expected.size(), is(5));
+ assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2",
"t_order_item_0", "t_order_item_2"));
+ }
+
+ @Test
+ void assertEvaluateForRange() {
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_order_${0..2},t_order_item_${0..1}"))).splitAndEvaluate();
+ assertThat(expected.size(), is(5));
+ assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2",
"t_order_item_0", "t_order_item_1"));
+ }
+
+ @Test
+ void assertEvaluateForComplex() {
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_${['new','old']}_order_${1..2}, t_config"))).splitAndEvaluate();
+ assertThat(expected.size(), is(5));
+ assertThat(expected, hasItems("t_new_order_1", "t_new_order_2",
"t_old_order_1", "t_old_order_2", "t_config"));
+ }
+
+ @Test
+ void assertEvaluateForCalculate() {
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_${[\"new${1+2}\",'old']}_order_${1..2}"))).splitAndEvaluate();
+ assertThat(expected.size(), is(4));
+ assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2",
"t_old_order_1", "t_old_order_2"));
+ }
+
+ @Test
+ void assertEvaluateForExpressionPlaceHolder() {
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}"))).splitAndEvaluate();
+ assertThat(expected.size(), is(4));
+ assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2",
"t_old_order_1", "t_old_order_2"));
+ }
+
+ @Test
+ void assertEvaluateForLong() {
+ StringBuilder expression = new StringBuilder();
+ for (int i = 0; i < 1024; i++) {
+ expression.append("ds_");
+ expression.append(i / 64);
+ expression.append(".t_user_");
+ expression.append(i);
+ if (i != 1023) {
+ expression.append(",");
+ }
+ }
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
expression.toString()))).splitAndEvaluate();
+ assertThat(expected.size(), is(1024));
+ assertThat(expected, hasItems("ds_0.t_user_0", "ds_15.t_user_1023"));
+ }
+
+ @Test
+ void assertHandlePlaceHolder() {
+ assertThat(TypedSPILoader.getService(InlineExpressionParser.class,
"GROOVY", PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_$->{[\"new$->{1+2}\"]}"))).handlePlaceHolder(), is("t_${[\"new${1+2}\"]}"));
+ assertThat(TypedSPILoader.getService(InlineExpressionParser.class,
"GROOVY", PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_${[\"new$->{1+2}\"]}"))).handlePlaceHolder(), is("t_${[\"new${1+2}\"]}"));
+ }
+
+ @Test
+ void assertEvaluateClosure() {
+ assertThat(TypedSPILoader.getService(InlineExpressionParser.class,
"GROOVY", PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"${1+2}"))).evaluateClosure().call().toString(), is("3"));
+ }
+}
diff --git
a/infra/expr/hotsopt/src/test/java/org/apache/shardingsphere/infra/expr/hotsopt/HotspotInlineExpressionParserTest.java
b/infra/expr/hotsopt/src/test/java/org/apache/shardingsphere/infra/expr/hotsopt/HotspotInlineExpressionParserTest.java
deleted file mode 100644
index 9a836eff0f9..00000000000
---
a/infra/expr/hotsopt/src/test/java/org/apache/shardingsphere/infra/expr/hotsopt/HotspotInlineExpressionParserTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.infra.expr.hotsopt;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.Collections;
-import java.util.List;
-
-import static org.hamcrest.CoreMatchers.hasItems;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-class HotspotInlineExpressionParserTest {
-
- @Test
- void assertEvaluateForExpressionIsNull() {
- List<String> expected = new
HotspotInlineExpressionParser().splitAndEvaluate(null);
- assertThat(expected, is(Collections.<String>emptyList()));
- }
-
- @Test
- void assertEvaluateForSimpleString() {
- List<String> expected = new
HotspotInlineExpressionParser().splitAndEvaluate(" t_order_0, t_order_1 ");
- assertThat(expected.size(), is(2));
- assertThat(expected, hasItems("t_order_0", "t_order_1"));
- }
-
- @Test
- void assertEvaluateForNull() {
- List<String> expected = new
HotspotInlineExpressionParser().splitAndEvaluate("t_order_${null}");
- assertThat(expected.size(), is(1));
- assertThat(expected, hasItems("t_order_"));
- }
-
- @Test
- void assertEvaluateForLiteral() {
- List<String> expected = new
HotspotInlineExpressionParser().splitAndEvaluate("t_order_${'xx'}");
- assertThat(expected.size(), is(1));
- assertThat(expected, hasItems("t_order_xx"));
- }
-
- @Test
- void assertEvaluateForArray() {
- List<String> expected = new
HotspotInlineExpressionParser().splitAndEvaluate("t_order_${[0, 1,
2]},t_order_item_${[0, 2]}");
- assertThat(expected.size(), is(5));
- assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2",
"t_order_item_0", "t_order_item_2"));
- }
-
- @Test
- void assertEvaluateForRange() {
- List<String> expected = new
HotspotInlineExpressionParser().splitAndEvaluate("t_order_${0..2},t_order_item_${0..1}");
- assertThat(expected.size(), is(5));
- assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2",
"t_order_item_0", "t_order_item_1"));
- }
-
- @Test
- void assertEvaluateForComplex() {
- List<String> expected = new
HotspotInlineExpressionParser().splitAndEvaluate("t_${['new','old']}_order_${1..2},
t_config");
- assertThat(expected.size(), is(5));
- assertThat(expected, hasItems("t_new_order_1", "t_new_order_2",
"t_old_order_1", "t_old_order_2", "t_config"));
- }
-
- @Test
- void assertEvaluateForCalculate() {
- List<String> expected = new
HotspotInlineExpressionParser().splitAndEvaluate("t_${[\"new${1+2}\",'old']}_order_${1..2}");
- assertThat(expected.size(), is(4));
- assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2",
"t_old_order_1", "t_old_order_2"));
- }
-
- @Test
- void assertEvaluateForExpressionPlaceHolder() {
- List<String> expected = new
HotspotInlineExpressionParser().splitAndEvaluate("t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}");
- assertThat(expected.size(), is(4));
- assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2",
"t_old_order_1", "t_old_order_2"));
- }
-
- @Test
- void assertEvaluateForLong() {
- StringBuilder expression = new StringBuilder();
- for (int i = 0; i < 1024; i++) {
- expression.append("ds_");
- expression.append(i / 64);
- expression.append(".t_user_");
- expression.append(i);
- if (i != 1023) {
- expression.append(",");
- }
- }
- List<String> expected = new
HotspotInlineExpressionParser().splitAndEvaluate(expression.toString());
- assertThat(expected.size(), is(1024));
- assertThat(expected, hasItems("ds_0.t_user_0", "ds_15.t_user_1023"));
- }
-
- @Test
- void assertHandlePlaceHolder() {
- assertThat(new
HotspotInlineExpressionParser().handlePlaceHolder("t_$->{[\"new$->{1+2}\"]}"),
is("t_${[\"new${1+2}\"]}"));
- assertThat(new
HotspotInlineExpressionParser().handlePlaceHolder("t_${[\"new$->{1+2}\"]}"),
is("t_${[\"new${1+2}\"]}"));
- }
-
- @Test
- void assertEvaluateClosure() {
- assertThat(new
HotspotInlineExpressionParser().evaluateClosure("${1+2}").call().toString(),
is("3"));
- }
-}
diff --git a/infra/expr/pom.xml b/infra/expr/pom.xml
index 14aa380d873..9f9e4e7cb64 100644
--- a/infra/expr/pom.xml
+++ b/infra/expr/pom.xml
@@ -30,8 +30,8 @@
<modules>
<module>spi</module>
<module>core</module>
- <module>hotsopt</module>
- <module>espresso</module>
+ <module>groovy</module>
<module>purelist</module>
+ <module>espresso</module>
</modules>
</project>
diff --git a/infra/expr/purelist/pom.xml b/infra/expr/purelist/pom.xml
index b45ff489b37..0e3d95b390b 100644
--- a/infra/expr/purelist/pom.xml
+++ b/infra/expr/purelist/pom.xml
@@ -34,8 +34,10 @@
</dependency>
<dependency>
- <groupId>org.apache.groovy</groupId>
- <artifactId>groovy</artifactId>
+ <groupId>org.apache.shardingsphere</groupId>
+ <artifactId>shardingsphere-test-util</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
</dependency>
</dependencies>
</project>
diff --git
a/infra/expr/purelist/src/main/java/org/apache/shardingsphere/infra/expr/purelist/PureListInlineExpressionParser.java
b/infra/expr/purelist/src/main/java/org/apache/shardingsphere/infra/expr/purelist/PureListInlineExpressionParser.java
index 347b6d4f3e2..ab1d3a34af2 100644
---
a/infra/expr/purelist/src/main/java/org/apache/shardingsphere/infra/expr/purelist/PureListInlineExpressionParser.java
+++
b/infra/expr/purelist/src/main/java/org/apache/shardingsphere/infra/expr/purelist/PureListInlineExpressionParser.java
@@ -18,12 +18,12 @@
package org.apache.shardingsphere.infra.expr.purelist;
import com.google.common.base.Strings;
-import groovy.lang.Closure;
import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Properties;
/**
* Pure List inline expression parser.
@@ -32,19 +32,27 @@ public final class PureListInlineExpressionParser
implements InlineExpressionPar
private static final char SPLITTER = ',';
+ private String inlineExpression;
+
+ /**
+ * Initialize SPI.
+ *
+ * @param props A Properties instance that carries inlineExpression.
+ * And for compatibility reasons, inlineExpression allows to
be null.
+ */
@Override
- public String handlePlaceHolder(final String inlineExpression) {
- return inlineExpression.contains("$->{") ?
inlineExpression.replaceAll("\\$->\\{", "\\$\\{") : inlineExpression;
+ public void init(final Properties props) {
+ this.inlineExpression = props.getProperty(INLINE_EXPRESSION_KEY);
}
@Override
- public List<String> splitAndEvaluate(final String inlineExpression) {
- return Strings.isNullOrEmpty(inlineExpression) ?
Collections.emptyList() : split(inlineExpression);
+ public String handlePlaceHolder() {
+ return inlineExpression;
}
@Override
- public Closure<?> evaluateClosure(final String inlineExpression) {
- throw new UnsupportedOperationException("Groovy classes cannot be used
directly within GraalVM Native Image.");
+ public List<String> splitAndEvaluate() {
+ return Strings.isNullOrEmpty(inlineExpression) ?
Collections.emptyList() : split(inlineExpression);
}
private List<String> split(final String inlineExpression) {
diff --git
a/infra/expr/purelist/src/test/java/org/apache/shardingsphere/infra/expr/purelist/PureListInlineExpressionParserTest.java
b/infra/expr/purelist/src/test/java/org/apache/shardingsphere/infra/expr/purelist/PureListInlineExpressionParserTest.java
index bb8ebbf8855..2ddeacdd7b4 100644
---
a/infra/expr/purelist/src/test/java/org/apache/shardingsphere/infra/expr/purelist/PureListInlineExpressionParserTest.java
+++
b/infra/expr/purelist/src/test/java/org/apache/shardingsphere/infra/expr/purelist/PureListInlineExpressionParserTest.java
@@ -17,26 +17,33 @@
package org.apache.shardingsphere.infra.expr.purelist;
+import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.test.util.PropertiesBuilder;
import org.junit.jupiter.api.Test;
import java.util.Collections;
import java.util.List;
+import java.util.Properties;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
class PureListInlineExpressionParserTest {
@Test
void assertEvaluateForExpressionIsNull() {
- List<String> expected = new
PureListInlineExpressionParser().splitAndEvaluate(null);
+ InlineExpressionParser parser =
TypedSPILoader.getService(InlineExpressionParser.class, "PURELIST", new
Properties());
+ List<String> expected = parser.splitAndEvaluate();
assertThat(expected, is(Collections.<String>emptyList()));
}
@Test
void assertEvaluateForSimpleString() {
- List<String> expected = new
PureListInlineExpressionParser().splitAndEvaluate(" t_order_0, t_order_1 ");
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "PURELIST",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, "
t_order_0, t_order_1 "))).splitAndEvaluate();
assertThat(expected.size(), is(2));
assertThat(expected, hasItems("t_order_0", "t_order_1"));
}
@@ -53,8 +60,23 @@ class PureListInlineExpressionParserTest {
expression.append(",");
}
}
- List<String> expected = new
PureListInlineExpressionParser().splitAndEvaluate(expression.toString());
+ List<String> expected =
TypedSPILoader.getService(InlineExpressionParser.class, "PURELIST",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
expression.toString()))).splitAndEvaluate();
assertThat(expected.size(), is(1024));
assertThat(expected, hasItems("ds_0.t_user_0", "ds_15.t_user_1023"));
}
+
+ @Test
+ void assertHandlePlaceHolder() {
+ assertThat(TypedSPILoader.getService(InlineExpressionParser.class,
"PURELIST", PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_$->{[\"new$->{1+2}\"]}"))).handlePlaceHolder(),
is("t_$->{[\"new$->{1+2}\"]}"));
+ assertThat(TypedSPILoader.getService(InlineExpressionParser.class,
"PURELIST", PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"t_${[\"new$->{1+2}\"]}"))).handlePlaceHolder(), is("t_${[\"new$->{1+2}\"]}"));
+ }
+
+ @Test
+ void assertEvaluateClosure() {
+ assertThrows(UnsupportedOperationException.class, () ->
TypedSPILoader.getService(InlineExpressionParser.class, "PURELIST",
PropertiesBuilder.build(
+ new
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY,
"${1+2}"))).evaluateClosure().call().toString());
+ }
}
diff --git
a/infra/expr/spi/src/main/java/org/apache/shardingsphere/infra/expr/spi/InlineExpressionParser.java
b/infra/expr/spi/src/main/java/org/apache/shardingsphere/infra/expr/spi/InlineExpressionParser.java
index 7baa8728629..7578f5f8f2d 100644
---
a/infra/expr/spi/src/main/java/org/apache/shardingsphere/infra/expr/spi/InlineExpressionParser.java
+++
b/infra/expr/spi/src/main/java/org/apache/shardingsphere/infra/expr/spi/InlineExpressionParser.java
@@ -30,26 +30,34 @@ import java.util.List;
public interface InlineExpressionParser extends TypedSPI {
/**
- * Replace all inline expression placeholders.
+ * The expression used to build the InlineExpressionParser instance will
be saved to the Properties instance via this key.
+ */
+ String INLINE_EXPRESSION_KEY = "inlineExpression";
+
+ /**
+ * This method is used to return the inlineExpression String itself. In
some cases, you may want to do
+ * additional processing on inlineExpression to return a specific value,
in which case you need to override this
+ * method.
*
- * @param inlineExpression inline expression with {@code $->}
- * @return result inline expression with {@code $}
+ * @return result processed inline expression defined by the SPI
implementation.
*/
- String handlePlaceHolder(String inlineExpression);
+ String handlePlaceHolder();
/**
* Split and evaluate inline expression.
*
- * @param inlineExpression inline expression
* @return result list
*/
- List<String> splitAndEvaluate(String inlineExpression);
+ List<String> splitAndEvaluate();
/**
* Evaluate closure.
*
- * @param inlineExpression inline expression
* @return closure
+ * @throws UnsupportedOperationException In most cases, users should not
implement this method, and the return value
+ * of this method can only be a
Groovy Closure.
*/
- Closure<?> evaluateClosure(String inlineExpression);
+ default Closure<?> evaluateClosure() {
+ throw new UnsupportedOperationException("This SPI implementation does
not support the use of this method.");
+ }
}
diff --git a/pom.xml b/pom.xml
index aa743a7b073..c1a8677d656 100644
--- a/pom.xml
+++ b/pom.xml
@@ -82,7 +82,6 @@
<jaxb.version>2.3.0</jaxb.version>
<annotation-api.version>1.3.2</annotation-api.version>
<activation-api.version>1.2.0</activation-api.version>
- <truffle-api.version>21.2.0</truffle-api.version>
<calcite.version>1.35.0</calcite.version>
<immutables.version>2.9.3</immutables.version>
@@ -627,12 +626,6 @@
<version>${awaitility.version}</version>
<scope>test</scope>
</dependency>
-
- <dependency>
- <groupId>org.graalvm.truffle</groupId>
- <artifactId>truffle-api</artifactId>
- <version>${truffle-api.version}</version>
- </dependency>
</dependencies>
</dependencyManagement>
@@ -1209,7 +1202,6 @@
<profile>
<id>generateStandardMetadata</id>
<properties>
- <truffle-api.version>23.0.1</truffle-api.version>
<jacoco.skip>true</jacoco.skip>
<maven.javadoc.skip>true</maven.javadoc.skip>
<checkstyle.skip>true</checkstyle.skip>
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/common/checker/ShardingRuleConfigurationImportChecker.java
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/common/checker/ShardingRuleConfigurationImportChecker.java
index 2260ffbdf90..6d95d37e16f 100644
---
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/common/checker/ShardingRuleConfigurationImportChecker.java
+++
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/common/checker/ShardingRuleConfigurationImportChecker.java
@@ -90,12 +90,12 @@ public final class ShardingRuleConfigurationImportChecker {
}
private Collection<String> getDataSourceNames(final
ShardingAutoTableRuleConfiguration shardingAutoTableRuleConfig) {
- Collection<String> actualDataSources =
InlineExpressionParserFactory.newInstance().splitAndEvaluate(shardingAutoTableRuleConfig.getActualDataSources());
+ Collection<String> actualDataSources =
InlineExpressionParserFactory.newInstance(shardingAutoTableRuleConfig.getActualDataSources()).splitAndEvaluate();
return new HashSet<>(actualDataSources);
}
private Collection<String> getDataSourceNames(final
ShardingTableRuleConfiguration shardingTableRuleConfig) {
- Collection<String> actualDataNodes =
InlineExpressionParserFactory.newInstance().splitAndEvaluate(shardingTableRuleConfig.getActualDataNodes());
+ Collection<String> actualDataNodes =
InlineExpressionParserFactory.newInstance(shardingTableRuleConfig.getActualDataNodes()).splitAndEvaluate();
return actualDataNodes.stream().map(each -> new
DataNode(each).getDataSourceName()).collect(Collectors.toList());
}
diff --git
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/cases/dataset/DataSet.java
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/cases/dataset/DataSet.java
index c973887c289..0d393b83c70 100644
---
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/cases/dataset/DataSet.java
+++
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/cases/dataset/DataSet.java
@@ -65,7 +65,7 @@ public final class DataSet {
* @return data set meta data belong to current data node
*/
public DataSetMetaData findMetaData(final DataNode dataNode) {
- Optional<DataSetMetaData> result = metaDataList.stream().filter(each
->
contains(InlineExpressionParserFactory.newInstance().splitAndEvaluate(each.getDataNodes()),
dataNode)).findFirst();
+ Optional<DataSetMetaData> result = metaDataList.stream().filter(each
->
contains(InlineExpressionParserFactory.newInstance(each.getDataNodes()).splitAndEvaluate(),
dataNode)).findFirst();
return result.orElseThrow(() -> new
IllegalArgumentException(String.format("Cannot find data node: %s", dataNode)));
}
diff --git
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/composer/BatchE2EContainerComposer.java
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/composer/BatchE2EContainerComposer.java
index d6b1341f633..d11bc084292 100644
---
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/composer/BatchE2EContainerComposer.java
+++
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/composer/BatchE2EContainerComposer.java
@@ -85,7 +85,7 @@ public final class BatchE2EContainerComposer extends
E2EContainerComposer implem
DataSet expected = getDataSet(actualUpdateCounts);
assertThat("Only support single table for DML.",
expected.getMetaDataList().size(), is(1));
DataSetMetaData expectedDataSetMetaData =
expected.getMetaDataList().get(0);
- for (String each :
InlineExpressionParserFactory.newInstance().splitAndEvaluate(expectedDataSetMetaData.getDataNodes()))
{
+ for (String each :
InlineExpressionParserFactory.newInstance(expectedDataSetMetaData.getDataNodes()).splitAndEvaluate())
{
DataNode dataNode = new DataNode(each);
DataSource dataSource =
getActualDataSourceMap().get(dataNode.getDataSourceName());
try (
diff --git
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/type/DDLE2EIT.java
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/type/DDLE2EIT.java
index cc2bd74b670..1beba8c29f9 100644
---
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/type/DDLE2EIT.java
+++
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/type/DDLE2EIT.java
@@ -170,7 +170,7 @@ class DDLE2EIT {
private void assertTableMetaData(final AssertionTestParameter testParam,
final SingleE2EContainerComposer containerComposer) throws SQLException {
String tableName =
containerComposer.getAssertion().getInitialSQL().getAffectedTable();
DataSetMetaData expected =
containerComposer.getDataSet().findMetaData(tableName);
- Collection<DataNode> dataNodes =
InlineExpressionParserFactory.newInstance().splitAndEvaluate(expected.getDataNodes()).stream().map(DataNode::new).collect(Collectors.toList());
+ Collection<DataNode> dataNodes =
InlineExpressionParserFactory.newInstance(expected.getDataNodes()).splitAndEvaluate().stream().map(DataNode::new).collect(Collectors.toList());
if (expected.getColumns().isEmpty()) {
assertNotContainsTable(containerComposer, dataNodes);
return;
diff --git
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/type/dml/BaseDMLE2EIT.java
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/type/dml/BaseDMLE2EIT.java
index e1a71a5cf6d..1d6cb531ef1 100644
---
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/type/dml/BaseDMLE2EIT.java
+++
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/engine/type/dml/BaseDMLE2EIT.java
@@ -93,7 +93,7 @@ public abstract class BaseDMLE2EIT {
}
private void assertDataSet(final AssertionTestParameter testParam, final
SingleE2EContainerComposer containerComposer, final DataSetMetaData
expectedDataSetMetaData) throws SQLException {
- for (String each :
InlineExpressionParserFactory.newInstance().splitAndEvaluate(expectedDataSetMetaData.getDataNodes()))
{
+ for (String each :
InlineExpressionParserFactory.newInstance(expectedDataSetMetaData.getDataNodes()).splitAndEvaluate())
{
DataNode dataNode = new DataNode(each);
DataSource dataSource =
containerComposer.getActualDataSourceMap().get(dataNode.getDataSourceName());
try (
diff --git
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/env/DataSetEnvironmentManager.java
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/env/DataSetEnvironmentManager.java
index a611f55a036..8fb260e443d 100644
---
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/env/DataSetEnvironmentManager.java
+++
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/env/DataSetEnvironmentManager.java
@@ -167,7 +167,7 @@ public final class DataSetEnvironmentManager {
private Map<String, Collection<String>> getDataNodeMap(final
DataSetMetaData dataSetMetaData) {
Map<String, Collection<String>> result = new LinkedHashMap<>();
- for (String each :
InlineExpressionParserFactory.newInstance().splitAndEvaluate(dataSetMetaData.getDataNodes()))
{
+ for (String each :
InlineExpressionParserFactory.newInstance(dataSetMetaData.getDataNodes()).splitAndEvaluate())
{
DataNode dataNode = new DataNode(each);
if (!result.containsKey(dataNode.getDataSourceName())) {
result.put(dataNode.getDataSourceName(), new LinkedList<>());