How to pass Vec<Value>> in rusqlite as query param - rust

I'm following the example from the rusqlite git hub https://github.com/rusqlite/rusqlite/blob/master/src/vtab/array.rs#L206. I have the exact same code but I get the compile error
the trait bound `std::vec::Vec<rusqlite::types::Value>: rusqlite::ToSql` is not satisfied
A snippet of the code is below. ids is a Vec of String
let intValues:Vec<i64> = ids.into_iter().map(|s| s.parse::<i64>().expect("Id Parse error.")).collect();
let values:Vec<rusqlite::types::Value> = intValues.into_iter().map(rusqlite::types::Value::from).collect();
let ptr = std::rc::Rc::new(values);
let mut statement = db_connection
.prepare("select * from item where id in rarray(?);")
.expect("Failed to prepare second query.");
let results = statement
// This is the error line
.query_map(&[&ptr], |row| {
Ok(database::ItemData {
id: row.get(0)?,
name: row.get(1)?,
time_to_prepare: row.get(2)?
})
});

I had to add "array" to the feature in the toml file.

Related

Flatbuffer multiple roots doesn't work as expected

I'm evaluating/learning flatbuffers and I've written a schema and some basic code. The schema contains two root tables but when I try to convert a wrong root it doesn't fail. Is this expected behavior?
schema.fbs:
table Weapon {
name:string;
damage:short;
two_handed:bool;
}
root_type Weapon;
table Shield {
name:string;
damage:short;
}
root_type Shield;
main.rs:
use flatbuffers;
// import the generated code
#[allow(dead_code, unused_imports)]
#[path = "./schema_generated.rs"]
mod schema;
fn main() {
let mut sword_builder = flatbuffers::FlatBufferBuilder::new();
let sword_name = sword_builder.create_string("Sword");
let sword = schema::Weapon::create(
&mut sword_builder,
&schema::WeaponArgs {
name: Some(sword_name),
damage: 10,
two_handed: false,
},
);
sword_builder.finish(sword, None);
let sword_buffer = sword_builder.finished_data();
let mut shield_builder = flatbuffers::FlatBufferBuilder::new();
let shield_name = shield_builder.create_string("Shield");
let shield = schema::Weapon::create(
&mut shield_builder,
&schema::WeaponArgs {
name: Some(shield_name),
damage: 2,
two_handed: true,
},
);
shield_builder.finish(shield, None);
let shield_buffer = shield_builder.finished_data();
// Lets decode our buffers
let sword_decoded = flatbuffers::root::<schema::Weapon>(&sword_buffer).unwrap();
println!("{:#?}", sword_decoded);
let shield_decoded = flatbuffers::root::<schema::Shield>(&shield_buffer).unwrap();
println!("{:#?}", shield_decoded);
// This should fail:
let sword_decoded_failure = flatbuffers::root::<schema::Weapon>(&shield_buffer).unwrap();
println!("{:#?}", sword_decoded_failure);
}
output:
Weapon {
name: Some(
"Sword",
),
damage: 10,
two_handed: false,
}
Shield {
name: Some(
"Shield",
),
damage: 2,
}
Weapon {
name: Some(
"Shield",
),
damage: 2,
two_handed: true,
}
github link: https://github.com/ic3man5/fb_test
Documentation for root:
Gets the root of the Flatbuffer, verifying it first with default options. Note that verification is an experimental feature and may not be maximally performant or catch every error (though that is the goal). See the _unchecked variants for previous behavior.
I would expect it to be able to catch a basic error like this? If so I can see two work arounds, one to prepend a header in front of the bytes to identify the table or using a flatbuffer union (I don't want to do this).
Flatbuffers only allows one root type per schema and one instance of it per buffer. So your schema needs to change to reflect this.
As for there being no error, a verifier takes a binary buffer of bytes and checks that it can be safely accessed according to the current schema. There is no type information in the binary bytes, so if the bytes happen to be safely accessible by another schema, it may succeed. To force it to not succeed, you could add a file_identifier to your schema, which if the Rust verifier checks it, would cause it to fail for the wrong schema.

How to return a single owned record with Diesel?

Actually I'm returing a cloned struct
pub fn matrix_first_or_create(&self, schema: String, symbol: String) -> RewardMatrix {
....
let rewards = reward_matrix
.filter(state.eq(schema.clone()))
.filter(turn_symbol.eq(symbol.clone()))
.limit(1)
.load::<RewardMatrix>(&self.connection)
.expect("Error loading posts");
if rewards.len() > 0 {
return rewards.get(0).unwrap().clone();
}
....
}
Is this the right way to handle a result in Diesel? Can I "extract" and own the first and only result from this query?
What you need here is the .first() method of the RunQueryDsl trait.
Here is an example of how it works:
let reward: RewardMatrix = reward_matrix
.filter(state.eq(schema.clone()))
.filter(turn_symbol.eq(symbol.clone()))
.first(&self.connection)?;
But if your query may not return that row, it’s also good to use the .optional() method of QueryResult:
let reward: Option<RewardMatrix> = reward_matrix
.filter(state.eq(schema.clone()))
.filter(turn_symbol.eq(symbol.clone()))
.first(&self.connection)
.optional()?;
load returns a simple owned Vec<RewardMatrix>, so any solution for getting an owned element from a Vec works here:
if let Some(reward) = rewards.into_iter().next() {
return reward;
}
but Diesel also provides better-suited alternatives like get_result and first that don’t involve Vec at all (combine with optional as recommended in the documentation):
let reward = reward_matrix
.filter(state.eq(&schema))
.filter(turn_symbol.eq(&symbol))
.first::<RewardMatrix>(&self.connection)
.optional()
.expect("Error loading posts");
if let Some(reward) = reward {
return reward;
}

How can I pull data out of an Option for independent use?

Is there a way to 'pull' data out of an Option? I have an API call that returns Some(HashMap). I want to use the HashMap as if it weren't inside Some and play with the data.
Based on what I've read, it looks like Some(...) is only good for match comparisons and some built-in functions.
Simple API call pulled from crate docs:
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::blocking::get("https://httpbin.org/ip")?
.json::<HashMap<String, String>>()?;
println!("{:#?}", resp.get("origin"));
Ok(())
}
Result:
Some("75.69.138.107")
if let Some(origin) = resp.get("origin") {
// use origin
}
If you can guarantee that it's impossible for the value to be None, then you can use:
let origin = resp.get("origin").unwrap();
Or:
let origin = resp.get("origin").expect("This shouldn't be possible!");
And, since your function returns a Result:
let origin = resp.get("origin").ok_or("This shouldn't be possible!")?;
Or with a custom error type:
let origin = resp.get("origin").ok_or(MyError::DoesntExist)?;
The most common way is with if let:
if let Some(origin) = resp.get("origin") {
origin.do_stuff()
}
For more fine grained control, you can use pattern matching:
match resp.get("origin") {
Some(origin) => origin.do_stuff(),
None => panic!("origin not found!")
}
You could also use unwrap, which will give you the underlying value of the option, or panic if it is None:
let origin = resp.get("origin").unwrap();
You can customize the panic message with expect:
let origin = resp.get("origin").expect("Oops!");
Or compute a default value with unwrap_or:
let origin = resp.get("origin").unwrap_or(&String::from("192.168.0.1"));
You can also return an error instead of panicking:
let origin = resp.get("origin").ok_or(Error::UnknownOrigin)?;
Your options are a plenty.
if let Some(origin) = resp.get("origin") {
// do stuff using origin
}
origin = resp.get("origin").unwrap()
// will panic if None
resp.get("origin").map(|origin| {
// do stuff using inner value, returning another option
})
resp.get("origin").and_then(|origin| {
// same as map but short-circuits if there is no inner value
})

