working pretty good I hope

This commit is contained in:
OMGeeky
2023-03-04 16:10:02 +01:00
parent daccd5289b
commit 8e662172a2
12 changed files with 554 additions and 167 deletions

View File

@@ -5,9 +5,17 @@ use std::str::FromStr;
use crate::client::{BigqueryClient, HasBigQueryClient};
use crate::utils::BigDataValueType;
pub trait BigDataTableBase<'a, TABLE, TPK>: HasBigQueryClient<'a>
where TPK: BigDataValueType + FromStr + std::fmt::Debug {
pub trait BigDataTableHasPk<TPK>
where TPK: BigDataValueType<TPK> + FromStr + std::fmt::Debug + Clone {
fn get_pk_name() -> String;
fn get_pk_value(&self) -> TPK;
}
pub trait BigDataTableBase<'a, TABLE, TPK>: HasBigQueryClient<'a> + BigDataTableHasPk<TPK>
where TPK: BigDataValueType<TPK> + FromStr + std::fmt::Debug + Clone
{
// fn get_pk_name() -> String;
// fn get_pk_value(&self) -> TPK;
fn get_field_name(field_name: &str) -> Result<String, Box<dyn Error>>;
fn get_query_fields() -> HashMap<String, String>;
fn get_table_name() -> String;
@@ -16,7 +24,6 @@ pub trait BigDataTableBase<'a, TABLE, TPK>: HasBigQueryClient<'a>
row: &google_bigquery2::api::TableRow,
index_to_name_mapping: &HashMap<String, usize>)
-> Result<(), Box<dyn Error>>;
fn get_pk_value(&self) -> TPK;
// fn get_query_fields_update_str(&self) -> String;
fn get_all_query_parameters(&self) -> Vec<google_bigquery2::api::QueryParameter>;
@@ -26,4 +33,6 @@ pub trait BigDataTableBase<'a, TABLE, TPK>: HasBigQueryClient<'a>
-> Result<Self, Box<dyn Error>>
where
Self: Sized;
// fn parse_bigquery_value<T: BigDataValueType<T>>(value: &String) -> Result<T, Box<dyn Error>>;
}

View File

