11use chrono:: { self , DateTime , FixedOffset , NaiveDate , NaiveDateTime , NaiveTime } ;
2+ use geo_types:: Point ;
23use macaddr:: { MacAddr6 , MacAddr8 } ;
34use postgres_types:: { Field , FromSql , Kind } ;
45use serde_json:: { json, Map , Value } ;
@@ -9,8 +10,8 @@ use bytes::{BufMut, BytesMut};
910use postgres_protocol:: types;
1011use pyo3:: {
1112 types:: {
12- PyAnyMethods , PyBool , PyBytes , PyDate , PyDateTime , PyDict , PyDictMethods , PyFloat , PyInt ,
13- PyList , PyListMethods , PyString , PyTime , PyTuple ,
13+ PyAnyMethods , PyBool , PyBytes , PyDate , PyDateTime , PyDict , PyDictMethods ,
14+ PyFloat , PyInt , PyList , PyListMethods , PySet , PyString , PyTime , PyTuple
1415 } ,
1516 Bound , Py , PyAny , Python , ToPyObject ,
1617} ;
@@ -23,8 +24,8 @@ use crate::{
2324 additional_types:: { RustMacAddr6 , RustMacAddr8 } ,
2425 exceptions:: rust_errors:: { RustPSQLDriverError , RustPSQLDriverPyResult } ,
2526 extra_types:: {
26- BigInt , Integer , PyJSON , PyJSONB , PyMacAddr6 , PyMacAddr8 , PyText , PyUUID , PyVarChar ,
27- SmallInt ,
27+ BigInt , Integer , PyJSON , PyJSONB , PyMacAddr6 , PyMacAddr8 , PyText , PyUUID ,
28+ PyVarChar , SmallInt ,
2829 } ,
2930} ;
3031
@@ -133,6 +134,37 @@ impl PythonDTO {
133134 ) ) ,
134135 }
135136 }
137+
138+ /// Get value from DTO
139+ ///
140+ /// # Errors
141+ /// May return Err Result if cannot convert python type into rust.
142+ pub fn get_value ( & self ) -> RustPSQLDriverPyResult < Value > {
143+ match self {
144+ PythonDTO :: PyNone => Ok ( Value :: Null ) ,
145+ PythonDTO :: PyBool ( pybool) => Ok ( json ! ( pybool) ) ,
146+ PythonDTO :: PyString ( pystring)
147+ | PythonDTO :: PyText ( pystring)
148+ | PythonDTO :: PyVarChar ( pystring) => Ok ( json ! ( pystring) ) ,
149+ PythonDTO :: PyIntI32 ( pyint) => Ok ( json ! ( pyint) ) ,
150+ PythonDTO :: PyIntI64 ( pyint) => Ok ( json ! ( pyint) ) ,
151+ PythonDTO :: PyIntU64 ( pyint) => Ok ( json ! ( pyint) ) ,
152+ PythonDTO :: PyFloat64 ( pyfloat) => Ok ( json ! ( pyfloat) ) ,
153+ PythonDTO :: PyList ( pylist) => {
154+ let mut vec_serde_values: Vec < Value > = vec ! [ ] ;
155+
156+ for py_object in pylist {
157+ vec_serde_values. push ( py_object. to_serde_value ( ) ?) ;
158+ }
159+
160+ Ok ( json ! ( vec_serde_values) )
161+ }
162+ PythonDTO :: PyJsonb ( py_dict) | PythonDTO :: PyJson ( py_dict) => Ok ( py_dict. clone ( ) ) ,
163+ _ => Err ( RustPSQLDriverError :: PyToRustValueConversionError (
164+ "Cannot convert your type into Rust type" . into ( ) ,
165+ ) ) ,
166+ }
167+ }
136168}
137169
138170/// Implement `ToSql` trait.
@@ -819,35 +851,38 @@ pub fn build_python_from_serde_value(
819851 }
820852}
821853
822- pub fn box_from_sql ( mut buf : & [ u8 ] ) -> Result < Box , StdBox < dyn Error + Sync + Send > > {
823- let x1 = buf. read_f64 :: < BigEndian > ( ) ?;
824- let y1 = buf. read_f64 :: < BigEndian > ( ) ?;
825- let x2 = buf. read_f64 :: < BigEndian > ( ) ?;
826- let y2 = buf. read_f64 :: < BigEndian > ( ) ?;
827- if !buf. is_empty ( ) {
828- return Err ( "invalid buffer size" . into ( ) ) ;
829- }
830- let num_fields = postgres_types:: private:: read_be_i32 ( & mut buf) . map_err ( |err| {
831- RustPSQLDriverError :: RustToPyValueConversionError ( format ! (
832- "Cannot read bytes data from PostgreSQL: {err}"
833- ) )
834- } ) ?;
835- Ok ( Box {
836- upper_right : Point { x : x1, y : y1 } ,
837- lower_left : Point { x : x2, y : y2 } ,
838- } )
839- }
854+ /// Convert python List or Tuple into geo `Point`.
855+ ///
856+ /// # Errors
857+ /// May return error if cannot convert Python type into Rust one.
858+ #[ allow( clippy:: needless_pass_by_value) ]
859+ pub fn build_point ( value : Py < PyAny > ) -> RustPSQLDriverPyResult < Point > {
860+ Python :: with_gil ( |gil| {
861+ let bind_value = value. bind ( gil) ;
862+ if bind_value. is_instance_of :: < PyList > ( )
863+ | bind_value. is_instance_of :: < PyTuple > ( )
864+ | bind_value. is_instance_of :: < PySet > ( )
865+ {
866+ let mut result_vec = vec ! [ ] ;
867+ let params = bind_value. extract :: < Vec < Py < PyAny > > > ( ) ?;
840868
841- pub fn box_from_sql ( mut buf : & [ u8 ] ) -> Result < Box , StdBox < dyn Error + Sync + Send > > {
842- let x1 = buf. read_f64 :: < BigEndian > ( ) ?;
843- let y1 = buf. read_f64 :: < BigEndian > ( ) ?;
844- let x2 = buf. read_f64 :: < BigEndian > ( ) ?;
845- let y2 = buf. read_f64 :: < BigEndian > ( ) ?;
846- if !buf. is_empty ( ) {
847- return Err ( "invalid buffer size" . into ( ) ) ;
848- }
849- Ok ( Box {
850- upper_right : Point { x : x1, y : y1 } ,
851- lower_left : Point { x : x2, y : y2 } ,
869+ for inner in params {
870+ let inner_bind = inner. bind ( gil) ;
871+ if inner_bind. is_instance_of :: < PyFloat > ( ) | inner_bind. is_instance_of :: < PyInt > ( ) {
872+ let python_dto = py_to_rust ( inner_bind) ?;
873+ let mut bu = BytesMut :: with_capacity ( 64 ) ;
874+ python_dto. to_sql ( postgres_types:: , & mut bu)
875+ } else {
876+ return Err ( RustPSQLDriverError :: PyToRustValueConversionError (
877+ "PyJSON supports only list/tuple/set of two int or two float." . to_string ( ) ,
878+ ) ) ;
879+ }
880+ }
881+ Ok ( point ! ( result_vec) )
882+ } else {
883+ return Err ( RustPSQLDriverError :: PyToRustValueConversionError (
884+ "PyPoint must have two int or float values passed in tuple, list or set." . to_string ( ) ,
885+ ) ) ;
886+ }
852887 } )
853- }
888+ }
0 commit comments