@@ -4,6 +4,7 @@ use std::sync::Arc;
44
55use async_stream:: stream;
66use futures:: Stream ;
7+ use pgwire:: api:: portal:: Format ;
78use pgwire:: api:: results:: { DataRowEncoder , FieldFormat , FieldInfo } ;
89use pgwire:: error:: { PgWireError , PgWireResult } ;
910use pgwire:: messages:: data:: DataRow ;
@@ -12,7 +13,7 @@ use trino_rust_client::models::{Column, QueryResultData};
1213use trino_rust_client:: { Client , Row } ;
1314
1415use crate :: session:: ActiveQueryId ;
15- use crate :: types:: { encode_value , trino_type_to_pg} ;
16+ use crate :: types:: { encode_cell , trino_type_to_pg} ;
1617
1718#[ derive( Clone ) ]
1819pub ( crate ) struct TrinoColumn {
@@ -29,17 +30,29 @@ impl From<&Column> for TrinoColumn {
2930 }
3031}
3132
32- pub ( crate ) fn build_pg_schema ( columns : & [ TrinoColumn ] ) -> Arc < Vec < FieldInfo > > {
33+ /// Build the PG `RowDescription` schema for a Trino result set.
34+ ///
35+ /// `result_format` is the per-column format the client bound for results;
36+ /// `None` means all-text (the simple-query protocol, which never negotiates
37+ /// binary). Each column's `FieldFormat` is taken from that request, so the
38+ /// schema drives both the advertised RowDescription and the per-cell encoding
39+ /// in `encode_row` — keeping them in lock-step.
40+ pub ( crate ) fn build_pg_schema (
41+ columns : & [ TrinoColumn ] ,
42+ result_format : Option < & Format > ,
43+ ) -> Arc < Vec < FieldInfo > > {
3344 Arc :: new (
3445 columns
3546 . iter ( )
36- . map ( |col| {
47+ . enumerate ( )
48+ . map ( |( idx, col) | {
49+ let format = result_format. map_or ( FieldFormat :: Text , |f| f. format_for ( idx) ) ;
3750 FieldInfo :: new (
3851 col. name . clone ( ) ,
3952 None ,
4053 None ,
4154 trino_type_to_pg ( & col. trino_type ) ,
42- FieldFormat :: Text ,
55+ format ,
4356 )
4457 } )
4558 . collect ( ) ,
@@ -52,8 +65,15 @@ pub(crate) fn encode_row(
5265 schema : & Arc < Vec < FieldInfo > > ,
5366) -> PgWireResult < DataRow > {
5467 let mut encoder = DataRowEncoder :: new ( schema. clone ( ) ) ;
55- for ( value, col) in values. iter ( ) . zip ( columns. iter ( ) ) {
56- encoder. encode_field ( & encode_value ( value, & col. trino_type ) ) ?;
68+ for ( idx, ( value, col) ) in values. iter ( ) . zip ( columns. iter ( ) ) . enumerate ( ) {
69+ let field = & schema[ idx] ;
70+ encode_cell (
71+ & mut encoder,
72+ value,
73+ field. datatype ( ) ,
74+ & col. trino_type ,
75+ field. format ( ) ,
76+ ) ?;
5777 }
5878 Ok ( encoder. take_row ( ) )
5979}
@@ -126,6 +146,7 @@ pub async fn execute_trino_query(
126146 client : & Arc < Client > ,
127147 sql : String ,
128148 active_query_id : Option < & ActiveQueryId > ,
149+ result_format : Option < & Format > ,
129150) -> Result <
130151 (
131152 Arc < Vec < FieldInfo > > ,
@@ -200,7 +221,7 @@ pub async fn execute_trino_query(
200221
201222 // Empty schema means DDL/DML; the caller returns Response::Execution
202223 // instead of Response::Query.
203- let schema = build_pg_schema ( & trino_columns) ;
224+ let schema = build_pg_schema ( & trino_columns, result_format ) ;
204225
205226 let stream_client = Arc :: clone ( client) ;
206227 let stream_columns = trino_columns. clone ( ) ;
@@ -298,7 +319,7 @@ mod tests {
298319 trino_type: "varchar" . to_owned( ) ,
299320 } ,
300321 ] ;
301- let schema = build_pg_schema ( & columns) ;
322+ let schema = build_pg_schema ( & columns, None ) ;
302323 assert_eq ! ( schema. len( ) , 2 ) ;
303324 assert_eq ! ( schema[ 0 ] . name( ) , "id" ) ;
304325 assert_eq ! ( * schema[ 0 ] . datatype( ) , Type :: INT4 ) ;
@@ -318,7 +339,7 @@ mod tests {
318339 trino_type: "varchar" . to_owned( ) ,
319340 } ,
320341 ] ;
321- let schema = build_pg_schema ( & columns) ;
342+ let schema = build_pg_schema ( & columns, None ) ;
322343 let values = vec ! [ json!( 42 ) , json!( "alice" ) ] ;
323344
324345 let row = encode_row ( & values, & columns, & schema) ;
@@ -331,7 +352,7 @@ mod tests {
331352 name: "val" . to_owned( ) ,
332353 trino_type: "varchar" . to_owned( ) ,
333354 } ] ;
334- let schema = build_pg_schema ( & columns) ;
355+ let schema = build_pg_schema ( & columns, None ) ;
335356 let values = vec ! [ Value :: Null ] ;
336357
337358 let row = encode_row ( & values, & columns, & schema) ;
0 commit comments