the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`) - mysql

I am doing my assignment that's include make connection with the database in Rust. I am using the latest version of mysql crate: mysql ="18.2.0".My Database connection is successful as I print the pool variable. I write my own code for table student but I get the error. Then i paste the code of documentation, I recieve the following error with'?' operator:
I am connecting the database in rust for the first time. Any help is appreciated.
warning: unused import: `std::io`
--> src/main.rs:2:5
|
2 | use std::io;
| ^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> src/main.rs:17:12
|
14 | / fn insert(){
15 | |
16 | |
17 | | let pool = Pool::new("mysql://root:root#localhost:3306/Rust_testing")?;
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
... |
58 | |
59 | | }
| |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> src/main.rs:19:16
|
14 | / fn insert(){
15 | |
16 | |
17 | | let pool = Pool::new("mysql://root:root#localhost:3306/Rust_testing")?;
18 | |
19 | | let mut conn = pool.get_conn()?;
| | ^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
... |
58 | |
59 | | }
| |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> src/main.rs:22:1
|
14 | / fn insert(){
15 | |
16 | |
17 | | let pool = Pool::new("mysql://root:root#localhost:3306/Rust_testing")?;
... |
22 | /| conn.query_drop(
23 | || r"CREATE TEMPORARY TABLE payment (
24 | || customer_id int not null,
25 | || amount int not null,
26 | || account_name text
27 | || )")?;
| ||________^ cannot use the `?` operator in a function that returns `()`
... |
58 | |
59 | | }
| |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> src/main.rs:38:1
|
14 | / fn insert(){
15 | |
16 | |
17 | | let pool = Pool::new("mysql://root:root#localhost:3306/Rust_testing")?;
... |
38 | /| conn.exec_batch(
39 | || r"INSERT INTO payment (customer_id, amount, account_name)
40 | || VALUES (:customer_id, :amount, :account_name)",
41 | || payments.iter().map(|p| params! {
... ||
45 | || })
46 | || )?;
| ||__^ cannot use the `?` operator in a function that returns `()`
... |
58 | |
59 | | }
| |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> src/main.rs:49:25
|
14 | / fn insert(){
15 | |
16 | |
17 | | let pool = Pool::new("mysql://root:root#localhost:3306/Rust_testing")?;
... |
49 | | let selected_payments = conn
| |_________________________^
50 | || .query_map(
51 | || "SELECT customer_id, amount, account_name from payment",
52 | || |(customer_id, amount, account_name)| {
53 | || Payment { customer_id, amount, account_name }
54 | || },
55 | || )?;
| ||______^ cannot use the `?` operator in a function that returns `()`
... |
58 | |
59 | | }
| |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
error: aborting due to 5 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.
error: could not compile `class-09`.
Here is the code, i copy from documentation to test:
use std::io;
use mysql::prelude::*;
use mysql::*;
#[derive(Debug, PartialEq, Eq)]
struct Payment {
customer_id: i32,
amount: i32,
account_name: Option<String>,
}
fn insert(){
let pool = Pool::new("mysql://root:root#localhost:3306/Rust_testing")?;
let mut conn = pool.get_conn()?;
// Let's create a table for payments.
conn.query_drop(
r"CREATE TEMPORARY TABLE payment (
customer_id int not null,
amount int not null,
account_name text
)")?;
let payments = vec![
Payment { customer_id: 1, amount: 2, account_name: None },
Payment { customer_id: 3, amount: 4, account_name: Some("foo".into()) },
Payment { customer_id: 5, amount: 6, account_name: None },
Payment { customer_id: 7, amount: 8, account_name: None },
Payment { customer_id: 9, amount: 10, account_name: Some("bar".into()) },
];
// Now let's insert payments to the database
conn.exec_batch(
r"INSERT INTO payment (customer_id, amount, account_name)
VALUES (:customer_id, :amount, :account_name)",
payments.iter().map(|p| params! {
"customer_id" => p.customer_id,
"amount" => p.amount,
"account_name" => &p.account_name,
})
)?;
// Let's select payments from database. Type inference should do the trick here.
let selected_payments = conn
.query_map(
"SELECT customer_id, amount, account_name from payment",
|(customer_id, amount, account_name)| {
Payment { customer_id, amount, account_name }
},
)?;
println!("Yay!");
}
fn main(){
insert();
}
and when i write my code without the ? operator, I got the following error:
warning: unused import: `std::io`
--> src/main.rs:2:5
|
2 | use std::io;
| ^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0599]: no method named `query_drop` found for enum `std::result::Result<mysql::conn::pool::PooledConn, mysql::error::Error>` in the current scope
--> src/main.rs:32:6
|
32 | conn.query_drop(
| ^^^^^^^^^^ method not found in `std::result::Result<mysql::conn::pool::PooledConn, mysql::error::Error>`
error[E0599]: no method named `exec_batch` found for enum `std::result::Result<mysql::conn::pool::PooledConn, mysql::error::Error>` in the current scope
--> src/main.rs:48:6
|
48 | conn.exec_batch(
| ^^^^^^^^^^ method not found in `std::result::Result<mysql::conn::pool::PooledConn, mysql::error::Error>`
error[E0599]: no method named `query_map` found for enum `std::result::Result<mysql::conn::pool::PooledConn, mysql::error::Error>` in the current scope
--> src/main.rs:60:6
|
60 | .query_map(
| ^^^^^^^^^ method not found in `std::result::Result<mysql::conn::pool::PooledConn, mysql::error::Error>`
warning: unused import: `mysql::prelude`
--> src/main.rs:4:5
|
4 | use mysql::prelude::*;
| ^^^^^^^^^^^^^^
error: aborting due to 3 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0599`.
error: could not compile `class-09`.

