@@ -3,76 +3,65 @@ use reqwest::{
3
3
Client , Error , Method , Response ,
4
4
} ;
5
5
6
- #[ derive( Default ) ]
7
6
pub struct Builder {
8
7
method : Method ,
9
8
url : String ,
10
9
schema : Option < String > ,
10
+ // Need this to allow access from `filter.rs`
11
11
pub ( crate ) queries : Vec < ( String , String ) > ,
12
12
headers : HeaderMap ,
13
13
body : Option < String > ,
14
14
is_rpc : bool ,
15
15
}
16
16
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
23
18
impl Builder {
24
- pub fn new < S > ( url : S , schema : Option < String > ) -> Self
19
+ pub fn new < T > ( url : T , schema : Option < String > ) -> Self
25
20
where
26
- S : Into < String > ,
21
+ T : Into < String > ,
27
22
{
28
23
let mut builder = Builder {
29
24
method : Method :: GET ,
30
25
url : url. into ( ) ,
31
26
schema,
27
+ queries : Vec :: new ( ) ,
32
28
headers : HeaderMap :: new ( ) ,
33
- ..Default :: default ( )
29
+ body : None ,
30
+ is_rpc : false ,
34
31
} ;
35
32
builder
36
33
. headers
37
34
. insert ( "Accept" , HeaderValue :: from_static ( "application/json" ) ) ;
38
35
builder
39
36
}
40
37
41
- pub fn auth < S > ( mut self , token : S ) -> Self
38
+ pub fn auth < T > ( mut self , token : T ) -> Self
42
39
where
43
- S : Into < String > ,
40
+ T : Into < String > ,
44
41
{
45
- self . headers . append (
42
+ self . headers . insert (
46
43
"Authorization" ,
47
44
HeaderValue :: from_str ( & format ! ( "Bearer {}" , token. into( ) ) ) . unwrap ( ) ,
48
45
) ;
49
46
self
50
47
}
51
48
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
59
52
where
60
- S : Into < String > ,
53
+ T : Into < String > ,
61
54
{
62
55
self . method = Method :: GET ;
63
- self . queries . push ( ( "select" . to_string ( ) , column . into ( ) ) ) ;
56
+ self . queries . push ( ( "select" . to_string ( ) , columns . into ( ) ) ) ;
64
57
self
65
58
}
66
59
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
72
61
where
73
- S : Into < String > ,
62
+ T : Into < String > ,
74
63
{
75
- self . queries . push ( ( "order" . to_string ( ) , column . into ( ) ) ) ;
64
+ self . queries . push ( ( "order" . to_string ( ) , columns . into ( ) ) ) ;
76
65
self
77
66
}
78
67
@@ -96,6 +85,31 @@ impl Builder {
96
85
self
97
86
}
98
87
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
+
99
113
pub fn single ( mut self ) -> Self {
100
114
self . headers . insert (
101
115
"Accept" ,
@@ -104,12 +118,9 @@ impl Builder {
104
118
self
105
119
}
106
120
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
111
122
where
112
- S : Into < String > ,
123
+ T : Into < String > ,
113
124
{
114
125
self . method = Method :: POST ;
115
126
self . headers
@@ -118,11 +129,9 @@ impl Builder {
118
129
self
119
130
}
120
131
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
124
133
where
125
- S : Into < String > ,
134
+ T : Into < String > ,
126
135
{
127
136
self . method = Method :: POST ;
128
137
self . headers . insert (
@@ -133,24 +142,9 @@ impl Builder {
133
142
self
134
143
}
135
144
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
137
146
where
138
- S : Into < String > ,
139
147
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 > ,
154
148
{
155
149
self . method = Method :: PATCH ;
156
150
self . headers
@@ -166,9 +160,9 @@ impl Builder {
166
160
self
167
161
}
168
162
169
- pub fn rpc < S > ( mut self , params : S ) -> Self
163
+ pub fn rpc < T > ( mut self , params : T ) -> Self
170
164
where
171
- S : Into < String > ,
165
+ T : Into < String > ,
172
166
{
173
167
self . method = Method :: POST ;
174
168
self . body = Some ( params. into ( ) ) ;
@@ -185,7 +179,7 @@ impl Builder {
185
179
"Content-Profile"
186
180
} ;
187
181
self . headers
188
- . append ( key, HeaderValue :: from_str ( & schema) . unwrap ( ) ) ;
182
+ . insert ( key, HeaderValue :: from_str ( & schema) . unwrap ( ) ) ;
189
183
}
190
184
if self . method != Method :: GET && self . method != Method :: HEAD {
191
185
self . headers
@@ -205,7 +199,7 @@ mod tests {
205
199
use super :: * ;
206
200
207
201
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" ;
209
203
210
204
#[ test]
211
205
fn only_accept_json ( ) {
@@ -284,15 +278,6 @@ mod tests {
284
278
) ;
285
279
}
286
280
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
-
296
281
#[ test]
297
282
fn not_rpc_should_not_have_flag ( ) {
298
283
let builder = Builder :: new ( TABLE_URL , None ) . select ( "ignored" ) ;
0 commit comments