@@ -82,6 +82,7 @@ class PostgresBinaryEncoder extends Converter<dynamic, Uint8List?> {
82
82
}
83
83
case PostgreSQLDataType .name:
84
84
case PostgreSQLDataType .text:
85
+ case PostgreSQLDataType .varChar:
85
86
{
86
87
if (value is String ) {
87
88
return castBytes (utf8.encode (value));
@@ -144,7 +145,7 @@ class PostgresBinaryEncoder extends Converter<dynamic, Uint8List?> {
144
145
'Invalid type for parameter value. Expected: DateTime Got: ${value .runtimeType }' );
145
146
}
146
147
147
- case PostgreSQLDataType .json :
148
+ case PostgreSQLDataType .jsonb :
148
149
{
149
150
final jsonBytes = utf8.encode (json.encode (value));
150
151
final writer = ByteDataWriter (bufferLength: jsonBytes.length + 1 );
@@ -153,6 +154,9 @@ class PostgresBinaryEncoder extends Converter<dynamic, Uint8List?> {
153
154
return writer.toBytes ();
154
155
}
155
156
157
+ case PostgreSQLDataType .json:
158
+ return castBytes (utf8.encode (json.encode (value)));
159
+
156
160
case PostgreSQLDataType .byteArray:
157
161
{
158
162
if (value is List <int >) {
@@ -199,10 +203,90 @@ class PostgresBinaryEncoder extends Converter<dynamic, Uint8List?> {
199
203
}
200
204
return outBuffer;
201
205
}
206
+
207
+ case PostgreSQLDataType .point:
208
+ {
209
+ if (value is PgPoint ) {
210
+ final bd = ByteData (16 );
211
+ bd.setFloat64 (0 , value.latitude);
212
+ bd.setFloat64 (8 , value.longitude);
213
+ return bd.buffer.asUint8List ();
214
+ }
215
+ throw FormatException (
216
+ 'Invalid type for parameter value. Expected: PgPoint Got: ${value .runtimeType }' );
217
+ }
218
+
219
+ case PostgreSQLDataType .integerArray:
220
+ {
221
+ if (value is List <int >) {
222
+ return writeListBytes <int >(
223
+ value, 23 , (_) => 4 , (writer, item) => writer.writeInt32 (item));
224
+ }
225
+ throw FormatException (
226
+ 'Invalid type for parameter value. Expected: List<int> Got: ${value .runtimeType }' );
227
+ }
228
+
229
+ case PostgreSQLDataType .textArray:
230
+ {
231
+ if (value is List <String >) {
232
+ final bytesArray = value.map ((v) => utf8.encode (v));
233
+ return writeListBytes <List <int >>(bytesArray, 25 ,
234
+ (item) => item.length, (writer, item) => writer.write (item));
235
+ }
236
+ throw FormatException (
237
+ 'Invalid type for parameter value. Expected: List<String> Got: ${value .runtimeType }' );
238
+ }
239
+
240
+ case PostgreSQLDataType .doubleArray:
241
+ {
242
+ if (value is List <double >) {
243
+ return writeListBytes <double >(value, 701 , (_) => 8 ,
244
+ (writer, item) => writer.writeFloat64 (item));
245
+ }
246
+ throw FormatException (
247
+ 'Invalid type for parameter value. Expected: List<double> Got: ${value .runtimeType }' );
248
+ }
249
+
250
+ case PostgreSQLDataType .jsonbArray:
251
+ {
252
+ if (value is List <Object >) {
253
+ final objectsArray = value.map ((v) => utf8.encode (json.encode (v)));
254
+ return writeListBytes <List <int >>(
255
+ objectsArray, 3802 , (item) => item.length + 1 , (writer, item) {
256
+ writer.writeUint8 (1 );
257
+ writer.write (item);
258
+ });
259
+ }
260
+ throw FormatException (
261
+ 'Invalid type for parameter value. Expected: List<Object> Got: ${value .runtimeType }' );
262
+ }
263
+
202
264
default :
203
265
throw PostgreSQLException ('Unsupported datatype' );
204
266
}
205
267
}
268
+
269
+ Uint8List writeListBytes <T >(
270
+ Iterable <T > value,
271
+ int type,
272
+ int Function (T item) lengthEncoder,
273
+ void Function (ByteDataWriter writer, T item) valueEncoder) {
274
+ final writer = ByteDataWriter ();
275
+
276
+ writer.writeInt32 (1 ); // dimension
277
+ writer.writeInt32 (0 ); // ign
278
+ writer.writeInt32 (type); // type
279
+ writer.writeInt32 (value.length); // size
280
+ writer.writeInt32 (1 ); // index
281
+
282
+ for (var i in value) {
283
+ final len = lengthEncoder (i);
284
+ writer.writeInt32 (len);
285
+ valueEncoder (writer, i);
286
+ }
287
+
288
+ return writer.toBytes ();
289
+ }
206
290
}
207
291
208
292
class PostgresBinaryDecoder extends Converter <Uint8List , dynamic > {
@@ -224,6 +308,7 @@ class PostgresBinaryDecoder extends Converter<Uint8List, dynamic> {
224
308
switch (dataType) {
225
309
case PostgreSQLDataType .name:
226
310
case PostgreSQLDataType .text:
311
+ case PostgreSQLDataType .varChar:
227
312
return utf8.decode (value);
228
313
case PostgreSQLDataType .boolean:
229
314
return buffer.getInt8 (0 ) != 0 ;
@@ -247,14 +332,17 @@ class PostgresBinaryDecoder extends Converter<Uint8List, dynamic> {
247
332
case PostgreSQLDataType .date:
248
333
return DateTime .utc (2000 ).add (Duration (days: buffer.getInt32 (0 )));
249
334
250
- case PostgreSQLDataType .json :
335
+ case PostgreSQLDataType .jsonb :
251
336
{
252
337
// Removes version which is first character and currently always '1'
253
338
final bytes = value.buffer
254
339
.asUint8List (value.offsetInBytes + 1 , value.lengthInBytes - 1 );
255
340
return json.decode (utf8.decode (bytes));
256
341
}
257
342
343
+ case PostgreSQLDataType .json:
344
+ return json.decode (utf8.decode (value));
345
+
258
346
case PostgreSQLDataType .byteArray:
259
347
return value;
260
348
@@ -277,6 +365,29 @@ class PostgresBinaryDecoder extends Converter<Uint8List, dynamic> {
277
365
278
366
return buf.toString ();
279
367
}
368
+
369
+ case PostgreSQLDataType .point:
370
+ return PgPoint (buffer.getFloat64 (0 ), buffer.getFloat64 (8 ));
371
+
372
+ case PostgreSQLDataType .integerArray:
373
+ return readListBytes <int >(value, (reader, _) => reader.readInt32 ());
374
+
375
+ case PostgreSQLDataType .textArray:
376
+ return readListBytes <String >(value, (reader, length) {
377
+ return utf8.decode (length > 0 ? reader.read (length) : []);
378
+ });
379
+
380
+ case PostgreSQLDataType .doubleArray:
381
+ return readListBytes <double >(
382
+ value, (reader, _) => reader.readFloat64 ());
383
+
384
+ case PostgreSQLDataType .jsonbArray:
385
+ return readListBytes <dynamic >(value, (reader, length) {
386
+ reader.read (1 );
387
+ final bytes = reader.read (length - 1 );
388
+ return json.decode (utf8.decode (bytes));
389
+ });
390
+
280
391
default :
281
392
{
282
393
// We'll try and decode this as a utf8 string and return that
@@ -292,6 +403,28 @@ class PostgresBinaryDecoder extends Converter<Uint8List, dynamic> {
292
403
}
293
404
}
294
405
406
+ List <T > readListBytes <T >(Uint8List data,
407
+ T Function (ByteDataReader reader, int length) valueDecoder) {
408
+ if (data.length < 16 ) {
409
+ return [];
410
+ }
411
+
412
+ final reader = ByteDataReader ()..add (data);
413
+ reader.read (12 ); // header
414
+
415
+ final decoded = [].cast <T >();
416
+ final size = reader.readInt32 ();
417
+
418
+ reader.read (4 ); // index
419
+
420
+ for (var i = 0 ; i < size; i++ ) {
421
+ final len = reader.readInt32 ();
422
+ decoded.add (valueDecoder (reader, len));
423
+ }
424
+
425
+ return decoded;
426
+ }
427
+
295
428
static final Map <int , PostgreSQLDataType > typeMap = {
296
429
16 : PostgreSQLDataType .boolean,
297
430
17 : PostgreSQLDataType .byteArray,
@@ -300,12 +433,19 @@ class PostgresBinaryDecoder extends Converter<Uint8List, dynamic> {
300
433
21 : PostgreSQLDataType .smallInteger,
301
434
23 : PostgreSQLDataType .integer,
302
435
25 : PostgreSQLDataType .text,
436
+ 114 : PostgreSQLDataType .json,
437
+ 600 : PostgreSQLDataType .point,
303
438
700 : PostgreSQLDataType .real,
304
439
701 : PostgreSQLDataType .double ,
440
+ 1007 : PostgreSQLDataType .integerArray,
441
+ 1009 : PostgreSQLDataType .textArray,
442
+ 1043 : PostgreSQLDataType .varChar,
443
+ 1022 : PostgreSQLDataType .doubleArray,
305
444
1082 : PostgreSQLDataType .date,
306
445
1114 : PostgreSQLDataType .timestampWithoutTimezone,
307
446
1184 : PostgreSQLDataType .timestampWithTimezone,
308
447
2950 : PostgreSQLDataType .uuid,
309
- 3802 : PostgreSQLDataType .json,
448
+ 3802 : PostgreSQLDataType .jsonb,
449
+ 3807 : PostgreSQLDataType .jsonbArray,
310
450
};
311
451
}
0 commit comments