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 f7fc77edc35 Refactor DatabaseAdminExecutorCreator (#36848)
f7fc77edc35 is described below

commit f7fc77edc3518414650268fa9e7be6118e8c974e
Author: Liang Zhang <[email protected]>
AuthorDate: Sat Oct 11 14:51:09 2025 +0800

    Refactor DatabaseAdminExecutorCreator (#36848)
---
 .../handler/ProxyBackendHandlerFactory.java        |  3 +--
 .../DatabaseAdminProxyBackendHandlerFactory.java   | 17 -----------------
 .../executor/DatabaseAdminExecutorCreator.java     |  8 --------
 .../admin/FirebirdAdminExecutorCreator.java        | 12 +++---------
 .../admin/FirebirdAdminExecutorCreatorTest.java    | 22 ++++++++--------------
 .../handler/admin/MySQLAdminExecutorCreator.java   |  5 -----
 .../admin/MySQLAdminExecutorCreatorTest.java       |  6 ------
 .../admin/OpenGaussAdminExecutorCreator.java       | 10 +++-------
 .../admin/OpenGaussAdminExecutorFactoryTest.java   |  2 +-
 .../admin/PostgreSQLAdminExecutorCreator.java      | 12 +++---------
 .../admin/PostgreSQLAdminExecutorCreatorTest.java  | 21 ++++++++-------------
 11 files changed, 27 insertions(+), 91 deletions(-)

diff --git 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java
 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java
index bb3063112d2..18c81f2541c 100644
--- 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java
+++ 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactory.java
@@ -147,8 +147,7 @@ public final class ProxyBackendHandlerFactory {
             return 
DatabaseProxyBackendHandlerFactory.newInstance(queryContext, connectionSession, 
preferPreparedStatement);
         }
         checkSQLExecution(queryContext, 
connectionSession.getConnectionContext().getGrantee(), databaseName);
-        return 
DatabaseAdminProxyBackendHandlerFactory.newInstance(databaseType, 
sqlStatementContext, connectionSession)
-                .orElseGet(() -> 
DatabaseProxyBackendHandlerFactory.newInstance(queryContext, connectionSession, 
preferPreparedStatement));
+        return DatabaseProxyBackendHandlerFactory.newInstance(queryContext, 
connectionSession, preferPreparedStatement);
     }
     
     private static void checkAllowedSQLStatementWhenTransactionFailed(final 
DatabaseType databaseType, final SQLStatement sqlStatement,
diff --git 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/DatabaseAdminProxyBackendHandlerFactory.java
 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/DatabaseAdminProxyBackendHandlerFactory.java
index 5ab14cbfd29..28333fe193f 100644
--- 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/DatabaseAdminProxyBackendHandlerFactory.java
+++ 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/DatabaseAdminProxyBackendHandlerFactory.java
@@ -38,23 +38,6 @@ import java.util.Optional;
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 public final class DatabaseAdminProxyBackendHandlerFactory {
     
-    /**
-     * Create new instance of database admin backend handler, and this handler 
requires a connection containing a schema to be used.
-     *
-     * @param databaseType database type
-     * @param sqlStatementContext SQL statement context
-     * @param connectionSession connection session
-     * @return created instance
-     */
-    public static Optional<ProxyBackendHandler> newInstance(final DatabaseType 
databaseType, final SQLStatementContext sqlStatementContext, final 
ConnectionSession connectionSession) {
-        Optional<DatabaseAdminExecutorCreator> executorCreator = 
DatabaseTypedSPILoader.findService(DatabaseAdminExecutorCreator.class, 
databaseType);
-        if (!executorCreator.isPresent()) {
-            return Optional.empty();
-        }
-        Optional<DatabaseAdminExecutor> executor = 
executorCreator.get().create(sqlStatementContext);
-        return executor.map(optional -> 
createProxyBackendHandler(sqlStatementContext, connectionSession, optional));
-    }
-    
     /**
      * Create new instance of database admin backend handler.
      *
diff --git 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/executor/DatabaseAdminExecutorCreator.java
 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/executor/DatabaseAdminExecutorCreator.java
index b9548060046..0c93fe2bcd5 100644
--- 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/executor/DatabaseAdminExecutorCreator.java
+++ 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/executor/DatabaseAdminExecutorCreator.java
@@ -30,14 +30,6 @@ import java.util.Optional;
 @SingletonSPI
 public interface DatabaseAdminExecutorCreator extends DatabaseTypedSPI {
     
-    /**
-     * Create database admin executor, and this executor requires a connection 
containing a schema to be used.
-     *
-     * @param sqlStatementContext SQL statement context
-     * @return created instance
-     */
-    Optional<DatabaseAdminExecutor> create(SQLStatementContext 
sqlStatementContext);
-    
     /**
      * Create database admin executor.
      *
diff --git 
a/proxy/backend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/backend/firebird/handler/admin/FirebirdAdminExecutorCreator.java
 
b/proxy/backend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/backend/firebird/handler/admin/FirebirdAdminExecutorCreator.java
index 9b30ba5db05..3420eb9840f 100644
--- 
a/proxy/backend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/backend/firebird/handler/admin/FirebirdAdminExecutorCreator.java
+++ 
b/proxy/backend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/backend/firebird/handler/admin/FirebirdAdminExecutorCreator.java
@@ -35,15 +35,6 @@ import java.util.Optional;
  */
 public final class FirebirdAdminExecutorCreator implements 
DatabaseAdminExecutorCreator {
     
-    @Override
-    public Optional<DatabaseAdminExecutor> create(final SQLStatementContext 
sqlStatementContext) {
-        SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
-        if (sqlStatement instanceof ShowStatement) {
-            return Optional.of(new 
FirebirdShowVariableExecutor((ShowStatement) sqlStatement));
-        }
-        return Optional.empty();
-    }
-    
     @Override
     public Optional<DatabaseAdminExecutor> create(final SQLStatementContext 
sqlStatementContext, final String sql, final String databaseName, final 
List<Object> parameters) {
         SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
@@ -54,6 +45,9 @@ public final class FirebirdAdminExecutorCreator implements 
DatabaseAdminExecutor
         if (sqlStatement instanceof SetStatement) {
             return Optional.of(new 
FirebirdSetVariableAdminExecutor((SetStatement) sqlStatement));
         }
+        if (sqlStatement instanceof ShowStatement) {
+            return Optional.of(new 
FirebirdShowVariableExecutor((ShowStatement) sqlStatement));
+        }
         return Optional.empty();
     }
     
diff --git 
a/proxy/backend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/backend/firebird/handler/admin/FirebirdAdminExecutorCreatorTest.java
 
b/proxy/backend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/backend/firebird/handler/admin/FirebirdAdminExecutorCreatorTest.java
index 6d848c6155f..abc4b55b9a2 100644
--- 
a/proxy/backend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/backend/firebird/handler/admin/FirebirdAdminExecutorCreatorTest.java
+++ 
b/proxy/backend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/backend/firebird/handler/admin/FirebirdAdminExecutorCreatorTest.java
@@ -29,7 +29,6 @@ import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.DatabaseAd
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dal.SetStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dal.ShowStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.DeleteStatement;
-import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.InsertStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
 import org.junit.jupiter.api.Test;
 
@@ -47,19 +46,6 @@ class FirebirdAdminExecutorCreatorTest {
     
     private final DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "Firebird");
     
-    @Test
-    void assertCreateWithOtherSQLStatementContextOnly() {
-        assertThat(new FirebirdAdminExecutorCreator().create(new 
CommonSQLStatementContext(new InsertStatement(databaseType))), 
is(Optional.empty()));
-    }
-    
-    @Test
-    void assertCreateWithShowSQLStatement() {
-        Optional<DatabaseAdminExecutor> actual = new 
FirebirdAdminExecutorCreator().create(
-                new CommonSQLStatementContext(new ShowStatement(databaseType, 
"server_version")));
-        assertTrue(actual.isPresent());
-        assertThat(actual.get(), isA(FirebirdShowVariableExecutor.class));
-    }
-    
     @Test
     void assertCreateWithSelectNonSystem() {
         SelectStatementContext selectStatementContext = 
mock(SelectStatementContext.class);
@@ -75,6 +61,14 @@ class FirebirdAdminExecutorCreatorTest {
         assertThat(actual.get(), isA(FirebirdSetVariableAdminExecutor.class));
     }
     
+    @Test
+    void assertCreateWithShowSQLStatement() {
+        Optional<DatabaseAdminExecutor> actual = new 
FirebirdAdminExecutorCreator().create(
+                new CommonSQLStatementContext(new ShowStatement(databaseType, 
"server_version")), "SHOW server_version", "", Collections.emptyList());
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), isA(FirebirdShowVariableExecutor.class));
+    }
+    
     @Test
     void assertCreateWithDMLStatement() {
         DeleteStatementContext sqlStatementContext = new 
DeleteStatementContext(new DeleteStatement(databaseType));
diff --git 
a/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreator.java
 
b/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreator.java
index 792d47fee3a..ff6584798b7 100644
--- 
a/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreator.java
+++ 
b/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreator.java
@@ -70,11 +70,6 @@ public final class MySQLAdminExecutorCreator implements 
DatabaseAdminExecutorCre
     
     private static final String SYS_SCHEMA = "sys";
     
-    @Override
-    public Optional<DatabaseAdminExecutor> create(final SQLStatementContext 
sqlStatementContext) {
-        return Optional.empty();
-    }
-    
     @Override
     public Optional<DatabaseAdminExecutor> create(final SQLStatementContext 
sqlStatementContext, final String sql, final String databaseName, final 
List<Object> parameters) {
         if (sqlStatementContext instanceof SelectStatementContext) {
diff --git 
a/proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreatorTest.java
 
b/proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreatorTest.java
index 95344d0e7d6..47527fc2291 100644
--- 
a/proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreatorTest.java
+++ 
b/proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreatorTest.java
@@ -117,12 +117,6 @@ class MySQLAdminExecutorCreatorTest {
         assertThat(actual.get(), isA(ShowTablesExecutor.class));
     }
     
-    @Test
-    void assertCreateWithOtherSQLStatementContext() {
-        SQLStatementContext sqlStatementContext = 
mock(SQLStatementContext.class);
-        assertThat(new 
MySQLAdminExecutorCreator().create(sqlStatementContext), is(Optional.empty()));
-    }
-    
     @Test
     void assertCreateWithUse() {
         SQLStatementContext sqlStatementContext = new 
CommonSQLStatementContext(new MySQLUseStatement(databaseType, null));
diff --git 
a/proxy/backend/dialect/opengauss/src/main/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreator.java
 
b/proxy/backend/dialect/opengauss/src/main/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreator.java
index 3cf59bfffb4..5f58f37796a 100644
--- 
a/proxy/backend/dialect/opengauss/src/main/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreator.java
+++ 
b/proxy/backend/dialect/opengauss/src/main/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreator.java
@@ -22,7 +22,6 @@ import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.DatabaseAd
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.DatabaseAdminExecutorCreator;
 import 
org.apache.shardingsphere.proxy.backend.opengauss.handler.admin.executor.OpenGaussShowVariableExecutor;
 import 
org.apache.shardingsphere.proxy.backend.postgresql.handler.admin.PostgreSQLAdminExecutorCreator;
-import 
org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dal.ShowStatement;
 
 import java.util.List;
@@ -35,12 +34,6 @@ public final class OpenGaussAdminExecutorCreator implements 
DatabaseAdminExecuto
     
     private final PostgreSQLAdminExecutorCreator delegate = new 
PostgreSQLAdminExecutorCreator();
     
-    @Override
-    public Optional<DatabaseAdminExecutor> create(final SQLStatementContext 
sqlStatementContext) {
-        SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
-        return sqlStatement instanceof ShowStatement ? Optional.of(new 
OpenGaussShowVariableExecutor((ShowStatement) sqlStatement)) : Optional.empty();
-    }
-    
     @Override
     public Optional<DatabaseAdminExecutor> create(final SQLStatementContext 
sqlStatementContext, final String sql, final String databaseName, final 
List<Object> parameters) {
         OpenGaussSystemTableQueryExecutorCreator 
systemTableQueryExecutorCreator = new 
OpenGaussSystemTableQueryExecutorCreator(sqlStatementContext, sql, parameters);
@@ -51,6 +44,9 @@ public final class OpenGaussAdminExecutorCreator implements 
DatabaseAdminExecuto
         if (functionQueryExecutorCreator.accept()) {
             return functionQueryExecutorCreator.create();
         }
+        if (sqlStatementContext.getSqlStatement() instanceof ShowStatement) {
+            return Optional.of(new 
OpenGaussShowVariableExecutor((ShowStatement) 
sqlStatementContext.getSqlStatement()));
+        }
         return delegate.create(sqlStatementContext, sql, databaseName, 
parameters);
     }
     
diff --git 
a/proxy/backend/dialect/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorFactoryTest.java
 
b/proxy/backend/dialect/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorFactoryTest.java
index 747d79c01de..fe1d697f53f 100644
--- 
a/proxy/backend/dialect/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorFactoryTest.java
+++ 
b/proxy/backend/dialect/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorFactoryTest.java
@@ -66,7 +66,7 @@ class OpenGaussAdminExecutorFactoryTest {
     @Test
     void assertNewInstanceWithSQLStatementContext() {
         SQLStatementContext sqlStatementContext = new 
CommonSQLStatementContext(new ShowStatement(databaseType, "all"));
-        Optional<DatabaseAdminExecutor> actual = 
openGaussAdminExecutorFactory.create(sqlStatementContext);
+        Optional<DatabaseAdminExecutor> actual = 
openGaussAdminExecutorFactory.create(sqlStatementContext, "SHOW ALL", null, 
Collections.emptyList());
         assertTrue(actual.isPresent());
     }
     
diff --git 
a/proxy/backend/dialect/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreator.java
 
b/proxy/backend/dialect/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreator.java
index dfaf8562e12..6e85e8e2702 100644
--- 
a/proxy/backend/dialect/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreator.java
+++ 
b/proxy/backend/dialect/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreator.java
@@ -62,15 +62,6 @@ public final class PostgreSQLAdminExecutorCreator implements 
DatabaseAdminExecut
         SCHEMA_TABLES.put("shardingsphere", new 
CaseInsensitiveSet<>(Collections.singletonList("cluster_information")));
     }
     
-    @Override
-    public Optional<DatabaseAdminExecutor> create(final SQLStatementContext 
sqlStatementContext) {
-        SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
-        if (sqlStatement instanceof ShowStatement) {
-            return Optional.of(new 
PostgreSQLShowVariableExecutor((ShowStatement) sqlStatement));
-        }
-        return Optional.empty();
-    }
-    
     @Override
     public Optional<DatabaseAdminExecutor> create(final SQLStatementContext 
sqlStatementContext, final String sql, final String databaseName, final 
List<Object> parameters) {
         SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
@@ -89,6 +80,9 @@ public final class PostgreSQLAdminExecutorCreator implements 
DatabaseAdminExecut
         if (sqlStatement instanceof PostgreSQLResetParameterStatement) {
             return Optional.of(new 
PostgreSQLResetVariableAdminExecutor((PostgreSQLResetParameterStatement) 
sqlStatement));
         }
+        if (sqlStatement instanceof ShowStatement) {
+            return Optional.of(new 
PostgreSQLShowVariableExecutor((ShowStatement) sqlStatement));
+        }
         return Optional.empty();
     }
     
diff --git 
a/proxy/backend/dialect/postgresql/src/test/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreatorTest.java
 
b/proxy/backend/dialect/postgresql/src/test/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreatorTest.java
index d5bc944adf3..8e0385bb00f 100644
--- 
a/proxy/backend/dialect/postgresql/src/test/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreatorTest.java
+++ 
b/proxy/backend/dialect/postgresql/src/test/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreatorTest.java
@@ -34,7 +34,6 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatemen
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dal.SetStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dal.ShowStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.DeleteStatement;
-import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.InsertStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.postgresql.dal.PostgreSQLResetParameterStatement;
 import org.junit.jupiter.api.Test;
@@ -68,18 +67,6 @@ class PostgreSQLAdminExecutorCreatorTest {
     
     private final DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "PostgreSQL");
     
-    @Test
-    void assertCreateWithOtherSQLStatementContextOnly() {
-        assertThat(new PostgreSQLAdminExecutorCreator().create(new 
CommonSQLStatementContext(new InsertStatement(databaseType))), 
is(Optional.empty()));
-    }
-    
-    @Test
-    void assertCreateWithShowSQLStatement() {
-        Optional<DatabaseAdminExecutor> actual = new 
PostgreSQLAdminExecutorCreator().create(new CommonSQLStatementContext(new 
ShowStatement(databaseType, "client_encoding")));
-        assertTrue(actual.isPresent());
-        assertThat(actual.get(), isA(PostgreSQLShowVariableExecutor.class));
-    }
-    
     @Test
     void assertCreateWithSelectDatabase() {
         SQLStatement sqlStatement = parseSQL(PSQL_SELECT_DATABASES);
@@ -145,6 +132,14 @@ class PostgreSQLAdminExecutorCreatorTest {
         assertThat(actual.get(), 
isA(PostgreSQLResetVariableAdminExecutor.class));
     }
     
+    @Test
+    void assertCreateWithShowSQLStatement() {
+        Optional<DatabaseAdminExecutor> actual = new 
PostgreSQLAdminExecutorCreator().create(
+                new CommonSQLStatementContext(new ShowStatement(databaseType, 
"client_encoding")), "SHOW client_encoding", "", Collections.emptyList());
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), isA(PostgreSQLShowVariableExecutor.class));
+    }
+    
     @Test
     void assertCreateWithDMLStatement() {
         DeleteStatementContext sqlStatementContext = new 
DeleteStatementContext(new DeleteStatement(databaseType));

Reply via email to