Skip to content

Commit

Permalink
RuntimeParameters (#352)
Browse files Browse the repository at this point in the history
  • Loading branch information
isoos authored Aug 29, 2024
1 parent 4c5dba4 commit bea7a6e
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- (internal) using `EncodedValue` instead of `EncodeOutput`
- `TypeCodec` interface (may become public) is used for encoding/decoding value by OIDs.
- `TypeEncoderFn` type definition for generic Dart -> Postgres object encoders (where type is not specified as parameter).
- `RuntimeParameters` (accessible through `TypeCodecContext`) to access server-provided parameter status values.

## 3.3.0

Expand Down
38 changes: 38 additions & 0 deletions lib/src/types/type_codec.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:typed_data';

Expand Down Expand Up @@ -47,12 +48,49 @@ abstract class TypeCodec {
FutureOr<Object?> decode(TypeCodecContext context, EncodedValue input);
}

/// The read-only, passive view of the Postgresql's runtime/session parameters.
///
/// Postgresql server reports certain parameter values at opening a connection
/// or whenever their values change. Such parameters may include:
/// - `application_name`
/// - `server_version`
/// - `server_encoding`
/// - `client_encoding`
/// - `is_superuser`
/// - `session_authorization`
/// - `DateStyle`
/// - `TimeZone`
/// - `integer_datetimes`
///
/// This class holds the latest parameter values send by the server.
/// The values are not queried or updated actively.
///
/// The available parameters may be discovered following the instructions on these URLs:
/// - https://www.postgresql.org/docs/current/sql-show.html
/// - https://www.postgresql.org/docs/current/runtime-config.html
/// - https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQPARAMETERSTATUS
class RuntimeParameters {
/// The latest values of the runtime parameters.
///
/// The backing map may be behind an [UnmodifiableMapView], clients may not
/// update these values directly.
final Map<String, String> latestValues;

RuntimeParameters({
required this.latestValues,
});

String? get applicationName => latestValues['application_name'];
}

class TypeCodecContext {
final Encoding encoding;
final RuntimeParameters runtimeParameters;
final TypeRegistry typeRegistry;

TypeCodecContext({
required this.encoding,
required this.runtimeParameters,
required this.typeRegistry,
});

Expand Down
22 changes: 14 additions & 8 deletions lib/src/v3/connection.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
Expand Down Expand Up @@ -343,6 +344,9 @@ class PgConnectionImplementation extends _PgSessionBase implements Connection {
_TransactionSession? _activeTransaction;

final _parameters = <String, String>{};
@internal
late final runtimeParameters =
RuntimeParameters(latestValues: UnmodifiableMapView(_parameters));

var _statementCounter = 0;
var _portalCounter = 0;
Expand Down Expand Up @@ -533,6 +537,14 @@ class PgConnectionImplementation extends _PgSessionBase implements Connection {
void _closeAfterError([PgException? cause]) {
_close(true, cause);
}

TypeCodecContext createTypeCodecContext() {
return TypeCodecContext(
encoding: encoding,
runtimeParameters: runtimeParameters,
typeRegistry: _settings.typeRegistry,
);
}
}

class _PreparedStatement extends Statement {
Expand Down Expand Up @@ -631,10 +643,7 @@ class _PgResultStreamSubscription
connection._pending = this;

final encodedFutures = <Future<EncodedValue?>>[];
final context = TypeCodecContext(
encoding: connection.encoding,
typeRegistry: connection._settings.typeRegistry,
);
final context = connection.createTypeCodecContext();
for (final e in statement.parameters) {
if (e.isSqlNull) {
encodedFutures.add(Future.value(null));
Expand Down Expand Up @@ -755,10 +764,7 @@ class _PgResultStreamSubscription
final columnCount = message.values.length;
final futures = <Future>[];
List<bool>? sqlNulls;
final context = TypeCodecContext(
encoding: session.encoding,
typeRegistry: session._connection._settings.typeRegistry,
);
final context = session._connection.createTypeCodecContext();
for (var i = 0; i < message.values.length; i++) {
final field = schema.columns[i];
final input = message.values[i];
Expand Down
7 changes: 7 additions & 0 deletions test/v3_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:async';
import 'package:async/async.dart';
import 'package:postgres/messages.dart';
import 'package:postgres/postgres.dart';
import 'package:postgres/src/v3/connection.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:test/test.dart';

Expand All @@ -26,6 +27,12 @@ void main() {

tearDown(() => connection.close());

test('runtime parameters', () async {
final c = connection as PgConnectionImplementation;
final p = c.runtimeParameters;
expect(p.applicationName, 'test_app');
});

test('simple queries', () async {
final rs = await connection.execute("SELECT 'dart', 42, NULL");
expect(rs, [
Expand Down

0 comments on commit bea7a6e

Please sign in to comment.