prax_query/
capabilities.rs1use crate::traits::QueryEngine;
15
16#[diagnostic::on_unimplemented(
20 message = "the engine `{Self}` does not support relation filters (`some` / `every` / `none` / `is` / `is_not`)",
21 note = "ScyllaDB / Cassandra do not support correlated subqueries. Consider flattening the join or restructuring the model."
22)]
23pub trait SupportsRelationFilter: QueryEngine {}
24
25#[diagnostic::on_unimplemented(
30 message = "the engine `{Self}` does not support correlated subqueries in WHERE clauses"
31)]
32pub trait SupportsCorrelatedSubquery: QueryEngine {}
33
34#[diagnostic::on_unimplemented(
36 message = "the engine `{Self}` does not support JSON path operators",
37 note = "Postgres / MySQL >= 5.7 / SQLite + JSON1 / MSSQL support JSON paths."
38)]
39pub trait SupportsJsonPath: QueryEngine {}
40
41#[diagnostic::on_unimplemented(
45 message = "the engine `{Self}` does not advertise native case-insensitive comparison"
46)]
47pub trait SupportsCaseInsensitiveMode: QueryEngine {}
48
49#[diagnostic::on_unimplemented(message = "the engine `{Self}` does not support full-text search")]
51pub trait SupportsFullTextSearch: QueryEngine {}
52
53#[diagnostic::on_unimplemented(message = "the engine `{Self}` does not support array operators")]
55pub trait SupportsArrayOps: QueryEngine {}
56
57#[diagnostic::on_unimplemented(
60 message = "the engine `{Self}` does not support generated columns",
61 note = "Postgres / MySQL / SQLite / MSSQL / DuckDB support GENERATED ALWAYS AS."
62)]
63pub trait SupportsGeneratedColumns: QueryEngine {}
64
65#[diagnostic::on_unimplemented(
70 message = "the engine `{Self}` does not support scalar subqueries in SELECT",
71 note = "All SQL engines satisfy this. MongoDB requires the $lookup-lowering follow-up plan."
72)]
73pub trait SupportsScalarSubqueryInSelect: QueryEngine {}
74
75#[diagnostic::on_unimplemented(
84 message = "the engine `{Self}` does not support nested writes",
85 note = "ScyllaDB / Cassandra batch semantics don't map onto Prisma-style nested writes. Use the engine-native BATCH API or restructure."
86)]
87pub trait SupportsNestedWrites: QueryEngine {}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[derive(Clone)]
95 struct StubEngine;
96
97 impl QueryEngine for StubEngine {
98 fn query_many<T: crate::traits::Model + crate::row::FromRow + Send + 'static>(
99 &self,
100 _sql: &str,
101 _params: Vec<crate::filter::FilterValue>,
102 ) -> crate::traits::BoxFuture<'_, crate::error::QueryResult<Vec<T>>> {
103 Box::pin(async { Ok(Vec::new()) })
104 }
105 fn query_one<T: crate::traits::Model + crate::row::FromRow + Send + 'static>(
106 &self,
107 _sql: &str,
108 _params: Vec<crate::filter::FilterValue>,
109 ) -> crate::traits::BoxFuture<'_, crate::error::QueryResult<T>> {
110 Box::pin(async { Err(crate::error::QueryError::not_found("t")) })
111 }
112 fn query_optional<T: crate::traits::Model + crate::row::FromRow + Send + 'static>(
113 &self,
114 _sql: &str,
115 _params: Vec<crate::filter::FilterValue>,
116 ) -> crate::traits::BoxFuture<'_, crate::error::QueryResult<Option<T>>> {
117 Box::pin(async { Ok(None) })
118 }
119 fn execute_insert<T: crate::traits::Model + crate::row::FromRow + Send + 'static>(
120 &self,
121 _sql: &str,
122 _params: Vec<crate::filter::FilterValue>,
123 ) -> crate::traits::BoxFuture<'_, crate::error::QueryResult<T>> {
124 Box::pin(async { Err(crate::error::QueryError::not_found("t")) })
125 }
126 fn execute_update<T: crate::traits::Model + crate::row::FromRow + Send + 'static>(
127 &self,
128 _sql: &str,
129 _params: Vec<crate::filter::FilterValue>,
130 ) -> crate::traits::BoxFuture<'_, crate::error::QueryResult<Vec<T>>> {
131 Box::pin(async { Ok(Vec::new()) })
132 }
133 fn execute_delete(
134 &self,
135 _sql: &str,
136 _params: Vec<crate::filter::FilterValue>,
137 ) -> crate::traits::BoxFuture<'_, crate::error::QueryResult<u64>> {
138 Box::pin(async { Ok(0) })
139 }
140 fn execute_raw(
141 &self,
142 _sql: &str,
143 _params: Vec<crate::filter::FilterValue>,
144 ) -> crate::traits::BoxFuture<'_, crate::error::QueryResult<u64>> {
145 Box::pin(async { Ok(0) })
146 }
147 fn count(
148 &self,
149 _sql: &str,
150 _params: Vec<crate::filter::FilterValue>,
151 ) -> crate::traits::BoxFuture<'_, crate::error::QueryResult<u64>> {
152 Box::pin(async { Ok(0) })
153 }
154 }
155
156 impl SupportsRelationFilter for StubEngine {}
157
158 fn needs_relation_filter<E: SupportsRelationFilter>() {}
159
160 #[test]
161 fn marker_trait_dispatch_compiles() {
162 needs_relation_filter::<StubEngine>();
163 }
164}