diff --git a/CHANGELOG.md b/CHANGELOG.md index 6764994..092ea70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 3.2.1 + +- Added or fixed decoders support for `QueryMode.simple`: + `double`, `real`, `timestampWithTimezone`, `timestampWithoutTimezone`, + `date`, `numeric`, `json`, `jsonb` [#338](https://github.com/isoos/postgresql-dart/pull/338) by [pst9354](https://github.com/pst9354). + ## 3.2.0 - Support for `tsvector` and `tsquery` types. diff --git a/lib/src/types/text_codec.dart b/lib/src/types/text_codec.dart index c6911d5..2d38740 100644 --- a/lib/src/types/text_codec.dart +++ b/lib/src/types/text_codec.dart @@ -240,7 +240,7 @@ class PostgresTextDecoder { return int.parse(di.asText); case TypeOid.real: case TypeOid.double: - return num.parse(di.asText); + return double.parse(di.asText); case TypeOid.boolean: // In text data format when using simple query protocol, "true" & "false" // are represented as `t` and `f`, respectively. @@ -255,12 +255,31 @@ class PostgresTextDecoder { case TypeOid.timestampWithTimezone: case TypeOid.timestampWithoutTimezone: - case TypeOid.interval: + final raw = DateTime.parse(di.asText); + return DateTime.utc( + raw.year, + raw.month, + raw.day, + raw.hour, + raw.minute, + raw.second, + raw.millisecond, + raw.microsecond, + ); + case TypeOid.numeric: - case TypeOid.byteArray: + return di.asText; + case TypeOid.date: + final raw = DateTime.parse(di.asText); + return DateTime.utc(raw.year, raw.month, raw.day); + case TypeOid.json: case TypeOid.jsonb: + return jsonDecode(di.asText); + + case TypeOid.interval: + case TypeOid.byteArray: case TypeOid.uuid: case TypeOid.point: case TypeOid.booleanArray: diff --git a/pubspec.yaml b/pubspec.yaml index 304bd71..922aab0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: postgres description: PostgreSQL database driver. Supports statement reuse and binary protocol and connection pooling. -version: 3.2.0 +version: 3.2.1 homepage: https://github.com/isoos/postgresql-dart topics: - sql diff --git a/test/decode_test.dart b/test/decode_test.dart index 8597523..1bcce74 100644 --- a/test/decode_test.dart +++ b/test/decode_test.dart @@ -4,6 +4,69 @@ import 'package:test/test.dart'; import 'docker.dart'; void main() { + withPostgresServer('simple query protocol decode', (server) { + late Connection conn; + setUp(() async { + conn = await server.newConnection(queryMode: QueryMode.simple); + }); + tearDown(() async { + await conn.close(); + }); + + test('double', () async { + final rs = await conn.execute('SELECT 3.14::DOUBLE PRECISION'); + expect(rs.single.single, 3.14); + }); + + test('timestamp with time zones', () async { + final rs = await conn.execute( + "SELECT '1999-01-08 04:05:06 -8:00'::TIMESTAMP WITH TIME ZONE"); + final item = rs.single.single as DateTime; + expect(item.toIso8601String(), '1999-01-08T12:05:06.000Z'); + }); + + test('timestamp without time zones', () async { + final rs = await conn + .execute("SELECT '1999-01-08 04:05:06'::TIMESTAMP WITHOUT TIME ZONE"); + final item = rs.single.single as DateTime; + expect(item.toIso8601String(), '1999-01-08T04:05:06.000Z'); + }); + + test('interval', () async { + final rs = await conn.execute( + "SELECT '2 years 15 months 100 weeks 99 hours 123456789 milliseconds'::INTERVAL"); + final item = rs.single.single; + expect((item as UndecodedBytes).asString, + '3 years 3 mons 700 days 133:17:36.789'); + // should be: + // expect(item, Interval(months: 39, days: 700, microseconds: 479856789000)); + }); + + test('numeric', () async { + final rs = await conn.execute('SELECT 3.141::NUMERIC(5,2)'); + final item = rs.single.single; + expect(item, '3.14'); + }); + + test('date', () async { + final rs = await conn.execute("SELECT '1999-01-08'::DATE"); + final item = rs.single.single as DateTime; + expect(item.toIso8601String(), '1999-01-08T00:00:00.000Z'); + }); + + test('json', () async { + final rs = await conn.execute("SELECT '{\"a\": 1}'::JSON"); + final item = rs.single.single; + expect(item, {'a': 1}); + }); + + test('jsonb', () async { + final rs = await conn.execute("SELECT '{\"a\": 1}'::JSONB"); + final item = rs.single.single; + expect(item, {'a': 1}); + }); + }); + withPostgresServer('decode', (server) { late Connection connection; setUp(() async { diff --git a/test/docker.dart b/test/docker.dart index d8b6373..6338fc6 100644 --- a/test/docker.dart +++ b/test/docker.dart @@ -62,6 +62,7 @@ class PostgresServer { Future newConnection({ ReplicationMode replicationMode = ReplicationMode.none, SslMode? sslMode, + QueryMode? queryMode, }) async { return Connection.open( await endpoint(), @@ -71,6 +72,7 @@ class PostgresServer { replicationMode: replicationMode, transformer: loggingTransformer('conn'), sslMode: sslMode, + queryMode: queryMode, ), ); }