10
10
//! [Learn more](https://developers.cloudflare.com/workers/learning/using-durable-objects) about
11
11
//! using Durable Objects.
12
12
13
- use std:: { fmt:: Display , ops:: Deref , time:: Duration } ;
13
+ use std:: { convert :: Into , fmt:: Display , marker :: PhantomData , ops:: Deref , time:: Duration } ;
14
14
15
15
use crate :: {
16
16
date:: Date ,
@@ -24,12 +24,13 @@ use crate::{
24
24
use async_trait:: async_trait;
25
25
use chrono:: { DateTime , Utc } ;
26
26
use futures_util:: Future ;
27
- use js_sys:: { Map , Number , Object } ;
27
+ use js_sys:: { IntoIter , Map , Number , Object } ;
28
28
use serde:: { de:: DeserializeOwned , Serialize } ;
29
29
use wasm_bindgen:: { prelude:: * , JsCast } ;
30
30
use worker_sys:: {
31
31
DurableObject as EdgeDurableObject , DurableObjectId ,
32
- DurableObjectNamespace as EdgeObjectNamespace , DurableObjectState , DurableObjectStorage ,
32
+ DurableObjectNamespace as EdgeObjectNamespace , DurableObjectSqlStorage ,
33
+ DurableObjectSqlStorageCursor , DurableObjectState , DurableObjectStorage ,
33
34
DurableObjectTransaction ,
34
35
} ;
35
36
// use wasm_bindgen_futures::future_to_promise;
@@ -501,6 +502,121 @@ impl Storage {
501
502
. map_err ( Error :: from)
502
503
. map ( |_| ( ) )
503
504
}
505
+
506
+ pub fn sql ( & self ) -> Result < SqlStorage > {
507
+ let sql = self . inner . sql ( ) ?;
508
+ Ok ( SqlStorage { inner : sql } )
509
+ }
510
+ }
511
+
512
+ pub enum SqlStorageValue {
513
+ Null ,
514
+ Boolean ( bool ) ,
515
+ Integer ( i32 ) ,
516
+ Float ( f64 ) ,
517
+ String ( String ) ,
518
+ Blob ( Vec < u8 > ) ,
519
+ }
520
+
521
+ impl < T : Into < SqlStorageValue > > From < Option < T > > for SqlStorageValue {
522
+ fn from ( value : Option < T > ) -> Self {
523
+ match value {
524
+ Some ( v) => v. into ( ) ,
525
+ None => SqlStorageValue :: Null ,
526
+ }
527
+ }
528
+ }
529
+
530
+ impl From < bool > for SqlStorageValue {
531
+ fn from ( value : bool ) -> Self {
532
+ Self :: Boolean ( value)
533
+ }
534
+ }
535
+
536
+ impl From < f64 > for SqlStorageValue {
537
+ fn from ( value : f64 ) -> Self {
538
+ Self :: Float ( value)
539
+ }
540
+ }
541
+
542
+ impl From < String > for SqlStorageValue {
543
+ fn from ( value : String ) -> Self {
544
+ Self :: String ( value)
545
+ }
546
+ }
547
+
548
+ impl From < Vec < u8 > > for SqlStorageValue {
549
+ fn from ( value : Vec < u8 > ) -> Self {
550
+ Self :: Blob ( value)
551
+ }
552
+ }
553
+
554
+ impl From < i32 > for SqlStorageValue {
555
+ fn from ( value : i32 ) -> Self {
556
+ Self :: Integer ( value)
557
+ }
558
+ }
559
+
560
+ impl Into < JsValue > for SqlStorageValue {
561
+ fn into ( self ) -> JsValue {
562
+ match self {
563
+ SqlStorageValue :: Null => JsValue :: NULL ,
564
+ SqlStorageValue :: Boolean ( b) => b. into ( ) ,
565
+ SqlStorageValue :: Integer ( i) => i. into ( ) ,
566
+ SqlStorageValue :: Float ( f) => f. into ( ) ,
567
+ SqlStorageValue :: String ( s) => s. into ( ) ,
568
+ SqlStorageValue :: Blob ( b) => b. into ( ) ,
569
+ }
570
+ }
571
+ }
572
+
573
+ pub struct SqlStorage {
574
+ inner : DurableObjectSqlStorage ,
575
+ }
576
+
577
+ impl SqlStorage {
578
+ pub fn exec < T : DeserializeOwned > (
579
+ & self ,
580
+ query : & str ,
581
+ params : Vec < SqlStorageValue > ,
582
+ ) -> Result < SqlStorageCursor < T > > {
583
+ let cursor = self
584
+ . inner
585
+ . exec ( query. into ( ) , params. into_iter ( ) . map ( Into :: into) . collect ( ) ) ?;
586
+ let iter = js_sys:: try_iter ( & cursor) ?;
587
+ Ok ( SqlStorageCursor {
588
+ inner : cursor,
589
+ iter,
590
+ _row_type : PhantomData ,
591
+ } )
592
+ }
593
+ }
594
+
595
+ pub struct SqlStorageCursor < T : DeserializeOwned > {
596
+ inner : DurableObjectSqlStorageCursor ,
597
+ iter : Option < IntoIter > ,
598
+ _row_type : PhantomData < T > ,
599
+ }
600
+
601
+ impl < T : DeserializeOwned > SqlStorageCursor < T > {
602
+ pub fn one ( & self ) -> Result < T > {
603
+ self . inner
604
+ . one ( )
605
+ . and_then ( |row| serde_wasm_bindgen:: from_value ( row) . map_err ( JsValue :: from) )
606
+ . map_err ( Error :: from)
607
+ }
608
+ }
609
+
610
+ impl < T : DeserializeOwned > Iterator for SqlStorageCursor < T > {
611
+ type Item = Result < T > ;
612
+
613
+ fn next ( & mut self ) -> Option < Self :: Item > {
614
+ let row = self . iter . as_mut ( ) ?. next ( ) ?;
615
+ Some (
616
+ row. and_then ( |row| serde_wasm_bindgen:: from_value ( row) . map_err ( JsValue :: from) )
617
+ . map_err ( Error :: from) ,
618
+ )
619
+ }
504
620
}
505
621
506
622
pub struct Transaction {
@@ -515,7 +631,7 @@ impl Transaction {
515
631
if val. is_undefined ( ) {
516
632
Err ( JsValue :: from ( "No such value in storage." ) )
517
633
} else {
518
- serde_wasm_bindgen:: from_value ( val) . map_err ( std :: convert :: Into :: into)
634
+ serde_wasm_bindgen:: from_value ( val) . map_err ( Into :: into)
519
635
}
520
636
} )
521
637
. map_err ( Error :: from)
0 commit comments