@@ -329,7 +329,11 @@ func (dsp *DistSQLPlanner) createPartialStatsPlan(
329
329
// Initialize a dummy scanNode for the requested statistic.
330
330
var scan scanNode
331
331
scan .desc = desc
332
- err = scan .initDescSpecificCol (colCfg , column )
332
+ if details .UsingExtremes {
333
+ err = scan .initDescSpecificCol (colCfg , column )
334
+ } else if details .WhereClause != "" {
335
+ err = scan .initDescSpecificIndex (colCfg , column , details .WhereIndexID )
336
+ }
333
337
if err != nil {
334
338
return nil , err
335
339
}
@@ -342,11 +346,6 @@ func (dsp *DistSQLPlanner) createPartialStatsPlan(
342
346
colIdxMap .Set (c .GetID (), i )
343
347
}
344
348
345
- var sb span.Builder
346
- sb .InitAllowingExternalRowData (
347
- planCtx .EvalContext (), planCtx .ExtendedEvalCtx .Codec , desc , scan .index ,
348
- )
349
-
350
349
var stat * stats.TableStatistic
351
350
// Find the statistic from the newest table statistic for our column that is
352
351
// not partial and not forecasted. The first one we find will be the latest
@@ -379,27 +378,47 @@ func (dsp *DistSQLPlanner) createPartialStatsPlan(
379
378
"column %s does not have a prior statistic" ,
380
379
column .GetName ())
381
380
}
382
- lowerBound , upperBound , err := bounds .GetUsingExtremesBounds (ctx , planCtx .EvalContext (), stat .Histogram )
383
- if err != nil {
384
- return nil , err
385
- }
386
- if lowerBound == nil {
387
- return nil , pgerror .Newf (
388
- pgcode .ObjectNotInPrerequisiteState ,
389
- "only outer or NULL bounded buckets exist in %s@%s (table ID %d, column IDs %v), " +
390
- "so partial stats cannot be collected" ,
391
- scan .desc .GetName (), scan .index .GetName (), stat .TableID , stat .ColumnIDs ,
381
+
382
+ var predicate string
383
+ var prevLowerBound tree.Datum
384
+ if details .UsingExtremes {
385
+ var sb span.Builder
386
+ sb .InitAllowingExternalRowData (
387
+ planCtx .EvalContext (), planCtx .ExtendedEvalCtx .Codec , desc , scan .index ,
392
388
)
393
- }
394
- extremesSpans , err := bounds .ConstructUsingExtremesSpans (lowerBound , upperBound , scan .index )
395
- if err != nil {
396
- return nil , err
397
- }
398
- extremesPredicate := bounds .ConstructUsingExtremesPredicate (lowerBound , upperBound , column .GetName ())
399
- // Get roachpb.Spans from constraint.Spans
400
- scan .spans , err = sb .SpansFromConstraintSpan (& extremesSpans , span .NoopSplitter ())
401
- if err != nil {
402
- return nil , err
389
+
390
+ lowerBound , upperBound , err := bounds .GetUsingExtremesBounds (ctx ,
391
+ planCtx .EvalContext (), stat .Histogram )
392
+ if err != nil {
393
+ return nil , err
394
+ }
395
+ if lowerBound == nil {
396
+ return nil , pgerror .Newf (
397
+ pgcode .ObjectNotInPrerequisiteState ,
398
+ "only outer or NULL bounded buckets exist in %s@%s (table ID %d, column IDs %v), " +
399
+ "so partial stats cannot be collected" ,
400
+ scan .desc .GetName (), scan .index .GetName (), stat .TableID , stat .ColumnIDs ,
401
+ )
402
+ }
403
+ prevLowerBound = lowerBound
404
+
405
+ extremesSpans , err := bounds .ConstructUsingExtremesSpans (lowerBound ,
406
+ upperBound , scan .index )
407
+ if err != nil {
408
+ return nil , err
409
+ }
410
+ predicate = bounds .ConstructUsingExtremesPredicate (lowerBound , upperBound , column .GetName ())
411
+ // Get roachpb.Spans from constraint.Spans
412
+ scan .spans , err = sb .SpansFromConstraintSpan (& extremesSpans , span .NoopSplitter ())
413
+ if err != nil {
414
+ return nil , err
415
+ }
416
+ } else if details .WhereClause != "" {
417
+ predicate = details .WhereClause
418
+ scan .spans = details .WhereSpans
419
+ } else {
420
+ return nil , errors .AssertionFailedf (
421
+ "partial stats require either USING EXTREMES or a WHERE clause" )
403
422
}
404
423
p , err := dsp .createTableReaders (ctx , planCtx , & scan )
405
424
if err != nil {
@@ -419,10 +438,13 @@ func (dsp *DistSQLPlanner) createPartialStatsPlan(
419
438
HistogramMaxBuckets : reqStat .histogramMaxBuckets ,
420
439
Columns : make ([]uint32 , len (reqStat .columns )),
421
440
StatName : reqStat .name ,
422
- PartialPredicate : extremesPredicate ,
423
- FullStatisticID : stat .StatisticID ,
424
- PrevLowerBound : tree .Serialize (lowerBound ),
441
+ PartialPredicate : predicate ,
442
+ }
443
+ if details .UsingExtremes && prevLowerBound != nil {
444
+ spec .PrevLowerBound = tree .Serialize (prevLowerBound )
445
+ spec .FullStatisticID = stat .StatisticID
425
446
}
447
+
426
448
// For now, this loop should iterate only once, as we only
427
449
// handle single-column partial statistics.
428
450
// TODO(faizaanmadhani): Add support for multi-column partial stats next
@@ -767,7 +789,7 @@ func (dsp *DistSQLPlanner) createPlanForCreateStats(
767
789
return nil , errors .New ("no stats requested" )
768
790
}
769
791
770
- if details .UsingExtremes {
792
+ if details .UsingExtremes || details . WhereClause != "" {
771
793
return dsp .createPartialStatsPlan (ctx , planCtx , tableDesc , reqStats , jobID , details , numIndexes , curIndex )
772
794
}
773
795
return dsp .createStatsPlan (ctx , planCtx , semaCtx , tableDesc , reqStats , jobID , details , numIndexes , curIndex )
0 commit comments