Skip to content

Commit

Permalink
Minimal RelationTracker (tracking RelationMessage) with further exten…
Browse files Browse the repository at this point in the history
…sibility for oid caching.
  • Loading branch information
isoos committed Sep 2, 2024
1 parent 40df664 commit 2b03dac
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- `TypeCodec` interface is used for encoding/decoding value by OIDs.
Gets a reference to `TypeCodecContext` which contains `encoding` and runtime parameters.
- `TypeEncoderFn` value converter for generic Dart -> Postgres object encoders (where type is not specified as parameter).
- `RelationTracker` tracks information about relations (currently limited to `RelationMessage` caching).
- `RuntimeParameters` to access server-provided parameter status values.

## 3.3.0
Expand Down
4 changes: 4 additions & 0 deletions lib/src/types/type_codec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import 'dart:collection';
import 'dart:convert';
import 'dart:typed_data';

import 'package:postgres/src/v3/relation_tracker.dart';

import '../buffer.dart';
import 'type_registry.dart';

Expand Down Expand Up @@ -85,11 +87,13 @@ class RuntimeParameters {

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

TypeCodecContext({
required this.encoding,
required this.relationTracker,
required this.runtimeParameters,
required this.typeRegistry,
});
Expand Down
13 changes: 13 additions & 0 deletions lib/src/v3/connection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import 'package:stream_channel/stream_channel.dart';

import '../../postgres.dart';
import '../auth/auth.dart';
import '../messages/logical_replication_messages.dart';
import '../types/type_codec.dart';
import '../types/type_registry.dart';
import 'protocol.dart';
import 'query_description.dart';
import 'relation_tracker.dart';
import 'resolved_settings.dart';

const _debugLog = false;
Expand Down Expand Up @@ -348,6 +350,9 @@ class PgConnectionImplementation extends _PgSessionBase implements Connection {
late final runtimeParameters =
RuntimeParameters(latestValues: UnmodifiableMapView(_parameters));

// TODO: share this between pooled connections
final _relationTracker = RelationTracker();

var _statementCounter = 0;
var _portalCounter = 0;
var _queryCount = 0;
Expand Down Expand Up @@ -406,6 +411,13 @@ class PgConnectionImplementation extends _PgSessionBase implements Connection {
try {
message as ServerMessage;

if (message is XLogDataLogicalMessage) {
final embedded = message.message;
if (embedded is RelationMessage) {
_relationTracker.addRelationMessage(embedded);
}
}

if (message is ParameterStatusMessage) {
_parameters[message.name] = message.value;
} else if (message is BackendKeyMessage || message is NoticeMessage) {
Expand Down Expand Up @@ -541,6 +553,7 @@ class PgConnectionImplementation extends _PgSessionBase implements Connection {
TypeCodecContext createTypeCodecContext() {
return TypeCodecContext(
encoding: encoding,
relationTracker: _relationTracker,
runtimeParameters: runtimeParameters,
typeRegistry: _settings.typeRegistry,
);
Expand Down
32 changes: 32 additions & 0 deletions lib/src/v3/relation_tracker.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:postgres/src/messages/logical_replication_messages.dart';

/// Trackes and caches the type and name info of relations (tables, views, indexes...).
///
/// Currently it only collects and caches [RelationMessage] instances.
///
/// TODO: Implement active querying using `pg_class` like the below query:
/// "SELECT relname FROM pg_class WHERE relkind='r' AND oid = ?",
/// https://www.postgresql.org/docs/current/catalog-pg-class.html
class RelationTracker {
final _relationMessages = <int, RelationMessage>{};

/// Returns the type OID for [relationId] and [columnIndex].
/// Returns `null` if the [relationId] is unknown or the [columnIndex]
/// is out of bounds.
int? getTypeOid(int relationId, int columnIndex) {
final m = _relationMessages[relationId];
if (m == null) {
return null;
}
if (columnIndex < 0 || columnIndex > m.columns.length) {
return null;
}
return m.columns[columnIndex].typeOid;
}
}

extension RelationInfoViewExt on RelationTracker {
void addRelationMessage(RelationMessage message) {
_relationMessages[message.relationId] = message;
}
}

0 comments on commit 2b03dac

Please sign in to comment.