@@ -103,8 +103,6 @@ impl postgres::Host for OutboundPg {
103103 }
104104}
105105
106- const DB_NULL : Option < i32 > = None ;
107-
108106fn to_sql_parameter ( value : & ParameterValue ) -> anyhow:: Result < & ( dyn ToSql + Sync ) > {
109107 match value {
110108 ParameterValue :: Boolean ( v) => Ok ( v) ,
@@ -120,7 +118,7 @@ fn to_sql_parameter(value: &ParameterValue) -> anyhow::Result<&(dyn ToSql + Sync
120118 | ParameterValue :: Uint64 ( _) => Err ( anyhow ! ( "Postgres does not support unsigned integers" ) ) ,
121119 ParameterValue :: Str ( v) => Ok ( v) ,
122120 ParameterValue :: Binary ( v) => Ok ( v) ,
123- ParameterValue :: DbNull => Ok ( & DB_NULL ) ,
121+ ParameterValue :: DbNull => Ok ( & PgNull ) ,
124122 }
125123}
126124
@@ -285,3 +283,45 @@ where
285283 }
286284 } ) ;
287285}
286+
287+ /// Although the Postgres crate converts Rust Option::None to Postgres NULL,
288+ /// it enforces the type of the Option as it does so. (For example, trying to
289+ /// pass an Option::<i32>::None to a VARCHAR column fails conversion.) As we
290+ /// do not know expected column types, we instead use a "neutral" custom type
291+ /// which allows conversion to any type but always tells the Postgres crate to
292+ /// treat it as a SQL NULL.
293+ struct PgNull ;
294+
295+ impl ToSql for PgNull {
296+ fn to_sql (
297+ & self ,
298+ _ty : & Type ,
299+ _out : & mut tokio_postgres:: types:: private:: BytesMut ,
300+ ) -> Result < tokio_postgres:: types:: IsNull , Box < dyn std:: error:: Error + Sync + Send > >
301+ where
302+ Self : Sized ,
303+ {
304+ Ok ( tokio_postgres:: types:: IsNull :: Yes )
305+ }
306+
307+ fn accepts ( _ty : & Type ) -> bool
308+ where
309+ Self : Sized ,
310+ {
311+ true
312+ }
313+
314+ fn to_sql_checked (
315+ & self ,
316+ _ty : & Type ,
317+ _out : & mut tokio_postgres:: types:: private:: BytesMut ,
318+ ) -> Result < tokio_postgres:: types:: IsNull , Box < dyn std:: error:: Error + Sync + Send > > {
319+ Ok ( tokio_postgres:: types:: IsNull :: Yes )
320+ }
321+ }
322+
323+ impl std:: fmt:: Debug for PgNull {
324+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
325+ f. debug_struct ( "NULL" ) . finish ( )
326+ }
327+ }
0 commit comments