@@ -19,10 +19,11 @@ use std::time::Duration;
19
19
use graph:: prelude:: anyhow:: anyhow;
20
20
use graph:: {
21
21
data:: subgraph:: schema:: POI_TABLE ,
22
- prelude:: { lazy_static, StoreError } ,
22
+ prelude:: { lazy_static, StoreError , BLOCK_NUMBER_MAX } ,
23
23
} ;
24
24
25
25
use crate :: {
26
+ block_range:: BLOCK_RANGE_COLUMN ,
26
27
pool:: ForeignServer ,
27
28
primary:: { Namespace , Site , NAMESPACE_PUBLIC } ,
28
29
relational:: SqlName ,
@@ -190,7 +191,6 @@ pub struct Catalog {
190
191
/// Whether the column `pg_stats.range_bounds_histogram` introduced in
191
192
/// Postgres 17 exists. See the [Postgres
192
193
/// docs](https://www.postgresql.org/docs/17/view-pg-stats.html)
193
- #[ allow( dead_code) ]
194
194
pg_stats_has_range_bounds_histogram : bool ,
195
195
}
196
196
@@ -305,10 +305,42 @@ impl Catalog {
305
305
tablename : s. tablename ,
306
306
ratio : s. ratio ,
307
307
last_pruned_block : s. last_pruned_block ,
308
+ block_range_lower : vec ! [ ] ,
309
+ block_range_upper : vec ! [ ] ,
308
310
}
309
311
}
310
312
}
311
313
314
+ #[ derive( Queryable , QueryableByName ) ]
315
+ struct RangeHistogram {
316
+ #[ diesel( sql_type = Text ) ]
317
+ tablename : String ,
318
+ #[ diesel( sql_type = Array <Integer >) ]
319
+ lower : Vec < i32 > ,
320
+ #[ diesel( sql_type = Array <Integer >) ]
321
+ upper : Vec < i32 > ,
322
+ }
323
+
324
+ fn block_range_histogram (
325
+ conn : & mut PgConnection ,
326
+ namespace : & Namespace ,
327
+ ) -> Result < Vec < RangeHistogram > , StoreError > {
328
+ let query = format ! (
329
+ "select tablename, \
330
+ array_agg(lower(block_range)) lower, \
331
+ array_agg(coalesce(upper(block_range), {BLOCK_NUMBER_MAX})) upper \
332
+ from (select tablename,
333
+ unnest(range_bounds_histogram::text::int4range[]) block_range
334
+ from pg_stats where schemaname = $1 and attname = '{BLOCK_RANGE_COLUMN}') a
335
+ group by tablename
336
+ order by tablename"
337
+ ) ;
338
+ let result = sql_query ( query)
339
+ . bind :: < Text , _ > ( namespace. as_str ( ) )
340
+ . get_results :: < RangeHistogram > ( conn) ?;
341
+ Ok ( result)
342
+ }
343
+
312
344
// Get an estimate of number of rows (pg_class.reltuples) and number of
313
345
// distinct entities (based on the planners idea of how many distinct
314
346
// values there are in the `id` column) See the [Postgres
@@ -342,7 +374,34 @@ impl Catalog {
342
374
. load :: < DbStats > ( conn)
343
375
. map_err ( StoreError :: from) ?;
344
376
345
- Ok ( stats. into_iter ( ) . map ( |s| s. into ( ) ) . collect ( ) )
377
+ let mut range_histogram = if self . pg_stats_has_range_bounds_histogram {
378
+ block_range_histogram ( conn, & self . site . namespace ) ?
379
+ } else {
380
+ vec ! [ ]
381
+ } ;
382
+
383
+ let stats = stats
384
+ . into_iter ( )
385
+ . map ( |s| {
386
+ let pos = range_histogram
387
+ . iter ( )
388
+ . position ( |h| h. tablename == s. tablename ) ;
389
+ let ( mut lower, mut upper) = pos
390
+ . map ( |pos| range_histogram. swap_remove ( pos) )
391
+ . map ( |h| ( h. lower , h. upper ) )
392
+ . unwrap_or ( ( vec ! [ ] , vec ! [ ] ) ) ;
393
+ // Since lower and upper are supposed to be histograms, we
394
+ // sort them
395
+ lower. sort_unstable ( ) ;
396
+ upper. sort_unstable ( ) ;
397
+ let mut vs = VersionStats :: from ( s) ;
398
+ vs. block_range_lower = lower;
399
+ vs. block_range_upper = upper;
400
+ vs
401
+ } )
402
+ . collect :: < Vec < _ > > ( ) ;
403
+
404
+ Ok ( stats)
346
405
}
347
406
}
348
407
0 commit comments