11extern crate libsqlite3_sys as ffi;
22
33use super :: raw:: RawConnection ;
4+ use super :: row:: PrivateSqliteRow ;
45use super :: serialized_value:: SerializedValue ;
56use super :: { Sqlite , SqliteAggregateFunction } ;
67use crate :: deserialize:: { FromSqlRow , StaticallySizedRow } ;
78use crate :: result:: { DatabaseErrorKind , Error , QueryResult } ;
89use crate :: row:: { Field , PartialRow , Row , RowIndex } ;
910use crate :: serialize:: { IsNull , Output , ToSql } ;
1011use crate :: sql_types:: HasSqlType ;
12+ use crate :: sqlite:: connection:: sqlite_value:: OwnedSqliteValue ;
13+ use crate :: sqlite:: SqliteValue ;
14+ use std:: cell:: { Ref , RefCell } ;
1115use std:: marker:: PhantomData ;
16+ use std:: mem:: ManuallyDrop ;
17+ use std:: ops:: DerefMut ;
18+ use std:: rc:: Rc ;
1219
1320pub fn register < ArgsSqlType , RetSqlType , Args , Ret , F > (
1421 conn : & RawConnection ,
8592}
8693
8794pub ( crate ) fn build_sql_function_args < ArgsSqlType , Args > (
88- args : & [ * mut ffi:: sqlite3_value ] ,
95+ args : & mut [ * mut ffi:: sqlite3_value ] ,
8996) -> Result < Args , Error >
9097where
9198 Args : FromSqlRow < ArgsSqlType , Sqlite > ,
@@ -117,14 +124,67 @@ where
117124 } )
118125}
119126
120- #[ derive( Clone ) ]
121127struct FunctionRow < ' a > {
122- args : & ' a [ * mut ffi:: sqlite3_value ] ,
128+ // we use `ManuallyDrop` to prevent dropping the content of the internal vector
129+ // as this buffer is owned by sqlite not by diesel
130+ args : Rc < RefCell < ManuallyDrop < PrivateSqliteRow < ' a > > > > ,
131+ field_count : usize ,
132+ marker : PhantomData < & ' a ffi:: sqlite3_value > ,
133+ }
134+
135+ impl < ' a > Drop for FunctionRow < ' a > {
136+ fn drop ( & mut self ) {
137+ if let Some ( args) = Rc :: get_mut ( & mut self . args ) {
138+ if let PrivateSqliteRow :: Duplicated { column_names, .. } =
139+ DerefMut :: deref_mut ( RefCell :: get_mut ( args) )
140+ {
141+ if let Some ( inner) = Rc :: get_mut ( column_names) {
142+ // an empty Vector does not allocate according to the documentation
143+ // so this prevents leaking memory
144+ std:: mem:: drop ( std:: mem:: replace ( inner, Vec :: new ( ) ) ) ;
145+ }
146+ }
147+ }
148+ }
123149}
124150
125151impl < ' a > FunctionRow < ' a > {
126- fn new ( args : & ' a [ * mut ffi:: sqlite3_value ] ) -> Self {
127- Self { args }
152+ fn new ( args : & mut [ * mut ffi:: sqlite3_value ] ) -> Self {
153+ let lenghts = args. len ( ) ;
154+ let args = unsafe {
155+ Vec :: from_raw_parts (
156+ // This cast is safe because:
157+ // * Casting from a pointer to an arry to a pointer to the first array
158+ // element is safe
159+ // * Casting from a raw pointer to `NonNull<T>` is safe,
160+ // because `NonNull` is #[repr(transparent)]
161+ // * Casting from `NonNull<T>` to `OwnedSqliteValue` is safe,
162+ // as the struct is `#[repr(transparent)]
163+ // * Casting from `NonNull<T>` to `Option<NonNull<T>>` as the documentation
164+ // states: "This is so that enums may use this forbidden value as a discriminant –
165+ // Option<NonNull<T>> has the same size as *mut T"
166+ // * The last point remains true for `OwnedSqliteValue` as `#[repr(transparent)]
167+ // guarantees the same layout as the inner type
168+ // * It's unsafe to drop the vector (and the vector elements)
169+ // because of this we wrap the vector (or better the Row)
170+ // Into `ManualDrop` to prevent the dropping
171+ args as * mut [ * mut ffi:: sqlite3_value ] as * mut ffi:: sqlite3_value
172+ as * mut Option < OwnedSqliteValue > ,
173+ lenghts,
174+ lenghts,
175+ )
176+ } ;
177+
178+ Self {
179+ field_count : lenghts,
180+ args : Rc :: new ( RefCell :: new ( ManuallyDrop :: new (
181+ PrivateSqliteRow :: Duplicated {
182+ values : args,
183+ column_names : Rc :: new ( vec ! [ None ; lenghts] ) ,
184+ } ,
185+ ) ) ) ,
186+ marker : PhantomData ,
187+ }
128188 }
129189}
130190
@@ -133,18 +193,17 @@ impl<'a> Row<'a, Sqlite> for FunctionRow<'a> {
133193 type InnerPartialRow = Self ;
134194
135195 fn field_count ( & self ) -> usize {
136- self . args . len ( )
196+ self . field_count
137197 }
138198
139199 fn get < I > ( & self , idx : I ) -> Option < Self :: Field >
140200 where
141201 Self : crate :: row:: RowIndex < I > ,
142202 {
143203 let idx = self . idx ( idx) ?;
144-
145- self . args . get ( idx) . map ( |arg| FunctionArgument {
146- arg : * arg,
147- p : PhantomData ,
204+ Some ( FunctionArgument {
205+ args : self . args . clone ( ) ,
206+ col_idx : idx as i32 ,
148207 } )
149208 }
150209
@@ -155,7 +214,7 @@ impl<'a> Row<'a, Sqlite> for FunctionRow<'a> {
155214
156215impl < ' a > RowIndex < usize > for FunctionRow < ' a > {
157216 fn idx ( & self , idx : usize ) -> Option < usize > {
158- if idx < self . args . len ( ) {
217+ if idx < self . field_count ( ) {
159218 Some ( idx)
160219 } else {
161220 None
@@ -170,8 +229,8 @@ impl<'a, 'b> RowIndex<&'a str> for FunctionRow<'b> {
170229}
171230
172231struct FunctionArgument < ' a > {
173- arg : * mut ffi :: sqlite3_value ,
174- p : PhantomData < & ' a ( ) > ,
232+ args : Rc < RefCell < ManuallyDrop < PrivateSqliteRow < ' a > > > > ,
233+ col_idx : i32 ,
175234}
176235
177236impl < ' a > Field < ' a , Sqlite > for FunctionArgument < ' a > {
@@ -187,7 +246,9 @@ impl<'a> Field<'a, Sqlite> for FunctionArgument<'a> {
187246 where
188247 ' a : ' b ,
189248 {
190- todo ! ( )
191- // unsafe { SqliteValue::new(self.arg) }
249+ SqliteValue :: new (
250+ Ref :: map ( self . args . borrow ( ) , |drop| std:: ops:: Deref :: deref ( drop) ) ,
251+ self . col_idx ,
252+ )
192253 }
193254}
0 commit comments