Skip to content

Commit d29dde5

Browse files
author
gitlab
committed
Merge branch 'fix/ZSTAC-74748' into '5.5.6'
<fix>[search]: add PK tiebreaker for pagination See merge request zstackio/zstack!9139
2 parents dbc0797 + b1156d8 commit d29dde5

2 files changed

Lines changed: 39 additions & 2 deletions

File tree

search/src/main/java/org/zstack/query/MysqlQueryBuilderImpl3.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,15 @@ String toJpql(boolean isCount) {
730730
throw new IllegalArgumentException(String.format("illegal sortBy[%s], entity[%s] doesn't have this field", msg.getSortBy(), info.entityClass.getName()));
731731
}
732732

733-
ret = String.format("%s order by %s.%s %s", ret, entityName, msg.getSortBy(), msg.getSortDirection().toUpperCase());
733+
String orderBy = String.format("order by %s.%s %s", entityName, msg.getSortBy(), msg.getSortDirection().toUpperCase());
734+
if (info.primaryKey != null && !msg.getSortBy().equals(info.primaryKey)) {
735+
orderBy += String.format(", %s.%s ASC", entityName, info.primaryKey);
736+
}
737+
ret = String.format("%s %s", ret, orderBy);
738+
} else if (msg.getStart() != null || msg.getLimit() != null) {
739+
if (info.primaryKey != null) {
740+
ret = String.format("%s order by %s.%s ASC", ret, entityName, info.primaryKey);
741+
}
734742
}
735743

736744
if (msg.getGroupBy() != null) {

search/src/main/java/org/zstack/query/QueryFacadeImpl.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.zstack.utils.*;
3131
import org.zstack.utils.gson.JSONObjectUtil;
3232
import org.zstack.utils.logging.CLogger;
33+
import org.zstack.core.db.EntityMetadata;
3334
import org.zstack.zql.ZQL;
3435
import org.zstack.zql.ZQLContext;
3536
import org.zstack.zql.ZQLQueryReturn;
@@ -483,7 +484,17 @@ public ZQLQueryReturn queryUseZQL(APIQueryMessage msg, Class inventoryClass) {
483484
}
484485

485486
if (msg.getSortBy() != null) {
486-
sb.add(String.format("order by %s %s", msg.getSortBy(), msg.getSortDirection()));
487+
String orderBy = String.format("order by %s %s", msg.getSortBy(), msg.getSortDirection());
488+
String pkFieldName = getPrimaryKeyFieldNameSafely(targetInventoryClass);
489+
if (pkFieldName != null && !msg.getSortBy().equals(pkFieldName)) {
490+
orderBy += String.format(", %s asc", pkFieldName);
491+
}
492+
sb.add(orderBy);
493+
} else if (!msg.isCount() && (msg.getLimit() != null || msg.getStart() != null)) {
494+
String pkFieldName = getPrimaryKeyFieldNameSafely(targetInventoryClass);
495+
if (pkFieldName != null) {
496+
sb.add(String.format("order by %s asc", pkFieldName));
497+
}
487498
}
488499

489500
if (msg.getLimit() != null) {
@@ -515,6 +526,24 @@ public ZQLQueryReturn queryUseZQL(APIQueryMessage msg, Class inventoryClass) {
515526
return result;
516527
}
517528

529+
private String getPrimaryKeyFieldNameSafely(Class inventoryClass) {
530+
try {
531+
ZQLMetadata.InventoryMetadata meta = ZQLMetadata.findInventoryMetadata(
532+
ZQL.queryTargetNameFromInventoryClass(inventoryClass));
533+
Class voClass = meta.inventoryAnnotation.mappingVOClass();
534+
Field pkField = EntityMetadata.getPrimaryKeyField(voClass);
535+
String pkName = pkField.getName();
536+
if (!meta.selfInventoryFieldNames.contains(pkName)) {
537+
return null;
538+
}
539+
return pkName;
540+
} catch (Exception e) {
541+
logger.trace(String.format("cannot resolve PK for %s, skip pagination tiebreaker: %s",
542+
inventoryClass.getSimpleName(), e.getMessage()));
543+
return null;
544+
}
545+
}
546+
518547
private QueryBelongFilter validateFilterNameAndGetExp(String filterName) {
519548
if (filterName.split(":").length < 2) {
520549
throw new OperationFailureException(argerr(ORG_ZSTACK_QUERY_10015, "filterName must be formatted as [filterType:condition(s)]"));

0 commit comments

Comments
 (0)