@@ -3,76 +3,65 @@ use reqwest::{
33 Client , Error , Method , Response ,
44} ;
55
6- #[ derive( Default ) ]
76pub struct Builder {
87 method : Method ,
98 url : String ,
109 schema : Option < String > ,
10+ // Need this to allow access from `filter.rs`
1111 pub ( crate ) queries : Vec < ( String , String ) > ,
1212 headers : HeaderMap ,
1313 body : Option < String > ,
1414 is_rpc : bool ,
1515}
1616
17- // TODO: Complex filters (not, and, or)
18- // TODO: Exact, planned, estimated count (HEAD verb)
19- // TODO: Response format
20- // TODO: Resource embedding (embedded filters, etc.)
21- // TODO: Content-Type (text/csv, etc.)
22- // TODO: Reject update/delete w/o filters
17+ // TODO: Test Unicode support
2318impl Builder {
24- pub fn new < S > ( url : S , schema : Option < String > ) -> Self
19+ pub fn new < T > ( url : T , schema : Option < String > ) -> Self
2520 where
26- S : Into < String > ,
21+ T : Into < String > ,
2722 {
2823 let mut builder = Builder {
2924 method : Method :: GET ,
3025 url : url. into ( ) ,
3126 schema,
27+ queries : Vec :: new ( ) ,
3228 headers : HeaderMap :: new ( ) ,
33- ..Default :: default ( )
29+ body : None ,
30+ is_rpc : false ,
3431 } ;
3532 builder
3633 . headers
3734 . insert ( "Accept" , HeaderValue :: from_static ( "application/json" ) ) ;
3835 builder
3936 }
4037
41- pub fn auth < S > ( mut self , token : S ) -> Self
38+ pub fn auth < T > ( mut self , token : T ) -> Self
4239 where
43- S : Into < String > ,
40+ T : Into < String > ,
4441 {
45- self . headers . append (
42+ self . headers . insert (
4643 "Authorization" ,
4744 HeaderValue :: from_str ( & format ! ( "Bearer {}" , token. into( ) ) ) . unwrap ( ) ,
4845 ) ;
4946 self
5047 }
5148
52- // TODO: Multiple columns
53- // TODO: Renaming columns
54- // TODO: Casting columns
55- // TODO: JSON columns
56- // TODO: Computed (virtual) columns
57- // TODO: Investigate character corner cases (Unicode, [ .,:()])
58- pub fn select < S > ( mut self , column : S ) -> Self
49+ // TODO: Renaming, casting, & JSON column examples
50+ // TODO: Resource embedding example
51+ pub fn select < T > ( mut self , columns : T ) -> Self
5952 where
60- S : Into < String > ,
53+ T : Into < String > ,
6154 {
6255 self . method = Method :: GET ;
63- self . queries . push ( ( "select" . to_string ( ) , column . into ( ) ) ) ;
56+ self . queries . push ( ( "select" . to_string ( ) , columns . into ( ) ) ) ;
6457 self
6558 }
6659
67- // TODO: desc/asc
68- // TODO: nullsfirst/nullslast
69- // TODO: Multiple columns
70- // TODO: Computed columns
71- pub fn order < S > ( mut self , column : S ) -> Self
60+ pub fn order < T > ( mut self , columns : T ) -> Self
7261 where
73- S : Into < String > ,
62+ T : Into < String > ,
7463 {
75- self . queries . push ( ( "order" . to_string ( ) , column . into ( ) ) ) ;
64+ self . queries . push ( ( "order" . to_string ( ) , columns . into ( ) ) ) ;
7665 self
7766 }
7867
@@ -96,6 +85,31 @@ impl Builder {
9685 self
9786 }
9887
88+ fn count ( mut self , method : & str ) -> Self {
89+ self . headers
90+ . insert ( "Range-Unit" , HeaderValue :: from_static ( "items" ) ) ;
91+ // Value is irrelevant, we just want the size
92+ self . headers
93+ . insert ( "Range" , HeaderValue :: from_static ( "0-0" ) ) ;
94+ self . headers . insert (
95+ "Prefer" ,
96+ HeaderValue :: from_str ( & format ! ( "count={}" , method) ) . unwrap ( ) ,
97+ ) ;
98+ self
99+ }
100+
101+ pub fn exact_count ( self ) -> Self {
102+ self . count ( "exact" )
103+ }
104+
105+ pub fn planned_count ( self ) -> Self {
106+ self . count ( "planned" )
107+ }
108+
109+ pub fn estimated_count ( self ) -> Self {
110+ self . count ( "estimated" )
111+ }
112+
99113 pub fn single ( mut self ) -> Self {
100114 self . headers . insert (
101115 "Accept" ,
@@ -104,12 +118,9 @@ impl Builder {
104118 self
105119 }
106120
107- // TODO: Write-only tables
108- // TODO: URL-encoded payload
109- // TODO: Allow specifying columns
110- pub fn insert < S > ( mut self , body : S ) -> Self
121+ pub fn insert < T > ( mut self , body : T ) -> Self
111122 where
112- S : Into < String > ,
123+ T : Into < String > ,
113124 {
114125 self . method = Method :: POST ;
115126 self . headers
@@ -118,11 +129,9 @@ impl Builder {
118129 self
119130 }
120131
121- // TODO: Allow Prefer: resolution=ignore-duplicates
122- // TODO: on_conflict (make UPSERT work on UNIQUE columns)
123- pub fn upsert < S > ( mut self , body : S ) -> Self
132+ pub fn upsert < T > ( mut self , body : T ) -> Self
124133 where
125- S : Into < String > ,
134+ T : Into < String > ,
126135 {
127136 self . method = Method :: POST ;
128137 self . headers . insert (
@@ -133,24 +142,9 @@ impl Builder {
133142 self
134143 }
135144
136- pub fn single_upsert < S , T , U > ( mut self , primary_column : S , key : T , body : U ) -> Self
145+ pub fn update < T > ( mut self , body : T ) -> Self
137146 where
138- S : Into < String > ,
139147 T : Into < String > ,
140- U : Into < String > ,
141- {
142- self . method = Method :: PUT ;
143- self . headers
144- . insert ( "Prefer" , HeaderValue :: from_static ( "return=representation" ) ) ;
145- self . queries
146- . push ( ( primary_column. into ( ) , format ! ( "eq.{}" , key. into( ) ) ) ) ;
147- self . body = Some ( body. into ( ) ) ;
148- self
149- }
150-
151- pub fn update < S > ( mut self , body : S ) -> Self
152- where
153- S : Into < String > ,
154148 {
155149 self . method = Method :: PATCH ;
156150 self . headers
@@ -166,9 +160,9 @@ impl Builder {
166160 self
167161 }
168162
169- pub fn rpc < S > ( mut self , params : S ) -> Self
163+ pub fn rpc < T > ( mut self , params : T ) -> Self
170164 where
171- S : Into < String > ,
165+ T : Into < String > ,
172166 {
173167 self . method = Method :: POST ;
174168 self . body = Some ( params. into ( ) ) ;
@@ -185,7 +179,7 @@ impl Builder {
185179 "Content-Profile"
186180 } ;
187181 self . headers
188- . append ( key, HeaderValue :: from_str ( & schema) . unwrap ( ) ) ;
182+ . insert ( key, HeaderValue :: from_str ( & schema) . unwrap ( ) ) ;
189183 }
190184 if self . method != Method :: GET && self . method != Method :: HEAD {
191185 self . headers
@@ -205,7 +199,7 @@ mod tests {
205199 use super :: * ;
206200
207201 const TABLE_URL : & str = "http://localhost:3000/table" ;
208- const RPC_URL : & str = "http://localhost/rpc" ;
202+ const RPC_URL : & str = "http://localhost:3000 /rpc" ;
209203
210204 #[ test]
211205 fn only_accept_json ( ) {
@@ -284,15 +278,6 @@ mod tests {
284278 ) ;
285279 }
286280
287- #[ test]
288- fn single_upsert_assert_prefer_header ( ) {
289- let builder = Builder :: new ( TABLE_URL , None ) . single_upsert ( "ignored" , "ignored" , "ignored" ) ;
290- assert_eq ! (
291- builder. headers. get( "Prefer" ) . unwrap( ) ,
292- HeaderValue :: from_static( "return=representation" )
293- ) ;
294- }
295-
296281 #[ test]
297282 fn not_rpc_should_not_have_flag ( ) {
298283 let builder = Builder :: new ( TABLE_URL , None ) . select ( "ignored" ) ;
0 commit comments