How can I pass query string to HttpRequest.url_for() in actix-web?

Documentation about url_for.
Code:
fn index(req: HttpRequest) -> HttpResponse {
let url = req.url_for("foo", &["1", "2", "3"]); // <- generate url for "foo" resource
HTTPOk.into()
}
fn main() {
let app = Application::new()
.resource("/test/{one}/{two}/{three}", |r| {
r.name("foo"); // <- set resource name, then it could be used in `url_for`
r.method(Method::GET).f(|_| httpcodes::HTTPOk);
})
.finish();
}
How can I add to generated URL a query string like ?name=Alex? Is there a nice built in way to do it using HttpRequest.url_for() (not just append like url += query_str)
url_for gives you a Result<Url, UrlGenerationError>, which you can unwrap and add query parameters using .set_query.
let mut myurl = req.url_for("foo", &["1", "2", "3"]).unwrap();
myurl.set_query(Some("q=asdf"));

Rust protobuf serialization is all messed up

I am using rust-protobuf version 2.4
I have following code
let mut msg = vec![];
let mut str = protobuf::CodedOutputStream::vec(&mut msg);
let mut rmsg = user_manager::user::user_data::new();
rmsg.set_id("1234".into());
rmsg.set_nick("test".into());
str.write_message(1, &rmsg).unwrap();
str.flush().unwrap();
println!("{:?}", msg);
let test: register_msg = protobuf::parse_from_bytes(&msg[..]).unwrap();
println!("serialized: {:?}\noriginal: {:?}", test, rmsg);
and the relevant proto description is as follows
message user_data{
string id = 1; //required
string nick = 2;
string theme = 3;
string admin_id = 4;
string lang = 5;
double credit = 6; //required
double bonus_credit = 7; //required
};
and what i get as a result is all messed up
First of all, why do I need to enter a number if im serializing the entire message? that's a really weird design.
Secondly, the first field as you may see in the proto file is the id but output from serialization shows the protobuf package serialized everything into the nick field which is the second field.
Am I doing something wrong or might this be a bug in the library?
UPDATE 1:
I have changed write_msg to write_to_bytes
this is how my code looks now.
let mut rmsg = user_manager::user::user_data::new();
rmsg.set_id("1234".into());
rmsg.set_nick("test".into());
let msg = rmsg.write_to_bytes().unwrap();
println!("{:?}", msg);
println!("{:?}", &msg[..]);
let test: register_msg = protobuf::parse_from_bytes(&msg).unwrap();
println!("serialized: {:?}\noriginal: {:?}", test, rmsg);
and still, the output is all messed up.
You can use Message::write_to_bytes to serialize a message that can be parsed with parse_from_bytes.
Also, make sure that you are deserializing the same type that you serialized.
Here's an example program that works correctly:
mod protos;
use protobuf::Message;
use protos::user_data::user_data;
fn main() {
let mut rmsg = user_data::new();
rmsg.set_id("1234".into());
rmsg.set_nick("test".into());
let msg = rmsg.write_to_bytes().unwrap();
println!("{:?}", msg);
let test: user_data = protobuf::parse_from_bytes(&msg).unwrap();
println!("serialized: {:?}\noriginal: {:?}", test, rmsg);
}
This line:
str.write_message(1, &rmsg).unwrap();
writes the message rmsg as a submessage with field id 1. So the fields end up one nesting level deeper, as if your .proto was:
message wrappermsg {
user_data msg = 1;
}
The correct method is:
rmsg.write_to(&mut str);

Resources