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 505424233e2 Support SqlServer for Using the UPDATE statement with
information from another table when use encrypt feature (#38926)
505424233e2 is described below
commit 505424233e2c320db166895f2db4d4f1faaa73d1
Author: Claire <[email protected]>
AuthorDate: Sat Jun 27 20:41:59 2026 +0800
Support SqlServer for Using the UPDATE statement with information from
another table when use encrypt feature (#38926)
* support Updating Data Based on Data From Other Tables
* update
* update test
---
RELEASE-NOTES.md | 1 +
.../dml/from/type/SimpleTableSegmentBinder.java | 41 +++++++++++++++++----
.../statement/dml/UpdateStatementBinderTest.java | 22 +++++++++++
.../statement/SQLServerStatementVisitor.java | 43 ++++++++++++++++++++--
.../engine/scenario/EncryptSQLRewriterIT.java | 23 +++++++++++-
.../case/query-with-cipher/dml/update/update.xml | 15 ++++++++
.../scenario/encrypt/config/query-with-cipher.yaml | 10 +++++
7 files changed, 143 insertions(+), 12 deletions(-)
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index c5b587f741a..23d376ea2b4 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -65,6 +65,7 @@
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. Encrypt: Support SqlServer for Using the UPDATE statement with information
from another table when use encrypt feature -
[#38926](https://github.com/apache/shardingsphere/pull/38926)
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)
1. SQL Parser: Support SQLServer table variable declaration parse -
[#38904](https://github.com/apache/shardingsphere/pull/38904)
diff --git
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SimpleTableSegmentBinder.java
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SimpleTableSegmentBinder.java
index 8b58d65f0c1..7d47b3e4ef0 100644
---
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SimpleTableSegmentBinder.java
+++
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SimpleTableSegmentBinder.java
@@ -73,6 +73,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Optional;
+import java.util.stream.Collectors;
/**
* Simple table segment binder.
@@ -95,10 +96,10 @@ public final class SimpleTableSegmentBinder {
Optional<IdentifierValue> schemaName = getSchemaName(segment,
binderContext, databaseName);
IdentifierValue tableName = segment.getTableName().getIdentifier();
Optional<ShardingSphereSchema> schema = schemaName.map(identifierValue
->
binderContext.getMetaData().getDatabase(databaseName).getSchema(identifierValue));
- if (isUpdateTargetTableAlias(binderContext, tableBinderContexts,
tableName.getValue(), segment)) {
+ if (isUpdateTargetTableAlias(binderContext, tableBinderContexts,
schemaName, tableName.getValue(), segment)) {
return bindUpdateTargetTableAlias(segment, binderContext,
tableBinderContexts, databaseName, schemaName, tableName);
}
- checkTableExists(binderContext, schema.orElse(null), tableName,
segment, tableBinderContexts);
+ checkTableExists(binderContext, schema.orElse(null), schemaName,
tableName, segment, tableBinderContexts);
checkTableMetadata(binderContext, schema.orElse(null),
schemaName.map(IdentifierValue::getValue).orElse(null), tableName);
String tableAliasOrName =
segment.getAliasName().orElseGet(tableName::getValue);
Optional<SimpleTableSegmentBinderContext> tableBinderContext =
createSimpleTableBinderContext(segment, schema.orElse(null), databaseName,
schemaName.orElse(null), binderContext);
@@ -151,7 +152,7 @@ public final class SimpleTableSegmentBinder {
}
private static boolean isUpdateTargetTableAlias(final
SQLStatementBinderContext binderContext, final Multimap<CaseInsensitiveString,
TableSegmentBinderContext> tableBinderContexts,
- final String
tableNameValue, final SimpleTableSegment segment) {
+ final
Optional<IdentifierValue> schemaName, final String tableNameValue, final
SimpleTableSegment segment) {
if (!(binderContext.getSqlStatement() instanceof UpdateStatement)) {
return false;
}
@@ -171,13 +172,17 @@ public final class SimpleTableSegmentBinder {
if (segment.getAliasName().isPresent()) {
return false;
}
- return
tableBinderContexts.containsKey(CaseInsensitiveString.of(tableNameValue));
+ return !segment.getOwner().isPresent() &&
tableBinderContexts.containsKey(CaseInsensitiveString.of(tableNameValue))
+ || tableBinderContexts.values().stream().anyMatch(each ->
isSameUpdateTargetTableContext(segment, schemaName, tableNameValue, each));
}
private static SimpleTableSegment bindUpdateTargetTableAlias(final
SimpleTableSegment segment, final SQLStatementBinderContext binderContext,
final
Multimap<CaseInsensitiveString, TableSegmentBinderContext> tableBinderContexts,
final IdentifierValue databaseName,
final
Optional<IdentifierValue> schemaName, final IdentifierValue tableName) {
- Collection<TableSegmentBinderContext> fromTableContexts =
tableBinderContexts.get(CaseInsensitiveString.of(tableName.getValue()));
+ Collection<TableSegmentBinderContext> fromTableContexts =
!segment.getOwner().isPresent() &&
tableBinderContexts.containsKey(CaseInsensitiveString.of(tableName.getValue()))
+ ?
tableBinderContexts.get(CaseInsensitiveString.of(tableName.getValue()))
+ : tableBinderContexts.values().stream()
+ .filter(each ->
isSameUpdateTargetTableContext(segment, schemaName, tableName.getValue(),
each)).collect(Collectors.toList());
IdentifierValue originalTableName = fromTableContexts.stream()
.map(TableSegmentBinderContext::getOriginalTableName).filter(Optional::isPresent).map(Optional::get).findFirst().orElse(tableName);
Optional<OwnerSegment> fromTableOwner = fromTableContexts.stream()
@@ -191,10 +196,32 @@ public final class SimpleTableSegmentBinder {
return result;
}
- private static void checkTableExists(final SQLStatementBinderContext
binderContext, final ShardingSphereSchema schema, final IdentifierValue
tableName, final SimpleTableSegment segment,
+ private static boolean isSameUpdateTargetTableContext(final
SimpleTableSegment targetTable, final Optional<IdentifierValue> schemaName,
final String tableName,
+ final
TableSegmentBinderContext tableBinderContext) {
+ return tableBinderContext.getOriginalTableName().map(each ->
each.getValue().equalsIgnoreCase(tableName)).orElse(false)
+ && isSameUpdateTargetOwner(targetTable, schemaName,
tableBinderContext);
+ }
+
+ private static boolean isSameUpdateTargetOwner(final SimpleTableSegment
targetTable, final Optional<IdentifierValue> schemaName,
+ final
TableSegmentBinderContext tableBinderContext) {
+ Optional<OwnerSegment> originalOwner =
tableBinderContext.getOriginalOwner();
+ if (!targetTable.getOwner().isPresent()) {
+ return !originalOwner.isPresent() || schemaName.map(optional ->
originalOwner.get().getIdentifier().getValue().equalsIgnoreCase(optional.getValue())).orElse(false);
+ }
+ return originalOwner.isPresent() &&
isSameOwner(targetTable.getOwner().get(), originalOwner.get());
+ }
+
+ private static boolean isSameOwner(final OwnerSegment targetOwner, final
OwnerSegment originalOwner) {
+ return
targetOwner.getIdentifier().getValue().equalsIgnoreCase(originalOwner.getIdentifier().getValue())
+ && targetOwner.getOwner().isPresent() ==
originalOwner.getOwner().isPresent()
+ && (!targetOwner.getOwner().isPresent() ||
isSameOwner(targetOwner.getOwner().get(), originalOwner.getOwner().get()));
+ }
+
+ private static void checkTableExists(final SQLStatementBinderContext
binderContext, final ShardingSphereSchema schema, final
Optional<IdentifierValue> schemaName,
+ final IdentifierValue tableName,
final SimpleTableSegment segment,
final Multimap<CaseInsensitiveString,
TableSegmentBinderContext> tableBinderContexts) {
String tableNameValue = tableName.getValue();
- if (isUpdateTargetTableAlias(binderContext, tableBinderContexts,
tableNameValue, segment)) {
+ if (isUpdateTargetTableAlias(binderContext, tableBinderContexts,
schemaName, tableNameValue, segment)) {
return;
}
// TODO refactor table exists check with spi @duanzhengqiang
diff --git
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinderTest.java
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinderTest.java
index 53b3ba27fc0..0dbdbcaf75f 100644
---
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinderTest.java
+++
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinderTest.java
@@ -129,6 +129,28 @@ class UpdateStatementBinderTest {
assertTrue(actual.isTargetTableIsFromAlias());
}
+ @Test
+ void assertBindUpdateTargetTableNameWithFromAlias() {
+ SimpleTableSegment targetTable = new SimpleTableSegment(new
TableNameSegment(0, 0, new IdentifierValue("t_order")));
+ SimpleTableSegment fromTable = new SimpleTableSegment(new
TableNameSegment(0, 0, new IdentifierValue("t_order")));
+ fromTable.setAlias(new AliasSegment(0, 0, new IdentifierValue("o")));
+ ColumnSegment columnSegment = new ColumnSegment(0, 0, new
IdentifierValue("status"));
+ UpdateStatement updateStatement = UpdateStatement.builder()
+ .databaseType(databaseType)
+ .table(targetTable)
+ .from(fromTable)
+ .setAssignment(new SetAssignmentSegment(0, 0,
Collections.singletonList(
+ new ColumnAssignmentSegment(0, 0,
Collections.singletonList(columnSegment), new LiteralExpressionSegment(0, 0,
1)))))
+ .targetTableIsFromAlias(true)
+ .build();
+ UpdateStatement actual = new
UpdateStatementBinder().bind(updateStatement,
+ new SQLStatementBinderContext(createMetaData(), "foo_db", new
HintValueContext(), updateStatement));
+ ColumnSegment actualColumn =
actual.getAssignment().get().getAssignments().iterator().next().getColumns().iterator().next();
+ assertThat(((SimpleTableSegment)
actual.getTable()).getTableName().getIdentifier().getValue(), is("t_order"));
+
assertThat(actualColumn.getColumnBoundInfo().getOriginalTable().getValue(),
is("t_order"));
+ assertTrue(actual.isTargetTableIsFromAlias());
+ }
+
@Test
void assertBindSchemaQualifiedUpdateTargetTableAlias() {
SimpleTableSegment targetTable = new SimpleTableSegment(new
TableNameSegment(0, 0, new IdentifierValue("o")));
diff --git
a/parser/sql/engine/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/engine/sqlserver/visitor/statement/SQLServerStatementVisitor.java
b/parser/sql/engine/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/engine/sqlserver/visitor/statement/SQLServerStatementVisitor.java
index e35e6a67a7c..8f22291b8e8 100644
---
a/parser/sql/engine/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/engine/sqlserver/visitor/statement/SQLServerStatementVisitor.java
+++
b/parser/sql/engine/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/engine/sqlserver/visitor/statement/SQLServerStatementVisitor.java
@@ -1732,20 +1732,55 @@ public abstract class SQLServerStatementVisitor extends
SQLServerStatementBaseVi
if (null == fromTable || !(targetTable instanceof SimpleTableSegment))
{
return false;
}
- String targetName = ((SimpleTableSegment)
targetTable).getTableName().getIdentifier().getValue();
- return isAliasInFromClause(targetName, fromTable);
+ SimpleTableSegment targetSimpleTable = (SimpleTableSegment)
targetTable;
+ String targetName =
targetSimpleTable.getTableName().getIdentifier().getValue();
+ return isAliasInFromClause(targetSimpleTable, targetName, fromTable)
|| isTableNameWithAliasInFromClause(targetSimpleTable, fromTable);
}
- private boolean isAliasInFromClause(final String targetName, final
TableSegment fromSegment) {
+ private boolean isAliasInFromClause(final SimpleTableSegment targetTable,
final String targetName, final TableSegment fromSegment) {
+ if (targetTable.getOwner().isPresent()) {
+ return false;
+ }
if (fromSegment instanceof SimpleTableSegment) {
return targetName.equalsIgnoreCase(((SimpleTableSegment)
fromSegment).getAliasName().orElse(null));
}
if (fromSegment instanceof JoinTableSegment) {
- return isAliasInFromClause(targetName, ((JoinTableSegment)
fromSegment).getLeft()) || isAliasInFromClause(targetName, ((JoinTableSegment)
fromSegment).getRight());
+ return isAliasInFromClause(targetTable, targetName,
((JoinTableSegment) fromSegment).getLeft())
+ || isAliasInFromClause(targetTable, targetName,
((JoinTableSegment) fromSegment).getRight());
+ }
+ return false;
+ }
+
+ private boolean isTableNameWithAliasInFromClause(final SimpleTableSegment
targetTable, final TableSegment fromSegment) {
+ if (fromSegment instanceof SimpleTableSegment) {
+ SimpleTableSegment simpleTableSegment = (SimpleTableSegment)
fromSegment;
+ return simpleTableSegment.getAliasName().isPresent()
+ &&
targetTable.getTableName().getIdentifier().getValue().equalsIgnoreCase(simpleTableSegment.getTableName().getIdentifier().getValue())
+ && isSameOwner(targetTable, simpleTableSegment);
+ }
+ if (fromSegment instanceof JoinTableSegment) {
+ return isTableNameWithAliasInFromClause(targetTable,
((JoinTableSegment) fromSegment).getLeft())
+ || isTableNameWithAliasInFromClause(targetTable,
((JoinTableSegment) fromSegment).getRight());
}
return false;
}
+ private boolean isSameOwner(final SimpleTableSegment targetTable, final
SimpleTableSegment fromTable) {
+ if (!targetTable.getOwner().isPresent() &&
!fromTable.getOwner().isPresent()) {
+ return true;
+ }
+ if (!targetTable.getOwner().isPresent() ||
!fromTable.getOwner().isPresent()) {
+ return false;
+ }
+ return isSameOwner(targetTable.getOwner().get(),
fromTable.getOwner().get());
+ }
+
+ private boolean isSameOwner(final OwnerSegment targetOwner, final
OwnerSegment fromOwner) {
+ return
targetOwner.getIdentifier().getValue().equalsIgnoreCase(fromOwner.getIdentifier().getValue())
+ && targetOwner.getOwner().isPresent() ==
fromOwner.getOwner().isPresent()
+ && (!targetOwner.getOwner().isPresent() ||
isSameOwner(targetOwner.getOwner().get(), fromOwner.getOwner().get()));
+ }
+
@Override
public ASTNode visitOptionHint(final OptionHintContext ctx) {
return new OptionHintSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(), getOriginalText(ctx));
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 578272e7b8b..b30e44788fe 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
@@ -89,7 +89,25 @@ class EncryptSQLRewriterIT extends SQLRewriterIT {
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()));
+ tables.add(new ShardingSphereTable("SalesPerson", Arrays.asList(
+ new ShardingSphereColumn("BusinessEntityID", Types.INTEGER,
false, false, false, true, false, false),
+ new ShardingSphereColumn("SalesYTD", Types.DECIMAL, false,
false, false, true, false, false),
+ new ShardingSphereColumn("Bonus", Types.DECIMAL, false, false,
false, true, false, false),
+ new ShardingSphereColumn("CommissionPct", Types.DECIMAL,
false, false, false, true, false, false)), Collections.emptyList(),
Collections.emptyList()));
+ tables.add(new ShardingSphereTable("SalesOrderHeader", Arrays.asList(
+ new ShardingSphereColumn("SalesOrderID", Types.INTEGER, false,
false, false, true, false, false),
+ new ShardingSphereColumn("SalesPersonID", Types.INTEGER,
false, false, false, true, false, false),
+ new ShardingSphereColumn("OrderDate", Types.DATE, false,
false, false, true, false, false),
+ new ShardingSphereColumn("SubTotal", Types.DECIMAL, false,
false, false, true, false, false)), Collections.emptyList(),
Collections.emptyList()));
+ Collection<ShardingSphereSchema> result = new LinkedList<>();
+ result.add(new ShardingSphereSchema(schemaName,
mock(DatabaseType.class), tables, Collections.emptyList()));
+ Collection<ShardingSphereTable> salesSchemaTables = new LinkedList<>();
+ salesSchemaTables.add(new ShardingSphereTable("SalesPerson",
Arrays.asList(
+ new ShardingSphereColumn("EmpID", Types.INTEGER, false, false,
false, true, false, false),
+ new ShardingSphereColumn("YearToDateAmt", Types.DECIMAL,
false, false, false, true, false, false),
+ new ShardingSphereColumn("RegionCode", Types.VARCHAR, false,
false, false, true, false, false)), Collections.emptyList(),
Collections.emptyList()));
+ result.add(new ShardingSphereSchema("Sales", mock(DatabaseType.class),
salesSchemaTables, Collections.emptyList()));
+ return result;
}
@Override
@@ -105,6 +123,9 @@ class EncryptSQLRewriterIT extends SQLRewriterIT {
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");
+
singleRule.get().getAttributes().getAttribute(MutableDataNodeRuleAttribute.class).put("encrypt_ds",
schemaName, "SalesPerson");
+
singleRule.get().getAttributes().getAttribute(MutableDataNodeRuleAttribute.class).put("encrypt_ds",
schemaName, "SalesOrderHeader");
+
singleRule.get().getAttributes().getAttribute(MutableDataNodeRuleAttribute.class).put("encrypt_ds",
"Sales", "SalesPerson");
}
}
}
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 58b3a11388b..7c8df50c3be 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
@@ -109,4 +109,19 @@
<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-assertion id="update_sales_person_from_join_for_literals"
db-types="SQLServer">
+ <input sql="UPDATE dbo.SalesPerson SET SalesYTD = SalesYTD + SubTotal,
Bonus = 3000.00 FROM dbo.SalesPerson AS sp JOIN dbo.SalesOrderHeader AS so ON
sp.BusinessEntityID = so.SalesPersonID AND so.OrderDate = (SELECT
MAX(OrderDate) FROM dbo.SalesOrderHeader WHERE SalesPersonID =
sp.BusinessEntityID)" />
+ <output sql="UPDATE dbo.SalesPerson SET SalesYTD = SalesYTD +
SubTotal, [bonus_cipher] = 'encrypt_3000.00' FROM dbo.SalesPerson AS sp JOIN
dbo.SalesOrderHeader AS so ON sp.BusinessEntityID = so.SalesPersonID AND
so.OrderDate = (SELECT MAX(OrderDate) FROM dbo.SalesOrderHeader WHERE
SalesPersonID = sp.BusinessEntityID)" />
+ </rewrite-assertion>
+
+ <rewrite-assertion
id="update_sales_person_from_cross_schema_join_for_literals"
db-types="SQLServer">
+ <input sql="UPDATE dbo.SalesPerson SET SalesYTD = SalesYTD + SubTotal,
Bonus = 3000.00 FROM Sales.SalesPerson AS sp JOIN dbo.SalesOrderHeader AS so ON
sp.EmpID = so.SalesPersonID WHERE dbo.SalesPerson.BusinessEntityID = sp.EmpID"
/>
+ <output sql="UPDATE dbo.SalesPerson SET SalesYTD = SalesYTD +
SubTotal, [bonus_cipher] = 'encrypt_3000.00' FROM Sales.SalesPerson AS sp JOIN
dbo.SalesOrderHeader AS so ON sp.EmpID = so.SalesPersonID WHERE
dbo.SalesPerson.BusinessEntityID = sp.EmpID" />
+ </rewrite-assertion>
+
+ <rewrite-assertion id="update_sales_person_with_subquery_for_literals"
db-types="SQLServer">
+ <input sql="UPDATE dbo.SalesPerson SET SalesYTD = SalesYTD + (SELECT
SUM(so.SubTotal) FROM dbo.SalesOrderHeader AS so WHERE so.OrderDate = (SELECT
MAX(OrderDate) FROM dbo.SalesOrderHeader AS so2 WHERE so2.SalesPersonID =
so.SalesPersonID) AND dbo.SalesPerson.BusinessEntityID = so.SalesPersonID GROUP
BY so.SalesPersonID), Bonus = 3000.00" />
+ <output sql="UPDATE dbo.SalesPerson SET SalesYTD = SalesYTD + (SELECT
SUM(so.SubTotal) FROM dbo.SalesOrderHeader AS so WHERE so.OrderDate = (SELECT
MAX(OrderDate) FROM dbo.SalesOrderHeader AS so2 WHERE so2.SalesPersonID =
so.SalesPersonID) AND dbo.SalesPerson.BusinessEntityID = so.SalesPersonID GROUP
BY so.SalesPersonID), [bonus_cipher] = 'encrypt_3000.00'" />
+ </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 ee2b6060f50..98ce1bed990 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
@@ -170,6 +170,16 @@ rules:
cipher:
name: country_region_name_cipher
encryptorName: rewrite_normal_fixture
+ SalesPerson:
+ columns:
+ Bonus:
+ cipher:
+ name: bonus_cipher
+ encryptorName: rewrite_normal_fixture
+ CommissionPct:
+ cipher:
+ name: commission_pct_cipher
+ encryptorName: rewrite_normal_fixture
encryptors:
rewrite_normal_fixture:
type: REWRITE.NORMAL.FIXTURE