1 /**************************************************************************
2 Copyright (c) 2017 sewenew
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 *************************************************************************/
16
17 #include "command.h"
18 #include <cassert>
19
20 namespace sw {
21
22 namespace redis {
23
24 namespace cmd {
25
26 // KEY commands.
27
restore(Connection & connection,const StringView & key,const StringView & val,long long ttl,bool replace)28 void restore(Connection &connection,
29 const StringView &key,
30 const StringView &val,
31 long long ttl,
32 bool replace) {
33 CmdArgs args;
34 args << "RESTORE" << key << ttl << val;
35
36 if (replace) {
37 args << "REPLACE";
38 }
39
40 connection.send(args);
41 }
42
43 // STRING commands.
44
bitop(Connection & connection,BitOp op,const StringView & destination,const StringView & key)45 void bitop(Connection &connection,
46 BitOp op,
47 const StringView &destination,
48 const StringView &key) {
49 CmdArgs args;
50
51 detail::set_bitop(args, op);
52
53 args << destination << key;
54
55 connection.send(args);
56 }
57
set(Connection & connection,const StringView & key,const StringView & val,long long ttl,UpdateType type)58 void set(Connection &connection,
59 const StringView &key,
60 const StringView &val,
61 long long ttl,
62 UpdateType type) {
63 CmdArgs args;
64 args << "SET" << key << val;
65
66 if (ttl > 0) {
67 args << "PX" << ttl;
68 }
69
70 detail::set_update_type(args, type);
71
72 connection.send(args);
73 }
74
75 // LIST commands.
76
linsert(Connection & connection,const StringView & key,InsertPosition position,const StringView & pivot,const StringView & val)77 void linsert(Connection &connection,
78 const StringView &key,
79 InsertPosition position,
80 const StringView &pivot,
81 const StringView &val) {
82 std::string pos;
83 switch (position) {
84 case InsertPosition::BEFORE:
85 pos = "BEFORE";
86 break;
87
88 case InsertPosition::AFTER:
89 pos = "AFTER";
90 break;
91
92 default:
93 assert(false);
94 }
95
96 connection.send("LINSERT %b %s %b %b",
97 key.data(), key.size(),
98 pos.c_str(),
99 pivot.data(), pivot.size(),
100 val.data(), val.size());
101 }
102
103 // GEO commands.
104
geodist(Connection & connection,const StringView & key,const StringView & member1,const StringView & member2,GeoUnit unit)105 void geodist(Connection &connection,
106 const StringView &key,
107 const StringView &member1,
108 const StringView &member2,
109 GeoUnit unit) {
110 CmdArgs args;
111 args << "GEODIST" << key << member1 << member2;
112
113 detail::set_geo_unit(args, unit);
114
115 connection.send(args);
116 }
117
georadius_store(Connection & connection,const StringView & key,const std::pair<double,double> & loc,double radius,GeoUnit unit,const StringView & destination,bool store_dist,long long count)118 void georadius_store(Connection &connection,
119 const StringView &key,
120 const std::pair<double, double> &loc,
121 double radius,
122 GeoUnit unit,
123 const StringView &destination,
124 bool store_dist,
125 long long count) {
126 CmdArgs args;
127 args << "GEORADIUS" << key << loc.first << loc.second;
128
129 detail::set_georadius_store_parameters(args,
130 radius,
131 unit,
132 destination,
133 store_dist,
134 count);
135
136 connection.send(args);
137 }
138
georadius(Connection & connection,const StringView & key,const std::pair<double,double> & loc,double radius,GeoUnit unit,long long count,bool asc,bool with_coord,bool with_dist,bool with_hash)139 void georadius(Connection &connection,
140 const StringView &key,
141 const std::pair<double, double> &loc,
142 double radius,
143 GeoUnit unit,
144 long long count,
145 bool asc,
146 bool with_coord,
147 bool with_dist,
148 bool with_hash) {
149 CmdArgs args;
150 args << "GEORADIUS" << key << loc.first << loc.second;
151
152 detail::set_georadius_parameters(args,
153 radius,
154 unit,
155 count,
156 asc,
157 with_coord,
158 with_dist,
159 with_hash);
160
161 connection.send(args);
162 }
163
georadiusbymember(Connection & connection,const StringView & key,const StringView & member,double radius,GeoUnit unit,long long count,bool asc,bool with_coord,bool with_dist,bool with_hash)164 void georadiusbymember(Connection &connection,
165 const StringView &key,
166 const StringView &member,
167 double radius,
168 GeoUnit unit,
169 long long count,
170 bool asc,
171 bool with_coord,
172 bool with_dist,
173 bool with_hash) {
174 CmdArgs args;
175 args << "GEORADIUSBYMEMBER" << key << member;
176
177 detail::set_georadius_parameters(args,
178 radius,
179 unit,
180 count,
181 asc,
182 with_coord,
183 with_dist,
184 with_hash);
185
186 connection.send(args);
187 }
188
georadiusbymember_store(Connection & connection,const StringView & key,const StringView & member,double radius,GeoUnit unit,const StringView & destination,bool store_dist,long long count)189 void georadiusbymember_store(Connection &connection,
190 const StringView &key,
191 const StringView &member,
192 double radius,
193 GeoUnit unit,
194 const StringView &destination,
195 bool store_dist,
196 long long count) {
197 CmdArgs args;
198 args << "GEORADIUSBYMEMBER" << key << member;
199
200 detail::set_georadius_store_parameters(args,
201 radius,
202 unit,
203 destination,
204 store_dist,
205 count);
206
207 connection.send(args);
208 }
209
210 // Stream commands.
211
xtrim(Connection & connection,const StringView & key,long long count,bool approx)212 void xtrim(Connection &connection, const StringView &key, long long count, bool approx) {
213 CmdArgs args;
214 args << "XTRIM" << key << "MAXLEN";
215
216 if (approx) {
217 args << "~";
218 }
219
220 args << count;
221
222 connection.send(args);
223 }
224
225 namespace detail {
226
set_bitop(CmdArgs & args,BitOp op)227 void set_bitop(CmdArgs &args, BitOp op) {
228 args << "BITOP";
229
230 switch (op) {
231 case BitOp::AND:
232 args << "AND";
233 break;
234
235 case BitOp::OR:
236 args << "OR";
237 break;
238
239 case BitOp::XOR:
240 args << "XOR";
241 break;
242
243 case BitOp::NOT:
244 args << "NOT";
245 break;
246
247 default:
248 throw Error("Unknown bit operations");
249 }
250 }
251
set_update_type(CmdArgs & args,UpdateType type)252 void set_update_type(CmdArgs &args, UpdateType type) {
253 switch (type) {
254 case UpdateType::EXIST:
255 args << "XX";
256 break;
257
258 case UpdateType::NOT_EXIST:
259 args << "NX";
260 break;
261
262 case UpdateType::ALWAYS:
263 // Do nothing.
264 break;
265
266 default:
267 throw Error("Unknown update type");
268 }
269 }
270
set_aggregation_type(CmdArgs & args,Aggregation aggr)271 void set_aggregation_type(CmdArgs &args, Aggregation aggr) {
272 args << "AGGREGATE";
273
274 switch (aggr) {
275 case Aggregation::SUM:
276 args << "SUM";
277 break;
278
279 case Aggregation::MIN:
280 args << "MIN";
281 break;
282
283 case Aggregation::MAX:
284 args << "MAX";
285 break;
286
287 default:
288 throw Error("Unknown aggregation type");
289 }
290 }
291
set_geo_unit(CmdArgs & args,GeoUnit unit)292 void set_geo_unit(CmdArgs &args, GeoUnit unit) {
293 switch (unit) {
294 case GeoUnit::M:
295 args << "m";
296 break;
297
298 case GeoUnit::KM:
299 args << "km";
300 break;
301
302 case GeoUnit::MI:
303 args << "mi";
304 break;
305
306 case GeoUnit::FT:
307 args << "ft";
308 break;
309
310 default:
311 throw Error("Unknown geo unit type");
312 break;
313 }
314 }
315
set_georadius_store_parameters(CmdArgs & args,double radius,GeoUnit unit,const StringView & destination,bool store_dist,long long count)316 void set_georadius_store_parameters(CmdArgs &args,
317 double radius,
318 GeoUnit unit,
319 const StringView &destination,
320 bool store_dist,
321 long long count) {
322 args << radius;
323
324 detail::set_geo_unit(args, unit);
325
326 args << "COUNT" << count;
327
328 if (store_dist) {
329 args << "STOREDIST";
330 } else {
331 args << "STORE";
332 }
333
334 args << destination;
335 }
336
set_georadius_parameters(CmdArgs & args,double radius,GeoUnit unit,long long count,bool asc,bool with_coord,bool with_dist,bool with_hash)337 void set_georadius_parameters(CmdArgs &args,
338 double radius,
339 GeoUnit unit,
340 long long count,
341 bool asc,
342 bool with_coord,
343 bool with_dist,
344 bool with_hash) {
345 args << radius;
346
347 detail::set_geo_unit(args, unit);
348
349 if (with_coord) {
350 args << "WITHCOORD";
351 }
352
353 if (with_dist) {
354 args << "WITHDIST";
355 }
356
357 if (with_hash) {
358 args << "WITHHASH";
359 }
360
361 args << "COUNT" << count;
362
363 if (asc) {
364 args << "ASC";
365 } else {
366 args << "DESC";
367 }
368 }
369
370 }
371
372 }
373
374 }
375
376 }
377