@@ -23,3 +23,187 @@ suite.testAsync('binary format mode parses integers correctly', async () => {
2323
2424 await client . end ( )
2525} )
26+
27+ const query = `SELECT
28+ -- Numeric types
29+ 1::smallint as smallint_val,
30+ 1000::int as int_val,
31+ 1000000::bigint as bigint_val,
32+ 3.14::real as real_val,
33+ 3.141592653589793::double precision as double_val,
34+ 123.45::numeric as numeric_val,
35+ 123.456789::decimal(10,6) as decimal_val,
36+
37+ -- Character types
38+ 'hello'::text as text_val,
39+ 'world'::varchar(50) as varchar_val,
40+ 'test'::char(10) as char_val,
41+ 'café'::text as unicode_val,
42+
43+ -- Boolean
44+ true::boolean as true_val,
45+ false::boolean as false_val,
46+
47+ -- Date/time types
48+ '2023-12-25'::date as date_val,
49+ '14:30:00'::time as time_val,
50+ '14:30:00+05:00'::timetz as timetz_val,
51+ '2023-12-25 14:30:00'::timestamp as timestamp_val,
52+ '2023-12-25 14:30:00+00:00'::timestamptz as timestamptz_val,
53+ '1 year 2 months 3 days'::interval as interval_val,
54+
55+ -- UUID
56+ '550e8400-e29b-41d4-a716-446655440000'::uuid as uuid_val,
57+
58+ -- Binary data
59+ '\\x48656c6c6f'::bytea as bytea_val,
60+
61+ -- JSON types
62+ '{"name": "John", "age": 30}'::json as json_val,
63+ '{"name": "Jane", "age": 25}'::jsonb as jsonb_val,
64+
65+ -- Arrays
66+ ARRAY[1,2,3]::int[] as int_array,
67+ ARRAY['a','b','c']::text[] as text_array,
68+ ARRAY[true,false,true]::boolean[] as bool_array,
69+ ARRAY[1.1,2.2,3.3]::real[] as real_array,
70+ ARRAY[10,20,30]::bigint[] as bigint_array,
71+ ARRAY[[1,2],[3,4]]::int[][] as multi_int_array,
72+ ARRAY[1,NULL,3]::int[] as int_array_with_nulls,
73+
74+ -- Network address types
75+ '192.168.1.1'::inet as inet_val,
76+ '192.168.1.0/24'::cidr as cidr_val,
77+ '08:00:2b:01:02:03'::macaddr as macaddr_val,
78+
79+ -- Geometric types
80+ '(1,2)'::point as point_val,
81+ '((0,0),(1,1))'::box as box_val,
82+ '<(0,0),1>'::circle as circle_val,
83+ '(0,0),(1,1)'::lseg as lseg_val,
84+ '((0,0),(1,0),(1,1),(0,1))'::polygon as polygon_val,
85+ '[(0,0),(1,1)]'::path as path_val,
86+
87+ -- Range types
88+ '[1,10)'::int4range as int_range,
89+ '[2023-01-01,2023-12-31]'::daterange as date_range,
90+ '(1.5,3.5]'::numrange as num_range,
91+
92+ -- NULL values
93+ NULL::int as null_int,
94+ NULL::text as null_text,
95+ NULL::int[] as null_array,
96+
97+ -- Edge cases
98+ 0::int as zero_int,
99+ (-2147483647-1)::int as min_int,
100+ 2147483647::int as max_int,
101+ ''::text as empty_text,
102+ ARRAY[]::int[] as empty_array
103+ `
104+ ; [ 'text' , 'binary' ] . forEach ( ( format ) => {
105+ suite . testAsync ( `${ format } format mode parses all types correctly` , async ( ) => {
106+ const client = new helper . pg . Client ( )
107+ await client . connect ( )
108+
109+ const result = await client . query ( {
110+ text : query ,
111+ binary : format === 'binary' ,
112+ } )
113+
114+ const offsetResult = await client . query (
115+ "SELECT EXTRACT(timezone_hour FROM '2023-12-25'::timestamptz)::integer as offset_hours"
116+ )
117+ const offsetHours = offsetResult . rows [ 0 ] . offset_hours
118+
119+ const row = result . rows [ 0 ]
120+
121+ // Numeric types
122+ assert . strictEqual ( row . smallint_val , 1 )
123+ assert . strictEqual ( row . int_val , 1000 )
124+ assert . strictEqual ( row . bigint_val , '1000000' )
125+ assert . strictEqual ( parseFloat ( row . real_val . toFixed ( 2 ) ) , 3.14 )
126+ assert . strictEqual ( row . double_val , 3.141592653589793 )
127+ assert . strictEqual ( row . numeric_val , '123.45' )
128+ assert . strictEqual ( row . decimal_val , '123.456789' )
129+
130+ // Character types
131+ assert . strictEqual ( row . text_val , 'hello' )
132+ assert . strictEqual ( row . varchar_val , 'world' )
133+ assert . strictEqual ( row . char_val , 'test ' ) // padded with spaces
134+ assert . strictEqual ( row . unicode_val , 'café' )
135+
136+ // Boolean
137+ assert . strictEqual ( row . true_val , true )
138+ assert . strictEqual ( row . false_val , false )
139+
140+ // Date/time types - both should be Date objects
141+ assert . strictEqual ( row . date_val . getUTCFullYear ( ) , 2023 )
142+ assert . strictEqual ( row . date_val . getUTCMonth ( ) , 11 ) // December
143+ assert . strictEqual ( row . date_val . getUTCDate ( ) , 25 )
144+ assert . strictEqual ( row . time_val , '14:30:00' )
145+ assert . strictEqual ( row . timetz_val , '14:30:00+05' )
146+ assert . strictEqual ( row . timestamp_val . getUTCFullYear ( ) , 2023 )
147+ assert . strictEqual ( row . timestamp_val . getUTCMonth ( ) , 11 )
148+ assert . strictEqual ( row . timestamp_val . getUTCDate ( ) , 25 )
149+ assert . strictEqual ( row . timestamp_val . getUTCHours ( ) + offsetHours , 14 )
150+ assert . strictEqual ( row . timestamp_val . getUTCMinutes ( ) , 30 )
151+ assert . strictEqual ( row . timestamptz_val . getTime ( ) , 1703514600000 )
152+ assert . deepEqual ( row . interval_val , { years : 1 , months : 2 , days : 3 } )
153+
154+ // UUID
155+ assert . strictEqual ( row . uuid_val , '550e8400-e29b-41d4-a716-446655440000' )
156+
157+ // Binary data
158+ assert ( Buffer . isBuffer ( row . bytea_val ) )
159+ assert . strictEqual ( row . bytea_val . toString ( ) , 'Hello' )
160+
161+ // JSON types
162+ assert . deepEqual ( row . json_val , { name : 'John' , age : 30 } )
163+ assert . deepEqual ( row . jsonb_val , { name : 'Jane' , age : 25 } )
164+
165+ // Arrays
166+ assert . deepEqual ( row . int_array , [ 1 , 2 , 3 ] )
167+ assert . deepEqual ( row . text_array , [ 'a' , 'b' , 'c' ] )
168+ assert . deepEqual ( row . bool_array , [ true , false , true ] )
169+ assert . deepEqual ( row . real_array , [ 1.1 , 2.2 , 3.3 ] )
170+ assert . deepEqual ( row . bigint_array , [ 10 , 20 , 30 ] )
171+ assert . deepEqual ( row . multi_int_array , [
172+ [ 1 , 2 ] ,
173+ [ 3 , 4 ] ,
174+ ] )
175+ assert . deepEqual ( row . int_array_with_nulls , [ 1 , null , 3 ] )
176+
177+ // Network address types
178+ assert . strictEqual ( row . inet_val , '192.168.1.1' )
179+ assert . strictEqual ( row . cidr_val , '192.168.1.0/24' )
180+ assert . strictEqual ( row . macaddr_val , '08:00:2b:01:02:03' )
181+
182+ // Geometric types
183+ assert . deepEqual ( row . point_val , { x : 1 , y : 2 } )
184+ assert . deepEqual ( row . box_val , '(1,1),(0,0)' )
185+ assert . deepEqual ( row . circle_val , { x : 0 , y : 0 , radius : 1 } )
186+ assert . deepEqual ( row . lseg_val , '[(0,0),(1,1)]' )
187+ assert . deepEqual ( row . polygon_val , '((0,0),(1,0),(1,1),(0,1))' )
188+ assert . deepEqual ( row . path_val , '[(0,0),(1,1)]' )
189+
190+ // Range types
191+ assert . deepEqual ( row . int_range , '[1,10)' )
192+ assert . deepEqual ( row . date_range , '[2023-01-01,2024-01-01)' )
193+ assert . deepEqual ( row . num_range , '(1.5,3.5]' )
194+
195+ // NULL values
196+ assert . strictEqual ( row . null_int , null )
197+ assert . strictEqual ( row . null_text , null )
198+ assert . strictEqual ( row . null_array , null )
199+
200+ // Edge cases
201+ assert . strictEqual ( row . zero_int , 0 )
202+ assert . strictEqual ( row . min_int , - 2147483648 )
203+ assert . strictEqual ( row . max_int , 2147483647 )
204+ assert . strictEqual ( row . empty_text , '' )
205+ assert . deepEqual ( row . empty_array , [ ] )
206+
207+ await client . end ( )
208+ } )
209+ } )
0 commit comments