@@ -1086,6 +1086,193 @@ public PlanFragment visitPhysicalOlapScan(OptExpression optExpr, ExecPlan contex
10861086 return fragment ;
10871087 }
10881088
1089+ <<<<<<< HEAD
1090+ =======
1091+ /**
1092+ * Compute partition key ranges for dynamic partition pruning.
1093+ * Returns a list of TKeyRange describing the value ranges of each used partition column.
1094+ * Returns empty if the partition has too many values (exceeding the session limit) or
1095+ * if the partition type is unsupported.
1096+ */
1097+ private List <TKeyRange > computePartitionRange (OlapTable table , Partition partition ,
1098+ Collection <Column > usedPartitionCols , SessionVariable session ) {
1099+ PartitionInfo partitionInfo = table .getPartitionInfo ();
1100+ if (usedPartitionCols .isEmpty () || !partition .hasData ()
1101+ || !(partitionInfo .isRangePartition () || partitionInfo .isListPartition ())) {
1102+ return List .of ();
1103+ }
1104+ List <Column > partitionCols = partitionInfo .getPartitionColumns (table .getIdToColumn ());
1105+ Preconditions .checkState (partitionCols .containsAll (usedPartitionCols ));
1106+
1107+ long limit = session .getDynamicPartitionPruneValuesLimit ();
1108+ if (partitionInfo .isRangePartition ()) {
1109+ return computeRangePartitionKeyRanges (partitionInfo , partition , partitionCols , usedPartitionCols , limit );
1110+ } else {
1111+ return computeListPartitionKeyRanges (partitionInfo , partition , partitionCols , usedPartitionCols , limit );
1112+ }
1113+ }
1114+
1115+ private List <TKeyRange > computeRangePartitionKeyRanges (PartitionInfo partitionInfo , Partition partition ,
1116+ List <Column > partitionCols ,
1117+ Collection <Column > usedPartitionCols , long limit ) {
1118+ RangePartitionInfo rangeInfo = (RangePartitionInfo ) partitionInfo ;
1119+ Range <PartitionKey > keyRange = rangeInfo .getRange (partition .getId ());
1120+ if (!keyRange .hasLowerBound () || !keyRange .hasUpperBound ()) {
1121+ return List .of ();
1122+ }
1123+
1124+ boolean isNullPartition = keyRange .lowerEndpoint ().isMinValue ();
1125+ long partitionValues = 1 ;
1126+ List <TKeyRange > result = Lists .newArrayList ();
1127+
1128+ for (int i = 0 ; i < partitionCols .size (); i ++) {
1129+ Column col = partitionCols .get (i );
1130+ if (!usedPartitionCols .contains (col )) {
1131+ continue ;
1132+ }
1133+
1134+ TKeyRange kr = new TKeyRange ();
1135+ long rangeSize ;
1136+
1137+ if (col .getType ().isDate ()) {
1138+ LiteralExpr lowerExpr = keyRange .lowerEndpoint ().getKeys ().get (i );
1139+ LiteralExpr upperExpr = keyRange .upperEndpoint ().getKeys ().get (i );
1140+ if (!(lowerExpr instanceof DateLiteral lower ) || !(upperExpr instanceof DateLiteral upper )) {
1141+ continue ;
1142+ }
1143+ kr .setBegin_key (lower .getYear () * 10000 + lower .getMonth () * 100 + lower .getDay ());
1144+ kr .setEnd_key (upper .getYear () * 10000 + upper .getMonth () * 100 + upper .getDay ());
1145+ rangeSize = upper .toLocalDateTime ().toLocalDate ().toEpochDay ()
1146+ - lower .toLocalDateTime ().toLocalDate ().toEpochDay ();
1147+ } else if (col .getType ().isIntegerType ()) {
1148+ long lowerVal = keyRange .lowerEndpoint ().getKeys ().get (i ).getLongValue ();
1149+ long upperVal = keyRange .upperEndpoint ().getKeys ().get (i ).getLongValue ();
1150+ kr .setBegin_key (lowerVal );
1151+ kr .setEnd_key (upperVal );
1152+ rangeSize = upperVal - lowerVal ;
1153+ } else {
1154+ continue ;
1155+ }
1156+
1157+ if (rangeSize <= 0 || wouldOverflowOrExceedLimit (partitionValues , rangeSize , limit )) {
1158+ break ;
1159+ }
1160+ partitionValues *= rangeSize ;
1161+
1162+ kr .setColumn_type (TypeSerializer .toThrift (col .getType ().getPrimitiveType ()));
1163+ // BE indexes the tuple's slots by col_name, which is the column id, so name the range by
1164+ // the id as well: a renamed partition column would otherwise be skipped and its
1165+ // scan ranges never pruned.
1166+ kr .setColumn_name (col .getColumnId ().getId ());
1167+ if (isNullPartition ) {
1168+ kr .setHas_null (true );
1169+ }
1170+ result .add (kr );
1171+ }
1172+
1173+ return result ;
1174+ }
1175+
1176+ private List <TKeyRange > computeListPartitionKeyRanges (PartitionInfo partitionInfo , Partition partition ,
1177+ List <Column > partitionCols ,
1178+ Collection <Column > usedPartitionCols , long limit ) {
1179+ ListPartitionInfo listInfo = (ListPartitionInfo ) partitionInfo ;
1180+ if (listInfo .getLiteralExprValues ().containsKey (partition .getId ())) {
1181+ return computeSingleColumnListKeyRanges (listInfo , partition , partitionCols , usedPartitionCols , limit );
1182+ } else if (listInfo .getMultiLiteralExprValues ().containsKey (partition .getId ())) {
1183+ return computeMultiColumnListKeyRanges (listInfo , partition , partitionCols , usedPartitionCols , limit );
1184+ } else {
1185+ return List .of ();
1186+ }
1187+ }
1188+
1189+ private List <TKeyRange > computeSingleColumnListKeyRanges (ListPartitionInfo listInfo , Partition partition ,
1190+ List <Column > partitionCols ,
1191+ Collection <Column > usedPartitionCols , long limit ) {
1192+ Preconditions .checkState (partitionCols .size () == 1 );
1193+ List <LiteralExpr > partitionValuesList = listInfo .getLiteralExprValues ().get (partition .getId ());
1194+ long partitionValues = 1 ;
1195+ List <TKeyRange > result = Lists .newArrayList ();
1196+
1197+ for (Column col : partitionCols ) {
1198+ if (!usedPartitionCols .contains (col )) {
1199+ continue ;
1200+ }
1201+
1202+ long listSize = partitionValuesList .size ();
1203+ if (wouldOverflowOrExceedLimit (partitionValues , listSize , limit )) {
1204+ break ;
1205+ }
1206+ partitionValues *= listSize ;
1207+
1208+ TKeyRange kr = new TKeyRange ();
1209+ kr .setColumn_type (TypeSerializer .toThrift (col .getType ().getPrimitiveType ()));
1210+ // BE indexes the tuple's slots by col_name, which is the column id, so name the range by
1211+ // the id as well: a renamed partition column would otherwise be skipped and its
1212+ // scan ranges never pruned.
1213+ kr .setColumn_name (col .getColumnId ().getId ());
1214+ List <TExpr > l = Lists .newArrayList ();
1215+ partitionValuesList .forEach (v -> l .add (ExprToThrift .treeToThrift (v )));
1216+ kr .setList_values (l );
1217+ result .add (kr );
1218+ }
1219+
1220+ return result ;
1221+ }
1222+
1223+ private List <TKeyRange > computeMultiColumnListKeyRanges (ListPartitionInfo listInfo , Partition partition ,
1224+ List <Column > partitionCols ,
1225+ Collection <Column > usedPartitionCols , long limit ) {
1226+ List <List <LiteralExpr >> partitionValuesList = listInfo .getMultiLiteralExprValues ().get (partition .getId ());
1227+ long partitionValues = 1 ;
1228+ List <TKeyRange > result = Lists .newArrayList ();
1229+
1230+ for (int i = 0 ; i < partitionCols .size (); i ++) {
1231+ Column col = partitionCols .get (i );
1232+ if (!usedPartitionCols .contains (col )) {
1233+ continue ;
1234+ }
1235+
1236+ long listSize = partitionValuesList .size ();
1237+ if (wouldOverflowOrExceedLimit (partitionValues , listSize , limit )) {
1238+ break ;
1239+ }
1240+ partitionValues *= listSize ;
1241+
1242+ TKeyRange kr = new TKeyRange ();
1243+ kr .setColumn_type (TypeSerializer .toThrift (col .getType ().getPrimitiveType ()));
1244+ // BE indexes the tuple's slots by col_name, which is the column id, so name the range by
1245+ // the id as well: a renamed partition column would otherwise be skipped and its
1246+ // scan ranges never pruned.
1247+ kr .setColumn_name (col .getColumnId ().getId ());
1248+ List <TExpr > l = Lists .newArrayList ();
1249+ for (var values : partitionValuesList ) {
1250+ Preconditions .checkState (values .size () == partitionCols .size ());
1251+ l .add (ExprToThrift .treeToThrift (values .get (i )));
1252+ }
1253+ kr .setList_values (l );
1254+ result .add (kr );
1255+ }
1256+
1257+ return result ;
1258+ }
1259+
1260+ /**
1261+ * Check if multiplying {@code current} by {@code factor} would overflow {@code long}
1262+ * or if the product would exceed the given {@code limit}.
1263+ */
1264+ private static boolean wouldOverflowOrExceedLimit (long current , long factor , long limit ) {
1265+ if (factor == 0 ) {
1266+ return false ;
1267+ }
1268+ // Overflow check: current * factor > Long.MAX_VALUE
1269+ if (current > limit / factor ) {
1270+ return true ;
1271+ }
1272+ return current * factor > limit ;
1273+ }
1274+
1275+ >>>>>>> e843b3cab2 ([BugFix ] Name a partition column 's key range by column id, not by column name (#77988))
10891276 @ NotNull
10901277 private static Map <Integer , Expr > getGlobalDictsExprs (Map <Integer , ScalarOperator > dictExprs ,
10911278 ExecPlan context ) {
0 commit comments