Skip to content

Commit 8cc74de

Browse files
committed
more optimizations
1 parent 20247b5 commit 8cc74de

File tree

2 files changed

+56
-50
lines changed

2 files changed

+56
-50
lines changed

src/driver/common.rs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,13 @@ macro_rules! impl_config_py_methods {
7777
#[cfg(not(unix))]
7878
#[getter]
7979
fn hosts(&self) -> Vec<String> {
80-
let mut hosts_vec = vec![];
81-
82-
let hosts = self.pg_config.get_hosts();
83-
for host in hosts {
84-
match host {
85-
Host::Tcp(host) => {
86-
hosts_vec.push(host.to_string());
87-
}
88-
_ => unreachable!(),
89-
}
90-
}
91-
92-
hosts_vec
80+
self.pg_config
81+
.get_hosts()
82+
.iter()
83+
.map(|host| match host {
84+
Host::Tcp(host) => host.to_string(),
85+
})
86+
.collect()
9387
}
9488

9589
#[getter]

src/value_converter/to_python.rs

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,9 @@ fn postgres_array_to_py<'py, T: IntoPyObject<'py> + Clone>(
9595
array: Option<Array<T>>,
9696
) -> Option<Py<PyList>> {
9797
array.map(|array| {
98-
inner_postgres_array_to_py(
99-
py,
100-
array.dimensions(),
101-
array.iter().cloned().collect::<Vec<T>>(),
102-
0,
103-
0,
104-
)
98+
// Collect data once instead of creating copies in recursion
99+
let data: Vec<T> = array.iter().cloned().collect();
100+
inner_postgres_array_to_py(py, array.dimensions(), &data, 0, 0)
105101
})
106102
}
107103

@@ -110,44 +106,60 @@ fn postgres_array_to_py<'py, T: IntoPyObject<'py> + Clone>(
110106
fn inner_postgres_array_to_py<'py, T>(
111107
py: Python<'py>,
112108
dimensions: &[Dimension],
113-
data: Vec<T>,
109+
data: &[T],
114110
dimension_index: usize,
115-
mut lower_bound: usize,
111+
data_offset: usize,
116112
) -> Py<PyList>
117113
where
118114
T: IntoPyObject<'py> + Clone,
119115
{
120-
let current_dimension = dimensions.get(dimension_index);
121-
122-
if let Some(current_dimension) = current_dimension {
123-
let possible_next_dimension = dimensions.get(dimension_index + 1);
124-
match possible_next_dimension {
125-
Some(next_dimension) => {
126-
let final_list = PyList::empty(py);
127-
128-
for _ in 0..current_dimension.len as usize {
129-
if dimensions.get(dimension_index + 1).is_some() {
130-
let inner_pylist = inner_postgres_array_to_py(
131-
py,
132-
dimensions,
133-
data[lower_bound..next_dimension.len as usize + lower_bound].to_vec(),
134-
dimension_index + 1,
135-
0,
136-
);
137-
final_list.append(inner_pylist).unwrap();
138-
lower_bound += next_dimension.len as usize;
139-
}
140-
}
141-
142-
return final_list.unbind();
143-
}
144-
None => {
145-
return PyList::new(py, data).unwrap().unbind(); // TODO unwrap is unsafe
146-
}
116+
// Check bounds early
117+
if dimension_index >= dimensions.len() || data_offset >= data.len() {
118+
return PyList::empty(py).unbind();
119+
}
120+
121+
let current_dimension = &dimensions[dimension_index];
122+
let current_len = current_dimension.len as usize;
123+
124+
// If this is the last dimension, create a list with the actual data
125+
if dimension_index + 1 >= dimensions.len() {
126+
let end_offset = (data_offset + current_len).min(data.len());
127+
let slice = &data[data_offset..end_offset];
128+
129+
// Create Python list more efficiently
130+
return match PyList::new(py, slice.iter().cloned()) {
131+
Ok(list) => list.unbind(),
132+
Err(_) => PyList::empty(py).unbind(),
133+
};
134+
}
135+
136+
// For multi-dimensional arrays, recursively create nested lists
137+
let final_list = PyList::empty(py);
138+
139+
// Calculate the size of each sub-array
140+
let sub_array_size = dimensions[dimension_index + 1..]
141+
.iter()
142+
.map(|d| d.len as usize)
143+
.product::<usize>();
144+
145+
let mut current_offset = data_offset;
146+
147+
for _ in 0..current_len {
148+
if current_offset >= data.len() {
149+
break;
147150
}
151+
152+
let inner_list =
153+
inner_postgres_array_to_py(py, dimensions, data, dimension_index + 1, current_offset);
154+
155+
if final_list.append(inner_list).is_err() {
156+
break;
157+
}
158+
159+
current_offset += sub_array_size;
148160
}
149161

150-
PyList::empty(py).unbind()
162+
final_list.unbind()
151163
}
152164

153165
#[allow(clippy::too_many_lines)]

0 commit comments

Comments
 (0)