From 25207a7ac1b16a48a5da1d0991290b0593a137a0 Mon Sep 17 00:00:00 2001 From: pcp <1182658898@qq.com> Date: Wed, 1 Jan 2025 14:23:25 +0800 Subject: [PATCH 1/5] docs : fix/optimizes utils.rs --- api/src/utils.rs | 119 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 97 insertions(+), 22 deletions(-) diff --git a/api/src/utils.rs b/api/src/utils.rs index 2c48ac1..2972ad7 100644 --- a/api/src/utils.rs +++ b/api/src/utils.rs @@ -18,41 +18,116 @@ pub fn get_column_names(rows: &[Row]) -> Vec { } pub fn rows_to_json(rows: &[Row]) -> Vec { + if rows.is_empty() { + return vec![]; + } + + let columns = rows[0].columns(); + let column_types: Vec<&Type> = columns.iter().map(|col| col.type_()).collect(); + let column_names: Vec<&str> = columns.iter().map(|col| col.name()).collect(); + rows.iter() .map(|row| { let mut map = serde_json::Map::new(); - for (i, column) in row.columns().iter().enumerate() { - let value: Value = match *column.type_() { - Type::INT2 => json!(row.get::<_, i16>(i)), - Type::INT4 => json!(row.get::<_, i32>(i)), - Type::INT8 => json!(row.get::<_, i64>(i)), - Type::FLOAT4 => json!(row.get::<_, f32>(i)), - Type::FLOAT8 => json!(row.get::<_, f64>(i)), - Type::BOOL => json!(row.get::<_, bool>(i)), - Type::VARCHAR | Type::TEXT | Type::BPCHAR => json!(row.get::<_, String>(i)), + for (i, column_type) in column_types.iter().enumerate() { + let column_name = column_names[i]; + let value: Value = match **column_type { + Type::INT2 => { + if row.is_null(i) { + Value::Null + } else { + json!(row.get::<_, i16>(i)) + } + } + Type::INT4 => { + if row.is_null(i) { + Value::Null + } else { + json!(row.get::<_, i32>(i)) + } + } + Type::INT8 => { + if row.is_null(i) { + Value::Null + } else { + json!(row.get::<_, i64>(i)) + } + } + Type::FLOAT4 => { + if row.is_null(i) { + Value::Null + } else { + json!(row.get::<_, f32>(i)) + } + } + Type::FLOAT8 => { + if row.is_null(i) { + Value::Null + } else { + json!(row.get::<_, f64>(i)) + } + } + Type::BOOL => { + if row.is_null(i) { + Value::Null + } else { + json!(row.get::<_, bool>(i)) + } + } + Type::VARCHAR | Type::TEXT | Type::BPCHAR => { + if row.is_null(i) { + Value::Null + } else { + json!(row.get::<_, String>(i)) + } + } Type::TIMESTAMP => { - let ts: NaiveDateTime = row.get(i); - json!(ts.to_string()) + if row.is_null(i) { + Value::Null + } else { + let ts: NaiveDateTime = row.get(i); + json!(ts.to_string()) + } } Type::TIMESTAMPTZ => { - let ts: DateTime = row.get(i); - json!(ts.to_rfc3339()) + if row.is_null(i) { + Value::Null + } else { + let ts: DateTime = row.get(i); + json!(ts.to_rfc3339()) + } } Type::DATE => { - let date: NaiveDate = row.get(i); - json!(date.to_string()) + if row.is_null(i) { + Value::Null + } else { + let date: NaiveDate = row.get(i); + json!(date.to_string()) + } } Type::JSON | Type::JSONB => { - let json_value: serde_json::Value = row.get(i); - json_value + if row.is_null(i) { + Value::Null + } else { + let json_value: serde_json::Value = row.get(i); + json_value + } } Type::UUID => { - let uuid: Uuid = row.get(i); - json!(uuid.to_string()) + if row.is_null(i) { + Value::Null + } else { + let uuid: Uuid = row.get(i); + json!(uuid.to_string()) + } + } + // Add more type handlers as needed + _ => { + log::warn!("Unhandled column type: {:?}", column_type); + Value::Null } - _ => Value::Null, }; - map.insert(column.name().to_string(), value); + map.insert(column_name.to_string(), value); } Value::Object(map) }) @@ -69,7 +144,7 @@ pub struct Pagination { impl Pagination { pub fn new(query: Query, total_count: i64) -> Self { let limit = query.limit.unwrap_or(200).clamp(1, 1000); - let total_pages = (total_count as f64 / limit as f64).ceil() as i64; + let total_pages = ((total_count as f64 / limit as f64).ceil() as i64).max(1); let page = query.page.unwrap_or(1).clamp(1, total_pages); From fcfdbd415beb10d7265a4cce6195fc3c79462cea Mon Sep 17 00:00:00 2001 From: pcp <1182658898@qq.com> Date: Fri, 3 Jan 2025 10:42:32 +0800 Subject: [PATCH 2/5] opt-repeat --- api/src/utils.rs | 105 ++++++++++------------------------------------- 1 file changed, 22 insertions(+), 83 deletions(-) diff --git a/api/src/utils.rs b/api/src/utils.rs index 2972ad7..616c209 100644 --- a/api/src/utils.rs +++ b/api/src/utils.rs @@ -29,102 +29,41 @@ pub fn rows_to_json(rows: &[Row]) -> Vec { rows.iter() .map(|row| { let mut map = serde_json::Map::new(); - for (i, column_type) in column_types.iter().enumerate() { + for (i, &column_type) in column_types.iter().enumerate() { let column_name = column_names[i]; - let value: Value = match **column_type { - Type::INT2 => { - if row.is_null(i) { - Value::Null - } else { - json!(row.get::<_, i16>(i)) - } - } - Type::INT4 => { - if row.is_null(i) { - Value::Null - } else { - json!(row.get::<_, i32>(i)) - } - } - Type::INT8 => { - if row.is_null(i) { - Value::Null - } else { - json!(row.get::<_, i64>(i)) - } - } - Type::FLOAT4 => { - if row.is_null(i) { - Value::Null - } else { - json!(row.get::<_, f32>(i)) - } - } - Type::FLOAT8 => { - if row.is_null(i) { - Value::Null - } else { - json!(row.get::<_, f64>(i)) - } - } - Type::BOOL => { - if row.is_null(i) { - Value::Null - } else { - json!(row.get::<_, bool>(i)) - } - } - Type::VARCHAR | Type::TEXT | Type::BPCHAR => { - if row.is_null(i) { - Value::Null - } else { - json!(row.get::<_, String>(i)) - } - } - Type::TIMESTAMP => { - if row.is_null(i) { - Value::Null - } else { + let value: Value = if row.is_null(i) { + Value::Null + } else { + match *column_type { + Type::INT2 => json!(row.get::<_, i16>(i)), + Type::INT4 => json!(row.get::<_, i32>(i)), + Type::INT8 => json!(row.get::<_, i64>(i)), + Type::FLOAT4 => json!(row.get::<_, f32>(i)), + Type::FLOAT8 => json!(row.get::<_, f64>(i)), + Type::BOOL => json!(row.get::<_, bool>(i)), + Type::VARCHAR | Type::TEXT | Type::BPCHAR => json!(row.get::<_, String>(i)), + Type::TIMESTAMP => { let ts: NaiveDateTime = row.get(i); json!(ts.to_string()) } - } - Type::TIMESTAMPTZ => { - if row.is_null(i) { - Value::Null - } else { + Type::TIMESTAMPTZ => { let ts: DateTime = row.get(i); json!(ts.to_rfc3339()) } - } - Type::DATE => { - if row.is_null(i) { - Value::Null - } else { + Type::DATE => { let date: NaiveDate = row.get(i); json!(date.to_string()) } - } - Type::JSON | Type::JSONB => { - if row.is_null(i) { - Value::Null - } else { - let json_value: serde_json::Value = row.get(i); - json_value - } - } - Type::UUID => { - if row.is_null(i) { - Value::Null - } else { + Type::JSON | Type::JSONB => row.get::<_, Value>(i), + Type::UUID => { let uuid: Uuid = row.get(i); json!(uuid.to_string()) } - } - // Add more type handlers as needed - _ => { - log::warn!("Unhandled column type: {:?}", column_type); - Value::Null + // Log unhandled types for future improvements + _ => { + log::warn!("Unhandled column type: {:?}", column_type); + Value::Null + } } }; map.insert(column_name.to_string(), value); From c9fcba717fe9a34370f72b573ee3d815eb197692 Mon Sep 17 00:00:00 2001 From: pcp <1182658898@qq.com> Date: Fri, 3 Jan 2025 11:31:37 +0800 Subject: [PATCH 3/5] fix is_null error --- api/src/utils.rs | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/api/src/utils.rs b/api/src/utils.rs index 616c209..6c3eb05 100644 --- a/api/src/utils.rs +++ b/api/src/utils.rs @@ -31,39 +31,42 @@ pub fn rows_to_json(rows: &[Row]) -> Vec { let mut map = serde_json::Map::new(); for (i, &column_type) in column_types.iter().enumerate() { let column_name = column_names[i]; - let value: Value = if row.is_null(i) { - Value::Null - } else { - match *column_type { - Type::INT2 => json!(row.get::<_, i16>(i)), - Type::INT4 => json!(row.get::<_, i32>(i)), - Type::INT8 => json!(row.get::<_, i64>(i)), - Type::FLOAT4 => json!(row.get::<_, f32>(i)), - Type::FLOAT8 => json!(row.get::<_, f64>(i)), - Type::BOOL => json!(row.get::<_, bool>(i)), - Type::VARCHAR | Type::TEXT | Type::BPCHAR => json!(row.get::<_, String>(i)), + + let value: Value = match row.try_get::, _>(i) { + Ok(None) => Value::Null, + Ok(Some(val)) => match *column_type { + Type::INT2 => json!(val as i16), + Type::INT4 => json!(val as i32), + Type::INT8 => json!(val as i64), + Type::FLOAT4 => json!(val as f32), + Type::FLOAT8 => json!(val as f64), + Type::BOOL => json!(val as bool), + Type::VARCHAR | Type::TEXT | Type::BPCHAR => json!(val as String), Type::TIMESTAMP => { - let ts: NaiveDateTime = row.get(i); + let ts: NaiveDateTime = val; json!(ts.to_string()) } Type::TIMESTAMPTZ => { - let ts: DateTime = row.get(i); + let ts: DateTime = val; json!(ts.to_rfc3339()) } Type::DATE => { - let date: NaiveDate = row.get(i); + let date: NaiveDate = val; json!(date.to_string()) } - Type::JSON | Type::JSONB => row.get::<_, Value>(i), + Type::JSON | Type::JSONB => json!(val as Value), Type::UUID => { - let uuid: Uuid = row.get(i); + let uuid: Uuid = val; json!(uuid.to_string()) } - // Log unhandled types for future improvements _ => { log::warn!("Unhandled column type: {:?}", column_type); Value::Null } + }, + Err(_) => { + log::error!("Failed to get value for column: {}", column_name); + Value::Null } }; map.insert(column_name.to_string(), value); From c5d00d5616a16c1b334373b58927738c24e6202a Mon Sep 17 00:00:00 2001 From: pcp <1182658898@qq.com> Date: Fri, 3 Jan 2025 12:04:05 +0800 Subject: [PATCH 4/5] fix suggestion is_null error --- api/src/utils.rs | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/api/src/utils.rs b/api/src/utils.rs index 6c3eb05..46dffb8 100644 --- a/api/src/utils.rs +++ b/api/src/utils.rs @@ -32,41 +32,39 @@ pub fn rows_to_json(rows: &[Row]) -> Vec { for (i, &column_type) in column_types.iter().enumerate() { let column_name = column_names[i]; - let value: Value = match row.try_get::, _>(i) { - Ok(None) => Value::Null, - Ok(Some(val)) => match *column_type { - Type::INT2 => json!(val as i16), - Type::INT4 => json!(val as i32), - Type::INT8 => json!(val as i64), - Type::FLOAT4 => json!(val as f32), - Type::FLOAT8 => json!(val as f64), - Type::BOOL => json!(val as bool), - Type::VARCHAR | Type::TEXT | Type::BPCHAR => json!(val as String), + let column_info = row.columns()[i].type_(); + let value: Value = if column_info.is_null() { + Value::Null + } else { + match *column_type { + Type::INT2 => json!(row.get::<_, i16>(i)), + Type::INT4 => json!(row.get::<_, i32>(i)), + Type::INT8 => json!(row.get::<_, i64>(i)), + Type::FLOAT4 => json!(row.get::<_, f32>(i)), + Type::FLOAT8 => json!(row.get::<_, f64>(i)), + Type::BOOL => json!(row.get::<_, bool>(i)), + Type::VARCHAR | Type::TEXT | Type::BPCHAR => json!(row.get::<_, String>(i)), Type::TIMESTAMP => { - let ts: NaiveDateTime = val; + let ts: NaiveDateTime = row.get(i); json!(ts.to_string()) } Type::TIMESTAMPTZ => { - let ts: DateTime = val; + let ts: DateTime = row.get(i); json!(ts.to_rfc3339()) } Type::DATE => { - let date: NaiveDate = val; + let date: NaiveDate = row.get(i); json!(date.to_string()) } - Type::JSON | Type::JSONB => json!(val as Value), + Type::JSON | Type::JSONB => row.get::<_, Value>(i), Type::UUID => { - let uuid: Uuid = val; + let uuid: Uuid = row.get(i); json!(uuid.to_string()) } _ => { log::warn!("Unhandled column type: {:?}", column_type); Value::Null } - }, - Err(_) => { - log::error!("Failed to get value for column: {}", column_name); - Value::Null } }; map.insert(column_name.to_string(), value); From e004d6db7464d5cb30a37cfbe189a1cc7076741b Mon Sep 17 00:00:00 2001 From: pcp <1182658898@qq.com> Date: Sat, 4 Jan 2025 11:23:58 +0800 Subject: [PATCH 5/5] fix suggestion is_null error --- api/src/utils.rs | 73 ++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/api/src/utils.rs b/api/src/utils.rs index 46dffb8..e046ea2 100644 --- a/api/src/utils.rs +++ b/api/src/utils.rs @@ -17,6 +17,15 @@ pub fn get_column_names(rows: &[Row]) -> Vec { } } +macro_rules! get_json_option { + ($row:expr, $idx:expr, $type:ty) => { + { + let v: Option<$type> = $row.try_get($idx).unwrap_or(None); + json!(v) + } + }; +} + pub fn rows_to_json(rows: &[Row]) -> Vec { if rows.is_empty() { return vec![]; @@ -32,39 +41,37 @@ pub fn rows_to_json(rows: &[Row]) -> Vec { for (i, &column_type) in column_types.iter().enumerate() { let column_name = column_names[i]; - let column_info = row.columns()[i].type_(); - let value: Value = if column_info.is_null() { - Value::Null - } else { - match *column_type { - Type::INT2 => json!(row.get::<_, i16>(i)), - Type::INT4 => json!(row.get::<_, i32>(i)), - Type::INT8 => json!(row.get::<_, i64>(i)), - Type::FLOAT4 => json!(row.get::<_, f32>(i)), - Type::FLOAT8 => json!(row.get::<_, f64>(i)), - Type::BOOL => json!(row.get::<_, bool>(i)), - Type::VARCHAR | Type::TEXT | Type::BPCHAR => json!(row.get::<_, String>(i)), - Type::TIMESTAMP => { - let ts: NaiveDateTime = row.get(i); - json!(ts.to_string()) - } - Type::TIMESTAMPTZ => { - let ts: DateTime = row.get(i); - json!(ts.to_rfc3339()) - } - Type::DATE => { - let date: NaiveDate = row.get(i); - json!(date.to_string()) - } - Type::JSON | Type::JSONB => row.get::<_, Value>(i), - Type::UUID => { - let uuid: Uuid = row.get(i); - json!(uuid.to_string()) - } - _ => { - log::warn!("Unhandled column type: {:?}", column_type); - Value::Null - } + let value: Value = match *column_type { + Type::INT2 => get_json_option!(row, i, i16), + Type::INT4 => get_json_option!(row, i, i32), + Type::INT8 => get_json_option!(row, i, i64), + Type::FLOAT4 => get_json_option!(row, i, f32), + Type::FLOAT8 => get_json_option!(row, i, f64), + Type::BOOL => get_json_option!(row, i, bool), + Type::VARCHAR | Type::TEXT | Type::BPCHAR => get_json_option!(row, i, String), + Type::TIMESTAMP => { + let v: Option = row.try_get(i).unwrap_or(None); + v.map(|ts| json!(ts.to_string())).unwrap_or(Value::Null) + } + Type::TIMESTAMPTZ => { + let v: Option> = row.try_get(i).unwrap_or(None); + v.map(|ts| json!(ts.to_rfc3339())).unwrap_or(Value::Null) + } + Type::DATE => { + let v: Option = row.try_get(i).unwrap_or(None); + v.map(|date| json!(date.to_string())).unwrap_or(Value::Null) + } + Type::JSON | Type::JSONB => { + let v: Option = row.try_get(i).unwrap_or(None); + v.unwrap_or(Value::Null) + } + Type::UUID => { + let v: Option = row.try_get(i).unwrap_or(None); + v.map(|uuid| json!(uuid.to_string())).unwrap_or(Value::Null) + } + _ => { + log::warn!("Unhandled column type: {:?}", column_type); + Value::Null } }; map.insert(column_name.to_string(), value);