Skip to content

Commit 8ed0724

Browse files
committed
more optimizations
1 parent e799526 commit 8ed0724

File tree

2 files changed

+70
-60
lines changed

2 files changed

+70
-60
lines changed

src/value_converter/dto/funcs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use postgres_types::Type;
44
pub fn array_type_to_single_type(array_type: &Type) -> Type {
55
match *array_type {
66
Type::BOOL_ARRAY => Type::BOOL,
7-
Type::UUID_ARRAY => Type::UUID_ARRAY,
7+
Type::UUID_ARRAY => Type::UUID,
88
Type::VARCHAR_ARRAY => Type::VARCHAR,
99
Type::TEXT_ARRAY => Type::TEXT,
1010
Type::INT2_ARRAY => Type::INT2,

src/value_converter/models/serde_value.rs

Lines changed: 69 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use postgres_types::FromSql;
33
use serde_json::{json, Map, Value};
44

55
use pyo3::{
6-
types::{PyAnyMethods, PyDict, PyDictMethods, PyList, PyTuple},
7-
Bound, FromPyObject, IntoPyObject, Py, PyAny, PyResult, Python,
6+
types::{PyAnyMethods, PyDict, PyDictMethods, PyList, PyListMethods},
7+
Bound, FromPyObject, IntoPyObject, PyAny, PyResult, Python,
88
};
99
use tokio_postgres::types::Type;
1010

@@ -37,7 +37,7 @@ impl<'py> IntoPyObject<'py> for InternalSerdeValue {
3737
type Error = RustPSQLDriverError;
3838

3939
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
40-
match build_python_from_serde_value(py, self.0.clone()) {
40+
match build_python_from_serde_value(py, self.0) {
4141
Ok(ok_value) => Ok(ok_value.bind(py).clone()),
4242
Err(err) => Err(err),
4343
}
@@ -57,25 +57,30 @@ impl<'a> FromSql<'a> for InternalSerdeValue {
5757
}
5858
}
5959

60-
fn serde_value_from_list(gil: Python<'_>, bind_value: &Bound<'_, PyAny>) -> PSQLPyResult<Value> {
61-
let mut result_vec: Vec<Value> = vec![];
60+
fn serde_value_from_list(_gil: Python<'_>, bind_value: &Bound<'_, PyAny>) -> PSQLPyResult<Value> {
61+
let py_list = bind_value.downcast::<PyList>().map_err(|e| {
62+
RustPSQLDriverError::PyToRustValueConversionError(format!(
63+
"Parameter must be a list, but it's not: {}",
64+
e
65+
))
66+
})?;
6267

63-
let params = bind_value.extract::<Vec<Py<PyAny>>>()?;
68+
let mut result_vec: Vec<Value> = Vec::with_capacity(py_list.len());
6469

65-
for inner in params {
66-
let inner_bind = inner.bind(gil);
67-
if inner_bind.is_instance_of::<PyDict>() {
68-
let python_dto = from_python_untyped(inner_bind)?;
70+
for item in py_list.iter() {
71+
if item.is_instance_of::<PyDict>() {
72+
let python_dto = from_python_untyped(&item)?;
6973
result_vec.push(python_dto.to_serde_value()?);
70-
} else if inner_bind.is_instance_of::<PyList>() {
71-
let serde_value = build_serde_value(inner.bind(gil))?;
74+
} else if item.is_instance_of::<PyList>() {
75+
let serde_value = build_serde_value(&item)?;
7276
result_vec.push(serde_value);
7377
} else {
7478
return Err(RustPSQLDriverError::PyToRustValueConversionError(
75-
"PyJSON must have dicts.".to_string(),
79+
"Items in JSON array must be dicts or lists.".to_string(),
7680
));
7781
}
7882
}
83+
7984
Ok(json!(result_vec))
8085
}
8186

@@ -86,19 +91,18 @@ fn serde_value_from_dict(bind_value: &Bound<'_, PyAny>) -> PSQLPyResult<Value> {
8691
))
8792
})?;
8893

89-
let mut serde_map: Map<String, Value> = Map::new();
94+
let dict_len = dict.len();
95+
let mut serde_map: Map<String, Value> = Map::with_capacity(dict_len);
9096

91-
for dict_item in dict.items() {
92-
let py_list = dict_item.downcast::<PyTuple>().map_err(|error| {
97+
for (key, value) in dict.iter() {
98+
let key_str = key.extract::<String>().map_err(|error| {
9399
RustPSQLDriverError::PyToRustValueConversionError(format!(
94-
"Cannot cast to list: {error}"
100+
"Cannot extract dict key as string: {error}"
95101
))
96102
})?;
97103

98-
let key = py_list.get_item(0)?.extract::<String>()?;
99-
let value = from_python_untyped(&py_list.get_item(1)?)?;
100-
101-
serde_map.insert(key, value.to_serde_value()?);
104+
let value_dto = from_python_untyped(&value)?;
105+
serde_map.insert(key_str, value_dto.to_serde_value()?);
102106
}
103107

104108
Ok(Value::Object(serde_map))
@@ -131,12 +135,10 @@ pub fn build_serde_value(value: &Bound<'_, PyAny>) -> PSQLPyResult<Value> {
131135
/// May return error if cannot create serde value.
132136
pub fn pythondto_array_to_serde(array: Option<Array<PythonDTO>>) -> PSQLPyResult<Value> {
133137
match array {
134-
Some(array) => inner_pythondto_array_to_serde(
135-
array.dimensions(),
136-
array.iter().collect::<Vec<&PythonDTO>>().as_slice(),
137-
0,
138-
0,
139-
),
138+
Some(array) => {
139+
let data: Vec<PythonDTO> = array.iter().cloned().collect();
140+
inner_pythondto_array_to_serde(array.dimensions(), &data, 0, 0)
141+
}
140142
None => Ok(Value::Null),
141143
}
142144
}
@@ -145,41 +147,49 @@ pub fn pythondto_array_to_serde(array: Option<Array<PythonDTO>>) -> PSQLPyResult
145147
#[allow(clippy::cast_sign_loss)]
146148
fn inner_pythondto_array_to_serde(
147149
dimensions: &[Dimension],
148-
data: &[&PythonDTO],
150+
data: &[PythonDTO],
149151
dimension_index: usize,
150-
mut lower_bound: usize,
152+
data_offset: usize,
151153
) -> PSQLPyResult<Value> {
152-
let current_dimension = dimensions.get(dimension_index);
153-
154-
if let Some(current_dimension) = current_dimension {
155-
let possible_next_dimension = dimensions.get(dimension_index + 1);
156-
match possible_next_dimension {
157-
Some(next_dimension) => {
158-
let mut final_list: Value = Value::Array(vec![]);
159-
160-
for _ in 0..current_dimension.len as usize {
161-
if dimensions.get(dimension_index + 1).is_some() {
162-
let inner_pylist = inner_pythondto_array_to_serde(
163-
dimensions,
164-
&data[lower_bound..next_dimension.len as usize + lower_bound],
165-
dimension_index + 1,
166-
0,
167-
)?;
168-
match final_list {
169-
Value::Array(ref mut array) => array.push(inner_pylist),
170-
_ => unreachable!(),
171-
}
172-
lower_bound += next_dimension.len as usize;
173-
}
174-
}
175-
176-
return Ok(final_list);
177-
}
178-
None => {
179-
return data.iter().map(|x| x.to_serde_value()).collect();
180-
}
154+
if dimension_index >= dimensions.len() || data_offset >= data.len() {
155+
return Ok(Value::Array(vec![]));
156+
}
157+
158+
let current_dimension = &dimensions[dimension_index];
159+
let current_len = current_dimension.len as usize;
160+
161+
if dimension_index + 1 >= dimensions.len() {
162+
let end_offset = (data_offset + current_len).min(data.len());
163+
let slice = &data[data_offset..end_offset];
164+
165+
let mut result_values = Vec::with_capacity(slice.len());
166+
for item in slice {
167+
result_values.push(item.to_serde_value()?);
181168
}
169+
170+
return Ok(Value::Array(result_values));
171+
}
172+
173+
let mut final_array = Vec::with_capacity(current_len);
174+
175+
let sub_array_size = dimensions[dimension_index + 1..]
176+
.iter()
177+
.map(|d| d.len as usize)
178+
.product::<usize>();
179+
180+
let mut current_offset = data_offset;
181+
182+
for _ in 0..current_len {
183+
if current_offset >= data.len() {
184+
break;
185+
}
186+
187+
let inner_value =
188+
inner_pythondto_array_to_serde(dimensions, data, dimension_index + 1, current_offset)?;
189+
190+
final_array.push(inner_value);
191+
current_offset += sub_array_size;
182192
}
183193

184-
Ok(Value::Array(vec![]))
194+
Ok(Value::Array(final_array))
185195
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy