Skip to content
This repository was archived by the owner on Jul 11, 2021. It is now read-only.

Commit b372072

Browse files
authored
Merge branch 'master' into clippy
2 parents c4c76c8 + 4b20d72 commit b372072

8 files changed

Lines changed: 210 additions & 59 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ It provides several benefits for your application.
1313

1414
1. Fast, it can top up to 130k inserts per *second*.
1515
2. Familiar, it works with standard SQL, no weird dialect or syntax to learn.
16-
3. Easy to Operate, it is based on Redis, just start the standard Redis binary and and pass the RediSQL binary.
16+
3. Easy to Operate, it is based on Redis, just start the standard Redis binary and pass the RediSQL binary.
1717
4. Easy to Use, being based on Redis there are already bindings for any language.
1818

1919
## Jump start

parser/src/exec.rs

Lines changed: 75 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use redisql_lib::redis_type::ffi::RedisModuleString;
1010

1111
#[derive(Debug, PartialEq, Clone)]
1212
pub enum ToExecute<'s> {
13-
Command(&'s str),
14-
Statement(&'s str),
13+
Command { query: &'s str, args: Vec<&'s str> },
14+
Statement { stmt: &'s str, args: Vec<&'s str> },
1515
}
1616

1717
#[derive(Debug, PartialEq, Clone)]
@@ -23,7 +23,6 @@ pub struct Exec<'s> {
2323
now: bool,
2424
no_header: bool,
2525
to_execute: Option<ToExecute<'s>>,
26-
pub args: Vec<&'s str>,
2726
}
2827

