@@ -7,11 +7,12 @@ use helper::bindings::{
77 } ,
88 wasi:: http0_2_0:: types:: { IncomingRequest , OutgoingResponse , ResponseOutparam } ,
99} ;
10+ use rust_decimal:: Decimal ;
1011
1112struct Component ;
1213helper:: gen_http_trigger_bindings!( Component ) ;
1314
14- // Format: "host=localhost port=5432 user=postgres password=my_password dbname=mydb "
15+ // Format: "host=localhost port=5432 user=postgres password=postgres dbname=spin_dev "
1516const PG_CONNECTION_STRING : & str = "PG_CONNECTION_STRING" ;
1617
1718impl bindings:: Guest for Component {
@@ -24,9 +25,7 @@ fn handle(request: IncomingRequest) -> anyhow::Result<OutgoingResponse> {
2425 let conn_str = get_header ( & request, PG_CONNECTION_STRING ) ?;
2526 let conn = Connection :: open ( & conn_str) ?;
2627
27- let rowset = numeric_types ( & conn) ?;
28- ensure ! ( rowset. rows. iter( ) . all( |r| r. len( ) == 12 ) ) ;
29- ensure ! ( matches!( rowset. rows[ 0 ] [ 11 ] , DbValue :: Floating64 ( f) if f == 1.0 ) ) ;
28+ test_numeric_types ( & conn) ?;
3029
3130 let rowset = character_types ( & conn) ?;
3231 ensure ! ( rowset. rows. iter( ) . all( |r| r. len( ) == 3 ) ) ;
@@ -82,38 +81,50 @@ fn handle(request: IncomingRequest) -> anyhow::Result<OutgoingResponse> {
8281 Ok ( helper:: ok_response ( ) )
8382}
8483
85- fn numeric_types ( conn : & Connection ) -> Result < RowSet , PgError > {
86- let create_table_sql = r#"
87- CREATE TEMPORARY TABLE test_numeric_types (
88- intid integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
89- rsmallserial smallserial NOT NULL,
90- rsmallint smallint NOT NULL,
91- rint2 int2 NOT NULL,
92- rserial serial NOT NULL,
93- rint int NOT NULL,
94- rint4 int4 NOT NULL,
95- rbigserial bigserial NOT NULL,
96- rbigint bigint NOT NULL,
97- rint8 int8 NOT NULL,
98- rreal real NOT NULL,
99- rdouble double precision NOT NULL
100- );
101- "# ;
102-
103- conn. execute ( create_table_sql, & [ ] ) ?;
84+ fn test_numeric_types ( conn : & Connection ) -> anyhow:: Result < ( ) > {
85+ const R_SMALLINT : i16 = 13 ;
86+ const R_INT2 : i16 = 14 ;
87+ const R_INT : i32 = 15 ;
88+ const R_INT4 : i32 = 16 ;
89+ const R_BIGINT : i64 = 17 ;
90+ const R_INT8 : i64 = 18 ;
91+ const R_REAL : f32 = 19.2 ;
92+ const R_DOUBLE : f64 = 20.3 ;
93+ const R_NUMERIC : & str = "123456789.123456789" ;
10494
105- let insert_sql = r#"
106- INSERT INTO test_numeric_types
107- (rsmallint, rint2, rint, rint4, rbigint, rint8, rreal, rdouble)
108- VALUES
109- (0, 0, 0, 0, 0, 0, 0, 1);
95+ let sql = r#"
96+ INSERT INTO test_numeric_types(
97+ id,
98+ rsmallint,
99+ rint2,
100+ rint,
101+ rint4,
102+ rbigint,
103+ rint8,
104+ rreal,
105+ rdouble,
106+ rnumeric
107+ ) VALUES (
108+ $1, $2, $3, $4, $5, $6, $7, $8, $9, $10
109+ );
110110 "# ;
111111
112- conn. execute ( insert_sql, & [ ] ) ?;
112+ conn. execute ( sql, & [
113+ ParameterValue :: Int32 ( 2 ) , // id used only for sorting
114+ ParameterValue :: Int16 ( R_SMALLINT ) ,
115+ ParameterValue :: Int16 ( R_INT2 ) ,
116+ ParameterValue :: Int32 ( R_INT ) ,
117+ ParameterValue :: Int32 ( R_INT4 ) ,
118+ ParameterValue :: Int64 ( R_BIGINT ) ,
119+ ParameterValue :: Int64 ( R_INT8 ) ,
120+ ParameterValue :: Floating32 ( R_REAL ) ,
121+ ParameterValue :: Floating64 ( R_DOUBLE ) ,
122+ ParameterValue :: Decimal ( R_NUMERIC . to_owned ( ) ) ,
123+ ] ) ?;
113124
114125 let sql = r#"
115126 SELECT
116- intid ,
127+ id ,
117128 rsmallserial,
118129 rsmallint,
119130 rint2,
@@ -124,11 +135,44 @@ fn numeric_types(conn: &Connection) -> Result<RowSet, PgError> {
124135 rbigint,
125136 rint8,
126137 rreal,
127- rdouble
128- FROM test_numeric_types;
138+ rdouble,
139+ rnumeric
140+ FROM test_numeric_types
141+ ORDER BY id;
129142 "# ;
130143
131- conn. query ( sql, & [ ] )
144+ let rowset = conn. query ( sql, & [ ] ) ?;
145+
146+ ensure ! ( rowset. rows. len( ) == 2 ) ;
147+ ensure ! ( rowset. rows. iter( ) . all( |r| r. len( ) == 13 ) ) ;
148+
149+ // Spin correctly decodes Postgres values
150+ ensure ! ( matches!( rowset. rows[ 0 ] [ 1 ] , DbValue :: Int16 ( _) ) ) ; // rsmallserial
151+ ensure ! ( matches!( rowset. rows[ 0 ] [ 2 ] , DbValue :: Int16 ( 1 ) ) ) ; // rsmallint
152+ ensure ! ( matches!( rowset. rows[ 0 ] [ 3 ] , DbValue :: Int16 ( 2 ) ) ) ; // rint2
153+ ensure ! ( matches!( rowset. rows[ 0 ] [ 4 ] , DbValue :: Int32 ( _) ) ) ; // rserial
154+ ensure ! ( matches!( rowset. rows[ 0 ] [ 5 ] , DbValue :: Int32 ( 3 ) ) ) ; // rint
155+ ensure ! ( matches!( rowset. rows[ 0 ] [ 6 ] , DbValue :: Int32 ( 4 ) ) ) ; // rint4
156+ ensure ! ( matches!( rowset. rows[ 0 ] [ 7 ] , DbValue :: Int64 ( _) ) ) ; // rbigserial
157+ ensure ! ( matches!( rowset. rows[ 0 ] [ 8 ] , DbValue :: Int64 ( 5 ) ) ) ; // rbigint
158+ ensure ! ( matches!( rowset. rows[ 0 ] [ 9 ] , DbValue :: Int64 ( 6 ) ) ) ; // rint8
159+ ensure ! ( matches!( rowset. rows[ 0 ] [ 10 ] , DbValue :: Floating32 ( 7.8 ) ) ) ; // rreal
160+ ensure ! ( matches!( rowset. rows[ 0 ] [ 11 ] , DbValue :: Floating64 ( 9.1 ) ) ) ; // rdouble
161+ ensure ! ( matches!( rowset. rows[ 0 ] [ 12 ] , DbValue :: Decimal ( ref d) if Decimal :: from_str_exact( d) ? == Decimal :: from_i128_with_scale( 123456789i128 , 9 ) ) ) ; // rnumeric
162+
163+ // Values inserted by Spin round-trip correctly
164+ // (we can omit the serials here as those are set by the database)
165+ ensure ! ( matches!( rowset. rows[ 1 ] [ 2 ] , DbValue :: Int16 ( R_SMALLINT ) ) ) ; // rsmallint
166+ ensure ! ( matches!( rowset. rows[ 1 ] [ 3 ] , DbValue :: Int16 ( R_INT2 ) ) ) ; // rint2
167+ ensure ! ( matches!( rowset. rows[ 1 ] [ 5 ] , DbValue :: Int32 ( R_INT ) ) ) ; // rint
168+ ensure ! ( matches!( rowset. rows[ 1 ] [ 6 ] , DbValue :: Int32 ( R_INT4 ) ) ) ; // rint4
169+ ensure ! ( matches!( rowset. rows[ 1 ] [ 8 ] , DbValue :: Int64 ( R_BIGINT ) ) ) ; // rbigint
170+ ensure ! ( matches!( rowset. rows[ 1 ] [ 9 ] , DbValue :: Int64 ( R_INT8 ) ) ) ; // rint8
171+ ensure ! ( matches!( rowset. rows[ 1 ] [ 10 ] , DbValue :: Floating32 ( R_REAL ) ) ) ; // rreal
172+ ensure ! ( matches!( rowset. rows[ 1 ] [ 11 ] , DbValue :: Floating64 ( R_DOUBLE ) ) ) ; // rdouble
173+ ensure ! ( matches!( rowset. rows[ 1 ] [ 12 ] , DbValue :: Decimal ( ref d) if Decimal :: from_str_exact( d) ? == Decimal :: from_i128_with_scale( 123456789123456789i128 , 9 ) ) ) ; // rnumeric
174+
175+ Ok ( ( ) )
132176}
133177
134178fn character_types ( conn : & Connection ) -> Result < RowSet , PgError > {
0 commit comments