graphrecords_query/operations/conversion/
cast.rs1use crate::{
2 Bare, BareValueDomain, Explain, IndexDomain, Indexed, Labeled, Operand, QueryResult,
3 capabilities::ValueCast,
4 cast::{Bool, CastTarget, DateTime, Duration, Float, Int, String},
5 element::{Pipeline, Preserving},
6 execution::EvaluationCache,
7 operations::{Apply, ElementKernel, ElementPipeline, Operation, OperationContext, Prepare},
8 optimizer::{Estimate, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs, Stats},
9 registry::operation_manifest,
10 traits::Cast,
11};
12use graphrecords_core::GraphRecord;
13
14#[derive(Clone, Explain, Operation, OperationInputs, OptimizerHints, PlanIdentity, PlanInputs)]
15#[operation(scope = Element)]
16#[explain(label = "Cast")]
17#[plan(optimizer_hints(allows_limit_pushdown, empty = if_any))]
18pub struct CastOperation<T: CastTarget> {
19 #[explain(label)]
20 target: T,
21}
22
23impl<T: CastTarget> Prepare for CastOperation<T> {
24 type Prepared<'a>
25 = &'a T
26 where
27 Self: 'a;
28
29 fn prepare<'a>(
30 &'a self,
31 _graphrecord: &'a GraphRecord,
32 _cache: &'a EvaluationCache<'a>,
33 ) -> QueryResult<Self::Prepared<'a>> {
34 Ok(&self.target)
35 }
36}
37
38impl<I, V, T> ElementKernel<Indexed<I, V>> for CastOperation<T>
39where
40 I: IndexDomain,
41 V: ValueCast<T>,
42 T: CastTarget,
43{
44 type Emission = Preserving;
45 type OutShape = Indexed<I, V>;
46
47 fn pipeline<'a>(
48 _graphrecord: &'a GraphRecord,
49 prepared: Self::Prepared<'a>,
50 ) -> QueryResult<ElementPipeline<'a, Indexed<I, V>, Self>> {
51 Ok(Pipeline::keyed(move |index, outcome: QueryResult<_>| {
52 outcome.and_then(|value| {
53 V::cast(Self::LABEL, value, prepared).map_err(|failure| failure.at::<I>(&index))
54 })
55 }))
56 }
57
58 fn estimate(&self, input: Estimate, _stats: &Stats) -> Estimate {
59 input.with_unknown_distinct()
60 }
61}
62
63impl<V, T> ElementKernel<Bare<V>> for CastOperation<T>
64where
65 V: ValueCast<T> + BareValueDomain,
66 T: CastTarget,
67{
68 type Emission = Preserving;
69 type OutShape = Bare<V>;
70
71 fn pipeline<'a>(
72 _graphrecord: &'a GraphRecord,
73 prepared: Self::Prepared<'a>,
74 ) -> QueryResult<ElementPipeline<'a, Bare<V>, Self>> {
75 Ok(Pipeline::new(move |outcome: QueryResult<_>| {
76 outcome.and_then(|value| V::cast(Self::LABEL, value, prepared))
77 }))
78 }
79
80 fn estimate(&self, input: Estimate, _stats: &Stats) -> Estimate {
81 input.with_unknown_distinct()
82 }
83}
84
85impl<O, T> Cast<T> for O
86where
87 CastOperation<T>: Operation,
88 O: Apply<CastOperation<T>>,
89 T: CastTarget,
90{
91 type ReturnOperand = O::Output;
92
93 fn cast(&self, target: T) -> Self::ReturnOperand {
94 Self::ReturnOperand::new(OperationContext::new(
95 self.clone(),
96 CastOperation { target },
97 ))
98 }
99}
100
101pub(super) mod bool {
102 use super::{Bare, Bool, Cast, CastOperation, Indexed, Preserving, operation_manifest};
103
104 operation_manifest! {
105 CastOperation<Bool> {
106 method: Cast<Bool>::cast;
107 scope: element;
108
109 kernel {
110 parameters: <I: IndexDomain, V: ValueCast<Bool>,>;
111 selector: Bool;
112 input: Indexed<I, V>;
113 output: Indexed<I, V>;
114 emission: Preserving;
115 }
116
117 kernel {
118 parameters: <V: ValueCast<Bool> + BareValueDomain>;
119 selector: Bool;
120 input: Bare<V>;
121 output: Bare<V>;
122 emission: Preserving;
123 }
124 }
125 }
126}
127
128pub(super) mod date_time {
129 use super::{Bare, Cast, CastOperation, DateTime, Indexed, Preserving, operation_manifest};
130
131 operation_manifest! {
132 CastOperation<DateTime> {
133 method: Cast<DateTime>::cast;
134 scope: element;
135
136 kernel {
137 parameters: <I: IndexDomain, V: ValueCast<DateTime>,>;
138 selector: DateTime;
139 input: Indexed<I, V>;
140 output: Indexed<I, V>;
141 emission: Preserving;
142 }
143
144 kernel {
145 parameters: <V: ValueCast<DateTime> + BareValueDomain>;
146 selector: DateTime;
147 input: Bare<V>;
148 output: Bare<V>;
149 emission: Preserving;
150 }
151 }
152 }
153}
154
155pub(super) mod duration {
156 use super::{Bare, Cast, CastOperation, Duration, Indexed, Preserving, operation_manifest};
157
158 operation_manifest! {
159 CastOperation<Duration> {
160 method: Cast<Duration>::cast;
161 scope: element;
162
163 kernel {
164 parameters: <I: IndexDomain, V: ValueCast<Duration>,>;
165 selector: Duration;
166 input: Indexed<I, V>;
167 output: Indexed<I, V>;
168 emission: Preserving;
169 }
170
171 kernel {
172 parameters: <V: ValueCast<Duration> + BareValueDomain>;
173 selector: Duration;
174 input: Bare<V>;
175 output: Bare<V>;
176 emission: Preserving;
177 }
178 }
179 }
180}
181
182pub(super) mod float {
183 use super::{Bare, Cast, CastOperation, Float, Indexed, Preserving, operation_manifest};
184
185 operation_manifest! {
186 CastOperation<Float> {
187 method: Cast<Float>::cast;
188 scope: element;
189
190 kernel {
191 parameters: <I: IndexDomain, V: ValueCast<Float>,>;
192 selector: Float;
193 input: Indexed<I, V>;
194 output: Indexed<I, V>;
195 emission: Preserving;
196 }
197
198 kernel {
199 parameters: <V: ValueCast<Float> + BareValueDomain>;
200 selector: Float;
201 input: Bare<V>;
202 output: Bare<V>;
203 emission: Preserving;
204 }
205 }
206 }
207}
208
209pub(super) mod int {
210 use super::{Bare, Cast, CastOperation, Indexed, Int, Preserving, operation_manifest};
211
212 operation_manifest! {
213 CastOperation<Int> {
214 method: Cast<Int>::cast;
215 scope: element;
216
217 kernel {
218 parameters: <I: IndexDomain, V: ValueCast<Int>,>;
219 selector: Int;
220 input: Indexed<I, V>;
221 output: Indexed<I, V>;
222 emission: Preserving;
223 }
224
225 kernel {
226 parameters: <V: ValueCast<Int> + BareValueDomain>;
227 selector: Int;
228 input: Bare<V>;
229 output: Bare<V>;
230 emission: Preserving;
231 }
232 }
233 }
234}
235
236pub(super) mod string {
237 use super::{Bare, Cast, CastOperation, Indexed, Preserving, String, operation_manifest};
238
239 operation_manifest! {
240 CastOperation<String> {
241 method: Cast<String>::cast;
242 scope: element;
243
244 kernel {
245 parameters: <I: IndexDomain, V: ValueCast<String>,>;
246 selector: String;
247 input: Indexed<I, V>;
248 output: Indexed<I, V>;
249 emission: Preserving;
250 }
251
252 kernel {
253 parameters: <V: ValueCast<String> + BareValueDomain>;
254 selector: String;
255 input: Bare<V>;
256 output: Bare<V>;
257 emission: Preserving;
258 }
259 }
260 }
261}