2928
impl Exec<'static> {
@@ -37,37 +36,51 @@ impl Exec<'static> {
3736
todo!("to_execute not set");
3837
}
3938
match (self.to_execute.unwrap(), self.read_only) {
40-
(ToExecute::Command(q), true) => Command::Query {
41-
query: q,
42-
timeout,
43-
return_method,
44-
client,
45-
},
46-
47-
(ToExecute::Command(q), false) => Command::Exec {
48-
query: q,
49-
timeout,
50-
client,
51-
return_method,
52-
},
53-
(ToExecute::Statement(identifier), true) => {
54-
Command::QueryStatement {
55-
identifier,
56-
arguments: self.args,
39+
(ToExecute::Command { query: q, args }, true) => {
40+
Command::Query {
41+
query: q,
42+
arguments: args,
5743
timeout,
58-
client,
5944
return_method,
45+
client,
6046
}
6147
}
62-
(ToExecute::Statement(identifier), false) => {
63-
Command::ExecStatement {
64-
identifier,
65-
arguments: self.args,
48+
49+
(ToExecute::Command { query: q, args }, false) => {
50+
Command::Exec {
51+
query: q,
52+
arguments: args,
6653
timeout,
67-
return_method,
6854
client,
55+
return_method,
6956
}
7057
}
58+
(
59+
ToExecute::Statement {
60+
stmt: identifier,
61+
args,
62+
},
63+
true,
64+
) => Command::QueryStatement {
65+
identifier,
66+
arguments: args,
67+
timeout,
68+
client,
69+
return_method,
70+
},
71+
(
72+
ToExecute::Statement {
73+
stmt: identifier,
74+
args,
75+
},
76+
false,
77+
) => Command::ExecStatement {
78+
identifier,
79+
arguments: args,
80+
timeout,
81+
return_method,
82+
client,
83+
},
7184
}
7285
}
7386
pub fn get_return_method(&self) -> ReturnMethod {
@@ -85,7 +98,7 @@ impl Exec<'static> {
8598
}
8699
pub fn get_query(&self) -> Option<&str> {
87100
match self.to_execute {
88-
Some(ToExecute::Command(q)) => Some(q),
101+
Some(ToExecute::Command { query: q, .. }) => Some(q),
89102
_ => None,
90103
}
91104
}
@@ -115,9 +128,13 @@ impl Exec<'static> {
115128
let to_push = RMString::new(ctx, "NOW");
116129
v.push(to_push.as_ptr());
117130
std::mem::forget(to_push);
118-
let (t, s) = match self.to_execute.as_ref() {
119-
Some(ToExecute::Command(s)) => ("COMMAND", s),
120-
Some(ToExecute::Statement(s)) => ("STATEMENT", s),
131+
let (t, s, args) = match self.to_execute.as_ref() {
132+
Some(ToExecute::Command { query: q, args }) => {
133+
("COMMAND", q, args)
134+
}
135+
Some(ToExecute::Statement { stmt: s, args }) => {
136+
("STATEMENT", s, args)
137+
}
121138
None => todo!("Should never happen"),
122139
};
123140
let to_push = RMString::new(ctx, t);
@@ -130,7 +147,7 @@ impl Exec<'static> {
130147
let to_push = RMString::new(ctx, "ARGS");
131148
v.push(to_push.as_ptr());
132149
std::mem::forget(to_push);
133-
for arg in self.args.iter() {
150+
for arg in args.iter() {
134151
let to_push = RMString::new(ctx, arg);
135152
v.push(to_push.as_ptr());
136153
std::mem::forget(to_push);
@@ -156,19 +173,18 @@ impl<'s> CommandV2<'s> for Exec<'s> {
156173
now: false,
157174
no_header: false,
158175
to_execute: None,
159-
args: Vec::new(),
160176
};
161177
while let Some(arg) = args_iter.next() {
162178
let mut arg_string = String::from(*arg);
163179
arg_string.make_ascii_uppercase();
164180
match arg_string.as_str() {
165181
"COMMAND" => match exec.to_execute {
166-
Some(ToExecute::Statement(_)) => {
182+
Some(ToExecute::Statement { .. }) => {
167183
return Err(
168184
RediSQLError::both_statement_and_query(),
169185
);
170186
}
171-
Some(ToExecute::Command(_)) => {
187+
Some(ToExecute::Command { .. }) => {
172188
return Err(RediSQLError::with_code(
173189
13,
174190
"Impossible to know which query should be executed".to_string(),
@@ -186,17 +202,19 @@ impl<'s> CommandV2<'s> for Exec<'s> {
186202
))
187203
}
188204
};
189-
exec.to_execute =
190-
Some(ToExecute::Command(query));
205+
exec.to_execute = Some(ToExecute::Command {
206+
query,
207+
args: Vec::new(),
208+
});
191209
}
192210
},
193211
"STATEMENT" => match exec.to_execute {
194-
Some(ToExecute::Command(_)) => {
212+
Some(ToExecute::Command { .. }) => {
195213
return Err(
196214
RediSQLError::both_statement_and_query(),
197215
);
198216
}
199-
Some(ToExecute::Statement(_)) => {
217+
Some(ToExecute::Statement { .. }) => {
200218
return Err(RediSQLError::with_code(
201219
14,
202220
"Impossible to know which statement should be executed".to_string(),
@@ -216,7 +234,10 @@ impl<'s> CommandV2<'s> for Exec<'s> {
216234
}
217235
};
218236
exec.to_execute =
219-
Some(ToExecute::Statement(stmt));
237+
Some(ToExecute::Statement {
238+
stmt,
239+
args: Vec::new(),
240+
});
220241
}
221242
},
222243
"READ_ONLY" => exec.read_only = true,
@@ -236,10 +257,23 @@ impl<'s> CommandV2<'s> for Exec<'s> {
236257
}
237258
"NO_HEADER" => exec.no_header = true,
238259
"ARGS" => {
260+
let args = match exec.to_execute {
261+
None => {
262+
return Err(RediSQLError::with_code(24, "You didn't provide neither `COMMAND` nor `STATEMENT` fields".to_string(), "Command incomplete, no `COMMAND` nor `STATEMENT` fields".to_string()));
263+
}
264+
Some(ToExecute::Command {
265+
ref mut args,
266+
..
267+
}) => args,
268+
Some(ToExecute::Statement {
269+
ref mut args,
270+
..
271+
}) => args,
272+
};
239273
let (size, _) = args_iter.size_hint();
240-
exec.args.reserve(size);
274+
args.reserve(size);
241275
while let Some(arg) = args_iter.next() {
242-
exec.args.push(*arg);
276+
args.push(*arg);
243277
}
244278
}
245279
_ => {}

parser/src/statement.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ impl Statement<'static> {
4444
can_update: self.can_update,
4545
client,
4646
},
47-
Action::Show => todo!(),
47+
Action::Show => Command::ShowStatement {
48+
identifier: self.stmt_name.unwrap(),
49+
return_method: ReturnMethod::ReplyWithHeader,
50+
client,
51+
},
4852
Action::List => Command::ListStatements {
4953
return_method: ReturnMethod::ReplyWithHeader,
5054
client,

redisql_lib/src/redis.rs

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ pub trait StatementCache<'a> {
8787
identifier: &str,
8888
args: &[&str],
8989
) -> Result<Cursor, RediSQLError>;
90+
fn show_statement(
91+
&self,
92+
identifier: &str,
93+
) -> Result<QueryResult, RediSQLError>;
9094
fn list_statements(&self) -> Result<QueryResult, RediSQLError>;
9195
}
9296

@@ -243,6 +247,47 @@ impl<'a> StatementCache<'a> for ReplicationBook {
243247
}
244248
}
245249
}
250+
fn show_statement(
251+
&self,
252+
identifier: &str,
253+
) -> Result<QueryResult, RediSQLError> {
254+
let map = self.data.read().unwrap();
255+
match map.get(identifier) {
256+
None => {
257+
let debug = String::from("No statement found");
258+
let description = String::from(
259+
"The statement is not present in the database",
260+
);
261+
Err(RediSQLError::new(debug, description))
262+
}
263+
Some(&(ref stmt, read_only)) => {
264+
let names = vec![
265+
"identifier".to_string(),
266+
"SQL".to_string(),
267+
"parameters_count".to_string(),
268+
"read_only".to_string(),
269+
];
270+
let types = vec!["TEXT", "TEXT", "INT", "INT"];
271+
let array = vec![
272+
Entity::Text {
273+
text: identifier.to_string(),
274+
},
275+
Entity::Text { text: stmt.sql() },
276+
Entity::Integer {
277+
int: stmt.parameters_count() as i64,
278+
},
279+
Entity::Integer {
280+
int: if read_only { 1 } else { 0 },
281+
},
282+
];
283+
Ok(QueryResult::Array {
284+
names,
285+
types,
286+
array,
287+
})
288+
}
289+
}
290+
}
246291
fn list_statements(&self) -> Result<QueryResult, RediSQLError> {
247292
let map = self.data.read().unwrap();
248293
let names = vec![
@@ -595,12 +640,14 @@ pub enum Command {
595640
Stop,
596641
Exec {
597642
query: &'static str,
643+
arguments: Vec<&'static str>,
598644
timeout: std::time::Instant,
599645
return_method: ReturnMethod,
600646
client: BlockedClient,
601647
},
602648
Query {
603649
query: &'static str,
650+
arguments: Vec<&'static str>,
604651
timeout: std::time::Instant,
605652
return_method: ReturnMethod,
606653
client: BlockedClient,
@@ -635,6 +682,11 @@ pub enum Command {
635682
return_method: ReturnMethod,
636683
client: BlockedClient,
637684
},
685+
ShowStatement {
686+
identifier: &'static str,
687+
return_method: ReturnMethod,
688+
client: BlockedClient,
689+
},
638690
ListStatements {
639691
return_method: ReturnMethod,
640692
client: BlockedClient,
@@ -1048,8 +1100,11 @@ impl RedisReply for QueryResult {
10481100
pub fn do_execute(
10491101
db: &ConcurrentConnection,
10501102
query: &str,
1103+
args: &Vec<&str>,
10511104
) -> Result<impl Returner, err::RediSQLError> {
1052-
let stmt = MultiStatement::new(db.clone(), query)?;
1105+
let mut stmt = MultiStatement::new(db.clone(), query)?;
1106+
stmt.reset();
1107+
let stmt = bind_statement(&mut stmt, args)?;
10531108
debug!("do_execute | created statement");
10541109
let cursor = stmt.execute()?;
10551110
debug!("do_execute | statement executed");
@@ -1059,9 +1114,12 @@ pub fn do_execute(
10591114
pub fn do_query(
10601115
db: &ConcurrentConnection,
10611116
query: &str,
1117+
args: &Vec<&str>,
10621118
) -> Result<impl Returner, err::RediSQLError> {
1063-
let stmt = MultiStatement::new(db.clone(), query)?;
1119+
let mut stmt = MultiStatement::new(db.clone(), query)?;
10641120
if stmt.is_read_only() {
1121+
stmt.reset();
1122+
let stmt = bind_statement(&mut stmt, args)?;
10651123
Ok(stmt.execute()?)
10661124
} else {
10671125
let debug = String::from("Not read only statement");
@@ -1323,12 +1381,14 @@ pub fn listen_and_execute<'a, L: 'a + LoopData>(
13231381
Ok(Command::Ping {}) => debug!("Received PING!"),
13241382
Ok(Command::Exec {
13251383
query,
1384+
arguments,
13261385
client,
13271386
return_method,
13281387
timeout,
13291388
}) => {
13301389
debug!("Exec | Query = {:?}", query);
1331-
let result = do_execute(&loopdata.get_db(), query);
1390+
let result =
1391+
do_execute(&loopdata.get_db(), query, &arguments);
13321392
match result {
13331393
Ok(_) => STATISTICS.exec_ok(),
13341394
Err(_) => STATISTICS.exec_err(),
@@ -1343,12 +1403,14 @@ pub fn listen_and_execute<'a, L: 'a + LoopData>(
13431403
}
13441404
Ok(Command::Query {
13451405
query,
1406+
arguments,
13461407
timeout,
13471408
return_method,
13481409
client,
13491410
}) => {
13501411
debug!("Query | Query = {:?}", query);
1351-
let result = do_query(&loopdata.get_db(), query);
1412+
let result =
1413+
do_query(&loopdata.get_db(), query, &arguments);
13521414

13531415
match (&return_method, &result) {
13541416
(ReturnMethod::Reply, Ok(_)) => {
@@ -1518,6 +1580,18 @@ pub fn listen_and_execute<'a, L: 'a + LoopData>(
15181580
timeout,
15191581
);
15201582
}
1583+
Ok(Command::ShowStatement {
1584+
identifier,
1585+
return_method,
1586+
client,
1587+
}) => {
1588+
let result = loopdata
1589+
.get_replication_book()
1590+
.show_statement(identifier);
1591+
let t = std::time::Instant::now()
1592+
+ std::time::Duration::from_secs(10);
1593+
return_value(&client, &return_method, result, t);
1594+
}
15211595
Ok(Command::ListStatements {
15221596
return_method,
15231597
client,

0 commit comments

Comments
 (0)