sift_query_sqlx/execution/
config.rs1use super::*;
2
3impl PgSiftQuery {
4 #[must_use]
5 pub fn new(pool: PgPool) -> Self {
6 Self {
7 pool,
8 policy: QueryPolicy::default(),
9 execution: PgExecutionPolicy::default(),
10 renderer: PgRenderer,
11 parallel_gate: Arc::new(Semaphore::new(16)),
12 scan_gate: Arc::new(Semaphore::new(4)),
13 scan_wait_gate: Arc::new(Semaphore::new(16)),
14 shape_cache: None,
15 extensions: crate::enrichment::PgExtensions::default(),
16 observers: crate::observe::Observers::default(),
17 }
18 }
19
20 pub fn with_policy(
21 pool: PgPool,
22 policy: QueryPolicy,
23 execution: PgExecutionPolicy,
24 ) -> Result<Self, ConfigError> {
25 if execution.timeout.is_zero() || execution.max_parallel_queries == 0 {
26 return Err(ConfigError::Invalid(
27 "PostgreSQL timeout and parallel query limit must be greater than zero".to_owned(),
28 ));
29 }
30 if execution.shape_cache_capacity > 16_384 {
31 return Err(ConfigError::Invalid(
32 "PostgreSQL shape cache capacity cannot exceed 16384".to_owned(),
33 ));
34 }
35 let parallel_gate = Arc::new(Semaphore::new(execution.max_parallel_queries));
36 let shape_cache = if execution.shape_cache_capacity > 0 {
37 Some(Arc::new(crate::QueryShapeCache::new(
38 execution.shape_cache_capacity,
39 )?))
40 } else {
41 None
42 };
43 Ok(Self {
44 pool,
45 policy,
46 execution,
47 renderer: PgRenderer,
48 parallel_gate,
49 scan_gate: Arc::new(Semaphore::new(4)),
50 scan_wait_gate: Arc::new(Semaphore::new(16)),
51 shape_cache,
52 extensions: crate::enrichment::PgExtensions::default(),
53 observers: crate::observe::Observers::default(),
54 })
55 }
56
57 #[must_use]
58 pub fn shape_cache_stats(&self) -> Option<ShapeCacheStats> {
59 self.shape_cache.as_ref().map(|cache| cache.stats())
60 }
61
62 pub fn clear_shape_cache(&self) {
63 if let Some(cache) = &self.shape_cache {
64 cache.clear();
65 }
66 }
67
68 pub fn with_scan_concurrency(
70 mut self,
71 active: usize,
72 waiting: usize,
73 ) -> Result<Self, ConfigError> {
74 if active == 0 || active > 1024 || waiting > 16_384 {
75 return Err(ConfigError::Invalid(
76 "invalid scan concurrency budget".to_owned(),
77 ));
78 }
79 self.scan_gate = Arc::new(Semaphore::new(active));
80 self.scan_wait_gate = Arc::new(Semaphore::new(waiting));
81 Ok(self)
82 }
83
84 #[must_use]
85 pub fn with_partition_resolver<R>(mut self, resolver: R) -> Self
86 where
87 R: PartitionResolver + 'static,
88 {
89 self.extensions.set_partition_resolver(Arc::new(resolver));
90 self
91 }
92
93 #[must_use]
94 pub fn with_sql_interceptor<I>(mut self, interceptor: I) -> Self
95 where
96 I: SqlInterceptor + 'static,
97 {
98 self.extensions.push_sql_interceptor(Arc::new(interceptor));
99 self
100 }
101
102 #[must_use]
103 pub fn with_result_filter<F>(mut self, filter: F) -> Self
104 where
105 F: ResultFilter + 'static,
106 {
107 self.extensions.push_result_filter(Arc::new(filter));
108 self
109 }
110
111 #[must_use]
112 pub fn with_page_enricher<E>(mut self, enricher: E) -> Self
113 where
114 E: crate::PageEnricher + 'static,
115 {
116 self.extensions.push_page_enricher(Arc::new(enricher));
117 self
118 }
119
120 #[must_use]
121 pub fn query_builder<E: SearchEntity>(&self) -> QueryBuilder<'_, E> {
122 QueryBuilder::new(&self.policy)
123 }
124}