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

Commit d1c9104

Browse files
authored
Merge pull request #100 from RedBeardLab/args_also_for_exec
Args also for exec
2 parents dbabf38 + ea97f7b commit d1c9104

File tree

7 files changed

+210
-59
lines changed

7 files changed

+210
-59
lines changed

parser/src/exec.rs

Lines changed: 76 additions & 42 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);
@@ -126,11 +143,11 @@ impl Exec<'static> {
126143
let to_push = RMString::new(ctx, s);
127144
v.push(to_push.as_ptr());
128145
std::mem::forget(to_push);
129-
if self.args.len() > 0 {
146+
if args.len() > 0 {
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
@@ -88,6 +88,10 @@ pub trait StatementCache<'a> {
8888
identifier: &str,
8989
args: &[&str],
9090
) -> Result<Cursor, RediSQLError>;
91+
fn show_statement(
92+
&self,
93+
identifier: &str,
94+
) -> Result<QueryResult, RediSQLError>;
9195
fn list_statements(&self) -> Result<QueryResult, RediSQLError>;
9296
}
9397

@@ -244,6 +248,47 @@ impl<'a> StatementCache<'a> for ReplicationBook {
244248
}
245249
}
246250
}
251+
fn show_statement(
252+
&self,
253+
identifier: &str,
254+
) -> Result<QueryResult, RediSQLError> {
255+
let map = self.data.read().unwrap();
256+
match map.get(identifier) {
257+
None => {
258+
let debug = String::from("No statement found");
259+
let description = String::from(
260+
"The statement is not present in the database",
261+
);
262+
Err(RediSQLError::new(debug, description))
263+
}
264+
Some(&(ref stmt, read_only)) => {
265+
let names = vec![
266+
"identifier".to_string(),
267+
"SQL".to_string(),
268+
"parameters_count".to_string(),
269+
"read_only".to_string(),
270+
];
271+
let types = vec!["TEXT", "TEXT", "INT", "INT"];
272+
let array = vec![
273+
Entity::Text {
274+
text: identifier.to_string(),
275+
},
276+
Entity::Text { text: stmt.sql() },
277+
Entity::Integer {
278+
int: stmt.parameters_count() as i64,
279+
},
280+
Entity::Integer {
281+
int: if read_only { 1 } else { 0 },
282+
},
283+
];
284+
Ok(QueryResult::Array {
285+
names,
286+
types,
287+
array,
288+
})
289+
}
290+
}
291+
}
247292
fn list_statements(&self) -> Result<QueryResult, RediSQLError> {
248293
let map = self.data.read().unwrap();
249294
let names = vec![
@@ -597,12 +642,14 @@ pub enum Command {
597642
Stop,
598643
Exec {
599644
query: &'static str,
645+
arguments: Vec<&'static str>,
600646
timeout: std::time::Instant,
601647
return_method: ReturnMethod,
602648
client: BlockedClient,
603649
},
604650
Query {
605651
query: &'static str,
652+
arguments: Vec<&'static str>,
606653
timeout: std::time::Instant,
607654
return_method: ReturnMethod,
608655
client: BlockedClient,
@@ -637,6 +684,11 @@ pub enum Command {
637684
return_method: ReturnMethod,
638685
client: BlockedClient,
639686
},
687+
ShowStatement {
688+
identifier: &'static str,
689+
return_method: ReturnMethod,
690+
client: BlockedClient,
691+
},
640692
ListStatements {
641693
return_method: ReturnMethod,
642694
client: BlockedClient,
@@ -1050,8 +1102,11 @@ impl RedisReply for QueryResult {
10501102
pub fn do_execute(
10511103
db: &ConcurrentConnection,
10521104
query: &str,
1105+
args: &Vec<&str>,
10531106
) -> Result<impl Returner, err::RediSQLError> {
1054-
let stmt = MultiStatement::new(db.clone(), query)?;
1107+
let mut stmt = MultiStatement::new(db.clone(), query)?;
1108+
stmt.reset();
1109+
let stmt = bind_statement(&mut stmt, args)?;
10551110
debug!("do_execute | created statement");
10561111
let cursor = stmt.execute()?;
10571112
debug!("do_execute | statement executed");
@@ -1061,9 +1116,12 @@ pub fn do_execute(
10611116
pub fn do_query(
10621117
db: &ConcurrentConnection,
10631118
query: &str,
1119+
args: &Vec<&str>,
10641120
) -> Result<impl Returner, err::RediSQLError> {
1065-
let stmt = MultiStatement::new(db.clone(), query)?;
1121+
let mut stmt = MultiStatement::new(db.clone(), query)?;
10661122
if stmt.is_read_only() {
1123+
stmt.reset();
1124+
let stmt = bind_statement(&mut stmt, args)?;
10671125
Ok(stmt.execute()?)
10681126
} else {
10691127
let debug = String::from("Not read only statement");
@@ -1325,12 +1383,14 @@ pub fn listen_and_execute<'a, L: 'a + LoopData>(
13251383
Ok(Command::Ping {}) => debug!("Received PING!"),
13261384
Ok(Command::Exec {
13271385
query,
1386+
arguments,
13281387
client,
13291388
return_method,
13301389
timeout,
13311390
}) => {
13321391
debug!("Exec | Query = {:?}", query);
1333-
let result = do_execute(&loopdata.get_db(), query);
1392+
let result =
1393+
do_execute(&loopdata.get_db(), query, &arguments);
13341394
match result {
13351395
Ok(_) => STATISTICS.exec_ok(),
13361396
Err(_) => STATISTICS.exec_err(),
@@ -1345,12 +1405,14 @@ pub fn listen_and_execute<'a, L: 'a + LoopData>(
13451405
}
13461406
Ok(Command::Query {
13471407
query,
1408+
arguments,
13481409
timeout,
13491410
return_method,
13501411
client,
13511412
}) => {
13521413
debug!("Query | Query = {:?}", query);
1353-
let result = do_query(&loopdata.get_db(), query);
1414+
let result =
1415+
do_query(&loopdata.get_db(), query, &arguments);
13541416

13551417
match (&return_method, &result) {
13561418
(ReturnMethod::Reply, Ok(_)) => {
@@ -1520,6 +1582,18 @@ pub fn listen_and_execute<'a, L: 'a + LoopData>(
15201582
timeout,
15211583
);
15221584
}
1585+
Ok(Command::ShowStatement {
1586+
identifier,
1587+
return_method,
1588+
client,
1589+
}) => {
1590+
let result = loopdata
1591+
.get_replication_book()
1592+
.show_statement(identifier);
1593+
let t = std::time::Instant::now()
1594+
+ std::time::Duration::from_secs(10);
1595+
return_value(&client, &return_method, result, t);
1596+
}
15231597
Ok(Command::ListStatements {
15241598
return_method,
15251599
client,

0 commit comments

Comments
 (0)