@@ -19,10 +19,11 @@ use std::time::Duration;
1919use graph:: prelude:: anyhow:: anyhow;
2020use graph:: {
2121 data:: subgraph:: schema:: POI_TABLE ,
22- prelude:: { lazy_static, StoreError } ,
22+ prelude:: { lazy_static, StoreError , BLOCK_NUMBER_MAX } ,
2323} ;
2424
2525use crate :: {
26+ block_range:: BLOCK_RANGE_COLUMN ,
2627 pool:: ForeignServer ,
2728 primary:: { Namespace , Site , NAMESPACE_PUBLIC } ,
2829 relational:: SqlName ,
@@ -190,7 +191,6 @@ pub struct Catalog {
190191 /// Whether the column `pg_stats.range_bounds_histogram` introduced in
191192 /// Postgres 17 exists. See the [Postgres
192193 /// docs](https://www.postgresql.org/docs/17/view-pg-stats.html)
193- #[ allow( dead_code) ]
194194 pg_stats_has_range_bounds_histogram : bool ,
195195}
196196
@@ -305,10 +305,42 @@ impl Catalog {
305305 tablename : s. tablename ,
306306 ratio : s. ratio ,
307307 last_pruned_block : s. last_pruned_block ,
308+ block_range_lower : vec ! [ ] ,
309+ block_range_upper : vec ! [ ] ,
308310 }
309311 }
310312 }
311313
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+
312344 // Get an estimate of number of rows (pg_class.reltuples) and number of
313345 // distinct entities (based on the planners idea of how many distinct
314346 // values there are in the `id` column) See the [Postgres
@@ -342,7 +374,34 @@ impl Catalog {
342374 . load :: < DbStats > ( conn)
343375 . map_err ( StoreError :: from) ?;
344376
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)
346405 }
347406}
348407
0 commit comments