sfackler / rust-postgres

Native PostgreSQL driver for the Rust programming language
Apache License 2.0
3.42k stars 436 forks source link

how do i use something like jsonb,date,time? with rust-postgres #1076

Closed Cariaga closed 10 months ago

Cariaga commented 10 months ago

i could not find an exact sample for jsonb,date,time

use serde_json::Error;
use serde_json::Value;
use serde_json::json;

use postgres::NoTls;
use postgres::Client;
use postgres::types::ToSql;
use std::sync::Arc;
use std::sync::Mutex;
use rand::Rng;
use chrono::{NaiveDate, NaiveDateTime, NaiveTime,Utc};
use chrono::{prelude::*, Local};
use std::time::SystemTime;
use std::time::UNIX_EPOCH;
use postgres::types::{FromSql, ToSql, Type, Timestamp, IsNull};
                    let mut query_params: Vec<Box<dyn postgres::types::ToSql + Sync>> = Vec::new(); // Change the type to hold owned values
                    query_params.push(Box::new(1 as i32)); // Integer
                    query_params.push(Box::new(1 as i64)); // BigInt
                    query_params.push(Box::new(1.1 as f32)); // Real
                    query_params.push(Box::new(1.1 as f64)); // Double precision
                    query_params.push(Box::new("hello".to_string())); // Text
                    query_params.push(Box::new(true)); // Boolean

                    let system_time = SystemTime::now();
                    query_params.push(Box::new(system_time)); //TIMESTAMP WITH TIME ZONE

                    let json_str = r#"
                    {
                        "name": "Alice",
                        "age": 25,
                        "is_student": true
                    }
                    "#;
                    /*
                    mssing something like  query_params.push(Box::new(json_str)); but with serde_json::Value
                     */

                    let database_url = "postgresql://postgres:postgres@localhost:5432/db";
                    let mut client = Client::connect(&database_url, NoTls)?;
                    let query_param_refs: Vec<&(dyn postgres::types::ToSql + Sync)> = query_params.iter().map(AsRef::as_ref).collect();
                    let query_param_slice = &query_param_refs[..];
                    let query = "SELECT $1::integer as param1, $2::bigint as param2, $3::real as param3, $4::double precision as param4, $5::text as param5, $6::boolean as param6,$7::TIMESTAMP WITH TIME ZONE as param7,$8::JSONB as param8";
                    let result = client.query(query, query_param_slice);

                    match result {
                        Ok(rows) => {
                            for row in rows {
                                println!("{:?}", row);
                                // Process the row data here
                            }
                        }
                        Err(err) => {
                            // Log the error
                            eprintln!("Error executing query: {:?}", err);
                        }
                    }
sfackler commented 10 months ago

You can parse the JSON string into a serde_json::Value with https://docs.rs/serde_json/latest/serde_json/fn.from_str.html

Cariaga commented 10 months ago

thank you

let mut query_params: Vec<Box<dyn postgres::types::ToSql + Sync>> = Vec::new(); 
let json_str = r#"
                    {
                        "name": "Alice",
                        "age": 25,
                        "is_student": true
                    }
                    "#;
let x: Value = serde_json::from_str(json_str).unwrap();

i guess the next issue now is

query_params.push(Box::new(x));

which is causing

error[E0277]: the trait bound `serde_json::Value: ToSql` is not satisfied
  --> cache_proxy\src\socket\message\mod.rs:65:39
   |
65 |                     query_params.push(Box::new(x));
   |                                       ^^^^^^^^^^^ the trait `ToSql` is not implemented for `serde_json::Value`
   |
   = help: the following other types implement trait `ToSql`:
             bool
             i8
             i16
             i32
             i64
             u32
             f32
             f64
           and 18 others
   = note: required for the cast from `Box<serde_json::Value>` to `Box<dyn ToSql + Sync>`
Cariaga commented 10 months ago

looks like i have to also add this in cargo.toml postgres ={version="0.19.7", features = ["with-serde_json-1","with-chrono-0_4","array-impls","with-geo-types-0_7","with-time-0_3","with-uuid-1"]}

based on here https://github.com/sfackler/rust-postgres/blob/master/postgres/Cargo.toml i got confused because https://docs.rs/postgres/latest/postgres/types/trait.ToSql.html does not say which cargo features its referring to which i got the correct imports from https://github.com/sfackler/rust-postgres/blob/master/postgres/Cargo.toml

sfackler commented 10 months ago

In addition, some implementations are provided for types in third party crates. These are disabled by default; to opt into one of these implementations, activate the Cargo feature corresponding to the crate’s name prefixed by with-. For example, the with-serde_json-1 feature enables the implementation for the serde_json::Value type.

Cariaga commented 10 months ago

thank you. Solved just wanted to include the postgres ={version="0.19.7", features = ["with-serde_json-1","with-chrono-0_4","array-impls","with-geo-types-0_7","with-time-0_3","with-uuid-1"]} for future reference what the docs mean