From 90d2ec561bead7ddc66572a98cdceeff8e64d344 Mon Sep 17 00:00:00 2001 From: gmpassos Date: Sun, 29 Jun 2025 05:57:46 -0300 Subject: [PATCH 1/7] v3.5.7 - `PgSessionBase`: - Optimize `_prepare` by passing the already captured `StackTrace` to `_sendAndWaitForQuery`. --- CHANGELOG.md | 5 +++++ lib/src/v3/connection.dart | 21 +++++++++++++-------- pubspec.yaml | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25e702b..bd52870 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 3.5.7 + +- `PgSessionBase`: + - Optimize `_prepare` by passing the already captured `StackTrace` to `_sendAndWaitForQuery`. + ## 3.5.6 - Accept `null` values as part of the binary List encodings. diff --git a/lib/src/v3/connection.dart b/lib/src/v3/connection.dart index 3ea77fb..77877e6 100644 --- a/lib/src/v3/connection.dart +++ b/lib/src/v3/connection.dart @@ -83,8 +83,9 @@ abstract class _PgSessionBase implements Session { /// Sends a message to the server and waits for a response [T], gracefully /// handling error messages that might come in instead. - Future _sendAndWaitForQuery(ClientMessage send) { - final trace = StackTrace.current; + Future _sendAndWaitForQuery(ClientMessage send, + {StackTrace? stackTrace}) { + final trace = stackTrace ?? StackTrace.current; return _withResource(() { _connection._channel.sink @@ -184,7 +185,8 @@ abstract class _PgSessionBase implements Session { } Future<_PreparedStatement> _prepare(Object query) async { - final trace = Trace.current(); + final stackTrace = StackTrace.current; + final trace = Trace.from(stackTrace); final conn = _connection; final name = 's/${conn._statementCounter++}'; final description = InternalQueryDescription.wrap( @@ -192,11 +194,14 @@ abstract class _PgSessionBase implements Session { typeRegistry: _connection._settings.typeRegistry, ); - await _sendAndWaitForQuery(ParseMessage( - description.transformedSql, - statementName: name, - typeOids: description.parameterTypes?.map((e) => e?.oid).toList(), - )); + await _sendAndWaitForQuery( + ParseMessage( + description.transformedSql, + statementName: name, + typeOids: description.parameterTypes?.map((e) => e?.oid).toList(), + ), + stackTrace: stackTrace, + ); return _PreparedStatement(description, name, this, trace); } diff --git a/pubspec.yaml b/pubspec.yaml index 8559026..c7a91e1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: postgres description: PostgreSQL database driver. Supports binary protocol, connection pooling and statement reuse. -version: 3.5.6 +version: 3.5.7 homepage: https://github.com/isoos/postgresql-dart topics: - sql From 4ee8552626929c3feab6a91902e0157a58dc1ac5 Mon Sep 17 00:00:00 2001 From: gmpassos Date: Sun, 29 Jun 2025 06:31:33 -0300 Subject: [PATCH 2/7] - Added `ResultStreamTrace`: - A `ResultStream` that adds a `callerTrace` parameter to the `listen` method. --- lib/postgres.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/postgres.dart b/lib/postgres.dart index 77ee763..c3087a9 100644 --- a/lib/postgres.dart +++ b/lib/postgres.dart @@ -5,6 +5,7 @@ import 'dart:io'; import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; import 'package:postgres/src/v3/connection_info.dart'; +import 'package:stack_trace/stack_trace.dart'; import 'package:stream_channel/stream_channel.dart'; import 'src/replication.dart'; @@ -245,6 +246,18 @@ abstract class ResultStream implements Stream { }); } +/// A [ResultStream] that adds a `callerTrace` parameter to the `listen` method. +abstract class ResultStreamTrace implements ResultStream { + @override + ResultStreamSubscription listen( + void Function(ResultRow event)? onData, { + Function? onError, + void Function()? onDone, + bool? cancelOnError, + Trace? callerTrace, + }); +} + abstract class ResultStreamSubscription implements StreamSubscription { Future get affectedRows; From 51be5fe1d44b0a91b8d98c415080bf0fe1e35593 Mon Sep 17 00:00:00 2001 From: gmpassos Date: Sun, 29 Jun 2025 06:34:46 -0300 Subject: [PATCH 3/7] - `_BoundStatement` now implements `ResultStreamTrace` rather than `ResultStream`. - `_PgResultStreamSubscription`: added an optional `callerTrace` parameter to its constructors. --- lib/src/v3/connection.dart | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/src/v3/connection.dart b/lib/src/v3/connection.dart index 77877e6..ce4dadd 100644 --- a/lib/src/v3/connection.dart +++ b/lib/src/v3/connection.dart @@ -720,7 +720,7 @@ class _PreparedStatement extends Statement { } } -class _BoundStatement extends Stream implements ResultStream { +class _BoundStatement extends Stream implements ResultStreamTrace { final _PreparedStatement statement; final List parameters; @@ -728,13 +728,17 @@ class _BoundStatement extends Stream implements ResultStream { @override ResultStreamSubscription listen(void Function(ResultRow event)? onData, - {Function? onError, void Function()? onDone, bool? cancelOnError}) { + {Function? onError, + void Function()? onDone, + bool? cancelOnError, + Trace? callerTrace}) { final controller = StreamController(); // ignore: cancel_subscriptions final subscription = controller.stream.listen(onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError); - return _PgResultStreamSubscription(this, controller, subscription); + return _PgResultStreamSubscription(this, controller, subscription, + callerTrace: callerTrace); } } @@ -761,12 +765,13 @@ class _PgResultStreamSubscription final Trace _callerTrace; _PgResultStreamSubscription( - _BoundStatement statement, this._controller, this._source) + _BoundStatement statement, this._controller, this._source, + {Trace? callerTrace}) : session = statement.statement._session, ignoreRows = false, _boundStatement = statement, _parentTrace = statement.statement._trace, - _callerTrace = Trace.current() { + _callerTrace = callerTrace ?? Trace.current() { _scheduleStatement(() async { connection._pending = this; @@ -803,9 +808,10 @@ class _PgResultStreamSubscription this._controller, this._source, this.ignoreRows, { + Trace? callerTrace, void Function()? cleanup, }) : _parentTrace = null, - _callerTrace = Trace.current() { + _callerTrace = callerTrace ?? Trace.current() { _scheduleStatement(() async { connection._pending = this; From d919dd21e0d81fa85d352d51fa568514111b6c2e Mon Sep 17 00:00:00 2001 From: gmpassos Date: Sun, 29 Jun 2025 06:37:33 -0300 Subject: [PATCH 4/7] - `PreparedStatement`: - Optimized `run` and `_closePendingPortals` by reducing `StackTrace` captures. --- lib/src/v3/connection.dart | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/src/v3/connection.dart b/lib/src/v3/connection.dart index ce4dadd..6e85479 100644 --- a/lib/src/v3/connection.dart +++ b/lib/src/v3/connection.dart @@ -666,7 +666,7 @@ class _PreparedStatement extends Statement { _PreparedStatement(this._description, this._name, this._session, this._trace); @override - ResultStream bind(Object? parameters) { + ResultStreamTrace bind(Object? parameters) { return _BoundStatement( this, _description.bindParameters( @@ -680,10 +680,12 @@ class _PreparedStatement extends Statement { Object? parameters, { Duration? timeout, }) async { + final stackTrace = StackTrace.current; + final trace = Trace.from(stackTrace); _session._connection._queryCount++; timeout ??= _session._settings.queryTimeout; final items = []; - final subscription = bind(parameters).listen(items.add); + final subscription = bind(parameters).listen(items.add, callerTrace: trace); try { return await (subscription as _PgResultStreamSubscription)._waitForResult( items: items, @@ -691,7 +693,7 @@ class _PreparedStatement extends Statement { ); } finally { await subscription.cancel(); - await _closePendingPortals(); + await _closePendingPortals(stackTrace: stackTrace); } } @@ -710,12 +712,13 @@ class _PreparedStatement extends Statement { _portalsToClose!.add(portalName); } - Future _closePendingPortals() async { + Future _closePendingPortals({StackTrace? stackTrace}) async { final list = _portalsToClose; while (list != null && list.isNotEmpty) { final portalName = list.removeFirst(); await _session._sendAndWaitForQuery( - CloseMessage.portal(portalName)); + CloseMessage.portal(portalName), + stackTrace: stackTrace); } } } From fd7e4f15bae1fc194903f339e07b810414ca5a5e Mon Sep 17 00:00:00 2001 From: gmpassos Date: Sun, 29 Jun 2025 06:38:09 -0300 Subject: [PATCH 5/7] CHANGELOG.md --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd52870..cb60875 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ - `PgSessionBase`: - Optimize `_prepare` by passing the already captured `StackTrace` to `_sendAndWaitForQuery`. +- Added `ResultStreamTrace`: + - A `ResultStream` that adds a `callerTrace` parameter to the `listen` method. + +- `_BoundStatement` now implements `ResultStreamTrace` rather than `ResultStream`. + +- `_PgResultStreamSubscription`: added an optional `callerTrace` parameter to its constructors. + +- `PreparedStatement`: + - Optimized `run` and `_closePendingPortals` by reducing `StackTrace` captures. + ## 3.5.6 - Accept `null` values as part of the binary List encodings. From 0aed5c5252e9f86585199a90e9baf36b6295e28c Mon Sep 17 00:00:00 2001 From: gmpassos Date: Wed, 1 Oct 2025 23:42:47 -0300 Subject: [PATCH 6/7] dart format --- lib/src/v3/connection.dart | 57 ++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/lib/src/v3/connection.dart b/lib/src/v3/connection.dart index 13e3a2e..de06c23 100644 --- a/lib/src/v3/connection.dart +++ b/lib/src/v3/connection.dart @@ -86,8 +86,10 @@ abstract class _PgSessionBase implements Session { /// Sends a message to the server and waits for a response [T], gracefully /// handling error messages that might come in instead. - Future _sendAndWaitForQuery(ClientMessage send, - {StackTrace? stackTrace}) { + Future _sendAndWaitForQuery( + ClientMessage send, { + StackTrace? stackTrace, + }) { final trace = stackTrace ?? StackTrace.current; return _withResource(() { @@ -751,8 +753,9 @@ class _PreparedStatement extends Statement { while (list != null && list.isNotEmpty) { final portalName = list.removeFirst(); await _session._sendAndWaitForQuery( - CloseMessage.portal(portalName), - stackTrace: stackTrace); + CloseMessage.portal(portalName), + stackTrace: stackTrace, + ); } } } @@ -764,18 +767,28 @@ class _BoundStatement extends Stream implements ResultStreamTrace { _BoundStatement(this.statement, this.parameters); @override - ResultStreamSubscription listen(void Function(ResultRow event)? onData, - {Function? onError, - void Function()? onDone, - bool? cancelOnError, - Trace? callerTrace}) { + ResultStreamSubscription listen( + void Function(ResultRow event)? onData, { + Function? onError, + void Function()? onDone, + bool? cancelOnError, + Trace? callerTrace, + }) { final controller = StreamController(); // ignore: cancel_subscriptions - final subscription = controller.stream.listen(onData, - onError: onError, onDone: onDone, cancelOnError: cancelOnError); - return _PgResultStreamSubscription(this, controller, subscription, - callerTrace: callerTrace); + final subscription = controller.stream.listen( + onData, + onError: onError, + onDone: onDone, + cancelOnError: cancelOnError, + ); + return _PgResultStreamSubscription( + this, + controller, + subscription, + callerTrace: callerTrace, + ); } } @@ -802,13 +815,15 @@ class _PgResultStreamSubscription final Trace _callerTrace; _PgResultStreamSubscription( - _BoundStatement statement, this._controller, this._source, - {Trace? callerTrace}) - : session = statement.statement._session, - ignoreRows = false, - _boundStatement = statement, - _parentTrace = statement.statement._trace, - _callerTrace = callerTrace ?? Trace.current() { + _BoundStatement statement, + this._controller, + this._source, { + Trace? callerTrace, + }) : session = statement.statement._session, + ignoreRows = false, + _boundStatement = statement, + _parentTrace = statement.statement._trace, + _callerTrace = callerTrace ?? Trace.current() { _scheduleStatement(() async { connection._pending = this; @@ -850,7 +865,7 @@ class _PgResultStreamSubscription Trace? callerTrace, void Function()? cleanup, }) : _parentTrace = null, - _callerTrace = callerTrace ?? Trace.current() { + _callerTrace = callerTrace ?? Trace.current() { _scheduleStatement(() async { connection._pending = this; From bcc108aa4a906149472d8148797478a2a6dcf237 Mon Sep 17 00:00:00 2001 From: Istvan Soos Date: Fri, 3 Oct 2025 12:50:14 +0200 Subject: [PATCH 7/7] Reverted public API changes, simpler changelog entry, kept changes otherwise --- CHANGELOG.md | 16 +--------------- lib/postgres.dart | 13 ------------- lib/src/v3/connection.dart | 9 ++++++--- pubspec.yaml | 2 +- 4 files changed, 8 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b12b12..c87e644 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,10 @@ # Changelog -## 3.5.9 - -- `PgSessionBase`: - - Optimize `_prepare` by passing the already captured `StackTrace` to `_sendAndWaitForQuery`. - -- Added `ResultStreamTrace`: - - A `ResultStream` that adds a `callerTrace` parameter to the `listen` method. - -- `_BoundStatement` now implements `ResultStreamTrace` rather than `ResultStream`. - -- `_PgResultStreamSubscription`: added an optional `callerTrace` parameter to its constructors. - -- `PreparedStatement`: - - Optimized `run` and `_closePendingPortals` by reducing `StackTrace` captures. - ## 3.5.8 - Upgraded SDK constraints and lints. - Supporting more URL-based connection-string parameters (mostly for pool). +- Optimized `StackTrace` capture [#432](https://github.com/isoos/postgresql-dart/pull/432) by [gmpassos](https://github.com/gmpassos). ## 3.5.7. diff --git a/lib/postgres.dart b/lib/postgres.dart index e881da8..6c2d358 100644 --- a/lib/postgres.dart +++ b/lib/postgres.dart @@ -6,7 +6,6 @@ import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; import 'package:postgres/src/connection_string.dart'; import 'package:postgres/src/v3/connection_info.dart'; -import 'package:stack_trace/stack_trace.dart'; import 'package:stream_channel/stream_channel.dart'; import 'src/replication.dart'; @@ -270,18 +269,6 @@ abstract class ResultStream implements Stream { }); } -/// A [ResultStream] that adds a `callerTrace` parameter to the `listen` method. -abstract class ResultStreamTrace implements ResultStream { - @override - ResultStreamSubscription listen( - void Function(ResultRow event)? onData, { - Function? onError, - void Function()? onDone, - bool? cancelOnError, - Trace? callerTrace, - }); -} - abstract class ResultStreamSubscription implements StreamSubscription { Future get affectedRows; diff --git a/lib/src/v3/connection.dart b/lib/src/v3/connection.dart index de06c23..4d8e27c 100644 --- a/lib/src/v3/connection.dart +++ b/lib/src/v3/connection.dart @@ -703,7 +703,7 @@ class _PreparedStatement extends Statement { _PreparedStatement(this._description, this._name, this._session, this._trace); @override - ResultStreamTrace bind(Object? parameters) { + ResultStream bind(Object? parameters) { return _BoundStatement( this, _description.bindParameters( @@ -720,7 +720,10 @@ class _PreparedStatement extends Statement { _session._connection._queryCount++; timeout ??= _session._settings.queryTimeout; final items = []; - final subscription = bind(parameters).listen(items.add, callerTrace: trace); + final subscription = (bind(parameters) as _BoundStatement).listen( + items.add, + callerTrace: trace, + ); try { return await (subscription as _PgResultStreamSubscription)._waitForResult( items: items, @@ -760,7 +763,7 @@ class _PreparedStatement extends Statement { } } -class _BoundStatement extends Stream implements ResultStreamTrace { +class _BoundStatement extends Stream implements ResultStream { final _PreparedStatement statement; final List parameters; diff --git a/pubspec.yaml b/pubspec.yaml index 1b93c49..9944d01 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: postgres description: PostgreSQL database driver. Supports binary protocol, connection pooling and statement reuse. -version: 3.5.9 +version: 3.5.8 homepage: https://github.com/isoos/postgresql-dart topics: - sql