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 ae9c2ca2d69 Support for the INSTALL PLUGIN statement (#37402)
ae9c2ca2d69 is described below
commit ae9c2ca2d69975e1abea8ece3120607427f0d7a5
Author: cxy <[email protected]>
AuthorDate: Tue Dec 16 21:14:07 2025 +0800
Support for the INSTALL PLUGIN statement (#37402)
---
.../src/main/antlr4/imports/doris/DALStatement.g4 | 22 +++++++++-
.../statement/type/DorisDALStatementVisitor.java | 49 +++++++++++++++++++++-
.../dal/plugin/MySQLInstallPluginStatement.java | 16 +++++++
.../type/MySQLInstallPluginStatementAssert.java | 19 ++++++++-
.../jaxb/segment/impl/plugin/ExpectedPlugin.java | 19 +++++++++
.../parser/src/main/resources/case/dal/install.xml | 49 ++++++++++++++++++++++
.../main/resources/sql/supported/dal/install.xml | 8 ++++
7 files changed, 179 insertions(+), 3 deletions(-)
diff --git
a/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DALStatement.g4
b/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DALStatement.g4
index 4aa436fbba3..38badae1a10 100644
---
a/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DALStatement.g4
+++
b/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DALStatement.g4
@@ -284,7 +284,27 @@ installComponent
;
installPlugin
- : INSTALL PLUGIN pluginName SONAME shardLibraryName
+ : INSTALL PLUGIN (pluginName SONAME shardLibraryName | FROM pluginSource
(PROPERTIES LP_ pluginPropertiesList RP_)?)
+ ;
+
+pluginSource
+ : identifier | string_
+ ;
+
+pluginPropertiesList
+ : pluginProperty (COMMA_ pluginProperty)*
+ ;
+
+pluginProperty
+ : pluginPropertyKey EQ_ pluginPropertyValue
+ ;
+
+pluginPropertyKey
+ : identifier | string_
+ ;
+
+pluginPropertyValue
+ : literals | identifier
;
uninstallComponent
diff --git
a/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDALStatementVisitor.java
b/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDALStatementVisitor.java
index 0e325acfe93..11cb7e4f1ed 100644
---
a/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDALStatementVisitor.java
+++
b/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDALStatementVisitor.java
@@ -125,6 +125,11 @@ import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.Propert
import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.ResourceNameContext;
import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.PropertyKeyContext;
import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.PropertyValueContext;
+import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.PluginSourceContext;
+import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.PluginPropertiesListContext;
+import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.PluginPropertyContext;
+import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.PluginPropertyKeyContext;
+import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.PluginPropertyValueContext;
import
org.apache.shardingsphere.sql.parser.engine.doris.visitor.statement.DorisStatementVisitor;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dal.CacheTableIndexSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dal.CloneActionSegment;
@@ -246,6 +251,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -474,7 +481,47 @@ public final class DorisDALStatementVisitor extends
DorisStatementVisitor implem
@Override
public ASTNode visitInstallPlugin(final InstallPluginContext ctx) {
- return new MySQLInstallPluginStatement(getDatabaseType(),
((IdentifierValue) visit(ctx.pluginName())).getValue());
+ if (null != ctx.pluginName()) {
+ return new MySQLInstallPluginStatement(getDatabaseType(),
((IdentifierValue) visit(ctx.pluginName())).getValue());
+ }
+ String source = getPluginSource(ctx.pluginSource());
+ Map<String, String> properties = null == ctx.pluginPropertiesList() ?
null : extractPluginProperties(ctx.pluginPropertiesList());
+ return new MySQLInstallPluginStatement(getDatabaseType(), source,
properties);
+ }
+
+ private String getPluginSource(final PluginSourceContext ctx) {
+ if (null != ctx.identifier()) {
+ return ((IdentifierValue) visit(ctx.identifier())).getValue();
+ }
+ return ((StringLiteralValue) visit(ctx.string_())).getValue();
+ }
+
+ private Map<String, String> extractPluginProperties(final
PluginPropertiesListContext ctx) {
+ Map<String, String> result = new LinkedHashMap<>();
+ for (PluginPropertyContext each : ctx.pluginProperty()) {
+ String key = getPluginPropertyKey(each.pluginPropertyKey());
+ String value = getPluginPropertyValue(each.pluginPropertyValue());
+ result.put(key, value);
+ }
+ return result;
+ }
+
+ private String getPluginPropertyKey(final PluginPropertyKeyContext ctx) {
+ if (null != ctx.identifier()) {
+ return ((IdentifierValue) visit(ctx.identifier())).getValue();
+ }
+ return ((StringLiteralValue) visit(ctx.string_())).getValue();
+ }
+
+ private String getPluginPropertyValue(final PluginPropertyValueContext
ctx) {
+ if (null != ctx.identifier()) {
+ return ((IdentifierValue) visit(ctx.identifier())).getValue();
+ }
+ ASTNode result = visit(ctx.literals());
+ if (result instanceof LiteralValue) {
+ return getLiteralValueAsString((LiteralValue<?>) result);
+ }
+ return result.toString();
}
@Override
diff --git
a/parser/sql/statement/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dal/plugin/MySQLInstallPluginStatement.java
b/parser/sql/statement/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dal/plugin/MySQLInstallPluginStatement.java
index b6f5c60f886..637d23729ac 100644
---
a/parser/sql/statement/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dal/plugin/MySQLInstallPluginStatement.java
+++
b/parser/sql/statement/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/statement/mysql/dal/plugin/MySQLInstallPluginStatement.java
@@ -21,6 +21,9 @@ import lombok.Getter;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dal.DALStatement;
+import java.util.Collections;
+import java.util.Map;
+
/**
* Install plugin statement for MySQL.
*/
@@ -29,8 +32,21 @@ public final class MySQLInstallPluginStatement extends
DALStatement {
private final String pluginName;
+ private final String source;
+
+ private final Map<String, String> properties;
+
public MySQLInstallPluginStatement(final DatabaseType databaseType, final
String pluginName) {
super(databaseType);
this.pluginName = pluginName;
+ this.source = null;
+ this.properties = Collections.emptyMap();
+ }
+
+ public MySQLInstallPluginStatement(final DatabaseType databaseType, final
String source, final Map<String, String> properties) {
+ super(databaseType);
+ this.pluginName = null;
+ this.source = source;
+ this.properties = null == properties ? Collections.emptyMap() :
properties;
}
}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/dal/dialect/mysql/type/MySQLInstallPluginStatementAssert.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/dal/dialect/mysql/type/MySQLInstallPluginStatementAssert.java
index c43f064de86..7fc58bc8cac 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/dal/dialect/mysql/type/MySQLInstallPluginStatementAssert.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/dal/dialect/mysql/type/MySQLInstallPluginStatementAssert.java
@@ -25,6 +25,7 @@ import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.s
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* Install plugin statement assert for MySQL.
@@ -40,6 +41,22 @@ public final class MySQLInstallPluginStatementAssert {
* @param expected expected install plugin statement test case
*/
public static void assertIs(final SQLCaseAssertContext assertContext,
final MySQLInstallPluginStatement actual, final
MySQLInstallPluginStatementTestCase expected) {
- assertThat(assertContext.getText("Actual plugin name does not match:
"), actual.getPluginName(), is(expected.getPlugin().getName()));
+ if (null != expected.getPlugin()) {
+ if (null != expected.getPlugin().getName()) {
+ assertThat(assertContext.getText("Actual plugin name does not
match: "), actual.getPluginName(), is(expected.getPlugin().getName()));
+ }
+ if (null != expected.getPlugin().getSource()) {
+ assertThat(assertContext.getText("Actual plugin source does
not match: "), actual.getSource(), is(expected.getPlugin().getSource()));
+ }
+ if (!expected.getPlugin().getProperties().isEmpty()) {
+ assertNotNull(actual.getProperties(),
assertContext.getText("Plugin properties should not be null"));
+ assertThat(assertContext.getText("Plugin properties size does
not match: "), actual.getProperties().size(),
is(expected.getPlugin().getProperties().size()));
+ expected.getPlugin().getProperties().forEach(property -> {
+ String actualValue =
actual.getProperties().get(property.getKey());
+ assertNotNull(actualValue, assertContext.getText("Plugin
property key '" + property.getKey() + "' should exist"));
+ assertThat(assertContext.getText("Plugin property value
for key '" + property.getKey() + "' does not match: "), actualValue,
is(property.getValue()));
+ });
+ }
+ }
}
}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plugin/ExpectedPlugin.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plugin/ExpectedPlugin.java
index ec503b55b29..8e11a443618 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plugin/ExpectedPlugin.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/plugin/ExpectedPlugin.java
@@ -17,10 +17,29 @@
package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.plugin;
+import lombok.Getter;
+import lombok.Setter;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedIdentifierSQLSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.PropertyTestCase;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import java.util.LinkedList;
+import java.util.List;
/**
* Expected plugin.
*/
+@XmlAccessorType(XmlAccessType.FIELD)
+@Getter
+@Setter
public final class ExpectedPlugin extends AbstractExpectedIdentifierSQLSegment
{
+
+ @XmlAttribute
+ private String source;
+
+ @XmlElement(name = "property")
+ private final List<PropertyTestCase> properties = new LinkedList<>();
}
diff --git a/test/it/parser/src/main/resources/case/dal/install.xml
b/test/it/parser/src/main/resources/case/dal/install.xml
index 7386a992843..11dfdb60bcd 100644
--- a/test/it/parser/src/main/resources/case/dal/install.xml
+++ b/test/it/parser/src/main/resources/case/dal/install.xml
@@ -29,4 +29,53 @@
<install-plugin sql-case-id="install_plugin">
<plugin name="binlog" start-index="15" stop-index="20" />
</install-plugin>
+
+ <install-plugin sql-case-id="install_plugin_from">
+ <plugin source="/home/users/doris/auditdemo.zip" />
+ </install-plugin>
+
+ <install-plugin sql-case-id="install_plugin_with_properties">
+ <plugin source="/home/users/doris/auditdemo.zip">
+ <property key="md5sum" value="d41d8cd98f00b204e9800998ecf8427e" />
+ </plugin>
+ </install-plugin>
+
+ <install-plugin sql-case-id="install_plugin_with_identifier">
+ <plugin source="plugin_path">
+ <property key="timeout" value="30" />
+ </plugin>
+ </install-plugin>
+
+ <install-plugin sql-case-id="install_plugin_with_number">
+ <plugin source="/path/to/plugin.zip">
+ <property key="timeout" value="30" />
+ </plugin>
+ </install-plugin>
+
+ <install-plugin sql-case-id="install_plugin_with_boolean">
+ <plugin source="/path/to/plugin.zip">
+ <property key="auto_load" value="true" />
+ </plugin>
+ </install-plugin>
+
+ <install-plugin sql-case-id="install_plugin_with_null">
+ <plugin source="/path/to/plugin.zip">
+ <property key="description" value="NULL" />
+ </plugin>
+ </install-plugin>
+
+ <install-plugin sql-case-id="install_plugin_multiple_properties">
+ <plugin source="/path/to/plugin.zip">
+ <property key="md5sum" value="abc123" />
+ <property key="timeout" value="30" />
+ </plugin>
+ </install-plugin>
+
+ <install-plugin sql-case-id="install_plugin_mixed_types">
+ <plugin source="/path/to/plugin.zip">
+ <property key="md5sum" value="abc123" />
+ <property key="timeout" value="30" />
+ <property key="auto_load" value="false" />
+ </plugin>
+ </install-plugin>
</sql-parser-test-cases>
diff --git a/test/it/parser/src/main/resources/sql/supported/dal/install.xml
b/test/it/parser/src/main/resources/sql/supported/dal/install.xml
index f290c1a56c6..b4fac15a00c 100644
--- a/test/it/parser/src/main/resources/sql/supported/dal/install.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dal/install.xml
@@ -20,4 +20,12 @@
<sql-case id="install_component" value="INSTALL COMPONENT
'file://component1'" db-types="MySQL" />
<sql-case id="install_components" value="INSTALL COMPONENT
'file://component1', 'file://component2'" db-types="MySQL" />
<sql-case id="install_plugin" value="INSTALL PLUGIN binlog SONAME
'shared_library_name'" db-types="MySQL" />
+ <sql-case id="install_plugin_from" value="INSTALL PLUGIN FROM
"/home/users/doris/auditdemo.zip"" db-types="Doris" />
+ <sql-case id="install_plugin_with_properties" value="INSTALL PLUGIN FROM
"/home/users/doris/auditdemo.zip" PROPERTIES ("md5sum" =
"d41d8cd98f00b204e9800998ecf8427e")" db-types="Doris" />
+ <sql-case id="install_plugin_with_identifier" value="INSTALL PLUGIN FROM
plugin_path PROPERTIES (`timeout` = `30`)" db-types="Doris" />
+ <sql-case id="install_plugin_with_number" value="INSTALL PLUGIN FROM
"/path/to/plugin.zip" PROPERTIES ("timeout" = 30)"
db-types="Doris" />
+ <sql-case id="install_plugin_with_boolean" value="INSTALL PLUGIN FROM
"/path/to/plugin.zip" PROPERTIES ("auto_load" = true)"
db-types="Doris" />
+ <sql-case id="install_plugin_with_null" value="INSTALL PLUGIN FROM
"/path/to/plugin.zip" PROPERTIES ("description" = NULL)"
db-types="Doris" />
+ <sql-case id="install_plugin_multiple_properties" value="INSTALL PLUGIN
FROM "/path/to/plugin.zip" PROPERTIES ("md5sum" =
"abc123", "timeout" = 30)" db-types="Doris" />
+ <sql-case id="install_plugin_mixed_types" value="INSTALL PLUGIN FROM
"/path/to/plugin.zip" PROPERTIES ("md5sum" =
"abc123", "timeout" = 30, "auto_load" = false)"
db-types="Doris" />
</sql-cases>