This is an automated email from the ASF dual-hosted git repository.
terrymanu 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 3b26fb77d1b Support SqlServer update statement for Specifying a view
as the target object when use encrypt feature (#38896)
3b26fb77d1b is described below
commit 3b26fb77d1bf0d871829242a3d8d695c268512e5
Author: Claire <[email protected]>
AuthorDate: Wed Jun 24 21:06:04 2026 +0800
Support SqlServer update statement for Specifying a view as the target
object when use encrypt feature (#38896)
* support Specifying a view as the target object
* update release
* add test
* update RELEASE-NOTES.md
* update
---
RELEASE-NOTES.md | 1 +
.../EncryptProjectionTokenGenerator.java | 11 +++++++++
.../EncryptSelectProjectionTokenGenerator.java | 27 ++++++++++++++++++----
.../engine/scenario/EncryptSQLRewriterIT.java | 9 ++++++++
.../query-with-cipher/ddl/alter/alter-view.xml | 24 +++++++++++++++++++
.../query-with-cipher/ddl/create/create-view.xml | 24 +++++++++++++++++++
.../case/query-with-cipher/dml/update/update.xml | 5 ++++
.../scenario/encrypt/config/query-with-cipher.yaml | 12 ++++++++++
8 files changed, 109 insertions(+), 4 deletions(-)
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index de91e5a4e71..cbba7ce1784 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -62,6 +62,7 @@
1. Proxy: Support Firebird prepared statement cache reuse for held connections
- [#38644](https://github.com/apache/shardingsphere/pull/38644)
1. JDBC & Proxy: Add a check to verify database name naming conventions. -
[#38883](https://github.com/apache/shardingsphere/pull/38883)
1. Encrypt: Support SqlServer update statement for Specifying a table alias as
the target object when use encrypt feature -
[#38733](https://github.com/apache/shardingsphere/pull/38733)
+1. Encrypt: Support SqlServer update statement for Specifying a view as the
target object when use encrypt feature -
[#38896](https://github.com/apache/shardingsphere/pull/38896)
1. Sharding: Fix HASH_MOD routing mismatch for same negative numeric values
across numeric Java types with compatibility switch
`normalize-numeric-int-range` -
[#38327](https://github.com/apache/shardingsphere/pull/38327)
1. Proxy Native: Support building Proxy Native via GraalVM CE for JDK 25 -
[#38682](https://github.com/apache/shardingsphere/pull/38682)
diff --git
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/projection/EncryptProjectionTokenGenerator.java
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/projection/EncryptProjectionTokenGenerator.java
index 4401420576d..cd2217843d2 100644
---
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/projection/EncryptProjectionTokenGenerator.java
+++
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/projection/EncryptProjectionTokenGenerator.java
@@ -255,6 +255,9 @@ public final class EncryptProjectionTokenGenerator {
if (null == subqueryType || SubqueryType.PROJECTION == subqueryType) {
return Collections.singleton(generateProjection(encryptColumn,
columnProjection));
}
+ if (SubqueryType.VIEW_DEFINITION == subqueryType) {
+ return
Collections.singleton(generateViewDefinitionProjection(encryptColumn,
columnProjection));
+ }
if (SubqueryType.TABLE == subqueryType || SubqueryType.JOIN ==
subqueryType || SubqueryType.WITH == subqueryType) {
return generateProjectionsInTableSegmentSubquery(encryptColumn,
columnProjection);
}
@@ -277,6 +280,14 @@ public final class EncryptProjectionTokenGenerator {
databaseType,
columnProjection.getLeftParentheses().orElse(null),
columnProjection.getRightParentheses().orElse(null));
}
+ private ColumnProjection generateViewDefinitionProjection(final
EncryptColumn encryptColumn, final ColumnProjection columnProjection) {
+ String encryptColumnName = getEncryptColumnName(columnProjection,
encryptColumn);
+ QuoteCharacter quoteCharacter = getQuoteCharacter(columnProjection);
+ IdentifierValue cipherColumnName = new
IdentifierValue(encryptColumnName, quoteCharacter);
+ return new ColumnProjection(columnProjection.getOwner().orElse(null),
cipherColumnName, null,
+ databaseType,
columnProjection.getLeftParentheses().orElse(null),
columnProjection.getRightParentheses().orElse(null));
+ }
+
private QuoteCharacter getQuoteCharacter(final ColumnProjection
columnProjection) {
return TableSourceType.PHYSICAL_TABLE ==
columnProjection.getColumnBoundInfo().getTableSourceType()
? dialectDatabaseMetaData.getQuoteCharacter()
diff --git
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/projection/EncryptSelectProjectionTokenGenerator.java
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/projection/EncryptSelectProjectionTokenGenerator.java
index dd228f77ead..e35330b0f86 100644
---
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/projection/EncryptSelectProjectionTokenGenerator.java
+++
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/projection/EncryptSelectProjectionTokenGenerator.java
@@ -22,13 +22,17 @@ import lombok.Setter;
import org.apache.shardingsphere.encrypt.rule.EncryptRule;
import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation;
import
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import
org.apache.shardingsphere.infra.binder.context.statement.type.ddl.AlterViewStatementContext;
+import
org.apache.shardingsphere.infra.binder.context.statement.type.ddl.CreateViewStatementContext;
import
org.apache.shardingsphere.infra.binder.context.statement.type.dml.SelectStatementContext;
import
org.apache.shardingsphere.infra.rewrite.sql.token.common.generator.CollectionSQLTokenGenerator;
import
org.apache.shardingsphere.infra.rewrite.sql.token.common.generator.aware.PreviousSQLTokensAware;
import org.apache.shardingsphere.infra.rewrite.sql.token.common.pojo.SQLToken;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
+import java.util.Optional;
/**
* Select projection token generator for encrypt.
@@ -36,7 +40,7 @@ import java.util.List;
@HighFrequencyInvocation
@RequiredArgsConstructor
@Setter
-public final class EncryptSelectProjectionTokenGenerator implements
CollectionSQLTokenGenerator<SelectStatementContext>, PreviousSQLTokensAware {
+public final class EncryptSelectProjectionTokenGenerator implements
CollectionSQLTokenGenerator<SQLStatementContext>, PreviousSQLTokensAware {
private final EncryptRule rule;
@@ -44,11 +48,26 @@ public final class EncryptSelectProjectionTokenGenerator
implements CollectionSQ
@Override
public boolean isGenerateSQLToken(final SQLStatementContext
sqlStatementContext) {
- return sqlStatementContext instanceof SelectStatementContext &&
!sqlStatementContext.getTablesContext().getSimpleTables().isEmpty();
+ return extractSelectStatementContext(sqlStatementContext).map(each ->
!each.getTablesContext().getSimpleTables().isEmpty()).orElse(false);
}
@Override
- public Collection<SQLToken> generateSQLTokens(final SelectStatementContext
sqlStatementContext) {
- return new EncryptProjectionTokenGenerator(previousSQLTokens,
sqlStatementContext.getSqlStatement().getDatabaseType(),
rule).generateSQLTokens(sqlStatementContext);
+ public Collection<SQLToken> generateSQLTokens(final SQLStatementContext
sqlStatementContext) {
+ return extractSelectStatementContext(sqlStatementContext)
+ .map(each -> new
EncryptProjectionTokenGenerator(previousSQLTokens,
each.getSqlStatement().getDatabaseType(), rule).generateSQLTokens(each))
+ .orElse(Collections.emptyList());
+ }
+
+ private Optional<SelectStatementContext>
extractSelectStatementContext(final SQLStatementContext sqlStatementContext) {
+ if (sqlStatementContext instanceof SelectStatementContext) {
+ return Optional.of((SelectStatementContext) sqlStatementContext);
+ }
+ if (sqlStatementContext instanceof CreateViewStatementContext) {
+ return Optional.of(((CreateViewStatementContext)
sqlStatementContext).getSelectStatementContext());
+ }
+ if (sqlStatementContext instanceof AlterViewStatementContext) {
+ return ((AlterViewStatementContext)
sqlStatementContext).getSelectStatementContext();
+ }
+ return Optional.empty();
}
}
diff --git
a/test/it/rewriter/src/test/java/org/apache/shardingsphere/test/it/rewriter/engine/scenario/EncryptSQLRewriterIT.java
b/test/it/rewriter/src/test/java/org/apache/shardingsphere/test/it/rewriter/engine/scenario/EncryptSQLRewriterIT.java
index e323e87eeb1..578272e7b8b 100644
---
a/test/it/rewriter/src/test/java/org/apache/shardingsphere/test/it/rewriter/engine/scenario/EncryptSQLRewriterIT.java
+++
b/test/it/rewriter/src/test/java/org/apache/shardingsphere/test/it/rewriter/engine/scenario/EncryptSQLRewriterIT.java
@@ -17,6 +17,7 @@
package org.apache.shardingsphere.test.it.rewriter.engine.scenario;
+import
org.apache.shardingsphere.database.connector.core.metadata.database.enums.TableType;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
@@ -82,6 +83,12 @@ class EncryptSQLRewriterIT extends SQLRewriterIT {
new ShardingSphereColumn("WorkOrderID", Types.INTEGER, false,
false, false, true, false, false),
new ShardingSphereColumn("ScrapReasonID", Types.INTEGER,
false, false, false, true, false, false),
new ShardingSphereColumn("ScrappedQty", Types.INTEGER, false,
false, false, true, false, false)), Collections.emptyList(),
Collections.emptyList()));
+ tables.add(new ShardingSphereTable("StateRegion", Arrays.asList(
+ new ShardingSphereColumn("StateCode", Types.INTEGER, false,
false, false, true, false, false),
+ new ShardingSphereColumn("CountryRegionName", Types.VARCHAR,
false, false, false, true, false, false)), Collections.emptyList(),
Collections.emptyList()));
+ tables.add(new ShardingSphereTable("vStateProvinceCountryRegion",
Arrays.asList(
+ new ShardingSphereColumn("StateCode", Types.INTEGER, false,
false, false, true, false, false),
+ new ShardingSphereColumn("CountryRegionName", Types.VARCHAR,
false, false, false, true, false, false)), Collections.emptyList(),
Collections.emptyList(), TableType.VIEW));
return Collections.singleton(new ShardingSphereSchema(schemaName,
mock(DatabaseType.class), tables, Collections.emptyList()));
}
@@ -96,6 +103,8 @@ class EncryptSQLRewriterIT extends SQLRewriterIT {
singleRule.get().getAttributes().getAttribute(MutableDataNodeRuleAttribute.class).put("encrypt_ds",
schemaName, "t_user");
singleRule.get().getAttributes().getAttribute(MutableDataNodeRuleAttribute.class).put("encrypt_ds",
schemaName, "ScrapReason");
singleRule.get().getAttributes().getAttribute(MutableDataNodeRuleAttribute.class).put("encrypt_ds",
schemaName, "WorkOrder");
+
singleRule.get().getAttributes().getAttribute(MutableDataNodeRuleAttribute.class).put("encrypt_ds",
schemaName, "StateRegion");
+
singleRule.get().getAttributes().getAttribute(MutableDataNodeRuleAttribute.class).put("encrypt_ds",
schemaName, "vStateProvinceCountryRegion");
}
}
}
diff --git
a/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/ddl/alter/alter-view.xml
b/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/ddl/alter/alter-view.xml
new file mode 100644
index 00000000000..2901799857f
--- /dev/null
+++
b/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/ddl/alter/alter-view.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<rewrite-assertions yaml-rule="scenario/encrypt/config/query-with-cipher.yaml">
+ <rewrite-assertion
id="alter_view_state_province_country_region_for_literals" db-types="SQLServer">
+ <input sql="ALTER VIEW dbo.vStateProvinceCountryRegion AS SELECT
StateCode, CountryRegionName FROM dbo.StateRegion" />
+ <output sql="ALTER VIEW dbo.vStateProvinceCountryRegion AS SELECT
StateCode, [country_region_name_cipher] FROM dbo.StateRegion" />
+ </rewrite-assertion>
+</rewrite-assertions>
diff --git
a/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/ddl/create/create-view.xml
b/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/ddl/create/create-view.xml
new file mode 100644
index 00000000000..d6c02711913
--- /dev/null
+++
b/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/ddl/create/create-view.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<rewrite-assertions yaml-rule="scenario/encrypt/config/query-with-cipher.yaml">
+ <rewrite-assertion
id="create_view_state_province_country_region_for_literals"
db-types="SQLServer">
+ <input sql="/* SHARDINGSPHERE_HINT: SKIP_METADATA_VALIDATE=true */
CREATE VIEW dbo.vStateProvinceCountryRegion AS SELECT StateCode,
CountryRegionName FROM dbo.StateRegion" />
+ <output sql="CREATE VIEW dbo.vStateProvinceCountryRegion AS SELECT
StateCode, [country_region_name_cipher] FROM dbo.StateRegion" />
+ </rewrite-assertion>
+</rewrite-assertions>
diff --git
a/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/update/update.xml
b/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/update/update.xml
index 161e1d6ca7d..58b3a11388b 100644
---
a/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/update/update.xml
+++
b/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/update/update.xml
@@ -104,4 +104,9 @@
<input sql="UPDATE ScrapReason AS sr SET Name = Name || ' - tool
malfunction', Remark = 'tool malfunction' FROM WorkOrder AS wo WHERE
sr.ScrapReasonID = wo.ScrapReasonID AND wo.ScrappedQty > 300" />
<output sql="UPDATE ScrapReason AS sr SET Name = Name || ' - tool
malfunction', "remark_cipher" = 'encrypt_tool malfunction' FROM
WorkOrder AS wo WHERE sr.ScrapReasonID = wo.ScrapReasonID AND wo.ScrappedQty
> 300" />
</rewrite-assertion>
+
+ <rewrite-assertion
id="update_state_province_country_region_view_for_literals"
db-types="SQLServer">
+ <input sql="UPDATE dbo.vStateProvinceCountryRegion SET
CountryRegionName = 'United States of America' WHERE CountryRegionName =
'United States'" />
+ <output sql="UPDATE dbo.vStateProvinceCountryRegion SET
[country_region_name_cipher] = 'encrypt_United States of America' WHERE
[country_region_name_cipher] = 'encrypt_United States'" />
+ </rewrite-assertion>
</rewrite-assertions>
diff --git
a/test/it/rewriter/src/test/resources/scenario/encrypt/config/query-with-cipher.yaml
b/test/it/rewriter/src/test/resources/scenario/encrypt/config/query-with-cipher.yaml
index 5c047405ec9..ee2b6060f50 100644
---
a/test/it/rewriter/src/test/resources/scenario/encrypt/config/query-with-cipher.yaml
+++
b/test/it/rewriter/src/test/resources/scenario/encrypt/config/query-with-cipher.yaml
@@ -158,6 +158,18 @@ rules:
cipher:
name: remark_cipher
encryptorName: rewrite_normal_fixture
+ StateRegion:
+ columns:
+ CountryRegionName:
+ cipher:
+ name: country_region_name_cipher
+ encryptorName: rewrite_normal_fixture
+ vStateProvinceCountryRegion:
+ columns:
+ CountryRegionName:
+ cipher:
+ name: country_region_name_cipher
+ encryptorName: rewrite_normal_fixture
encryptors:
rewrite_normal_fixture:
type: REWRITE.NORMAL.FIXTURE