@@ -15,19 +15,17 @@ use crate::{
1515} ;
1616use sqlite3ext_sys:: { sqlite3, sqlite3_context, sqlite3_user_data, sqlite3_value} ;
1717
18- // TODO typedef repeating parameter types, across multiple files
19-
2018fn create_window_function (
2119 db : * mut sqlite3 ,
2220 name : & str ,
2321 num_args : c_int ,
2422 func_flags : FunctionFlags ,
2523 p_app : * mut c_void ,
26- x_step : Option < unsafe extern "C" fn ( * mut sqlite3_context , i32 , * mut * mut sqlite3_value ) > ,
27- x_final : Option < unsafe extern "C" fn ( * mut sqlite3_context ) > ,
24+ x_step : unsafe extern "C" fn ( * mut sqlite3_context , i32 , * mut * mut sqlite3_value ) ,
25+ x_final : unsafe extern "C" fn ( * mut sqlite3_context ) ,
2826 x_value : Option < unsafe extern "C" fn ( * mut sqlite3_context ) > ,
2927 x_inverse : Option < unsafe extern "C" fn ( * mut sqlite3_context , i32 , * mut * mut sqlite3_value ) > ,
30- destroy : Option < unsafe extern "C" fn ( * mut c_void ) > ,
28+ destroy : unsafe extern "C" fn ( * mut c_void ) ,
3129) -> Result < ( ) > {
3230
3331 let cname = CString :: new ( name) ?;
@@ -38,11 +36,11 @@ fn create_window_function(
3836 num_args,
3937 func_flags. bits ( ) ,
4038 p_app,
41- x_step,
42- x_final,
39+ Some ( x_step) ,
40+ Some ( x_final) ,
4341 x_value,
4442 x_inverse,
45- destroy,
43+ Some ( destroy) ,
4644 )
4745 } ;
4846
@@ -53,46 +51,25 @@ fn create_window_function(
5351 }
5452}
5553
54+ type ValueCallback = fn ( context : * mut sqlite3_context , values : & [ * mut sqlite3_value ] ) -> Result < ( ) > ;
55+ type ContextCallback = fn ( context : * mut sqlite3_context ) -> Result < ( ) > ;
56+
5657pub struct WindowFunctionCallbacks
5758{
58- x_step : fn ( context : * mut sqlite3_context , values : & [ * mut sqlite3_value ] ) -> Result < ( ) > ,
59- x_final : fn ( context : * mut sqlite3_context ) -> Result < ( ) > ,
60- x_value : fn ( context : * mut sqlite3_context ) -> Result < ( ) > ,
61- x_inverse : fn ( context : * mut sqlite3_context , values : & [ * mut sqlite3_value ] ) -> Result < ( ) > ,
59+ x_step : ValueCallback ,
60+ x_final : ContextCallback ,
61+ x_value : Option < ContextCallback > ,
62+ x_inverse : Option < ValueCallback > ,
6263}
6364
6465impl WindowFunctionCallbacks {
6566 pub fn new (
66- x_step : fn ( context : * mut sqlite3_context , values : & [ * mut sqlite3_value ] ) -> Result < ( ) > ,
67- x_final : fn ( context : * mut sqlite3_context ) -> Result < ( ) > ,
68- x_value : fn ( context : * mut sqlite3_context ) -> Result < ( ) > ,
69- x_inverse : fn ( context : * mut sqlite3_context , values : & [ * mut sqlite3_value ] ) -> Result < ( ) >
67+ x_step : ValueCallback ,
68+ x_final : ContextCallback ,
69+ x_value : Option < ContextCallback > ,
70+ x_inverse : Option < ValueCallback >
7071 ) -> Self {
71- WindowFunctionCallbacks {
72- x_step,
73- x_final,
74- x_value,
75- x_inverse,
76- }
77- }
78- }
79-
80- pub struct WindowFunctionCallbacksWithAux < T >
81- {
82- x_step : fn ( context : * mut sqlite3_context , values : & [ * mut sqlite3_value ] , aux : & T ) -> Result < ( ) > ,
83- x_final : fn ( context : * mut sqlite3_context , aux : & T ) -> Result < ( ) > ,
84- x_value : fn ( context : * mut sqlite3_context , aux : & T ) -> Result < ( ) > ,
85- x_inverse : fn ( context : * mut sqlite3_context , values : & [ * mut sqlite3_value ] , aux : & T ) -> Result < ( ) > ,
86- }
87-
88- impl < T > WindowFunctionCallbacksWithAux < T > {
89- pub fn new (
90- x_step : fn ( context : * mut sqlite3_context , values : & [ * mut sqlite3_value ] , aux : & T ) -> Result < ( ) > ,
91- x_final : fn ( context : * mut sqlite3_context , aux : & T ) -> Result < ( ) > ,
92- x_value : fn ( context : * mut sqlite3_context , aux : & T ) -> Result < ( ) > ,
93- x_inverse : fn ( context : * mut sqlite3_context , values : & [ * mut sqlite3_value ] , aux : & T ) -> Result < ( ) >
94- ) -> Self {
95- WindowFunctionCallbacksWithAux {
72+ Self {
9673 x_step,
9774 x_final,
9875 x_value,
@@ -102,148 +79,33 @@ impl<T> WindowFunctionCallbacksWithAux<T> {
10279}
10380
10481// TODO add documentation
105- // TODO add new test with aux object
106- // TODO parentheses matching
107- /// The aux parameter can be used to pass another context object altogether
108- pub fn define_window_function_with_aux < T > (
109- db : * mut sqlite3 ,
110- name : & str ,
111- num_args : c_int ,
112- func_flags : FunctionFlags ,
113- callbacks : WindowFunctionCallbacksWithAux < T > ,
114- aux : T ,
115- ) -> Result < ( ) >
116- {
117- let callbacks_pointer = Box :: into_raw ( Box :: new ( callbacks) ) ;
118- let aux_pointer: * mut T = Box :: into_raw ( Box :: new ( aux) ) ;
119- let app_pointer = Box :: into_raw ( Box :: new ( ( callbacks_pointer, aux_pointer) ) ) ;
120-
121- unsafe extern "C" fn x_step_wrapper < T > (
122- context : * mut sqlite3_context ,
123- argc : c_int ,
124- argv : * mut * mut sqlite3_value ,
125- )
126- {
127- let x = sqlite3_user_data ( context) . cast :: < ( * mut WindowFunctionCallbacksWithAux < T > , * mut T ) > ( ) ;
128- let boxed_function = Box :: from_raw ( ( * x) . 0 ) . as_ref ( ) . x_step ;
129- let aux = ( * x) . 1 ;
130- // .collect slows things waaaay down, so stick with slice for now
131- let args = slice:: from_raw_parts ( argv, argc as usize ) ;
132- let b: Box < T > = Box :: from_raw ( aux) ;
133- match boxed_function ( context, args, & * b) {
134- Ok ( ( ) ) => ( ) ,
135- Err ( e) => {
136- if api:: result_error ( context, & e. result_error_message ( ) ) . is_err ( ) {
137- api:: result_error_code ( context, SQLITE_INTERNAL ) ;
138- }
139- }
140- }
141- Box :: into_raw ( b) ;
142- }
143-
144- unsafe extern "C" fn x_inverse_wrapper < T > (
145- context : * mut sqlite3_context ,
146- argc : c_int ,
147- argv : * mut * mut sqlite3_value ,
148- )
149- {
150- let x = sqlite3_user_data ( context) . cast :: < ( * mut WindowFunctionCallbacksWithAux < T > , * mut T ) > ( ) ;
151- let boxed_function = Box :: from_raw ( ( * x) . 0 ) . as_ref ( ) . x_inverse ;
152- let aux = ( * x) . 1 ;
153- // .collect slows things waaaay down, so stick with slice for now
154- let args = slice:: from_raw_parts ( argv, argc as usize ) ;
155- let b = Box :: from_raw ( aux) ;
156- match boxed_function ( context, args, & * b) {
157- Ok ( ( ) ) => ( ) ,
158- Err ( e) => {
159- if api:: result_error ( context, & e. result_error_message ( ) ) . is_err ( ) {
160- api:: result_error_code ( context, SQLITE_INTERNAL ) ;
161- }
162- }
163- }
164- Box :: into_raw ( b) ;
165- }
166-
167- unsafe extern "C" fn x_final_wrapper < T > (
168- context : * mut sqlite3_context ,
169- )
170- {
171- let x = sqlite3_user_data ( context) . cast :: < ( * mut WindowFunctionCallbacksWithAux < T > , * mut T ) > ( ) ;
172- let boxed_function = Box :: from_raw ( ( * x) . 0 ) . as_ref ( ) . x_final ;
173- let aux = ( * x) . 1 ;
174- let b = Box :: from_raw ( aux) ;
175- match boxed_function ( context, & * b) {
176- Ok ( ( ) ) => ( ) ,
177- Err ( e) => {
178- if api:: result_error ( context, & e. result_error_message ( ) ) . is_err ( ) {
179- api:: result_error_code ( context, SQLITE_INTERNAL ) ;
180- }
181- }
182- }
183- Box :: into_raw ( b) ;
184- }
185-
186- unsafe extern "C" fn x_value_wrapper < T > (
187- context : * mut sqlite3_context ,
188- )
189- {
190- let x = sqlite3_user_data ( context) . cast :: < ( * mut WindowFunctionCallbacksWithAux < T > , * mut T ) > ( ) ;
191- let boxed_function = Box :: from_raw ( ( * x) . 0 ) . as_ref ( ) . x_value ;
192- let aux = ( * x) . 1 ;
193- let b = Box :: from_raw ( aux) ;
194- match boxed_function ( context, & * b) {
195- Ok ( ( ) ) => ( ) ,
196- Err ( e) => {
197- if api:: result_error ( context, & e. result_error_message ( ) ) . is_err ( ) {
198- api:: result_error_code ( context, SQLITE_INTERNAL ) ;
199- }
200- }
201- }
202- Box :: into_raw ( b) ;
203- }
204-
205- create_window_function (
206- db,
207- name,
208- num_args,
209- func_flags,
210- // app_pointer,
211- app_pointer. cast :: < c_void > ( ) ,
212- Some ( x_step_wrapper :: < T > ) ,
213- Some ( x_final_wrapper :: < T > ) ,
214- Some ( x_value_wrapper :: < T > ) ,
215- Some ( x_inverse_wrapper :: < T > ) ,
216- None , // Note: release resources in x_final if necessary
217- )
218-
219-
220- }
221-
222- // TODO add documentation
223- // TODO parentheses matching
22482/// The aux parameter can be used to pass another context object altogether
22583pub fn define_window_function (
22684 db : * mut sqlite3 ,
22785 name : & str ,
22886 num_args : c_int ,
22987 func_flags : FunctionFlags ,
230- callbacks : WindowFunctionCallbacks ,
88+ x_step : ValueCallback ,
89+ x_final : ContextCallback ,
90+ x_value : Option < ContextCallback > ,
91+ x_inverse : Option < ValueCallback >
23192) -> Result < ( ) >
23293{
233- let callbacks_pointer = Box :: into_raw ( Box :: new ( callbacks) ) ;
234- let app_pointer = Box :: into_raw ( Box :: new ( callbacks_pointer) ) ;
94+ let app_pointer = Box :: into_raw (
95+ Box :: new (
96+ WindowFunctionCallbacks :: new ( x_step, x_final, x_value, x_inverse)
97+ )
98+ ) ;
23599
236100 unsafe extern "C" fn x_step_wrapper (
237101 context : * mut sqlite3_context ,
238102 argc : c_int ,
239103 argv : * mut * mut sqlite3_value ,
240104 )
241105 {
242- let x = sqlite3_user_data ( context) . cast :: < * mut WindowFunctionCallbacks > ( ) ;
243- let boxed_function = Box :: from_raw ( * x) . as_ref ( ) . x_step ;
244- // .collect slows things waaaay down, so stick with slice for now
106+ let x = sqlite3_user_data ( context) . cast :: < WindowFunctionCallbacks > ( ) ;
245107 let args = slice:: from_raw_parts ( argv, argc as usize ) ;
246- match boxed_function ( context, args) {
108+ match ( ( * x ) . x_step ) ( context, args) {
247109 Ok ( ( ) ) => ( ) ,
248110 Err ( e) => {
249111 if api:: result_error ( context, & e. result_error_message ( ) ) . is_err ( ) {
@@ -259,27 +121,26 @@ pub fn define_window_function(
259121 argv : * mut * mut sqlite3_value ,
260122 )
261123 {
262- let x = sqlite3_user_data ( context) . cast :: < * mut WindowFunctionCallbacks > ( ) ;
263- let boxed_function = Box :: from_raw ( * x) . as_ref ( ) . x_inverse ;
264- // .collect slows things waaaay down, so stick with slice for now
265- let args = slice :: from_raw_parts ( argv , argc as usize ) ;
266- match boxed_function ( context , args ) {
267- Ok ( ( ) ) => ( ) ,
268- Err ( e ) => {
269- if api:: result_error ( context, & e . result_error_message ( ) ) . is_err ( ) {
270- api :: result_error_code ( context , SQLITE_INTERNAL ) ;
124+ let x = sqlite3_user_data ( context) . cast :: < WindowFunctionCallbacks > ( ) ;
125+ if let Some ( x_inverse ) = ( * x) . x_inverse {
126+ let args = slice:: from_raw_parts ( argv , argc as usize ) ;
127+ match x_inverse ( context , args ) {
128+ Ok ( ( ) ) => ( ) ,
129+ Err ( e ) => {
130+ if api :: result_error ( context , & e . result_error_message ( ) ) . is_err ( ) {
131+ api:: result_error_code ( context, SQLITE_INTERNAL ) ;
132+ }
271133 }
272- }
134+ }
273135 }
274136 }
275137
276138 unsafe extern "C" fn x_final_wrapper (
277139 context : * mut sqlite3_context ,
278140 )
279141 {
280- let x = sqlite3_user_data ( context) . cast :: < * mut WindowFunctionCallbacks > ( ) ;
281- let boxed_function = Box :: from_raw ( * x) . as_ref ( ) . x_final ;
282- match boxed_function ( context) {
142+ let x = sqlite3_user_data ( context) . cast :: < WindowFunctionCallbacks > ( ) ;
143+ match ( ( * x) . x_final ) ( context) {
283144 Ok ( ( ) ) => ( ) ,
284145 Err ( e) => {
285146 if api:: result_error ( context, & e. result_error_message ( ) ) . is_err ( ) {
@@ -293,30 +154,38 @@ pub fn define_window_function(
293154 context : * mut sqlite3_context ,
294155 )
295156 {
296- let x = sqlite3_user_data ( context) . cast :: < * mut WindowFunctionCallbacks > ( ) ;
297- let boxed_function = Box :: from_raw ( * x) . as_ref ( ) . x_value ;
298- match boxed_function ( context) {
299- Ok ( ( ) ) => ( ) ,
300- Err ( e) => {
301- if api:: result_error ( context, & e. result_error_message ( ) ) . is_err ( ) {
302- api:: result_error_code ( context, SQLITE_INTERNAL ) ;
157+ let x = sqlite3_user_data ( context) . cast :: < WindowFunctionCallbacks > ( ) ;
158+ if let Some ( x_value) = ( * x) . x_value {
159+ match x_value ( context) {
160+ Ok ( ( ) ) => ( ) ,
161+ Err ( e) => {
162+ if api:: result_error ( context, & e. result_error_message ( ) ) . is_err ( ) {
163+ api:: result_error_code ( context, SQLITE_INTERNAL ) ;
164+ }
303165 }
304- }
166+ }
305167 }
306168 }
307169
170+ unsafe extern "C" fn destroy (
171+ p_app : * mut c_void ,
172+ )
173+ {
174+ let callbacks = p_app. cast :: < WindowFunctionCallbacks > ( ) ;
175+ let _ = Box :: from ( callbacks) ; // drop
176+ }
177+
308178 create_window_function (
309179 db,
310180 name,
311181 num_args,
312182 func_flags,
313- // app_pointer,
314183 app_pointer. cast :: < c_void > ( ) ,
315- Some ( x_step_wrapper) ,
316- Some ( x_final_wrapper) ,
184+ x_step_wrapper,
185+ x_final_wrapper,
317186 Some ( x_value_wrapper) ,
318187 Some ( x_inverse_wrapper) ,
319- None , // Note: release resources in x_final if necessary
188+ destroy ,
320189 )
321190
322191
0 commit comments