@@ -3,6 +3,7 @@ use std::sync::Arc;
33
44use spin_factors:: wasmtime:: component:: Resource ;
55use spin_factors:: { anyhow, SelfInstanceBuilder } ;
6+ use spin_world:: spin:: sqlite:: sqlite as v3;
67use spin_world:: v1:: sqlite as v1;
78use spin_world:: v2:: sqlite as v2;
89use tracing:: field:: Empty ;
@@ -34,40 +35,24 @@ impl InstanceState {
3435 }
3536
3637 /// Get a connection for a given database label.
37- fn get_connection (
38+ fn get_connection < T : ' static > (
3839 & self ,
39- connection : Resource < v2 :: Connection > ,
40- ) -> Result < & dyn Connection , v2 :: Error > {
40+ connection : Resource < T > ,
41+ ) -> Result < & dyn Connection , v3 :: Error > {
4142 self . connections
4243 . get ( connection. rep ( ) )
4344 . map ( |conn| conn. as_ref ( ) )
44- . ok_or ( v2 :: Error :: InvalidConnection )
45+ . ok_or ( v3 :: Error :: InvalidConnection )
4546 }
4647
47- /// Get the set of allowed databases.
48- pub fn allowed_databases ( & self ) -> & HashSet < String > {
49- & self . allowed_databases
50- }
51- }
52-
53- impl SelfInstanceBuilder for InstanceState { }
54-
55- impl v2:: Host for InstanceState {
56- fn convert_error ( & mut self , error : v2:: Error ) -> anyhow:: Result < v2:: Error > {
57- Ok ( error)
58- }
59- }
60-
61- impl v2:: HostConnection for InstanceState {
62- #[ instrument( name = "spin_sqlite.open" , skip( self ) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "sqlite" , sqlite. backend = Empty ) ) ]
63- async fn open ( & mut self , database : String ) -> Result < Resource < v2:: Connection > , v2:: Error > {
48+ async fn open_impl < T : ' static > ( & mut self , database : String ) -> Result < Resource < T > , v3:: Error > {
6449 if !self . allowed_databases . contains ( & database) {
65- return Err ( v2 :: Error :: AccessDenied ) ;
50+ return Err ( v3 :: Error :: AccessDenied ) ;
6651 }
6752 let conn = self
6853 . connection_creators
6954 . get ( & database)
70- . ok_or ( v2 :: Error :: NoSuchDatabase ) ?
55+ . ok_or ( v3 :: Error :: NoSuchDatabase ) ?
7156 . create_connection ( & database)
7257 . await ?;
7358 tracing:: Span :: current ( ) . record (
@@ -76,26 +61,117 @@ impl v2::HostConnection for InstanceState {
7661 ) ;
7762 self . connections
7863 . push ( conn)
79- . map_err ( |( ) | v2 :: Error :: Io ( "too many connections opened" . to_string ( ) ) )
64+ . map_err ( |( ) | v3 :: Error :: Io ( "too many connections opened" . to_string ( ) ) )
8065 . map ( Resource :: new_own)
8166 }
8267
68+ async fn execute_impl < T : ' static > (
69+ & mut self ,
70+ connection : Resource < T > ,
71+ query : String ,
72+ parameters : Vec < v3:: Value > ,
73+ ) -> Result < v3:: QueryResult , v3:: Error > {
74+ let conn = self . get_connection ( connection) ?;
75+ tracing:: Span :: current ( ) . record (
76+ "sqlite.backend" ,
77+ conn. summary ( ) . as_deref ( ) . unwrap_or ( "unknown" ) ,
78+ ) ;
79+ conn. query ( & query, parameters) . await
80+ }
81+
82+ /// Get the set of allowed databases.
83+ pub fn allowed_databases ( & self ) -> & HashSet < String > {
84+ & self . allowed_databases
85+ }
86+ }
87+
88+ impl SelfInstanceBuilder for InstanceState { }
89+
90+ impl v3:: Host for InstanceState {
91+ fn convert_error ( & mut self , error : v3:: Error ) -> anyhow:: Result < v3:: Error > {
92+ Ok ( error)
93+ }
94+ }
95+
96+ impl v3:: HostConnection for InstanceState {
97+ #[ instrument( name = "spin_sqlite.open" , skip( self ) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "sqlite" , sqlite. backend = Empty ) ) ]
98+ async fn open ( & mut self , database : String ) -> Result < Resource < v3:: Connection > , v3:: Error > {
99+ self . open_impl ( database) . await
100+ }
101+
83102 #[ instrument( name = "spin_sqlite.execute" , skip( self , connection, parameters) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "sqlite" , otel. name = query, sqlite. backend = Empty ) ) ]
84103 async fn execute (
85104 & mut self ,
86- connection : Resource < v2 :: Connection > ,
105+ connection : Resource < v3 :: Connection > ,
87106 query : String ,
88- parameters : Vec < v2:: Value > ,
89- ) -> Result < v2:: QueryResult , v2:: Error > {
107+ parameters : Vec < v3:: Value > ,
108+ ) -> Result < v3:: QueryResult , v3:: Error > {
109+ self . execute_impl ( connection, query, parameters) . await
110+ }
111+
112+ async fn changes (
113+ & mut self ,
114+ connection : Resource < v3:: Connection > ,
115+ ) -> spin_factors:: wasmtime:: Result < u64 > {
90116 let conn = match self . get_connection ( connection) {
91117 Ok ( c) => c,
92- Err ( err) => return Err ( err) ,
118+ Err ( err) => return Err ( err. into ( ) ) ,
93119 } ;
94120 tracing:: Span :: current ( ) . record (
95121 "sqlite.backend" ,
96122 conn. summary ( ) . as_deref ( ) . unwrap_or ( "unknown" ) ,
97123 ) ;
98- conn. query ( & query, parameters) . await
124+ conn. changes ( ) . await . map_err ( |e| e. into ( ) )
125+ }
126+
127+ async fn last_insert_rowid (
128+ & mut self ,
129+ connection : Resource < v3:: Connection > ,
130+ ) -> spin_factors:: wasmtime:: Result < i64 > {
131+ let conn = match self . get_connection ( connection) {
132+ Ok ( c) => c,
133+ Err ( err) => return Err ( err. into ( ) ) ,
134+ } ;
135+ tracing:: Span :: current ( ) . record (
136+ "sqlite.backend" ,
137+ conn. summary ( ) . as_deref ( ) . unwrap_or ( "unknown" ) ,
138+ ) ;
139+ conn. last_insert_rowid ( ) . await . map_err ( |e| e. into ( ) )
140+ }
141+
142+ async fn drop ( & mut self , connection : Resource < v3:: Connection > ) -> anyhow:: Result < ( ) > {
143+ let _ = self . connections . remove ( connection. rep ( ) ) ;
144+ Ok ( ( ) )
145+ }
146+ }
147+
148+ impl v2:: Host for InstanceState {
149+ fn convert_error ( & mut self , error : v2:: Error ) -> anyhow:: Result < v2:: Error > {
150+ Ok ( error)
151+ }
152+ }
153+
154+ impl v2:: HostConnection for InstanceState {
155+ #[ instrument( name = "spin_sqlite.open" , skip( self ) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "sqlite" , sqlite. backend = Empty ) ) ]
156+ async fn open ( & mut self , database : String ) -> Result < Resource < v2:: Connection > , v2:: Error > {
157+ self . open_impl ( database) . await . map_err ( to_v2_error)
158+ }
159+
160+ #[ instrument( name = "spin_sqlite.execute" , skip( self , connection, parameters) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "sqlite" , otel. name = query, sqlite. backend = Empty ) ) ]
161+ async fn execute (
162+ & mut self ,
163+ connection : Resource < v2:: Connection > ,
164+ query : String ,
165+ parameters : Vec < v2:: Value > ,
166+ ) -> Result < v2:: QueryResult , v2:: Error > {
167+ self . execute_impl (
168+ connection,
169+ query,
170+ parameters. into_iter ( ) . map ( from_v2_value) . collect ( ) ,
171+ )
172+ . await
173+ . map ( to_v2_query_result)
174+ . map_err ( to_v2_error)
99175 }
100176
101177 async fn drop ( & mut self , connection : Resource < v2:: Connection > ) -> anyhow:: Result < ( ) > {
@@ -106,7 +182,7 @@ impl v2::HostConnection for InstanceState {
106182
107183impl v1:: Host for InstanceState {
108184 async fn open ( & mut self , database : String ) -> Result < u32 , v1:: Error > {
109- let result = <Self as v2 :: HostConnection >:: open ( self , database) . await ;
185+ let result = <Self as v3 :: HostConnection >:: open ( self , database) . await ;
110186 result. map_err ( to_legacy_error) . map ( |s| s. rep ( ) )
111187 }
112188
@@ -117,7 +193,7 @@ impl v1::Host for InstanceState {
117193 parameters : Vec < spin_world:: v1:: sqlite:: Value > ,
118194 ) -> Result < spin_world:: v1:: sqlite:: QueryResult , v1:: Error > {
119195 let this = Resource :: new_borrow ( connection) ;
120- let result = <Self as v2 :: HostConnection >:: execute (
196+ let result = <Self as v3 :: HostConnection >:: execute (
121197 self ,
122198 this,
123199 query,
@@ -136,45 +212,88 @@ impl v1::Host for InstanceState {
136212 }
137213}
138214
139- fn to_legacy_error ( error : v2 :: Error ) -> v1 :: Error {
215+ fn to_v2_error ( error : v3 :: Error ) -> v2 :: Error {
140216 match error {
141- v2:: Error :: NoSuchDatabase => v1:: Error :: NoSuchDatabase ,
142- v2:: Error :: AccessDenied => v1:: Error :: AccessDenied ,
143- v2:: Error :: InvalidConnection => v1:: Error :: InvalidConnection ,
144- v2:: Error :: DatabaseFull => v1:: Error :: DatabaseFull ,
145- v2:: Error :: Io ( s) => v1:: Error :: Io ( s) ,
217+ v3:: Error :: NoSuchDatabase => v2:: Error :: NoSuchDatabase ,
218+ v3:: Error :: AccessDenied => v2:: Error :: AccessDenied ,
219+ v3:: Error :: InvalidConnection => v2:: Error :: InvalidConnection ,
220+ v3:: Error :: DatabaseFull => v2:: Error :: DatabaseFull ,
221+ v3:: Error :: Io ( s) => v2:: Error :: Io ( s) ,
222+ }
223+ }
224+
225+ fn to_legacy_error ( error : v3:: Error ) -> v1:: Error {
226+ match error {
227+ v3:: Error :: NoSuchDatabase => v1:: Error :: NoSuchDatabase ,
228+ v3:: Error :: AccessDenied => v1:: Error :: AccessDenied ,
229+ v3:: Error :: InvalidConnection => v1:: Error :: InvalidConnection ,
230+ v3:: Error :: DatabaseFull => v1:: Error :: DatabaseFull ,
231+ v3:: Error :: Io ( s) => v1:: Error :: Io ( s) ,
232+ }
233+ }
234+
235+ fn to_v2_query_result ( result : v3:: QueryResult ) -> v2:: QueryResult {
236+ v2:: QueryResult {
237+ columns : result. columns ,
238+ rows : result. rows . into_iter ( ) . map ( to_v2_row_result) . collect ( ) ,
146239 }
147240}
148241
149- fn to_legacy_query_result ( result : v2 :: QueryResult ) -> v1:: QueryResult {
242+ fn to_legacy_query_result ( result : v3 :: QueryResult ) -> v1:: QueryResult {
150243 v1:: QueryResult {
151244 columns : result. columns ,
152245 rows : result. rows . into_iter ( ) . map ( to_legacy_row_result) . collect ( ) ,
153246 }
154247}
155248
156- fn to_legacy_row_result ( result : v2:: RowResult ) -> v1:: RowResult {
249+ fn to_v2_row_result ( result : v3:: RowResult ) -> v2:: RowResult {
250+ v2:: RowResult {
251+ values : result. values . into_iter ( ) . map ( to_v2_value) . collect ( ) ,
252+ }
253+ }
254+
255+ fn to_legacy_row_result ( result : v3:: RowResult ) -> v1:: RowResult {
157256 v1:: RowResult {
158257 values : result. values . into_iter ( ) . map ( to_legacy_value) . collect ( ) ,
159258 }
160259}
161260
162- fn to_legacy_value ( value : v2:: Value ) -> v1:: Value {
261+ fn to_v2_value ( value : v3:: Value ) -> v2:: Value {
262+ match value {
263+ v3:: Value :: Integer ( i) => v2:: Value :: Integer ( i) ,
264+ v3:: Value :: Real ( r) => v2:: Value :: Real ( r) ,
265+ v3:: Value :: Text ( t) => v2:: Value :: Text ( t) ,
266+ v3:: Value :: Blob ( b) => v2:: Value :: Blob ( b) ,
267+ v3:: Value :: Null => v2:: Value :: Null ,
268+ }
269+ }
270+
271+ fn to_legacy_value ( value : v3:: Value ) -> v1:: Value {
272+ match value {
273+ v3:: Value :: Integer ( i) => v1:: Value :: Integer ( i) ,
274+ v3:: Value :: Real ( r) => v1:: Value :: Real ( r) ,
275+ v3:: Value :: Text ( t) => v1:: Value :: Text ( t) ,
276+ v3:: Value :: Blob ( b) => v1:: Value :: Blob ( b) ,
277+ v3:: Value :: Null => v1:: Value :: Null ,
278+ }
279+ }
280+
281+ fn from_v2_value ( value : v2:: Value ) -> v3:: Value {
163282 match value {
164- v2:: Value :: Integer ( i) => v1 :: Value :: Integer ( i) ,
165- v2:: Value :: Real ( r) => v1 :: Value :: Real ( r) ,
166- v2:: Value :: Text ( t) => v1 :: Value :: Text ( t) ,
167- v2:: Value :: Blob ( b) => v1 :: Value :: Blob ( b) ,
168- v2:: Value :: Null => v1 :: Value :: Null ,
283+ v2:: Value :: Integer ( i) => v3 :: Value :: Integer ( i) ,
284+ v2:: Value :: Real ( r) => v3 :: Value :: Real ( r) ,
285+ v2:: Value :: Text ( t) => v3 :: Value :: Text ( t) ,
286+ v2:: Value :: Blob ( b) => v3 :: Value :: Blob ( b) ,
287+ v2:: Value :: Null => v3 :: Value :: Null ,
169288 }
170289}
171290
172- fn from_legacy_value ( value : v1:: Value ) -> v2 :: Value {
291+ fn from_legacy_value ( value : v1:: Value ) -> v3 :: Value {
173292 match value {
174- v1:: Value :: Integer ( i) => v2 :: Value :: Integer ( i) ,
175- v1:: Value :: Real ( r) => v2 :: Value :: Real ( r) ,
176- v1:: Value :: Text ( t) => v2 :: Value :: Text ( t) ,
177- v1:: Value :: Blob ( b) => v2 :: Value :: Blob ( b) ,
178- v1:: Value :: Null => v2 :: Value :: Null ,
293+ v1:: Value :: Integer ( i) => v3 :: Value :: Integer ( i) ,
294+ v1:: Value :: Real ( r) => v3 :: Value :: Real ( r) ,
295+ v1:: Value :: Text ( t) => v3 :: Value :: Text ( t) ,
296+ v1:: Value :: Blob ( b) => v3 :: Value :: Blob ( b) ,
297+ v1:: Value :: Null => v3 :: Value :: Null ,
179298 }
180299}
0 commit comments