From 0df965cf7ceb87df67991d8603c3837c47d286d0 Mon Sep 17 00:00:00 2001 From: amigin Date: Sat, 22 Feb 2025 20:44:40 +0200 Subject: [PATCH] Fixing DateTime as Timestamp performance issue --- .../src/connection/connection_string.rs | 2 +- .../connection/postgres_row_read_stream.rs | 8 +++-- my-postgres-core/src/sql/select_builder.rs | 2 +- .../src/sql_select/from_db_row.rs | 8 +++-- .../src/sql_select/select_with_params.rs | 6 ++-- my-postgres-core/src/utils.rs | 5 +++ .../src/postgres_struct_schema.rs | 6 ++-- .../src/table_schema/generate.rs | 9 ++--- my-postgres-tests/src/dto/mod.rs | 3 +- .../src/dto/where_model_with_timestamp.rs | 34 +++++++++++++++++++ 10 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 my-postgres-tests/src/dto/where_model_with_timestamp.rs diff --git a/my-postgres-core/src/connection/connection_string.rs b/my-postgres-core/src/connection/connection_string.rs index 93bade4..a952fe0 100644 --- a/my-postgres-core/src/connection/connection_string.rs +++ b/my-postgres-core/src/connection/connection_string.rs @@ -500,7 +500,7 @@ pub enum ConnectionStringFormat<'s> { } impl<'s> ConnectionStringFormat<'s> { - pub fn parse_and_detect(conn_string: &'s str) -> ConnectionStringFormat { + pub fn parse_and_detect(conn_string: &'s str) -> ConnectionStringFormat<'s> { if conn_string.trim().starts_with(PREFIX) { return ConnectionStringFormat::AsUrl(conn_string); } diff --git a/my-postgres-core/src/connection/postgres_row_read_stream.rs b/my-postgres-core/src/connection/postgres_row_read_stream.rs index e1313bc..b090656 100644 --- a/my-postgres-core/src/connection/postgres_row_read_stream.rs +++ b/my-postgres-core/src/connection/postgres_row_read_stream.rs @@ -46,7 +46,7 @@ async fn start_reading( use crate::connection::get_sql_telemetry_tags; pin_mut!(stream); - + #[cfg(feature = "with-logs-and-telemetry")] let mut read_ok_rows = 0; loop { @@ -65,7 +65,11 @@ async fn start_reading( match read_result.unwrap() { Ok(row) => { - read_ok_rows += 1; + #[cfg(feature = "with-logs-and-telemetry")] + { + read_ok_rows += 1; + } + if row.is_none() { #[cfg(feature = "with-logs-and-telemetry")] ctx.write_success( diff --git a/my-postgres-core/src/sql/select_builder.rs b/my-postgres-core/src/sql/select_builder.rs index 9bceba2..5549c1d 100644 --- a/my-postgres-core/src/sql/select_builder.rs +++ b/my-postgres-core/src/sql/select_builder.rs @@ -344,7 +344,7 @@ pub fn fill_select_fields(sql: &mut String, items: &[SelectFieldValue]) { sql.push_str("(extract(EPOCH FROM "); sql.push_str(field_name.db_column_name); sql.push_str(") * 1000000)::bigint as \""); - sql.push_str(field_name.db_column_name); + crate::utils::fill_adjusted_column_name(field_name.db_column_name, sql); sql.push('"'); } SelectFieldValue::DateTimeAsBigint(field_name) => { diff --git a/my-postgres-core/src/sql_select/from_db_row.rs b/my-postgres-core/src/sql_select/from_db_row.rs index 36db298..9909587 100644 --- a/my-postgres-core/src/sql_select/from_db_row.rs +++ b/my-postgres-core/src/sql_select/from_db_row.rs @@ -249,7 +249,9 @@ impl<'s> FromDbRow<'s, DateTimeAsMicroseconds> for DateTimeAsMicroseconds { column_name: DbColumnName, _metadata: &Option, ) -> DateTimeAsMicroseconds { - let unix_microseconds: i64 = row.get(column_name.db_column_name); + let mut db_column_name = String::new(); + crate::utils::fill_adjusted_column_name(column_name.db_column_name, &mut db_column_name); + let unix_microseconds: i64 = row.get(db_column_name.as_str()); DateTimeAsMicroseconds::new(unix_microseconds) } @@ -258,7 +260,9 @@ impl<'s> FromDbRow<'s, DateTimeAsMicroseconds> for DateTimeAsMicroseconds { column_name: DbColumnName, _metadata: &Option, ) -> Option { - let unix_microseconds: Option = row.get(column_name.db_column_name); + let mut db_column_name = String::new(); + crate::utils::fill_adjusted_column_name(column_name.db_column_name, &mut db_column_name); + let unix_microseconds: Option = row.get(db_column_name.as_str()); let unix_microseconds = unix_microseconds?; Some(DateTimeAsMicroseconds::new(unix_microseconds)) } diff --git a/my-postgres-core/src/sql_select/select_with_params.rs b/my-postgres-core/src/sql_select/select_with_params.rs index 5d794da..f41ef43 100644 --- a/my-postgres-core/src/sql_select/select_with_params.rs +++ b/my-postgres-core/src/sql_select/select_with_params.rs @@ -10,17 +10,17 @@ pub struct SqlWithParams<'s> { } pub trait WithSqlParams<'s> { - fn inject_sql_params_data(&'s self, params: SqlValues) -> SqlWithParams; + fn inject_sql_params_data(&'s self, params: SqlValues) -> SqlWithParams<'s>; } impl<'s> WithSqlParams<'s> for String { - fn inject_sql_params_data(&'s self, params: SqlValues) -> SqlWithParams { + fn inject_sql_params_data(&'s self, params: SqlValues) -> SqlWithParams<'s> { SqlWithParams { sql: self, params } } } impl<'s> WithSqlParams<'s> for &'s str { - fn inject_sql_params_data(&'s self, params: SqlValues) -> SqlWithParams { + fn inject_sql_params_data(&'s self, params: SqlValues) -> SqlWithParams<'s> { SqlWithParams { sql: self, params } } } diff --git a/my-postgres-core/src/utils.rs b/my-postgres-core/src/utils.rs index fec9bfd..4033628 100644 --- a/my-postgres-core/src/utils.rs +++ b/my-postgres-core/src/utils.rs @@ -35,6 +35,11 @@ pub fn get_case_and_model<'s>( (case.unwrap(), model.unwrap()) } +pub fn fill_adjusted_column_name(column_name: &str, out: &mut String) { + out.push_str(column_name); + out.push_str("_at_adjusted"); +} + /* pub struct CaseAndModelValue { case: JsonKeyValue, diff --git a/my-postgres-macros/src/postgres_struct_schema.rs b/my-postgres-macros/src/postgres_struct_schema.rs index 6af2faf..2df37a2 100644 --- a/my-postgres-macros/src/postgres_struct_schema.rs +++ b/my-postgres-macros/src/postgres_struct_schema.rs @@ -23,13 +23,13 @@ pub struct DbIndexField<'s> { } pub trait PostgresStructSchema<'s> { - fn get_fields(&'s self) -> Vec<&'s StructProperty>; + fn get_fields(&'s self) -> Vec<&'s StructProperty<'s>>; fn get_name(&'s self) -> &'s TypeName; fn get_select_properties_to_generate( &'s self, - ) -> Result>, syn::Error> { + ) -> Result>>, syn::Error> { let mut result = BTreeMap::new(); for prop in self.get_fields() { @@ -174,7 +174,7 @@ pub trait PostgresStructSchema<'s> { } impl<'s> PostgresStructSchema<'s> for StructureSchema<'s> { - fn get_fields(&'s self) -> Vec<&'s StructProperty> { + fn get_fields(&'s self) -> Vec<&'s StructProperty<'s>> { let all = self.get_all(); let mut result = Vec::with_capacity(all.len()); diff --git a/my-postgres-macros/src/table_schema/generate.rs b/my-postgres-macros/src/table_schema/generate.rs index 60c50ae..91d37e3 100644 --- a/my-postgres-macros/src/table_schema/generate.rs +++ b/my-postgres-macros/src/table_schema/generate.rs @@ -1,7 +1,7 @@ use proc_macro2::TokenStream; -use types_reader::{ macros::{MacrosParameters, MacrosEnum}, StructureSchema}; +use types_reader::{ macros::MacrosEnum, StructureSchema}; use crate::{postgres_struct_ext::PostgresStructPropertyExt, postgres_struct_schema::PostgresStructSchema}; #[derive(MacrosEnum)] @@ -12,12 +12,7 @@ pub enum GenerateType{ Update, } -#[derive(MacrosParameters)] -pub struct GenerateAdditionalUpdateModelAttributeParams { - #[default] - pub name: String, - pub param_type: GenerateType, -} + pub fn generate(ast: &syn::DeriveInput) -> Result { diff --git a/my-postgres-tests/src/dto/mod.rs b/my-postgres-tests/src/dto/mod.rs index 5910467..7f076ac 100644 --- a/my-postgres-tests/src/dto/mod.rs +++ b/my-postgres-tests/src/dto/mod.rs @@ -13,8 +13,8 @@ mod test_json_field; mod test_json_field_where_cases; mod test_json_hashmap_dto; mod test_primary_key; -mod test_various_select_attributes; mod test_union; +mod test_various_select_attributes; mod test_where_inline_case; mod test_where_inline_case_with_no_value; mod test_where_json_field; @@ -25,4 +25,5 @@ mod where_from_real_life; mod where_model; mod where_model_with_ignore_if_none; mod where_model_with_str; +mod where_model_with_timestamp; mod where_model_with_vec; diff --git a/my-postgres-tests/src/dto/where_model_with_timestamp.rs b/my-postgres-tests/src/dto/where_model_with_timestamp.rs new file mode 100644 index 0000000..100d65d --- /dev/null +++ b/my-postgres-tests/src/dto/where_model_with_timestamp.rs @@ -0,0 +1,34 @@ +use my_postgres::macros::WhereDbModel; +use rust_extensions::date_time::DateTimeAsMicroseconds; + +#[derive(WhereDbModel)] +pub struct FindOlderThanPsqlWhere { + #[operator("<")] + #[sql_type("timestamp")] + #[db_column_name("created_at")] + pub created_at: DateTimeAsMicroseconds, + #[limit] + pub limit: usize, +} + +#[cfg(test)] +mod tests { + use my_postgres::{sql::SqlValues, sql_where::SqlWhereModel}; + use rust_extensions::date_time::DateTimeAsMicroseconds; + + use super::FindOlderThanPsqlWhere; + + #[test] + fn test() { + let where_model = FindOlderThanPsqlWhere { + created_at: DateTimeAsMicroseconds::from_str("2024-05-12T12:34:56.789012").unwrap(), + limit: 10, + }; + + let mut params = SqlValues::new(); + let mut sql = String::new(); + where_model.fill_where_component(&mut sql, &mut params); + + println!("sql: {}", sql); + } +}