@@ -3,6 +3,7 @@ use std::sync::Arc;
3
3
4
4
use spin_factors:: wasmtime:: component:: Resource ;
5
5
use spin_factors:: { anyhow, SelfInstanceBuilder } ;
6
+ use spin_world:: spin:: sqlite:: sqlite as v3;
6
7
use spin_world:: v1:: sqlite as v1;
7
8
use spin_world:: v2:: sqlite as v2;
8
9
use tracing:: field:: Empty ;
@@ -34,40 +35,24 @@ impl InstanceState {
34
35
}
35
36
36
37
/// Get a connection for a given database label.
37
- fn get_connection (
38
+ fn get_connection < T : ' static > (
38
39
& self ,
39
- connection : Resource < v2 :: Connection > ,
40
- ) -> Result < & dyn Connection , v2 :: Error > {
40
+ connection : Resource < T > ,
41
+ ) -> Result < & dyn Connection , v3 :: Error > {
41
42
self . connections
42
43
. get ( connection. rep ( ) )
43
44
. map ( |conn| conn. as_ref ( ) )
44
- . ok_or ( v2 :: Error :: InvalidConnection )
45
+ . ok_or ( v3 :: Error :: InvalidConnection )
45
46
}
46
47
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 > {
64
49
if !self . allowed_databases . contains ( & database) {
65
- return Err ( v2 :: Error :: AccessDenied ) ;
50
+ return Err ( v3 :: Error :: AccessDenied ) ;
66
51
}
67
52
let conn = self
68
53
. connection_creators
69
54
. get ( & database)
70
- . ok_or ( v2 :: Error :: NoSuchDatabase ) ?
55
+ . ok_or ( v3 :: Error :: NoSuchDatabase ) ?
71
56
. create_connection ( & database)
72
57
. await ?;
73
58
tracing:: Span :: current ( ) . record (
@@ -76,26 +61,117 @@ impl v2::HostConnection for InstanceState {
76
61
) ;
77
62
self . connections
78
63
. 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 ( ) ) )
80
65
. map ( Resource :: new_own)
81
66
}
82
67
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
+
83
102
#[ 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 ) ) ]
84
103
async fn execute (
85
104
& mut self ,
86
- connection : Resource < v2 :: Connection > ,
105
+ connection : Resource < v3 :: Connection > ,
87
106
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 > {
90
116
let conn = match self . get_connection ( connection) {
91
117
Ok ( c) => c,
92
- Err ( err) => return Err ( err) ,
118
+ Err ( err) => return Err ( err. into ( ) ) ,
93
119
} ;
94
120
tracing:: Span :: current ( ) . record (
95
121
"sqlite.backend" ,
96
122
conn. summary ( ) . as_deref ( ) . unwrap_or ( "unknown" ) ,
97
123
) ;
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)
99
175
}
100
176
101
177
async fn drop ( & mut self , connection : Resource < v2:: Connection > ) -> anyhow:: Result < ( ) > {
@@ -106,7 +182,7 @@ impl v2::HostConnection for InstanceState {
106
182
107
183
impl v1:: Host for InstanceState {
108
184
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 ;
110
186
result. map_err ( to_legacy_error) . map ( |s| s. rep ( ) )
111
187
}
112
188
@@ -117,7 +193,7 @@ impl v1::Host for InstanceState {
117
193
parameters : Vec < spin_world:: v1:: sqlite:: Value > ,
118
194
) -> Result < spin_world:: v1:: sqlite:: QueryResult , v1:: Error > {
119
195
let this = Resource :: new_borrow ( connection) ;
120
- let result = <Self as v2 :: HostConnection >:: execute (
196
+ let result = <Self as v3 :: HostConnection >:: execute (
121
197
self ,
122
198
this,
123
199
query,
@@ -136,45 +212,88 @@ impl v1::Host for InstanceState {
136
212
}
137
213
}
138
214
139
- fn to_legacy_error ( error : v2 :: Error ) -> v1 :: Error {
215
+ fn to_v2_error ( error : v3 :: Error ) -> v2 :: Error {
140
216
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 ( ) ,
146
239
}
147
240
}
148
241
149
- fn to_legacy_query_result ( result : v2 :: QueryResult ) -> v1:: QueryResult {
242
+ fn to_legacy_query_result ( result : v3 :: QueryResult ) -> v1:: QueryResult {
150
243
v1:: QueryResult {
151
244
columns : result. columns ,
152
245
rows : result. rows . into_iter ( ) . map ( to_legacy_row_result) . collect ( ) ,
153
246
}
154
247
}
155
248
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 {
157
256
v1:: RowResult {
158
257
values : result. values . into_iter ( ) . map ( to_legacy_value) . collect ( ) ,
159
258
}
160
259
}
161
260
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 {
163
282
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 ,
169
288
}
170
289
}
171
290
172
- fn from_legacy_value ( value : v1:: Value ) -> v2 :: Value {
291
+ fn from_legacy_value ( value : v1:: Value ) -> v3 :: Value {
173
292
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 ,
179
298
}
180
299
}
0 commit comments