Skip to content

Commit cf42d2d

Browse files
committed
Started adding expicit array types
Signed-off-by: chandr-andr (Kiselev Aleksandr) <chandr@chandr.net>
1 parent e7c0b58 commit cf42d2d

File tree

4 files changed

+99
-8
lines changed

4 files changed

+99
-8
lines changed

python/psqlpy/_internal/extra_types.pyi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,13 @@ class PyCircle:
251251
### Parameters:
252252
- `value`: any valid structure with int/float numbers.
253253
"""
254+
255+
256+
class BoolArray:
257+
"""Represent circle field in PostgreSQL and Circle in Rust."""
258+
259+
def __init__(
260+
self: Self,
261+
value: typing.Any,
262+
) -> None:
263+
"""Create new instance."""

python/psqlpy/extra_types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
PyText,
1919
PyVarChar,
2020
SmallInt,
21+
BoolArray,
2122
)
2223

2324
__all__ = [
@@ -40,4 +41,5 @@
4041
"PyLine",
4142
"PyLineSegment",
4243
"PyCircle",
44+
"BoolArray",
4345
]

src/extra_types.rs

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use std::str::FromStr;
1+
use std::{net::IpAddr, str::FromStr};
22

3+
use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime};
34
use geo_types::{Line as LineSegment, LineString, Point, Rect};
45
use macaddr::{MacAddr6, MacAddr8};
56
use pyo3::{
@@ -12,8 +13,13 @@ use serde_json::Value;
1213
use crate::{
1314
additional_types::{Circle, Line},
1415
exceptions::rust_errors::RustPSQLDriverPyResult,
15-
value_converter::{build_flat_geo_coords, build_geo_coords, build_serde_value},
16+
value_converter::{
17+
build_flat_geo_coords, build_geo_coords, build_serde_value, InternalSerdeValue,
18+
InternalUuid, PythonDTO,
19+
},
1620
};
21+
use pyo3::exceptions::PyStopIteration;
22+
use pyo3::prelude::*;
1723

1824
macro_rules! build_python_type {
1925
($st_name:ident, $rust_type:ty) => {
@@ -290,6 +296,67 @@ impl PyCircle {
290296
}
291297
}
292298

299+
macro_rules! build_array_type {
300+
($st_name:ident, $rust_type:ty, $single_rust_type:ty) => {
301+
#[pyclass(sequence)]
302+
#[derive(Clone)]
303+
pub struct $st_name {
304+
inner: $rust_type,
305+
index: usize,
306+
}
307+
308+
#[pymethods]
309+
impl $st_name {
310+
#[new]
311+
#[must_use]
312+
pub fn new_class(inner: $rust_type) -> Self {
313+
Self { inner, index: 0 }
314+
}
315+
316+
fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
317+
slf
318+
}
319+
320+
fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<$single_rust_type> {
321+
let index = slf.index;
322+
slf.index += 1;
323+
if let Some(element) = slf.inner.get(index) {
324+
return Some(*element);
325+
}
326+
None
327+
}
328+
}
329+
330+
impl $st_name {
331+
#[must_use]
332+
pub fn inner(&self) -> $rust_type {
333+
self.inner.clone()
334+
}
335+
}
336+
};
337+
}
338+
339+
build_array_type!(BoolArray, Vec<bool>, bool);
340+
// build_array_type!(BoolArray, Vec<bool>);
341+
// build_array_type!(UUIDArray, Vec<InternalUuid>);
342+
// build_array_type!(VarCharArray, Vec<String>);
343+
// build_array_type!(TextArray, Vec<String>);
344+
// build_array_type!(Int16Array, Vec<i16>);
345+
// build_array_type!(Int32Array, Vec<i32>);
346+
// build_array_type!(Int64Array, Vec<i64>);
347+
// build_array_type!(Flaot32Array, Vec<f32>);
348+
// build_array_type!(Flaot64Array, Vec<f64>);
349+
// build_array_type!(MoneyArray, Vec<i64>);
350+
// build_array_type!(IpAddressArray, Vec<IpAddr>);
351+
// build_array_type!(JSONBArray, Vec<InternalSerdeValue>);
352+
// build_array_type!(JSONArray, Vec<InternalSerdeValue>);
353+
// build_array_type!(DateArray, Vec<NaiveDate>);
354+
// build_array_type!(TimeArray, Vec<NaiveTime>);
355+
// build_array_type!(DateTimeArray, Vec<NaiveDateTime>);
356+
// build_array_type!(DateTimeTZArray, Vec<DateTime<FixedOffset>>);
357+
// build_array_type!(MacAddr6Array, Vec<PyMacAddr6>);
358+
// build_array_type!(MacAddr8Array, Vec<PyMacAddr8>);
359+
293360
#[allow(clippy::module_name_repetitions)]
294361
#[allow(clippy::missing_errors_doc)]
295362
pub fn extra_types_module(_py: Python<'_>, pymod: &Bound<'_, PyModule>) -> PyResult<()> {
@@ -312,5 +379,7 @@ pub fn extra_types_module(_py: Python<'_>, pymod: &Bound<'_, PyModule>) -> PyRes
312379
pymod.add_class::<PyLine>()?;
313380
pymod.add_class::<PyLineSegment>()?;
314381
pymod.add_class::<PyCircle>()?;
382+
383+
pymod.add_class::<BoolArray>()?;
315384
Ok(())
316385
}

src/value_converter.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ use pyo3::{
1414
sync::GILOnceCell,
1515
types::{
1616
PyAnyMethods, PyBool, PyBytes, PyDate, PyDateTime, PyDict, PyDictMethods, PyFloat, PyInt,
17-
PyList, PyListMethods, PySequence, PySet, PyString, PyTime, PyTuple, PyType, PyTypeMethods,
17+
PyIterator, PyList, PyListMethods, PySequence, PySet, PyString, PyTime, PyTuple, PyType,
18+
PyTypeMethods,
1819
},
19-
Bound, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject,
20+
Bound, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject,
2021
};
2122
use tokio_postgres::{
2223
types::{to_sql_checked, Type},
@@ -30,8 +31,8 @@ use crate::{
3031
},
3132
exceptions::rust_errors::{RustPSQLDriverError, RustPSQLDriverPyResult},
3233
extra_types::{
33-
BigInt, Float32, Float64, Integer, Money, PyBox, PyCircle, PyCustomType, PyJSON, PyJSONB,
34-
PyLine, PyLineSegment, PyMacAddr6, PyMacAddr8, PyPath, PyPoint, PyText, PyVarChar,
34+
BigInt, BoolArray, Float32, Float64, Integer, Money, PyBox, PyCircle, PyCustomType, PyJSON,
35+
PyJSONB, PyLine, PyLineSegment, PyMacAddr6, PyMacAddr8, PyPath, PyPoint, PyText, PyVarChar,
3536
SmallInt,
3637
},
3738
};
@@ -57,7 +58,10 @@ fn get_decimal_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> {
5758
///
5859
/// We use custom struct because we need to implement external traits
5960
/// to it.
60-
struct InternalUuid(Uuid);
61+
#[derive(Clone)]
62+
pub struct InternalUuid(Uuid);
63+
64+
impl<'a> FromPyObject<'a> for InternalUuid {}
6165

6266
impl ToPyObject for InternalUuid {
6367
fn to_object(&self, py: Python<'_>) -> PyObject {
@@ -82,7 +86,10 @@ impl<'a> FromSql<'a> for InternalUuid {
8286
///
8387
/// We use custom struct because we need to implement external traits
8488
/// to it.
85-
struct InternalSerdeValue(Value);
89+
#[derive(Clone)]
90+
pub struct InternalSerdeValue(Value);
91+
92+
impl<'a> FromPyObject<'a> for InternalSerdeValue {}
8693

8794
impl ToPyObject for InternalSerdeValue {
8895
fn to_object(&self, py: Python<'_>) -> PyObject {
@@ -786,6 +793,9 @@ pub fn py_to_rust(parameter: &pyo3::Bound<'_, PyAny>) -> RustPSQLDriverPyResult<
786793
}
787794
}
788795

796+
let a = parameter.downcast::<PyIterator>();
797+
println!("{:?}", a.iter());
798+
789799
Err(RustPSQLDriverError::PyToRustValueConversionError(format!(
790800
"Can not covert you type {parameter} into inner one",
791801
)))

0 commit comments

Comments
 (0)