@@ -12,7 +12,7 @@ use crate::utils::BigDataValueType;
pub trait BigDataTableBaseConvenience<'a, TABLE, TPK>
: BigDataTableBase<'a, TABLE, TPK>
where TPK: BigDataValueType + FromStr + Debug {
where TPK: BigDataValueType<TPK> + FromStr + Debug + Clone {
fn get_pk_param(&self) -> google_bigquery2::api::QueryParameter;
fn get_query_fields_str() -> String;
fn get_query_fields_insert_str() -> String;
@@ -53,11 +53,11 @@ pub trait BigDataTableBaseConvenience<'a, TABLE, TPK>
// async fn get_identifier_and_base_where_from_client(client: &'a BigqueryClient, pk_name: &str, table_name: &str) -> Result<(String, String), Box<dyn Error>>;
fn get_query_param<TField: BigDataValueType>(field_name: &str, field_value: &Option<TField>)
-> google_bigquery2::api::QueryParameter;
fn get_query_param<TField: BigDataValueType<TField>>(field_name: &str, field_value: &Option<TField>)
-> google_bigquery2::api::QueryParameter;
fn parse_value_to_parameter<TValue>(value: &TValue) -> String
where TValue: std::fmt::Display + BigDataValueType;
where TValue: std::fmt::Display + BigDataValueType<TValue>;
// fn create_from_table_row(client: &'a BigqueryClient,
// row: &google_bigquery2::api::TableRow,
@@ -70,7 +70,7 @@ pub trait BigDataTableBaseConvenience<'a, TABLE, TPK>
impl<'a, TABLE, TPK> BigDataTableBaseConvenience<'a, TABLE, TPK> for TABLE
where
TABLE: BigDataTableBase<'a, TABLE, TPK>,
TPK: BigDataValueType + FromStr + Debug,
TPK: BigDataValueType<TPK> + FromStr + Debug + Clone,
<TPK as FromStr>::Err: Debug,
{
fn get_pk_param(&self) -> QueryParameter {
@@ -89,32 +89,36 @@ impl<'a, TABLE, TPK> BigDataTableBaseConvenience<'a, TABLE, TPK> for TABLE
// }
}
fn get_query_fields_str() -> String {
Self::get_query_fields().values().into_iter()
let mut values = Self::get_query_fields().values()
.into_iter()
.map(|v| format!("{}", v))
.collect::<Vec<String>>()
.join(", ")
.collect::<Vec<String>>();
values.sort();
values.join(", ")
}
fn get_query_fields_insert_str() -> String {
Self::get_query_fields()
let mut values = Self::get_query_fields()
.values()
.into_iter()
.map(|v| format!("@__{}", v))
.collect::<Vec<String>>()
.join(", ")
.collect::<Vec<String>>();
values.sort();
values.join(", ")
}
fn get_query_fields_update_str(&self) -> String {
let x = Self::get_query_fields();
let pk_name = Self::get_pk_name();
let mut vec = x.values()
let mut values = x.values()
.filter(|k| *k != &pk_name)
.map(|k| format!("{} = @__{}", k, k))
.collect::<Vec<String>>();
// vec.sort();
let update_str = vec.join(", ");
values.sort();
let update_str = values.join(", ");
update_str
}
fn get_where_part(field_name: &str, is_comparing_to_null: bool) -> String {
if is_comparing_to_null {
format!("{} IS NULL", field_name)
@@ -148,7 +152,6 @@ impl<'a, TABLE, TPK> BigDataTableBaseConvenience<'a, TABLE, TPK> for TABLE
println!();
}
let (res, query_res) = client.get_client().jobs().query(req, project_id)
.doit().await?;
@@ -218,12 +221,12 @@ impl<'a, TABLE, TPK> BigDataTableBaseConvenience<'a, TABLE, TPK> for TABLE
Self::get_where_part(&pk_name, false)
}
default fn get_query_param<TField: BigDataValueType>(field_name: &str, field_value: &Option<TField>) -> google_bigquery2::api::QueryParameter
default fn get_query_param<TField: BigDataValueType<TField>>(field_name: &str, field_value: &Option<TField>) -> google_bigquery2::api::QueryParameter
{
let type_to_string: String = TField::to_bigquery_type();
let value: Option<google_bigquery2::api::QueryParameterValue> = Some(google_bigquery2::api::QueryParameterValue {
value: match field_value {
Some(value) =>Some(value.to_bigquery_param_value()),//TODO: maybe add a way to use array types
value: match field_value {
Some(value) => Some(value.to_bigquery_param_value()),//TODO: maybe add a way to use array types
None => None,
},
..Default::default()
@@ -240,7 +243,7 @@ impl<'a, TABLE, TPK> BigDataTableBaseConvenience<'a, TABLE, TPK> for TABLE
}
}
fn parse_value_to_parameter<TValue>(value: &TValue) -> String
where TValue: std::fmt::Display + BigDataValueType
where TValue: std::fmt::Display + BigDataValueType<TValue>
{
return value.to_bigquery_param_value();
}

View File

@@ -6,6 +6,7 @@ use std::str::FromStr;
use google_bigquery2::api::{QueryParameter, TableSchema};
pub use big_data_table_base::BigDataTableBase;
pub use big_data_table_base::BigDataTableHasPk;
pub use big_data_table_base_convenience::BigDataTableBaseConvenience;
use crate::client::{BigqueryClient, HasBigQueryClient};
@@ -14,22 +15,24 @@ use crate::utils::BigDataValueType;
mod big_data_table_base_convenience;
mod big_data_table_base;
// pub trait BigDataTable<'a, TABLE, TPK: BigDataValueType + FromStr + Debug>: HasBigQueryClient<'a> + BigDataTableBaseConvenience<'a, TABLE, TPK> + BigDataTableBase<'a, TABLE, TPK> {
// pub trait BigDataTable<'a, TABLE, TPK: BigDataValueType<TPK> + FromStr + Debug>: HasBigQueryClient<'a> + BigDataTableBaseConvenience<'a, TABLE, TPK> + BigDataTableBase<'a, TABLE, TPK> {
pub trait BigDataTable<'a, TABLE, TPK>
: HasBigQueryClient<'a>
+ BigDataTableHasPk<TPK>
+ BigDataTableBaseConvenience<'a, TABLE, TPK>
+ BigDataTableBase<'a, TABLE, TPK>
+ Default
where TPK: BigDataValueType + FromStr + Debug {
async fn from_pk(
where TPK: BigDataValueType<TPK> + FromStr + Debug + Clone {
async fn create_and_load_from_pk(
client: &'a BigqueryClient,
pk: TPK,
) -> Result<Self, Box<dyn Error>>
where
Self: Sized;
async fn load_from_pk(client: &'a BigqueryClient, pk: TPK) -> Result<Option<Self>, Box<dyn Error>> where Self: Sized;
async fn save_to_bigquery(&self) -> Result<(), Box<dyn Error>>;
async fn load_from_bigquery(&mut self) -> Result<(), Box<dyn Error>>;
async fn load_by_field<T: BigDataValueType>(client: &'a BigqueryClient, field_name: &str, field_value: Option<T>, max_amount: usize)
async fn load_by_field<T: BigDataValueType<T>>(client: &'a BigqueryClient, field_name: &str, field_value: Option<T>, max_amount: usize)
-> Result<Vec<TABLE>, Box<dyn Error>>;
async fn load_by_custom_query(client: &'a BigqueryClient, query: &str, parameters: Vec<QueryParameter>, max_amount: usize)
@@ -38,16 +41,22 @@ pub trait BigDataTable<'a, TABLE, TPK>
impl<'a, TABLE, TPK> BigDataTable<'a, TABLE, TPK> for TABLE
where
TABLE: HasBigQueryClient<'a> + BigDataTableBaseConvenience<'a, TABLE, TPK> + Default,
TPK: BigDataValueType + FromStr + Debug,
TABLE: HasBigQueryClient<'a> + BigDataTableBaseConvenience<'a, TABLE, TPK> + Default + BigDataTableHasPk<TPK>,
TPK: BigDataValueType<TPK> + FromStr + Debug + Clone,
<TPK as FromStr>::Err: Debug
{
async fn from_pk(client: &'a BigqueryClient, pk: TPK) -> Result<Self, Box<dyn Error>> where Self: Sized {
async fn create_and_load_from_pk(client: &'a BigqueryClient, pk: TPK) -> Result<Self, Box<dyn Error>> where Self: Sized {
let mut res = Self::create_with_pk(client, pk);
res.load_from_bigquery().await?;
Ok(res)
}
async fn load_from_pk(client: &'a BigqueryClient, pk: TPK) -> Result<Option<Self>, Box<dyn Error>> where Self: Sized {
let x = Self::load_by_field(client, &Self::get_pk_name(), Some(pk), 1).await
.map(|mut v| v.pop())?;
Ok(x)
}
async fn save_to_bigquery(&self) -> Result<(), Box<dyn Error>> {
let project_id = self.get_client().get_project_id();
@@ -100,10 +109,13 @@ where
let query = match exists_row {
true => format!("update {} set {} where {}", table_identifier, self.get_query_fields_update_str(), where_clause),
false => format!("insert into {} ({}, {}) values(@__{}, {})", table_identifier,
Self::get_pk_name(),
// false => format!("insert into {} ({}, {}) values(@__{}, {})", table_identifier,
// Self::get_pk_name(),
// Self::get_query_fields_str(),
// Self::get_pk_name(),
// Self::get_query_fields_insert_str()),
false => format!("insert into {} ({}) values({})", table_identifier,
Self::get_query_fields_str(),
Self::get_pk_name(),
Self::get_query_fields_insert_str()),
};
@@ -148,13 +160,13 @@ where
return Err(format!("Wrong amount of data returned! ({})", rows.len()).into());
}
let mut index_to_name_mapping: HashMap<String, usize> = get_name_index_mapping(query_res.schema);
println!("index_to_name_mapping: {:?}", index_to_name_mapping);
// println!("index_to_name_mapping: {:?}", index_to_name_mapping);
let row = &rows[0];
self.write_from_table_row(row, &index_to_name_mapping)
}
async fn load_by_field<T: BigDataValueType>(client: &'a BigqueryClient, field_name: &str, field_value: Option<T>, max_amount: usize)
async fn load_by_field<T: BigDataValueType<T>>(client: &'a BigqueryClient, field_name: &str, field_value: Option<T>, max_amount: usize)
-> Result<Vec<TABLE>, Box<dyn Error>> {
let field_name: String = field_name.into();
let field_name = Self::get_field_name(&field_name).expect(format!("Field '{}' not found!", field_name).as_str());

View File

@@ -2,16 +2,22 @@
#![feature(specialization)]
#![allow(unused)]
#![allow(incomplete_features)]
// #![feature(impl_trait_projections)]
pub use google_bigquery_derive::HasBigQueryClient as HasBigQueryClientDerive;
pub use google_bigquery_derive::BigDataTable as BigDataTableDerive;
// pub use google_bigquery_derive::MyDerive;
pub use client::{BigqueryClient, HasBigQueryClient};
pub use data::{BigDataTable, BigDataTableBase, BigDataTableBaseConvenience, BigDataTableHasPk};
pub mod client;
mod googlebigquery;
mod data;
mod utils;
pub mod utils;
pub use google_bigquery_derive;
pub fn add(left: usize, right: usize) -> usize {
left + right
}
// pub fn add(left: usize, right: usize) -> usize {
// left + right
// }
#[cfg(test)]
mod tests;

View File

@@ -1,15 +1,12 @@
use std::cmp::Ordering;
use std::collections::HashMap;
use std::error::Error;
use std::fmt::Display;
use google_bigquery2::api::{QueryParameter, QueryParameterType, QueryResponse, TableRow};
use google_bigquery_derive::BigDataTable;
use google_bigquery_derive::HasBigQueryClient;
use crate::client::{BigqueryClient, HasBigQueryClient};
use crate::data::{BigDataTable, BigDataTableBase, BigDataTableBaseConvenience};
use crate::utils::{BigDataValueType, ConvertTypeToBigQueryType, ConvertValueToBigqueryParamValue};
use crate::client::HasBigQueryClient;
use crate::utils::BigDataValueType;
use crate::utils::ConvertValueToBigqueryParamValue;
use super::*;
@@ -23,7 +20,7 @@ use super::*;
async fn save() {
let client = get_test_client().await;
let mut q = Infos::load_by_field(&client, stringify!(info1), Some("a"), 10).await.unwrap();
let mut q = Infos::load_by_field(&client, stringify!(info1), Some("a".to_string()), 10).await.unwrap();
assert_eq!(q.len(), 1);
let mut i1 = &mut q[0];
@@ -54,7 +51,7 @@ async fn save() {
async fn load_by_field() {
let client = get_test_client().await;
let q = Infos::load_by_field(&client, stringify!(info1), Some("a"), 10).await.unwrap();
let q = Infos::load_by_field(&client, stringify!(info1), Some("a".to_string()), 10).await.unwrap();
assert_eq!(q.len(), 1);
let i1 = &q[0];
@@ -78,7 +75,7 @@ async fn load_by_field() {
assert_eq!(i4.info3, Some("cc".to_string()));
let q = Infos::load_by_field(&client, stringify!(info1), Some("aosdinsofnpsngusn"), 10).await.unwrap();
let q = Infos::load_by_field(&client, stringify!(info1), Some("aosdinsofnpsngusn".to_string()), 10).await.unwrap();
assert_eq!(q.len(), 0);
}
@@ -92,7 +89,7 @@ async fn load_by_field_none_param() {
#[tokio::test]
async fn from_pk() {
let client = get_test_client().await;
let i1 = Infos::from_pk(&client, 3).await.unwrap();
let i1 = Infos::load_from_pk(&client, "3".to_string()).await.unwrap().unwrap();
assert_eq!(i1.row_id, 3);
assert_eq!(i1.info1, Some("a".to_string()));
assert_eq!(i1.info3, Some("c".to_string()));
@@ -110,10 +107,12 @@ async fn get_test_client() -> BigqueryClient {
#[cfg_attr(man_impl_has_client = "false", derive(HasBigQueryClient))]
#[cfg_attr(not(man_impl = "true"), derive(BigDataTable))]
pub struct Infos<'a> {
#[cfg_attr(not(man_impl = "true"), primary_key)]
#[cfg_attr(not(man_impl = "true"), required)]
#[cfg_attr(not(man_impl = "true"), db_name("Id"))]
row_id: i64,
#[cfg_attr(not(man_impl = "true"), required)]
#[cfg_attr(not(man_impl = "true"), primary_key)]
row_ids: String,
#[cfg_attr(any(not(man_impl = "true"), man_impl_has_client = "false"), client)]
/// This client should never be left as None, doing so will cause a panic when trying to use it
client: Option<&'a BigqueryClient>,
@@ -133,6 +132,16 @@ impl<'a> HasBigQueryClient<'a> for Infos<'a> {
self.client.unwrap()
}
}
//
// impl<'a> BigDataTableHasPk<String> for Infos<'a> {
// fn get_pk_name() -> String {
// "row_ids".to_string()
// }
//
// fn get_pk_value(&self) -> String {
// self.row_ids.clone()
// }
// }
impl<'a> Default for Infos<'a> {
fn default() -> Self {
@@ -140,6 +149,7 @@ impl<'a> Default for Infos<'a> {
// client: &BigqueryClient::new("none", "none", None).await.unwrap(),
client: None,
row_id: -9999,
row_ids: "-9999".to_string(),
info1: Default::default(),
info2: Default::default(),
info3: Default::default(),

View File

@@ -0,0 +1,128 @@
use std::error::Error;
use std::fmt::Debug;
use std::str::FromStr;
use chrono::{DateTime, Utc};
use crate::utils::BigDataValueType;
//
// pub fn to_value<T>(x: &String) -> Result<T, Box<dyn Error>> {
// let x = x.parse()?;
// Ok(x)
// }
// //TODO: figure out how I can make this work so i can have specific
// // implementations for DateTime<Utc> and some other types but also have a
// // generic implementation for all other types
//
// impl ConvertBigQueryValueToValue2<DateTime<Utc>> {
// pub fn to_value(x: &String) -> Result<DateTime<Utc>, Box<dyn Error>> {
// let x = DateTime::parse_from_rfc3339(x)?;
// let time = x.with_timezone(&Utc);
// Ok(time)
// }
// }
//
// impl<T> ConvertBigQueryValueToOptionValue2<T> {
// pub fn to_value(x: &String) -> Option<T> {
// ConvertBigQueryValueToValue2::<T>::to_value(x).ok()
// }
// }
//
// impl ConvertBigQueryValueToOptionValue2<DateTime<Utc>> {
// pub fn to_value(x: &String) -> Option<DateTime<Utc>> {
// ConvertBigQueryValueToValue2::<DateTime<Utc>>::to_value(x).ok()
// }
// }
//
// pub trait ConvertBigQueryValueToValue<T> {
// fn to_value(&self) -> Result<T, Box<dyn Error>>;
// }
//
// pub trait ConvertBigQueryValueToOptionValue<T> {
// fn to_opt_value(&self) -> Result<Option<T>, Box<dyn Error>>;
// }
//
// impl ConvertBigQueryValueToValue<chrono::DateTime<Utc>> for &String {
// fn to_value(&self) -> Result<chrono::DateTime<Utc>, Box<dyn Error>> {
// println!("ConvertBigQueryValueToValue DateTime<Utc> -> in: {:?}", self);
// let x = chrono::DateTime::parse_from_rfc3339(self)?;
// let time = x.with_timezone(&Utc);
// println!("ConvertBigQueryValueToValue DateTime<Utc> -> out: {:?}", time);
// Ok(time)
// }
// }
//
// impl<R: FromStr> ConvertBigQueryValueToValue<R> for &String
// where R::Err: Error + 'static
// {
// default fn to_value(&self) -> Result<R, Box<dyn Error>> {
// let x = self.parse()?;
// Ok(x)
// }
// }
//
// impl ConvertBigQueryValueToValue<String> for &String {
// default fn to_value(&self) -> Result<String, Box<dyn Error>> {
// let x = self.to_string();
// Ok(x)
// }
// }
//
// // impl<S: ConvertBigQueryValueToValue<R>, R: FromStr> ConvertBigQueryValueToOptionValue<R> for S
// // where R::Err: Error + 'static,
// // S: ConvertBigQueryValueToValue<R> {
// // default fn to_opt_value(&self) -> Result<Option<R>, Box<dyn Error>> {
// // Ok(match (self as &dyn ConvertBigQueryValueToValue<R>).to_value() {
// // Ok(x) => Some(x),
// // Err(_) => None,
// // })
// // }
// // }
//
// impl ConvertBigQueryValueToOptionValue<DateTime<Utc>> for &String
// {
// default fn to_opt_value(&self) -> Result<Option<DateTime<Utc>>, Box<dyn Error>> {
// Ok(match (self as &dyn ConvertBigQueryValueToValue<DateTime<Utc>>).to_value() {
// Ok(x) => Some(x),
// Err(_) => None,
// })
// }
// }
//
// #[cfg(test)]
// fn test123() {
// let x = &"2021-01-01T00:00:00Z".to_string();
// let y: chrono::DateTime<Utc> = x.to_value().unwrap();
// let z: Option<chrono::DateTime<Utc>> = x.to_opt_value().unwrap();
// println!("{:?}", y);
// let x = "2021-01-01T00:00:00Z".to_string();
// let y: i64 = x.to_value().unwrap();
// let z: Option<i64> = x.to_opt_value().unwrap();
// println!("{:?}", y);
// }
//
//
//
// impl<R: FromStr + Debug> ConvertBigQueryValueToValue<R> for String
// where R::Err: Error + 'static
// {
// default fn to_value(&self) -> Result<R, Box<dyn Error>> {
// println!("ConvertBigQueryValueToValue<{}> -> in: {:?}", stringify!(R), self);
// let x = self.parse()?;
// println!("ConvertBigQueryValueToValue<{}> -> out: {:?}", stringify!(R), x);
// Ok(x)
// }
// }
//
// impl<R: ConvertBigQueryValueToValue<R> + FromStr> ConvertBigQueryValueToOptionValue<R> for String
// where R::Err: Error + 'static {
// default fn to_opt_value(&self) -> Result<Option<R>, Box<dyn Error>> {
// Ok(match self.to_value() {
// Ok(x) => Some(x),
// Err(_) => None,
// })
// }
// }

View File

@@ -1,7 +1,7 @@
use std::fmt::Display;
pub trait ConvertTypeToBigQueryType {
fn to_bigquery_type() -> String;
fn to_bigquery_type() -> String where Self: Sized;
}
impl ConvertTypeToBigQueryType for bool {
@@ -33,3 +33,10 @@ impl ConvertTypeToBigQueryType for &str {
"STRING".to_string()
}
}
impl<T> ConvertTypeToBigQueryType for chrono::DateTime<T>
where T: chrono::TimeZone + Display + Send + Sync + 'static {
fn to_bigquery_type() -> String {
"DATETIME".to_string()
}
}

View File

@@ -1,7 +1,29 @@
use std::error::Error;
use std::fmt::Display;
use std::str::FromStr;
use chrono::{NaiveDateTime, Utc};
pub trait ConvertValueToBigqueryParamValue {
fn to_bigquery_param_value(&self) -> String;
fn from_bigquery_value(value :&String) -> Result<Self, Box<dyn Error>> where Self: Sized;
}
impl ConvertValueToBigqueryParamValue for i64 {
fn to_bigquery_param_value(&self) -> String {
format!("{}", self)
}
fn from_bigquery_value(value :&String) -> Result<Self, Box<dyn Error>> where Self: Sized{
Ok(value.parse()?)
}
}
impl ConvertValueToBigqueryParamValue for String {
fn to_bigquery_param_value(&self) -> String {
self.to_string()
}
fn from_bigquery_value(value :&String) -> Result<Self, Box<dyn Error>> where Self: Sized{
Ok(value.to_string())
}
}
impl ConvertValueToBigqueryParamValue for bool {
@@ -12,10 +34,61 @@ impl ConvertValueToBigqueryParamValue for bool {
_ => panic!("Invalid value for bool"),
}
}
fn from_bigquery_value(value :&String) -> Result<Self, Box<dyn Error>> where Self: Sized{
match value.as_str() {
"TRUE" => Ok(true),
"FALSE" => Ok(false),
_ => Err("Invalid value for bool".into()),
}
}
}
impl<R: Display> ConvertValueToBigqueryParamValue for R {
default fn to_bigquery_param_value(&self) -> String {
format!("{}", self)
impl ConvertValueToBigqueryParamValue for chrono::DateTime<Utc> {
fn to_bigquery_param_value(&self) -> String {
println!("ConvertValueToBigqueryParamValue::to_bigquery_param_value DateTime<Utc> -> in: {:?}", self);
let value = self.to_rfc3339_opts(chrono::SecondsFormat::Secs, true);
let value = value.replace("Z", "").replace("T", " ");
// let value = format!("\"{}\"", value);
println!("ConvertValueToBigqueryParamValue::to_bigquery_param_value DateTime<Utc> -> out: {}", value);
value
}
}
fn from_bigquery_value(value :&String) -> Result<Self, Box<dyn Error>> where Self: Sized{
// println!("ConvertValueToBigqueryParamValue::from_bigquery_value DateTime<Utc> -> in: {:?}", value);
let value = value.replace("T", " ").replace("Z", "");
// let x = NaiveDateTime::from_str(&value)
let x = NaiveDateTime::parse_from_str(&value,"%Y-%m-%d %H:%M:%S")
.expect(&format!("Could not parse &String to NaiveDateTime: {}", value));
let time = chrono::DateTime::<Utc>::from_utc(x, Utc);
// let x = chrono::DateTime::parse_from_rfc3339(value)?;
// let time = x.with_timezone(&Utc);
// println!("ConvertValueToBigqueryParamValue::from_bigquery_value DateTime<Utc> -> out: {:?}", time);
Ok(time)
}
}
impl<R:ConvertValueToBigqueryParamValue> ConvertValueToBigqueryParamValue for Option<R>{
fn to_bigquery_param_value(&self) -> String {
match self {
Some(x) => x.to_bigquery_param_value(),
None => "NULL".to_string(),
}
}
fn from_bigquery_value(value :&String) -> Result<Option<R>, Box<dyn Error>> where Self: Sized {
if value == "NULL" {
Ok(None)
} else {
Ok(R::from_bigquery_value(value).ok())
}
}
}
// impl<R: Display + FromStr> ConvertValueToBigqueryParamValue for R where <R as FromStr>::Err: std::error::Error{
// default fn to_bigquery_param_value(&self) -> String {
// format!("{}", self)
// }
// default fn from_bigquery_value(value :&String) -> Result<Self, Box<dyn Error>> where Self: Sized{
// Ok(value.parse()?)
// }
// }

View File

@@ -1,8 +1,14 @@
// pub use convert_bigquery_value_to_value::ConvertBigQueryValueToValue2 as ConvertBigQueryValueToValue;
// pub use convert_bigquery_value_to_value::ConvertBigQueryValueToOptionValue2 as ConvertBigQueryValueToOptionValue;
pub use convert_type_to_big_query_type::ConvertTypeToBigQueryType;
pub use convert_value_to_bigquery_param_value::ConvertValueToBigqueryParamValue;
mod convert_type_to_big_query_type;
mod convert_value_to_bigquery_param_value;
mod convert_bigquery_value_to_value;
pub trait BigDataValueType<T>: ConvertTypeToBigQueryType + ConvertValueToBigqueryParamValue {}
impl<T: ConvertTypeToBigQueryType + ConvertValueToBigqueryParamValue> BigDataValueType<T> for T
{}
pub trait BigDataValueType: ConvertTypeToBigQueryType + ConvertValueToBigqueryParamValue {}
impl<T: ConvertTypeToBigQueryType + ConvertValueToBigqueryParamValue> BigDataValueType for T {}