Skip to content

Commit 8aaa0fc

Browse files
xiangguangyxgmergify[bot]
authored andcommitted
[BugFix] Reject full-column ORDER BY that reorders key columns of a key-derived range-distribution table (#76256)
Signed-off-by: xiangguangyxg <xiangguangyxg@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 10c0fa5) # Conflicts: # fe/fe-core/src/test/java/com/starrocks/alter/RangeRewriteRoutingTest.java
1 parent e283866 commit 8aaa0fc

2 files changed

Lines changed: 423 additions & 0 deletions

File tree

fe/fe-core/src/main/java/com/starrocks/alter/SchemaChangeHandler.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,33 @@ private void processReorderColumn(ReorderColumnsClause alterClause, OlapTable ol
11711171
if (newSchema.size() != targetIndexSchema.size()) {
11721172
throw new DdlException("Reorder stmt should contains all columns");
11731173
}
1174+
// A full-column ORDER BY on a cloud-native range-distribution table whose sort key is key-derived
1175+
// (no explicit ORDER BY at creation, so getSortKeyIdxes() == null) reorders the schema and thus the
1176+
// key-derived range sort key. But this plain schema-change job copies each shadow tablet's range
1177+
// verbatim, so the stored boundary tuples stay in the OLD key-column space while the new sort key
1178+
// is the new key order; RangeDistributionPruner (FE) and RangeRouter (BE) then compare new-order
1179+
// key tuples against old-order boundaries -> silent wrong pruning / mis-routed loads. Reject a
1180+
// reorder that permutes the key columns. Changing the sort key via a subset
1181+
// "ALTER TABLE ... ORDER BY (<sort-key columns>)" routes through the range-rewrite path, which
1182+
// re-samples the K-tablet boundaries and is safe.
1183+
if (targetIndexMetaId == olapTable.getBaseIndexMetaId()
1184+
&& olapTable.isCloudNativeTable() && olapTable.isRangeDistribution()
1185+
&& olapTable.getIndexMetaByMetaId(olapTable.getBaseIndexMetaId()).getSortKeyIdxes() == null) {
1186+
List<String> newKeyOrder = newSchema.stream().filter(Column::isKey)
1187+
.map(Column::getName).collect(Collectors.toList());
1188+
List<String> curKeyOrder = targetIndexSchema.stream().filter(Column::isKey)
1189+
.map(Column::getName).collect(Collectors.toList());
1190+
boolean keyOrderChanged = newKeyOrder.size() != curKeyOrder.size();
1191+
for (int i = 0; !keyOrderChanged && i < newKeyOrder.size(); i++) {
1192+
keyOrderChanged = !newKeyOrder.get(i).equalsIgnoreCase(curKeyOrder.get(i));
1193+
}
1194+
if (keyOrderChanged) {
1195+
throw new DdlException("ALTER TABLE ORDER BY that reorders the key columns of a "
1196+
+ "range-distribution table is not supported: it would leave stale tablet range "
1197+
+ "boundaries. Change the sort key with ALTER TABLE ... ORDER BY (<sort-key "
1198+
+ "columns>) instead, which re-samples the tablet layout. Table: " + olapTable.getName());
1199+
}
1200+
}
11741201
// replace the old column list
11751202
indexMetaIdToSchema.put(targetIndexMetaId, newSchema);
11761203
}

0 commit comments

Comments
 (0)