As the compiler is telling you: you are missing a return type in your function.
The ? operator will return (propagate) the error if any, but for that to work you need to have a return type that can be constructed with the error type.
For prototyping, you can just call unwrap. But this approach should be carefully considered when writing production code, as it will just crash the program when the function returns an error.
find more here

Related

How to handle errors when extracting data from untyped JSON in serde_json?

I have a serde_json::Value which I expect to contain an array of objects. From those objects I want to extract 2 values and return an error if anything fails. This is my code so far:
use std::collections::HashMap;
use anyhow::Result;
fn get_stock(response: serde_json::Value) -> Result<HashMap<String, u32>>{
response["products"]
.as_array()?.iter()
.map(|product| {
let product = product.as_object()?;
(
product["name"].as_str()?.to_owned(),
//as_u64 fails for some reason
product["stock"].as_str()?.parse::<u32>()?,
)
})
.collect()?
}
When I used .unwrap() this worked fine, but after changing the return type to Result and replacing unwraps with ? I'm getting the following compilation errors:
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
--> src/bin/products.rs:7:20
|
5 | / fn get_stock(response: serde_json::Value) -> Result<HashMap<String, u32>>{
6 | | response["products"]
7 | | .as_array()?.iter()
| | ^ use `.ok_or(...)?` to provide an error compatible with `Result<HashMap<std::string::String, u32>, anyhow::Error>`
8 | | .map(|product| {
... |
16 | | .collect()?
17 | | }
| |_- this function returns a `Result`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<HashMap<std::string::String, u32>, anyhow::Error>`
= note: required by `from_residual`
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> src/bin/products.rs:9:46
|
8 | .map(|product| {
| ______________-
9 | | let product = product.as_object()?;
| | ^ cannot use the `?` operator in a closure that returns `(std::string::String, u32)`
10 | | (
11 | | product["name"].as_str()?.to_owned(),
... |
14 | | )
15 | | })
| |_________- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `(std::string::String, u32)`
= note: required by `from_residual`
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> src/bin/products.rs:11:41
|
8 | .map(|product| {
| ______________-
9 | | let product = product.as_object()?;
10 | | (
11 | | product["name"].as_str()?.to_owned(),
| | ^ cannot use the `?` operator in a closure that returns `(std::string::String, u32)`
... |
14 | | )
15 | | })
| |_________- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `(std::string::String, u32)`
= note: required by `from_residual`
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> src/bin/products.rs:13:42
|
8 | .map(|product| {
| ______________-
9 | | let product = product.as_object()?;
10 | | (
11 | | product["name"].as_str()?.to_owned(),
12 | | //as_u64 fails for some reason
13 | | product["stock"].as_str()?.parse::<u32>()?,
| | ^ cannot use the `?` operator in a closure that returns `(std::string::String, u32)`
14 | | )
15 | | })
| |_________- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `(std::string::String, u32)`
= note: required by `from_residual`
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> src/bin/products.rs:13:58
|
8 | .map(|product| {
| ______________-
9 | | let product = product.as_object()?;
10 | | (
11 | | product["name"].as_str()?.to_owned(),
12 | | //as_u64 fails for some reason
13 | | product["stock"].as_str()?.parse::<u32>()?,
| | ^ cannot use the `?` operator in a closure that returns `(std::string::String, u32)`
miav#battlestation catbot % cargo run --bin products
Compiling catbot v0.1.0 (/Users/miav/Documents/Personal/Projects/programming/catbot)
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
--> src/bin/products.rs:7:20
|
5 | / fn get_stock(response: serde_json::Value) -> Result<HashMap<String, u32>>{
6 | | response["products"]
7 | | .as_array()?.iter()
| | ^ use `.ok_or(...)?` to provide an error compatible with `Result<HashMap<std::string::String, u32>, anyhow::Error>`
8 | | .map(|product| {
... |
16 | | .collect()?
17 | | }
| |_- this function returns a `Result`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<HashMap<std::string::String, u32>, anyhow::Error>`
= note: required by `from_residual`
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> src/bin/products.rs:9:46
|
8 | .map(|product| {
| ______________-
9 | | let product = product.as_object()?;
| | ^ cannot use the `?` operator in a closure that returns `(std::string::String, u32)`
10 | | (
11 | | product["name"].as_str()?.to_owned(),
... |
14 | | )
15 | | })
| |_________- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `(std::string::String, u32)`
= note: required by `from_residual`
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> src/bin/products.rs:11:41
|
8 | .map(|product| {
| ______________-
9 | | let product = product.as_object()?;
10 | | (
11 | | product["name"].as_str()?.to_owned(),
| | ^ cannot use the `?` operator in a closure that returns `(std::string::String, u32)`
... |
14 | | )
15 | | })
| |_________- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `(std::string::String, u32)`
= note: required by `from_residual`
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> src/bin/products.rs:13:42
|
8 | .map(|product| {
| ______________-
9 | | let product = product.as_object()?;
10 | | (
11 | | product["name"].as_str()?.to_owned(),
12 | | //as_u64 fails for some reason
13 | | product["stock"].as_str()?.parse::<u32>()?,
| | ^ cannot use the `?` operator in a closure that returns `(std::string::String, u32)`
14 | | )
15 | | })
| |_________- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `(std::string::String, u32)`
= note: required by `from_residual`
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> src/bin/products.rs:13:58
|
8 | .map(|product| {
| ______________-
9 | | let product = product.as_object()?;
10 | | (
11 | | product["name"].as_str()?.to_owned(),
12 | | //as_u64 fails for some reason
13 | | product["stock"].as_str()?.parse::<u32>()?,
| | ^ cannot use the `?` operator in a closure that returns `(std::string::String, u32)`
14 | | )
15 | | })
| |_________- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `FromResidual<Result<Infallible, ParseIntError>>` is not implemented for `(std::string::String, u32)`
= note: required by `from_residual`
error: aborting due to 5 previous errors
I don't know the exact structure of the JSON in advance, so I cannot parse it into a struct. All I know is that it is most likely an array of objects which have a name string field and a stock integer field, which I want to extract into a map. If that doesn't happen to be the case, then I want to return an error. What is the simplest way to do this?
UPDATE:
After following Lagerbaer's suggestions and doing some digging I came up with the following solution.
use anyhow::{anyhow, Result};
use std::collections::HashMap;
fn get_stock(response: serde_json::Value) -> Result<HashMap<String, u32>> {
response
.get("products")
.ok_or(anyhow!("'products' not found"))?
.as_array()
.ok_or(anyhow!("'products' is not an array"))?
.iter()
.map(|product| -> Result<(String, u32)> {
let product = product.as_object().unwrap();
Ok((
product
.get("name")
.ok_or(anyhow!("'name' not found"))?
.as_str()
.ok_or(anyhow!("'name' is not a string"))?
.trim()
.to_owned(),
//as_u64 fails for some reason
product
.get("stock")
.ok_or(anyhow!("'stock' not found"))?
.as_str()
.ok_or(anyhow!("'stock' is not a string"))?
.parse::<u32>()?,
))
})
.collect()
}
Used ok_or() to map Option to Result, had to use the anyhow! macro to make it compatible with the anyhow result type.
It also turns out that collect() actually accepts an iterator of
Result<(String, u32)> to produce a Result<HashMap<String, u32>> with the exact behavior I wanted, that is, returning the first error or the complete hash map if there were no errors.
So there's a couple issues here and the compiler tries its best to tell you.
I'll get you started on the first, and then I encourage you to try going it alone for a bit.
So the very first error is that, apparently, as_array returns an Option and not Result and, hence, you can't use the ? operator there.
Luckily, the compiler tells you what to do: Option has a method ok_or that you should call. It will turn the Option into Result. If the Option is Some(value) you'll get a Ok(value), and if the Option is None, you'll get whatever error you specified in the ok_or argument.
Another easy to spot mistake is this: Your function returns a Result, so the return value should, obviously, be a Result. Hence the very final last ? should be removed, because that ? would take a Result and turn it into the "pure" value (if the result was Ok).
And then what's left is to figure out exactly what the closure should return. Maybe you can try that after fixing the other mistakes that I explained above.

Mysql query isn't working especially the Scan() method

I am trying the print the struct variable but it's returning the zero value where I want an actual database row value.
Code:
package main
import (
"database/sql"
"fmt"
"log"
"time"
_ "github.com/go-sql-driver/mysql"
)
type Users struct {
Id int
Username string
Password string
Email string
First_name string
Last_name string
Created_at time.Time
Super_user bool
}
func main() {
db, err := sql.Open("mysql", "root:Megamind#1#(127.0.0.1:3306)/note?parseTime=true")
if err != nil {
log.Fatalln("Couldn't connect to the database")
}
var user Users
row := db.QueryRow("select password from users where username=$1", "someone")
row.Scan(&user.Id, &user.Username, &user.Password, &user.Email, &user.First_name, &user.Last_name, &user.Created_at, &user.Super_user)
fmt.Println(user)
}
Database:
mysql> select * from users;
+----+---------------+--------------------------------------------------------------+---------------------------+------------+-----------+---------------------+------------+
| id | username | password | email | first_name | last_name | created_at | super_user |
+----+---------------+--------------------------------------------------------------+---------------------------+------------+-----------+---------------------+------------+
| 3 | someone | $2a$10$a0g.eIGEHoVnD/s55YCePeL5BxCPYDF58nP2gb.TmYKwCuV5E7gP. | abc#gmail.com | NULL | NULL | 2020-06-22 01:24:43 | NULL |
| 4 | oneanother | $2a$10$VMo4iuvruCA/yQlkfMI2QOMWo2H2jIiyyoYprKQtQMT4U7UWb78CS | one#one.com | NULL | NULL | 2020-06-22 01:26:48 | NULL |
| 5 | alpha | $2a$10$oD0YKBkTvJQVPF4rilEVYemjRtwNF3ATGlVLUOVGZzR5lNx5fRl3. | alpha#gmail.com | NULL | NULL | 2020-06-22 01:45:34 | NULL |
+----+---------------+--------------------------------------------------------------+---------------------------+------------+-----------+---------------------+------------+
3 rows in set (0.02 sec)
Output:
(base) [dave#192 test]$ go run main.go
{0 0001-01-01 00:00:00 +0000 UTC false}

How to call a function from another file and fetch in web

I'm new to Rust and still I am learning things. There is a rust application with main.rs and routes.rs. main.rs file has server configuration and routes.rs has methods with paths.
main.rs
#[macro_use]
extern crate log;
use actix_web::{App, HttpServer};
use dotenv::dotenv;
use listenfd::ListenFd;
use std::env;
mod search;
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
env_logger::init();
let mut listenfd = ListenFd::from_env();
let mut server = HttpServer::new(||
App::new()
.configure(search::init_routes)
);
server = match listenfd.take_tcp_listener(0)? {
Some(listener) => server.listen(listener)?,
None => {
let host = env::var("HOST").expect("Host not set");
let port = env::var("PORT").expect("Port not set");
server.bind(format!("{}:{}", host, port))?
}
};
info!("Starting server");
server.run().await
}
routes.rs
use crate::search::User;
use actix_web::{get, post, put, delete, web, HttpResponse, Responder};
use serde_json::json;
extern crate reqwest;
extern crate serde;
use reqwest::Error;
use serde::{Deserialize};
use rocket_contrib::json::Json;
use serde_json::Value;
// mod bargainfindermax;
#[get("/users")]
async fn find_all() -> impl Responder {
HttpResponse::Ok().json(
vec![
User { id: 1, email: "tore#cloudmaker.dev".to_string() },
User { id: 2, email: "tore#cloudmaker.dev".to_string() },
]
)
}
pub fn init_routes(cfg: &mut web::ServiceConfig) {
cfg.service(find_all);
}
Now what I want is I want to fetch an API using a method in another separate rs file (fetch_test.rs) and route it in the routes.rs file. Then I want to get the response from a web browser by running that route path(link).
How can I do these things ?? I searched everywhere, but I found nothing helpful. And sometimes I didn't understand some documentations also.
**Update.
fetch_test.rs
extern crate reqwest;
use hyper::header::{Headers, Authorization, Basic, ContentType};
pub fn authenticate() -> String {
fn construct_headers() -> Headers {
let mut headers = Headers::new();
headers.set(
Authorization(
Basic {
username: "HI:ABGTYH".to_owned(),
password: Some("%8YHT".to_owned())
}
)
);
headers.set(ContentType::form_url_encoded());
headers
}
let client = reqwest::Client::new();
let resz = client.post("https://api.test.com/auth/token")
.headers(construct_headers())
.body("grant_type=client_credentials")
.json(&map)
.send()
.await?;
}
Errors.
Compiling sabre-actix-kist v0.1.0 (E:\wamp64\www\BukFlightsNewLevel\flights\APIs\sabre-actix-kist)
error[E0425]: cannot find value `map` in this scope
--> src\search\routes\common.rs:28:12
|
28 | .json(&map)
| ^^^ not found in this scope
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> src\search\routes\common.rs:25:12
|
4 | pub fn authenticate() -> String {
| ------------ this is not `async`
...
25 | let resz = client.post("https://api-crt.cert.havail.sabre.com/v2/auth/token")
| ____________^
26 | | .headers(construct_headers())
27 | | .body("grant_type=client_credentials")
28 | | .json(&map)
29 | | .send()
30 | | .await?;
| |__________^ only allowed inside `async` functions and blocks
error[E0277]: the trait bound `std::result::Result<search::routes::reqwest::Response, search::routes::reqwest::Error>: std::future::Future` is not satisfied
--> src\search\routes\common.rs:25:12
|
25 | let resz = client.post("https://api-crt.cert.havail.sabre.com/v2/auth/token")
| ____________^
26 | | .headers(construct_headers())
27 | | .body("grant_type=client_credentials")
28 | | .json(&map)
29 | | .send()
30 | | .await?;
| |__________^ the trait `std::future::Future` is not implemented for `std::result::Result<search::routes::reqwest::Response, search::routes::reqwest::Error>`
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> src\search\routes\common.rs:25:12
|
4 | / pub fn authenticate() -> String {
5 | |
6 | | let res = reqwest::get("http://api.github.com/users")
7 | | .expect("Couldnt")
... |
25 | | let resz = client.post("https://api-crt.cert.havail.sabre.com/v2/auth/token")
| |____________^
26 | || .headers(construct_headers())
27 | || .body("grant_type=client_credentials")
28 | || .json(&map)
29 | || .send()
30 | || .await?;
| ||___________^ cannot use the `?` operator in a function that returns `std::string::String`
31 | |
32 | | }
| |_- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `std::string::String`
= note: required by `std::ops::Try::from_error`
error[E0308]: mismatched types
--> src\search\routes\common.rs:4:26
|
4 | pub fn authenticate() -> String {
| ------------ ^^^^^^ expected struct `std::string::String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
**Update Again.
extern crate reqwest;
use hyper::header::{Headers, Authorization, Basic, ContentType};
fn construct_headers() -> Headers {
let mut headers = Headers::new();
headers.set(
Authorization(
Basic {
username: "HI:ABGTYH".to_owned(),
password: Some("%8YHT".to_owned())
}
)
);
headers.set(ContentType::form_url_encoded());
headers
}
pub async fn authenticate() -> Result<String, reqwest::Error> {
let client = reqwest::Client::new();
let resz = client.post("https://api.test.com/auth/token")
.headers(construct_headers())
.body("grant_type=client_credentials")
.json(&map)
.send()
.await?;
}
**New Error.
error[E0425]: cannot find value `map` in this scope
--> src\search\routes\common.rs:24:12
|
24 | .json(&map)
| ^^^ not found in this scope
error[E0277]: the trait bound `impl std::future::Future: search::routes::serde::Serialize` is not satisfied
--> src\search\routes.rs:24:29
|
24 | HttpResponse::Ok().json(set_token)
| ^^^^^^^^^ the trait `search::routes::serde::Serialize` is not implemented for `impl std::future::Future`
error[E0308]: mismatched types
--> src\search\routes\common.rs:22:14
|
22 | .headers(construct_headers())
| ^^^^^^^^^^^^^^^^^^^ expected struct `search::routes::reqwest::header::HeaderMap`, found struct `hyper::header::Headers`
|
= note: expected struct `search::routes::reqwest::header::HeaderMap`
found struct `hyper::header::Headers`
error[E0599]: no method named `json` found for struct `search::routes::reqwest::RequestBuilder` in the current scope
--> src\search\routes\common.rs:24:6
|
24 | .json(&map)
| ^^^^ method not found in `search::routes::reqwest::RequestBuilder`
error[E0308]: mismatched types
--> src\search\routes\common.rs:18:63
|
18 | pub async fn authenticate() -> Result<String, reqwest::Error> {
| _______________________________________________________________^
19 | |
20 | | let client = reqwest::Client::new();
21 | | let resz = client.post("https://api.test.com/auth/token")
... |
27 | |
28 | | }
| |_^ expected enum `std::result::Result`, found `()`
|
= note: expected enum `std::result::Result<std::string::String, search::routes::reqwest::Error>`
found unit type `()`
Can I clarify your question? As I understand you already know how to use functions from another file. Do you need to know how to make API requests and pass a result form a request as Response?
Firstly, you need to create fetch_test.rs with using for example reqwest lib:
let client = reqwest::Client::new();
let res = client.post("http://httpbin.org/post")
.json(&map)
.send()
.await?;
Map result or pass it as it is.
Return result in routes.rs: HttpResponse::Ok().json(res)
I hope it will help you.

go mysql returning null values

I am currently working on a Golang Google App Engine Project and have run into a small problem. I have a database "party" with table "parties". The problem is that when the following code is executed, a EMPTY json array is printed - it actually is properly long, but it only contains empty Parties. (And I do have entries in my database)
Go code (not all of it):
func getParties(w http.ResponseWriter, r *http.Request) {
rows := getRowsFromSql("select * from parties;")
parties := scanForParties(rows)
json, _ := json.Marshal(parties)
fmt.Fprint(w, string(json))
}
func scanForParties(rows *sql.Rows) []Party {
var parties []Party
for rows.Next() {
var id int
var name, author, datetime, datetime_to, host, location, description, longtitude, latitude, primary_image_id string
rows.Scan(&id, &name, &author, &datetime, &datetime_to, &host, &location, &description, &longtitude, &latitude, &primary_image_id)
party := Party{
Id: id,
Name: name,
Author: author,
Datetime: datetime,
Datetime_to: datetime_to,
Host: host,
Location: location,
Description: description,
Longtitude: longtitude,
Latitude: latitude,
PrimaryImgId: primary_image_id,
}
parties = append(parties, party)
}
return parties
}
func getRowsFromSql(query string) *sql.Rows {
con, err := sql.Open("mysql", dbConnectString)
if err != nil {
panic(err)
}
defer con.Close()
rows, err2 := con.Query(query)
if err != nil {
panic(err2)
}
return rows
}
type Party struct {
Id int
Name string
Author string
Datetime string
Datetime_to string
Host string
Location string
Description string
Longtitude string
Latitude string
PrimaryImgId string
}
And my parties table:
mysql> describe parties;
+------------------+----------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+----------------+------+-----+-------------------+-----------------------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(64) | NO | | | |
| author | varchar(64) | YES | | NULL | |
| datetime | datetime | YES | | NULL | |
| last_edited | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| datetime_to | datetime | YES | | NULL | |
| host | text | YES | | NULL | |
| location | text | YES | | NULL | |
| description | text | YES | | NULL | |
| longitude | decimal(23,20) | YES | | NULL | |
| latitude | decimal(23,20) | YES | | NULL | |
| primary_image_id | varchar(256) | YES | | NULL | |
+------------------+----------------+------+-----+-------------------+-----------------------------+
However, this old version of code works just fine:
func getParties(w http.ResponseWriter, r *http.Request) {
con, dbErr := sql.Open("mysql", dbConnectString)
defer con.Close()
if dbErr == nil {
rows, _ := con.Query("select id, name, author, datetime from parties where datetime >= NOW();")
var parties []Party
var id int
var name string
var author string
var datetime string
for rows.Next() {
rows.Scan(&id, &name, &author, &datetime)
party := Party{}
party.Id = id
party.Name = name
party.Author = author
party.Datetime = datetime
parties = append(parties, party)
}
if len(parties) > 0 {
json, _ := json.Marshal(parties)
fmt.Fprint(w, string(json))
} else {
fmt.Fprint(w, "{}")
}
} else {
fmt.Fprint(w, "{\"Error\"}")
}
}
Any idea why this happens?
Thanks in advance :)
This is a guess, but I'm thinking that it's because you're closing the connection to the database here:
defer con.Close()
This will close the connection to the database when getRowsFromSql returns, so by the time you start calling rows.Next() in scanForParties the DB connection is gone. Once the DB connection is closed, any collection of rows will no longer be available.
Something is probably returning an error because of this, but since you're not checking any errors anywhere you won't know. In Go it is idiomatic to check for errors whenever a function can return one (and other languages too, just more so in Go because of the lack of exceptions).
Okay so all the others were right about the errors: rows.Scan() returns an error. And when I finally checked it, it said that there are insufficient scan variables provided. Simple fix: add the missing one.
Thank you guys :)

How to extract data from Mysql column stored in serialized JSON column?

I have column in mysql DB which contains serialized data (used PHP JSON encode to serialize them).
Here is an example:
{"name":"Group ltd","email":"support#domain.org","auth":"Andrey Ucholnik"}
Is there a built in function in mysql to extract these values without PHP ?
I mean to build query that will unserialize data.
Of course its possible to use combination of LOCATE and SUBSTR function to do that but I prefer something built in if possible.
There is no build in function in MySQL but by using small code in PHP you can easily do it as under:
<?php
$json = '{{"generated": "2010-02-26T22:26:03.156866 blahblahblah ": null, "thumbnail_url": "http://thumbs.mochiads.com/c/g/tetword-pro/_thumb_100x100.jpg", "screen4_url": "http://thumbs.mochiads.com/c/g/tetword-pro/screen4.png", "leaderboard_enabled": true, "resolution": "600x550", "width": 600}]}}';
$out = json_decode($json, true);
foreach($out["games"] as $game) {
$name = addslashes($game[name]);
$description = addslashes($game[description]);
//Here you can use your mysql_insert code
mysql_query("INSERT INTO games (name, description) VALUES('$name', '$description')") or die (mysql_error());
}
?>
There are no built-in MySQL functions to work with JSON, but here is a very simple stored function to extract values from JSON:
DELIMITER $$
CREATE FUNCTION JSON_EXTRACT(json TEXT, name CHAR(64))
RETURNS CHAR(64) DETERMINISTIC
BEGIN
SET #namePos = LOCATE(name, json);
IF #namePos = 0 THEN RETURN ''; END IF;
SET #valuePos = LOCATE(':', json, #namePos) + 1;
IF SUBSTR(json, #valuePos, 1) = '"' THEN
SET #valuePos = #valuePos + 1;
RETURN SUBSTR(json, #valuePos, LOCATE('"', json, #valuePos) - #valuePos);
ELSE
SET #valueBegin = TRIM(SUBSTR(json, #valuePos));
SET #delim1 = LOCATE(' ', #valueBegin); SET #delim1 = IF(#delim1 = 0, 64, #delim1);
SET #delim2 = LOCATE(',', #valueBegin); SET #delim2 = IF(#delim2 = 0, 64, #delim2);
SET #delim3 = LOCATE('}', #valueBegin); SET #delim3 = IF(#delim3 = 0, 64, #delim3);
RETURN LEFT(#valueBegin, LEAST(#delim1, #delim2, #delim3) - 1);
END IF;
END$$
Usage example:
SELECT JSON_EXTRACT('{"a":"aa","b" : 1, "c": 3}', 'b') AS test;
Note that the function has many limitations. For example, it doesn't handle nested classes and key names shouldn't be included in the values.
Yes , you can definitely to it using JSON_EXTRACT() function in mysql.
lets take a table that contains JSON (table client_services here) :
+-----+-----------+--------------------------------------+
| id | client_id | service_values |
+-----+-----------+------------+-------------------------+
| 100 | 1000 | { "quota": 1,"data_transfer":160000} |
| 101 | 1000 | { "quota": 2,"data_transfer":800000} |
| 102 | 1000 | { "quota": 3,"data_transfer":70000} |
| 103 | 1001 | { "quota": 1,"data_transfer":97000} |
| 104 | 1001 | { "quota": 2,"data_transfer":1760} |
| 105 | 1002 | { "quota": 2,"data_transfer":1060} |
+-----+-----------+--------------------------------------+
To Select each JSON fields , run this query :
SELECT
id, client_id,
json_extract(service_values, '$.quota') AS quota,
json_extract(service_values, '$.data_transfer') AS data_transfer
FROM client_services;
So the output will be :
+-----+-----------+----------------------+
| id | client_id | quota | data_transfer|
+-----+-----------+----------------------+
| 100 | 1000 | 1 | 160000 |
| 101 | 1000 | 2 | 800000 |
| 102 | 1000 | 3 | 70000 |
| 103 | 1001 | 1 | 97000 |
| 104 | 1001 | 2 | 1760 |
| 105 | 1002 | 2 | 1060 |
+-----+-----------+----------------------+
Hope this helps!