From c62f501e18570b5f4ee19fe19c6b5e15635e8fac Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Mon, 22 Feb 2021 19:32:48 -0800 Subject: [PATCH 01/33] initial migration --- lib/src/binary_codec.dart | 30 +++---- lib/src/client_messages.dart | 20 ++--- lib/src/connection.dart | 86 ++++++++++---------- lib/src/connection_fsm.dart | 46 +++++------ lib/src/exceptions.dart | 72 ++++++++-------- lib/src/message_window.dart | 6 +- lib/src/query.dart | 63 +++++++------- lib/src/query_cache.dart | 8 +- lib/src/query_queue.dart | 8 +- lib/src/server_messages.dart | 34 ++++---- lib/src/substituter.dart | 15 ++-- lib/src/text_codec.dart | 2 +- lib/src/transaction_proxy.dart | 18 ++-- lib/src/utf8_backed_string.dart | 6 +- pubspec.yaml | 10 +-- test/connection_test.dart | 140 ++++++++++++++++---------------- test/decode_test.dart | 6 +- test/encoding_test.dart | 9 +- test/framer_test.dart | 2 +- test/json_test.dart | 6 +- test/map_return_test.dart | 6 +- test/notification_test.dart | 8 +- test/query_reuse_test.dart | 20 ++--- test/query_test.dart | 16 ++-- test/timeout_test.dart | 8 +- test/transaction_test.dart | 32 ++++---- 26 files changed, 337 insertions(+), 340 deletions(-) diff --git a/lib/src/binary_codec.dart b/lib/src/binary_codec.dart index 89c75ce..93aa9a4 100644 --- a/lib/src/binary_codec.dart +++ b/lib/src/binary_codec.dart @@ -36,7 +36,7 @@ class PostgresBinaryEncoder extends Converter { @override Uint8List convert(dynamic value) { if (value == null) { - return null; + return Uint8List.fromList([]); } switch (_dataType) { @@ -199,9 +199,9 @@ class PostgresBinaryEncoder extends Converter { } return outBuffer; } + default: + throw PostgreSQLException('Unsupported datatype'); } - - throw PostgreSQLException('Unsupported datatype'); } } @@ -214,7 +214,7 @@ class PostgresBinaryDecoder extends Converter { dynamic convert(Uint8List value) { final dataType = typeMap[typeCode]; - if (value == null) { + if (value.isEmpty) { return null; } @@ -277,16 +277,18 @@ class PostgresBinaryDecoder extends Converter { return buf.toString(); } - } - - // We'll try and decode this as a utf8 string and return that - // for many internal types, this is valid. If it fails, - // we just return the bytes and let the caller figure out what to - // do with it. - try { - return utf8.decode(value); - } catch (_) { - return value; + default: + { + // We'll try and decode this as a utf8 string and return that + // for many internal types, this is valid. If it fails, + // we just return the bytes and let the caller figure out what to + // do with it. + try { + return utf8.decode(value); + } catch (_) { + return value; + } + } } } diff --git a/lib/src/client_messages.dart b/lib/src/client_messages.dart index e072c07..c085657 100644 --- a/lib/src/client_messages.dart +++ b/lib/src/client_messages.dart @@ -42,11 +42,11 @@ void _applyStringToBuffer(UTF8BackedString string, ByteDataWriter buffer) { } class StartupMessage extends ClientMessage { - final UTF8BackedString _username; + final UTF8BackedString? _username; final UTF8BackedString _databaseName; final UTF8BackedString _timeZone; - StartupMessage(String databaseName, String timeZone, {String username}) + StartupMessage(String databaseName, String timeZone, {String? username}) : _databaseName = UTF8BackedString(databaseName), _timeZone = UTF8BackedString(timeZone), _username = username == null ? null : UTF8BackedString(username); @@ -58,7 +58,7 @@ class StartupMessage extends ClientMessage { if (_username != null) { fixedLength += 5; - variableLength += _username.utf8Length + 1; + variableLength += _username!.utf8Length + 1; } buffer.writeInt32(fixedLength + variableLength); @@ -66,7 +66,7 @@ class StartupMessage extends ClientMessage { if (_username != null) { buffer.write(UTF8ByteConstants.user); - _applyStringToBuffer(_username, buffer); + _applyStringToBuffer(_username!, buffer); } buffer.write(UTF8ByteConstants.database); @@ -83,7 +83,7 @@ class StartupMessage extends ClientMessage { } class AuthMD5Message extends ClientMessage { - UTF8BackedString _hashedAuthString; + UTF8BackedString? _hashedAuthString; AuthMD5Message(String username, String password, List saltBytes) { final passwordHash = md5.convert('$password$username'.codeUnits).toString(); @@ -96,9 +96,9 @@ class AuthMD5Message extends ClientMessage { @override void applyToBuffer(ByteDataWriter buffer) { buffer.writeUint8(ClientMessage.PasswordIdentifier); - final length = 5 + _hashedAuthString.utf8Length; + final length = 5 + _hashedAuthString!.utf8Length; buffer.writeUint32(length); - _applyStringToBuffer(_hashedAuthString, buffer); + _applyStringToBuffer(_hashedAuthString!, buffer); } } @@ -157,14 +157,14 @@ class BindMessage extends ClientMessage { final List _parameters; final UTF8BackedString _statementName; final int _typeSpecCount; - int _cachedLength; + int _cachedLength = -1; BindMessage(this._parameters, {String statementName = ''}) : _typeSpecCount = _parameters.where((p) => p.isBinary).length, _statementName = UTF8BackedString(statementName); int get length { - if (_cachedLength == null) { + if (_cachedLength == -1) { var inputParameterElementCount = _parameters.length; if (_typeSpecCount == _parameters.length || _typeSpecCount == 0) { inputParameterElementCount = 1; @@ -221,7 +221,7 @@ class BindMessage extends ClientMessage { buffer.writeInt32(-1); } else { buffer.writeInt32(p.length); - buffer.write(p.bytes); + buffer.write(p.bytes!); } }); diff --git a/lib/src/connection.dart b/lib/src/connection.dart index ba3455e..3e88aa0 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -40,8 +40,8 @@ class PostgreSQLConnection extends Object /// [useSSL] when true, uses a secure socket when connecting to a PostgreSQL database. PostgreSQLConnection( this.host, - this.port, this.databaseName, { + this.port = 5432, this.username, this.password, this.timeoutInSeconds = 30, @@ -67,10 +67,10 @@ class PostgreSQLConnection extends Object final String databaseName; /// Username for authenticating this connection. - final String username; + final String? username; /// Password for authenticating this connection. - final String password; + final String? password; /// Whether or not this connection should connect securely. final bool useSSL; @@ -113,18 +113,18 @@ class PostgreSQLConnection extends Object final _cache = QueryCache(); final _oidCache = _OidCache(); - Socket _socket; + Socket? _socket; MessageFramer _framer = MessageFramer(); - int _processID; + late int _processID; // ignore: unused_field - int _secretKey; - List _salt; + late int _secretKey; + late List _salt; bool _hasConnectedPreviously = false; - _PostgreSQLConnectionState _connectionState; + late _PostgreSQLConnectionState _connectionState; @override - PostgreSQLExecutionContext get _transaction => null; + PostgreSQLExecutionContext get _transaction => this; @override PostgreSQLConnection get _connection => this; @@ -156,11 +156,12 @@ class PostgreSQLConnection extends Object _framer = MessageFramer(); if (useSSL) { - _socket = await _upgradeSocketToSSL(_socket, timeout: timeoutInSeconds); + _socket = + await _upgradeSocketToSSL(_socket!, timeout: timeoutInSeconds); } final connectionComplete = Completer(); - _socket.listen(_readData, onError: _close, onDone: _close); + _socket!.listen(_readData, onError: _close, onDone: _close); _transitionToState( _PostgreSQLConnectionStateSocketConnected(connectionComplete)); @@ -214,7 +215,7 @@ class PostgreSQLConnection extends Object /// default query timeout will be used. Future transaction( Future Function(PostgreSQLExecutionContext connection) queryBlock, { - int commitTimeoutInSeconds, + int commitTimeoutInSeconds = 0, }) async { if (isClosed) { throw PostgreSQLException( @@ -229,7 +230,7 @@ class PostgreSQLConnection extends Object } @override - void cancelTransaction({String reason}) { + void cancelTransaction({String? reason}) { // Default is no-op } @@ -249,13 +250,15 @@ class PostgreSQLConnection extends Object _connectionState.connection = this; } - Future _close([dynamic error, StackTrace trace]) async { + Future _close([dynamic error, StackTrace? trace]) async { _connectionState = _PostgreSQLConnectionStateClosed(); - await _socket?.close(); - await _notifications?.close(); + if (_socket != null) { + await _socket!.close(); + } + await _notifications.close(); - _queue?.cancel(error, trace); + _queue.cancel(error, trace); } void _readData(List bytes) { @@ -355,16 +358,15 @@ class _OidCache { Future> _resolveTableNames( _PostgreSQLExecutionContextMixin c, - List columns) async { - if (columns == null) return null; + List? columns) async { + if (columns == null) return []; //todo (joeconwaystk): If this was a cached query, resolving is table oids is unnecessary. // It's not a significant impact here, but an area for optimization. This includes // assigning resolvedTableName final unresolvedTableOIDs = columns .map((f) => f.tableID) .toSet() - .where((oid) => - oid != null && oid > 0 && !_tableOIDNameMap.containsKey(oid)) + .where((oid) => oid > 0 && !_tableOIDNameMap.containsKey(oid)) .toList() ..sort(); @@ -411,9 +413,9 @@ abstract class _PostgreSQLExecutionContextMixin @override Future query( String fmtString, { - Map substitutionValues, - bool allowReuse, - int timeoutInSeconds, + Map substitutionValues = const {}, + bool allowReuse = false, + int timeoutInSeconds = 0, }) => _query( fmtString, @@ -424,14 +426,12 @@ abstract class _PostgreSQLExecutionContextMixin Future _query( String fmtString, { - Map substitutionValues, - bool allowReuse, - int timeoutInSeconds, - bool resolveOids, + Map substitutionValues = const {}, + bool allowReuse = true, + int? timeoutInSeconds, + bool resolveOids = true, }) async { - allowReuse ??= true; timeoutInSeconds ??= _connection.queryTimeoutInSeconds; - resolveOids ??= true; if (_connection.isClosed) { throw PostgreSQLException( @@ -446,7 +446,7 @@ abstract class _PostgreSQLExecutionContextMixin final queryResult = await _enqueue(query, timeoutInSeconds: timeoutInSeconds); - var columnDescriptions = query.fieldDescriptions; + List? columnDescriptions = query.fieldDescriptions; if (resolveOids) { columnDescriptions = await _connection._oidCache ._resolveTableNames(this, columnDescriptions); @@ -456,7 +456,7 @@ abstract class _PostgreSQLExecutionContextMixin return _PostgreSQLResult( queryResult.affectedRowCount, metaData, - queryResult.value + queryResult.value! .map((columns) => _PostgreSQLResultRow(metaData, columns)) .toList()); } @@ -464,9 +464,9 @@ abstract class _PostgreSQLExecutionContextMixin @override Future>>> mappedResultsQuery( String fmtString, - {Map substitutionValues, - bool allowReuse, - int timeoutInSeconds}) async { + {Map substitutionValues = const {}, + bool allowReuse = false, + int timeoutInSeconds = 0}) async { final rs = await query( fmtString, substitutionValues: substitutionValues, @@ -478,7 +478,8 @@ abstract class _PostgreSQLExecutionContextMixin @override Future execute(String fmtString, - {Map substitutionValues, int timeoutInSeconds}) async { + {Map substitutionValues = const {}, + int? timeoutInSeconds}) async { timeoutInSeconds ??= _connection.queryTimeoutInSeconds; if (_connection.isClosed) { throw PostgreSQLException( @@ -521,18 +522,19 @@ abstract class _PostgreSQLExecutionContextMixin } } - Future _onQueryError(Query query, dynamic error, [StackTrace trace]) async {} + Future _onQueryError(Query query, dynamic error, [StackTrace? trace]) async {} } class _PostgreSQLResultMetaData { final List columnDescriptions; - List _tableNames; + late List _tableNames; - _PostgreSQLResultMetaData(this.columnDescriptions); + _PostgreSQLResultMetaData(this.columnDescriptions) { + _tableNames = + columnDescriptions.map((column) => column.tableName).toSet().toList(); + } List get tableNames { - _tableNames ??= - columnDescriptions.map((column) => column.tableName).toSet().toList(); return _tableNames; } } @@ -570,7 +572,7 @@ class _PostgreSQLResultRow extends UnmodifiableListView }); for (var i = 0; i < _metaData.columnDescriptions.length; i++) { final col = _metaData.columnDescriptions[i]; - rowMap[col.tableName][col.columnName] = this[i]; + rowMap[col.tableName]![col.columnName] = this[i]; } return rowMap; } diff --git a/lib/src/connection_fsm.dart b/lib/src/connection_fsm.dart index 3dbb2b4..bd4b903 100644 --- a/lib/src/connection_fsm.dart +++ b/lib/src/connection_fsm.dart @@ -1,7 +1,7 @@ part of postgres.connection; abstract class _PostgreSQLConnectionState { - PostgreSQLConnection connection; + PostgreSQLConnection? connection; _PostgreSQLConnectionState onEnter() { return this; @@ -48,10 +48,10 @@ class _PostgreSQLConnectionStateSocketConnected @override _PostgreSQLConnectionState onEnter() { final startupMessage = StartupMessage( - connection.databaseName, connection.timeZone, - username: connection.username); + connection!.databaseName, connection!.timeZone, + username: connection!.username); - connection._socket.add(startupMessage.asBytes()); + connection!._socket!.add(startupMessage.asBytes()); return this; } @@ -73,7 +73,7 @@ class _PostgreSQLConnectionStateSocketConnected if (authMessage.type == AuthenticationMessage.KindOK) { return _PostgreSQLConnectionStateAuthenticated(completer); } else if (authMessage.type == AuthenticationMessage.KindMD5Password) { - connection._salt = authMessage.salt; + connection!._salt = authMessage.salt; return _PostgreSQLConnectionStateAuthenticating(completer); } @@ -98,9 +98,9 @@ class _PostgreSQLConnectionStateAuthenticating @override _PostgreSQLConnectionState onEnter() { final authMessage = AuthMD5Message( - connection.username, connection.password, connection._salt); + connection!.username!, connection!.password!, connection!._salt); - connection._socket.add(authMessage.asBytes()); + connection!._socket!.add(authMessage.asBytes()); return this; } @@ -117,10 +117,10 @@ class _PostgreSQLConnectionStateAuthenticating @override _PostgreSQLConnectionState onMessage(ServerMessage message) { if (message is ParameterStatusMessage) { - connection.settings[message.name] = message.value; + connection!.settings[message.name] = message.value; } else if (message is BackendKeyMessage) { - connection._processID = message.processID; - connection._secretKey = message.secretKey; + connection!._processID = message.processID; + connection!._secretKey = message.secretKey; } else if (message is ReadyForQueryMessage) { if (message.state == ReadyForQueryMessage.StateIdle) { return _PostgreSQLConnectionStateIdle(openCompleter: completer); @@ -153,10 +153,10 @@ class _PostgreSQLConnectionStateAuthenticated @override _PostgreSQLConnectionState onMessage(ServerMessage message) { if (message is ParameterStatusMessage) { - connection.settings[message.name] = message.value; + connection!.settings[message.name] = message.value; } else if (message is BackendKeyMessage) { - connection._processID = message.processID; - connection._secretKey = message.secretKey; + connection!._processID = message.processID; + connection!._secretKey = message.secretKey; } else if (message is ReadyForQueryMessage) { if (message.state == ReadyForQueryMessage.StateIdle) { return _PostgreSQLConnectionStateIdle(openCompleter: completer); @@ -174,11 +174,11 @@ class _PostgreSQLConnectionStateAuthenticated class _PostgreSQLConnectionStateIdle extends _PostgreSQLConnectionState { _PostgreSQLConnectionStateIdle({this.openCompleter}); - Completer openCompleter; + Completer? openCompleter; @override _PostgreSQLConnectionState awake() { - final pendingQuery = connection._queue.pending; + final pendingQuery = connection!._queue.pending; if (pendingQuery != null) { return processQuery(pendingQuery); } @@ -189,18 +189,18 @@ class _PostgreSQLConnectionStateIdle extends _PostgreSQLConnectionState { _PostgreSQLConnectionState processQuery(Query q) { try { if (q.onlyReturnAffectedRowCount) { - q.sendSimple(connection._socket); + q.sendSimple(connection!._socket!); return _PostgreSQLConnectionStateBusy(q); } - final cached = connection._cache[q.statement]; - q.sendExtended(connection._socket, cacheQuery: cached); + final cached = connection!._cache[q.statement]; + q.sendExtended(connection!._socket!, cacheQuery: cached); return _PostgreSQLConnectionStateBusy(q); } catch (e, st) { scheduleMicrotask(() { q.completeError(e, st); - connection._transitionToState(_PostgreSQLConnectionStateIdle()); + connection!._transitionToState(_PostgreSQLConnectionStateIdle()); }); return _PostgreSQLConnectionStateDeferredFailure(); @@ -228,7 +228,7 @@ class _PostgreSQLConnectionStateBusy extends _PostgreSQLConnectionState { _PostgreSQLConnectionStateBusy(this.query); Query query; - PostgreSQLException returningException; + PostgreSQLException? returningException; int rowsAffected = 0; @override @@ -318,12 +318,12 @@ class _PostgreSQLConnectionStateReadyInTransaction _PostgreSQLConnectionState processQuery(Query q) { try { if (q.onlyReturnAffectedRowCount) { - q.sendSimple(connection._socket); + q.sendSimple(connection!._socket!); return _PostgreSQLConnectionStateBusy(q); } - final cached = connection._cache[q.statement]; - q.sendExtended(connection._socket, cacheQuery: cached); + final cached = connection!._cache[q.statement]; + q.sendExtended(connection!._socket!, cacheQuery: cached); return _PostgreSQLConnectionStateBusy(q); } catch (e, st) { diff --git a/lib/src/exceptions.dart b/lib/src/exceptions.dart index 44e6a00..33952e0 100644 --- a/lib/src/exceptions.dart +++ b/lib/src/exceptions.dart @@ -42,71 +42,71 @@ class PostgreSQLException implements Exception { PostgreSQLException._(List errorFields, {this.stackTrace}) { final finder = (int identifer) => (errorFields.firstWhere( (ErrorField e) => e.identificationToken == identifer, - orElse: () => null)); + orElse: () => ErrorField(null, null))); severity = ErrorField.severityFromString( finder(ErrorField.SeverityIdentifier).text); code = finder(ErrorField.CodeIdentifier).text; message = finder(ErrorField.MessageIdentifier).text; - detail = finder(ErrorField.DetailIdentifier)?.text; - hint = finder(ErrorField.HintIdentifier)?.text; - - internalQuery = finder(ErrorField.InternalQueryIdentifier)?.text; - trace = finder(ErrorField.WhereIdentifier)?.text; - schemaName = finder(ErrorField.SchemaIdentifier)?.text; - tableName = finder(ErrorField.TableIdentifier)?.text; - columnName = finder(ErrorField.ColumnIdentifier)?.text; - dataTypeName = finder(ErrorField.DataTypeIdentifier)?.text; - constraintName = finder(ErrorField.ConstraintIdentifier)?.text; - fileName = finder(ErrorField.FileIdentifier)?.text; - routineName = finder(ErrorField.RoutineIdentifier)?.text; - - var i = finder(ErrorField.PositionIdentifier)?.text; + detail = finder(ErrorField.DetailIdentifier).text; + hint = finder(ErrorField.HintIdentifier).text; + + internalQuery = finder(ErrorField.InternalQueryIdentifier).text; + trace = finder(ErrorField.WhereIdentifier).text; + schemaName = finder(ErrorField.SchemaIdentifier).text; + tableName = finder(ErrorField.TableIdentifier).text; + columnName = finder(ErrorField.ColumnIdentifier).text; + dataTypeName = finder(ErrorField.DataTypeIdentifier).text; + constraintName = finder(ErrorField.ConstraintIdentifier).text; + fileName = finder(ErrorField.FileIdentifier).text; + routineName = finder(ErrorField.RoutineIdentifier).text; + + var i = finder(ErrorField.PositionIdentifier).text; position = (i != null ? int.parse(i) : null); - i = finder(ErrorField.InternalPositionIdentifier)?.text; + i = finder(ErrorField.InternalPositionIdentifier).text; internalPosition = (i != null ? int.parse(i) : null); - i = finder(ErrorField.LineIdentifier)?.text; + i = finder(ErrorField.LineIdentifier).text; lineNumber = (i != null ? int.parse(i) : null); } /// The severity of the exception. - PostgreSQLSeverity severity; + PostgreSQLSeverity? severity; /// The PostgreSQL error code. /// /// May be null if the exception was not generated by the database. - String code; + String? code; /// A message indicating the error. - String message; + String? message; /// Additional details if provided by the database. - String detail; + String? detail; /// A hint on how to remedy an error, if provided by the database. - String hint; + String? hint; /// An index into an executed query string where an error occurred, if by provided by the database. - int position; + int? position; /// An index into a query string generated by the database, if provided. - int internalPosition; - - String internalQuery; - String trace; - String schemaName; - String tableName; - String columnName; - String dataTypeName; - String constraintName; - String fileName; - int lineNumber; - String routineName; + int? internalPosition; + + String? internalQuery; + String? trace; + String? schemaName; + String? tableName; + String? columnName; + String? dataTypeName; + String? constraintName; + String? fileName; + int? lineNumber; + String? routineName; /// A [StackTrace] if available. - StackTrace stackTrace; + StackTrace? stackTrace; @override String toString() { diff --git a/lib/src/message_window.dart b/lib/src/message_window.dart index c40129a..91c47d6 100644 --- a/lib/src/message_window.dart +++ b/lib/src/message_window.dart @@ -30,8 +30,8 @@ class MessageFramer { final _reader = ByteDataReader(); final messageQueue = Queue(); - int _type; - int _expectedLength; + int? _type; + int _expectedLength = 0; bool get _hasReadHeader => _type != null; bool get _canReadHeader => _reader.remainingLength >= _headerByteSize; @@ -59,7 +59,7 @@ class MessageFramer { msgMaker == null ? UnknownMessage(_type, data) : msgMaker(data); messageQueue.add(msg); _type = null; - _expectedLength = null; + _expectedLength = 0; evaluateNextMessage = true; } } diff --git a/lib/src/query.dart b/lib/src/query.dart index 26bd2d5..2c801eb 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -24,7 +24,7 @@ class Query { final bool onlyReturnAffectedRowCount; - String statementIdentifier; + String? statementIdentifier; Future> get future => _onComplete.future; @@ -33,13 +33,13 @@ class Query { final PostgreSQLExecutionContext transaction; final PostgreSQLConnection connection; - List _specifiedParameterTypeCodes; + late List _specifiedParameterTypeCodes; final rows = >[]; - CachedQuery cache; + CachedQuery? cache; final _onComplete = Completer>.sync(); - List _fieldDescriptions; + late List _fieldDescriptions; List get fieldDescriptions => _fieldDescriptions; @@ -56,9 +56,9 @@ class Query { socket.add(queryMessage.asBytes()); } - void sendExtended(Socket socket, {CachedQuery cacheQuery}) { + void sendExtended(Socket socket, {CachedQuery? cacheQuery}) { if (cacheQuery != null) { - fieldDescriptions = cacheQuery.fieldDescriptions; + fieldDescriptions = cacheQuery.fieldDescriptions!; sendCachedQuery(socket, cacheQuery, substitutionValues); return; @@ -89,7 +89,7 @@ class Query { ]; if (statementIdentifier != null) { - cache = CachedQuery(statementIdentifier, formatIdentifiers); + cache = CachedQuery(statementIdentifier!, formatIdentifiers); } socket.add(ClientMessage.aggregateBytes(messages)); @@ -98,12 +98,12 @@ class Query { void sendCachedQuery(Socket socket, CachedQuery cacheQuery, Map substitutionValues) { final statementName = cacheQuery.preparedStatementName; - final parameterList = cacheQuery.orderedParameters + final parameterList = cacheQuery.orderedParameters! .map((identifier) => ParameterValue(identifier, substitutionValues)) .toList(); final bytes = ClientMessage.aggregateBytes([ - BindMessage(parameterList, statementName: statementName), + BindMessage(parameterList, statementName: statementName!), ExecuteMessage(), SyncMessage() ]); @@ -111,7 +111,7 @@ class Query { socket.add(bytes); } - PostgreSQLException validateParameters(List parameterTypeIDs) { + PostgreSQLException? validateParameters(List parameterTypeIDs) { final actualParameterTypeCodeIterator = parameterTypeIDs.iterator; final parametersAreMismatched = _specifiedParameterTypeCodes.map((specifiedType) { @@ -161,12 +161,12 @@ class Query { _onComplete.complete(QueryResult(rowsAffected, rows as T)); } - void completeError(dynamic error, [StackTrace stackTrace]) { + void completeError(dynamic error, [StackTrace? stackTrace]) { if (_onComplete.isCompleted) { return; } - _onComplete.completeError(error, stackTrace); + _onComplete.completeError(error as Object, stackTrace); } @override @@ -175,7 +175,7 @@ class Query { class QueryResult { final int affectedRowCount; - final T value; + final T? value; const QueryResult(this.affectedRowCount, this.value); } @@ -183,9 +183,9 @@ class QueryResult { class CachedQuery { CachedQuery(this.preparedStatementName, this.orderedParameters); - final String preparedStatementName; - final List orderedParameters; - List fieldDescriptions; + final String? preparedStatementName; + final List? orderedParameters; + List? fieldDescriptions; bool get isValid { return preparedStatementName != null && @@ -202,19 +202,19 @@ class ParameterValue { } return ParameterValue.binary( - substitutionValues[identifier.name], identifier.type); + substitutionValues[identifier.name], identifier.type!); } factory ParameterValue.binary( dynamic value, PostgreSQLDataType postgresType) { final converter = PostgresBinaryEncoder(postgresType); final bytes = converter.convert(value); - final length = bytes?.length ?? 0; + final length = bytes.length; return ParameterValue._(true, bytes, length); } factory ParameterValue.text(dynamic value) { - Uint8List bytes; + Uint8List? bytes; if (value != null) { final converter = PostgresTextEncoder(); bytes = castBytes( @@ -227,7 +227,7 @@ class ParameterValue { ParameterValue._(this.isBinary, this.bytes, this.length); final bool isBinary; - final Uint8List bytes; + final Uint8List? bytes; final int length; } @@ -281,11 +281,11 @@ class FieldDescription implements ColumnDescription { return FieldDescription._( converter, fieldName, tableID, columnID, typeID, dataTypeSize, typeModifier, formatCode, - null, // tableName + '', // tableName ); } - FieldDescription change({String tableName}) { + FieldDescription change({String? tableName}) { return FieldDescription._(converter, columnName, tableID, columnID, typeID, dataTypeSize, typeModifier, formatCode, tableName ?? this.tableName); } @@ -328,8 +328,8 @@ class PostgreSQLFormatIdentifier { factory PostgreSQLFormatIdentifier(String t) { String name; - PostgreSQLDataType type; - String typeCast; + PostgreSQLDataType? type; + String? typeCast; final components = t.split('::'); if (components.length > 1) { @@ -343,12 +343,11 @@ class PostgreSQLFormatIdentifier { name = variableComponents.first; final dataTypeString = variableComponents.last; - if (dataTypeString != null) { - type = typeStringToCodeMap[dataTypeString]; - if (type == null) { - throw FormatException( - "Invalid type code in substitution variable '$t'"); - } + try { + type = typeStringToCodeMap[dataTypeString]!; + } catch (e) { + throw FormatException( + "Invalid type code in substitution variable '$t'"); } } else { throw FormatException( @@ -363,6 +362,6 @@ class PostgreSQLFormatIdentifier { PostgreSQLFormatIdentifier._(this.name, this.type, this.typeCast); final String name; - final PostgreSQLDataType type; - final String typeCast; + final PostgreSQLDataType? type; + final String? typeCast; } diff --git a/lib/src/query_cache.dart b/lib/src/query_cache.dart index 2acf5d9..4fa4690 100644 --- a/lib/src/query_cache.dart +++ b/lib/src/query_cache.dart @@ -12,12 +12,12 @@ class QueryCache { return; } - if (query.cache.isValid) { - _queries[query.statement] = query.cache; + if (query.cache!.isValid) { + _queries[query.statement] = query.cache!; } } - CachedQuery operator [](String statementId) { + CachedQuery? operator [](String? statementId) { if (statementId == null) { return null; } @@ -28,7 +28,7 @@ class QueryCache { String identifierForQuery(Query query) { final existing = _queries[query.statement]; if (existing != null) { - return existing.preparedStatementName; + return existing.preparedStatementName!; } final string = '$_idCounter'.padLeft(12, '0'); diff --git a/lib/src/query_queue.dart b/lib/src/query_queue.dart index 29514cb..d30c40a 100644 --- a/lib/src/query_queue.dart +++ b/lib/src/query_queue.dart @@ -13,14 +13,14 @@ class QueryQueue extends ListBase> PostgreSQLException get _cancellationException => PostgreSQLException( 'Query cancelled due to the database connection closing.'); - Query get pending { + Query? get pending { if (_inner.isEmpty) { return null; } return _inner.first; } - void cancel([dynamic error, StackTrace stackTrace]) { + void cancel([dynamic error, StackTrace? stackTrace]) { _isCancelled = true; error ??= _cancellationException; final existing = _inner; @@ -30,8 +30,8 @@ class QueryQueue extends ListBase> // get the error and not the close message, since completeError is // synchronous. scheduleMicrotask(() { - existing?.forEach((q) { - q.completeError(error, stackTrace); + existing.forEach((q) { + q.completeError(error, stackTrace!); }); }); } diff --git a/lib/src/server_messages.dart b/lib/src/server_messages.dart index 4ee1f9a..1eab22b 100644 --- a/lib/src/server_messages.dart +++ b/lib/src/server_messages.dart @@ -14,8 +14,8 @@ class ErrorResponseMessage implements ServerMessage { ErrorResponseMessage(Uint8List bytes) { final reader = ByteDataReader()..add(bytes); - int identificationToken; - StringBuffer sb; + int? identificationToken; + StringBuffer? sb; while (reader.remainingLength > 0) { final byte = reader.readUint8(); @@ -27,7 +27,7 @@ class ErrorResponseMessage implements ServerMessage { identificationToken = null; sb = null; } else { - sb.writeCharCode(byte); + sb!.writeCharCode(byte); } } if (identificationToken != null && sb != null) { @@ -54,9 +54,9 @@ class AuthenticationMessage implements ServerMessage { factory AuthenticationMessage(Uint8List bytes) { final reader = ByteDataReader()..add(bytes); final type = reader.readUint32(); - List salt; + final salt = []; if (type == KindMD5Password) { - salt = reader.read(4, copy: true); + salt.addAll(reader.read(4, copy: true)); } return AuthenticationMessage._(type, salt); } @@ -127,7 +127,7 @@ class DataRowMessage extends ServerMessage { if (dataSize == 0) { values.add(Uint8List(0)); } else if (dataSize == -1) { - values.add(null); + values.add(Uint8List.fromList([])); } else { final rawBytes = reader.read(dataSize); values.add(rawBytes); @@ -168,7 +168,7 @@ class CommandCompleteMessage extends ServerMessage { final str = utf8.decode(bytes.sublist(0, bytes.length - 1)); final match = identifierExpression.firstMatch(str); var rowsAffected = 0; - if (match.end < str.length) { + if (match != null && match.end < str.length) { rowsAffected = int.parse(str.split(' ').last); } return CommandCompleteMessage._(rowsAffected); @@ -210,8 +210,8 @@ class NoDataMessage extends ServerMessage { } class UnknownMessage extends ServerMessage { - final int code; - final Uint8List bytes; + final int? code; + final Uint8List? bytes; UnknownMessage(this.code, this.bytes); @@ -223,11 +223,11 @@ class UnknownMessage extends ServerMessage { @override bool operator ==(dynamic other) { if (bytes != null) { - if (bytes.length != other.bytes.length) { + if (bytes!.length != other.bytes.length) { return false; } - for (var i = 0; i < bytes.length; i++) { - if (bytes[i] != other.bytes[i]) { + for (var i = 0; i < bytes!.length; i++) { + if (bytes![i] != other.bytes[i]) { return false; } } @@ -259,7 +259,7 @@ class ErrorField { static const int LineIdentifier = 76; static const int RoutineIdentifier = 82; - static PostgreSQLSeverity severityFromString(String str) { + static PostgreSQLSeverity severityFromString(String? str) { switch (str) { case 'ERROR': return PostgreSQLSeverity.error; @@ -277,13 +277,13 @@ class ErrorField { return PostgreSQLSeverity.info; case 'LOG': return PostgreSQLSeverity.log; + default: + return PostgreSQLSeverity.unknown; } - - return PostgreSQLSeverity.unknown; } - final int identificationToken; - final String text; + final int? identificationToken; + final String? text; ErrorField(this.identificationToken, this.text); } diff --git a/lib/src/substituter.dart b/lib/src/substituter.dart index 0d7f647..f97038a 100644 --- a/lib/src/substituter.dart +++ b/lib/src/substituter.dart @@ -5,7 +5,7 @@ import 'types.dart'; class PostgreSQLFormat { static final int _atSignCodeUnit = '@'.codeUnitAt(0); - static String id(String name, {PostgreSQLDataType type}) { + static String id(String name, {PostgreSQLDataType? type}) { if (type != null) { return '@$name:${dataTypeStringForDataType(type)}'; } @@ -13,7 +13,7 @@ class PostgreSQLFormat { return '@$name'; } - static String dataTypeStringForDataType(PostgreSQLDataType dt) { + static String? dataTypeStringForDataType(PostgreSQLDataType dt) { switch (dt) { case PostgreSQLDataType.text: return 'text'; @@ -47,19 +47,18 @@ class PostgreSQLFormat { return 'name'; case PostgreSQLDataType.uuid: return 'uuid'; + default: + return null; } - - return null; } static String substitute(String fmtString, Map values, - {SQLReplaceIdentifierFunction replace}) { + {SQLReplaceIdentifierFunction? replace}) { final converter = PostgresTextEncoder(); - values ??= {}; replace ??= (spec, index) => converter.convert(values[spec.name]); final items = []; - PostgreSQLFormatToken currentPtr; + PostgreSQLFormatToken? currentPtr; final iterator = RuneIterator(fmtString); while (iterator.moveNext()) { @@ -121,7 +120,7 @@ class PostgreSQLFormat { return t.buffer; } - final val = replace(identifier, idx); + final val = replace!(identifier, idx); idx++; if (identifier.typeCast != null) { diff --git a/lib/src/text_codec.dart b/lib/src/text_codec.dart index 852f986..8eca302 100644 --- a/lib/src/text_codec.dart +++ b/lib/src/text_codec.dart @@ -110,7 +110,7 @@ class PostgresTextEncoder { return value ? 'TRUE' : 'FALSE'; } - String _encodeDateTime(DateTime value, {bool isDateOnly}) { + String _encodeDateTime(DateTime value, {bool isDateOnly = false}) { var string = value.toIso8601String(); if (isDateOnly) { diff --git a/lib/src/transaction_proxy.dart b/lib/src/transaction_proxy.dart index 67ea2b1..5a1f453 100644 --- a/lib/src/transaction_proxy.dart +++ b/lib/src/transaction_proxy.dart @@ -13,12 +13,12 @@ class _TransactionProxy extends Object _beginQuery.future.then(startTransaction).catchError((err, StackTrace st) { Future(() { - _completer.completeError(err, st); + _completer.completeError(err as Object, st); }); }); } - Query _beginQuery; + late Query _beginQuery; final _completer = Completer(); Future get future => _completer.future; @@ -35,8 +35,8 @@ class _TransactionProxy extends Object bool _hasRolledBack = false; @override - void cancelTransaction({String reason}) { - throw _TransactionRollbackException(reason); + void cancelTransaction({String? reason}) { + throw _TransactionRollbackException(reason ?? 'Reason not given.'); } Future startTransaction(dynamic _) async { @@ -70,7 +70,7 @@ class _TransactionProxy extends Object } } - Future _cancelAndRollback(dynamic object, [StackTrace trace]) async { + Future _cancelAndRollback(dynamic object, [StackTrace? trace]) async { if (_hasRolledBack) { return; } @@ -87,7 +87,7 @@ class _TransactionProxy extends Object 'that prevented this query from executing.'); _queue.cancel(err); - final rollback = Query('ROLLBACK', {}, _connection, _transaction, + final rollback = Query('ROLLBACK', {}, _connection, _transaction!, onlyReturnAffectedRowCount: true); _queue.addEvenIfCancelled(rollback); @@ -102,11 +102,11 @@ class _TransactionProxy extends Object if (object is _TransactionRollbackException) { _completer.complete(PostgreSQLRollback._(object.reason)); } else { - _completer.completeError(object, trace); + _completer.completeError(object as Object, trace); } } - Future _transactionFailed(dynamic error, [StackTrace trace]) async { + Future _transactionFailed(dynamic error, [StackTrace? trace]) async { if (_hasFailed) { return; } @@ -117,7 +117,7 @@ class _TransactionProxy extends Object } @override - Future _onQueryError(Query query, dynamic error, [StackTrace trace]) { + Future _onQueryError(Query query, dynamic error, [StackTrace? trace]) { return _transactionFailed(error, trace); } } diff --git a/lib/src/utf8_backed_string.dart b/lib/src/utf8_backed_string.dart index 360344d..f8612e8 100644 --- a/lib/src/utf8_backed_string.dart +++ b/lib/src/utf8_backed_string.dart @@ -3,7 +3,7 @@ import 'dart:convert'; class UTF8BackedString { UTF8BackedString(this.string); - List _cachedUTF8Bytes; + List? _cachedUTF8Bytes; bool get hasCachedBytes => _cachedUTF8Bytes != null; @@ -11,11 +11,11 @@ class UTF8BackedString { int get utf8Length { _cachedUTF8Bytes ??= utf8.encode(string); - return _cachedUTF8Bytes.length; + return _cachedUTF8Bytes!.length; } List get utf8Bytes { _cachedUTF8Bytes ??= utf8.encode(string); - return _cachedUTF8Bytes; + return _cachedUTF8Bytes!; } } diff --git a/pubspec.yaml b/pubspec.yaml index 48ef18e..cd24c15 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,13 +4,13 @@ version: 2.2.0 homepage: https://github.com/stablekernel/postgresql-dart environment: - sdk: ">=2.8.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: - buffer: ^1.0.6 - crypto: ^2.0.0 + buffer: ^1.1.0-nullsafety.0 + crypto: ^3.0.0 dev_dependencies: - pedantic: ^1.0.0 - test: ^1.3.0 + pedantic: ^1.10.0 + test: ^1.16.3 coverage: any diff --git a/test/connection_test.dart b/test/connection_test.dart index d95b7d0..189855f 100644 --- a/test/connection_test.dart +++ b/test/connection_test.dart @@ -10,15 +10,15 @@ import 'package:postgres/postgres.dart'; void main() { group('Connection lifecycle', () { - PostgreSQLConnection conn; + late PostgreSQLConnection conn; tearDown(() async { - await conn?.close(); + await conn.close(); }); test('Connect with md5 auth required', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await conn.open(); @@ -26,8 +26,8 @@ void main() { }); test('SSL Connect with md5 auth required', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart', useSSL: true); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart', useSSL: true); await conn.open(); @@ -41,16 +41,16 @@ void main() { }); test('Connect with no auth required', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust'); await conn.open(); expect(await conn.execute('select 1'), equals(1)); }); test('SSL Connect with no auth required', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust', useSSL: true); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust', useSSL: true); await conn.open(); expect(await conn.execute('select 1'), equals(1)); @@ -58,8 +58,8 @@ void main() { test('Closing idle connection succeeds, closes underlying socket', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust'); await conn.open(); await conn.close(); @@ -70,14 +70,12 @@ void main() { final underlyingSocket = reflect(conn).getField(socketMirror.simpleName).reflectee as Socket; expect(await underlyingSocket.done, isNotNull); - - conn = null; }); test('SSL Closing idle connection succeeds, closes underlying socket', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust', useSSL: true); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust', useSSL: true); await conn.open(); await conn.close(); @@ -88,15 +86,13 @@ void main() { final underlyingSocket = reflect(conn).getField(socketMirror.simpleName).reflectee as Socket; expect(await underlyingSocket.done, isNotNull); - - conn = null; }); test( 'Closing connection while busy succeeds, queued queries are all accounted for (canceled), closes underlying socket', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust'); await conn.open(); final errors = []; @@ -122,8 +118,8 @@ void main() { test( 'SSL Closing connection while busy succeeds, queued queries are all accounted for (canceled), closes underlying socket', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust', useSSL: true); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust', useSSL: true); await conn.open(); final errors = []; @@ -148,16 +144,16 @@ void main() { }); group('Successful queries over time', () { - PostgreSQLConnection conn; + late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust'); await conn.open(); }); tearDown(() async { - await conn?.close(); + await conn.close(); }); test( @@ -224,17 +220,17 @@ void main() { }); group('Unintended user-error situations', () { - PostgreSQLConnection conn; - Future openFuture; + late PostgreSQLConnection conn; + late Future openFuture; tearDown(() async { await openFuture; - await conn?.close(); + await conn.close(); }); test('Sending queries to opening connection triggers error', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust'); openFuture = conn.open(); try { @@ -246,8 +242,8 @@ void main() { }); test('SSL Sending queries to opening connection triggers error', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust', useSSL: true); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust', useSSL: true); openFuture = conn.open(); try { @@ -260,8 +256,8 @@ void main() { test('Starting transaction while opening connection triggers error', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust'); openFuture = conn.open(); try { @@ -276,8 +272,8 @@ void main() { test('SSL Starting transaction while opening connection triggers error', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust', useSSL: true); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust', useSSL: true); openFuture = conn.open(); try { @@ -292,8 +288,8 @@ void main() { test('Invalid password reports error, conn is closed, disables conn', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'notdart'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'notdart'); try { await conn.open(); @@ -307,8 +303,8 @@ void main() { test('SSL Invalid password reports error, conn is closed, disables conn', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'notdart', useSSL: true); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'notdart', useSSL: true); try { await conn.open(); @@ -322,8 +318,8 @@ void main() { test('A query error maintains connectivity, allows future queries', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (i int unique)'); @@ -341,8 +337,8 @@ void main() { test( 'A query error maintains connectivity, continues processing pending queries', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (i int unique)'); @@ -383,8 +379,8 @@ void main() { test( 'A query error maintains connectivity, continues processing pending transactions', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (i int unique)'); @@ -415,8 +411,8 @@ void main() { test( 'Building query throws error, connection continues processing pending queries', () async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'darttrust'); await conn.open(); // Make some async queries that'll exit the event loop, but then fail on a query that'll die early @@ -449,18 +445,18 @@ void main() { }); group('Network error situations', () { - ServerSocket serverSocket; - Socket socket; + late ServerSocket serverSocket; + late Socket socket; tearDown(() async { - await serverSocket?.close(); - await socket?.close(); + await serverSocket.close(); + await socket.close(); }); test( 'Socket fails to connect reports error, disables connection for future use', () async { - final conn = PostgreSQLConnection('localhost', 5431, 'dart_test'); + final conn = PostgreSQLConnection('localhost', 'dart_test', port: 5431); try { await conn.open(); @@ -475,8 +471,8 @@ void main() { test( 'SSL Socket fails to connect reports error, disables connection for future use', () async { - final conn = - PostgreSQLConnection('localhost', 5431, 'dart_test', useSSL: true); + final conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5431, useSSL: true); try { await conn.open(); @@ -499,8 +495,8 @@ void main() { s.listen((bytes) {}); }); - final conn = PostgreSQLConnection('localhost', 5433, 'dart_test', - timeoutInSeconds: 2); + final conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5433, timeoutInSeconds: 2); try { await conn.open(); @@ -523,8 +519,8 @@ void main() { s.listen((bytes) {}); }); - final conn = PostgreSQLConnection('localhost', 5433, 'dart_test', - timeoutInSeconds: 2, useSSL: true); + final conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5433, timeoutInSeconds: 2, useSSL: true); try { await conn.open(); @@ -548,8 +544,8 @@ void main() { Future.delayed(Duration(milliseconds: 100), openCompleter.complete); }); - final conn = PostgreSQLConnection('localhost', 5433, 'dart_test', - timeoutInSeconds: 2); + final conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5433, timeoutInSeconds: 2); conn.open().catchError((e) {}); await openCompleter.future; @@ -574,8 +570,8 @@ void main() { Future.delayed(Duration(milliseconds: 100), openCompleter.complete); }); - final conn = PostgreSQLConnection('localhost', 5433, 'dart_test', - timeoutInSeconds: 2, useSSL: true); + final conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5433, timeoutInSeconds: 2, useSSL: true); conn.open().catchError((e) { return null; }); @@ -599,8 +595,8 @@ void main() { }); test('If connection is closed, do not allow .execute', () async { - final conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + final conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); try { await conn.execute('SELECT 1'); fail('unreachable'); @@ -610,8 +606,8 @@ void main() { }); test('If connection is closed, do not allow .query', () async { - final conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + final conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); try { await conn.query('SELECT 1'); fail('unreachable'); @@ -621,8 +617,8 @@ void main() { }); test('If connection is closed, do not allow .mappedResultsQuery', () async { - final conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + final conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); try { await conn.mappedResultsQuery('SELECT 1'); fail('unreachable'); @@ -634,8 +630,8 @@ void main() { test( 'Queue size, should be 0 on open, >0 if queries added and 0 again after queries executed', () async { - final conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + final conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await conn.open(); expect(conn.queueSize, 0); diff --git a/test/decode_test.dart b/test/decode_test.dart index 27096fb..b53adde 100644 --- a/test/decode_test.dart +++ b/test/decode_test.dart @@ -2,10 +2,10 @@ import 'package:postgres/postgres.dart'; import 'package:test/test.dart'; void main() { - PostgreSQLConnection connection; + late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await connection.open(); await connection.execute(''' diff --git a/test/encoding_test.dart b/test/encoding_test.dart index edfc81e..a053e92 100644 --- a/test/encoding_test.dart +++ b/test/encoding_test.dart @@ -9,19 +9,18 @@ import 'package:postgres/src/text_codec.dart'; import 'package:postgres/src/types.dart'; import 'package:postgres/src/utf8_backed_string.dart'; -PostgreSQLConnection conn; +late PostgreSQLConnection conn; void main() { group('Binary encoders', () { setUp(() async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await conn.open(); }); tearDown(() async { await conn.close(); - conn = null; }); // expectInverse ensures that: @@ -404,7 +403,7 @@ Future expectInverse(dynamic value, PostgreSQLDataType dataType) async { } else if (dataType == PostgreSQLDataType.bigSerial) { dataType = PostgreSQLDataType.bigInteger; } - int code; + late int code; PostgresBinaryDecoder.typeMap.forEach((key, type) { if (type == dataType) { code = key; diff --git a/test/framer_test.dart b/test/framer_test.dart index 77a3996..064c54e 100644 --- a/test/framer_test.dart +++ b/test/framer_test.dart @@ -8,7 +8,7 @@ import 'package:postgres/src/message_window.dart'; import 'package:postgres/src/server_messages.dart'; void main() { - MessageFramer framer; + late MessageFramer framer; setUp(() { framer = MessageFramer(); }); diff --git a/test/json_test.dart b/test/json_test.dart index cee5b27..402363b 100644 --- a/test/json_test.dart +++ b/test/json_test.dart @@ -2,11 +2,11 @@ import 'package:postgres/postgres.dart'; import 'package:test/test.dart'; void main() { - PostgreSQLConnection connection; + late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await connection.open(); await connection.execute(''' diff --git a/test/map_return_test.dart b/test/map_return_test.dart index b0135ed..5d7c518 100644 --- a/test/map_return_test.dart +++ b/test/map_return_test.dart @@ -4,11 +4,11 @@ import 'package:postgres/postgres.dart'; import 'package:test/test.dart'; void main() { - PostgreSQLConnection connection; + late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await connection.open(); await connection.execute(''' diff --git a/test/notification_test.dart b/test/notification_test.dart index d6cb5d9..a4827b7 100644 --- a/test/notification_test.dart +++ b/test/notification_test.dart @@ -5,12 +5,12 @@ import 'package:test/test.dart'; void main() { group('Successful notifications', () { - var connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + var connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); setUp(() async { - connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await connection.open(); }); diff --git a/test/query_reuse_test.dart b/test/query_reuse_test.dart index 44ebbae..c98bbf5 100644 --- a/test/query_reuse_test.dart +++ b/test/query_reuse_test.dart @@ -11,11 +11,11 @@ String sid(String id, PostgreSQLDataType dt) => void main() { group('Retaining type information', () { - PostgreSQLConnection connection; + late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await connection.open(); await connection.execute( 'CREATE TEMPORARY TABLE t (i int, s serial, bi bigint, bs bigserial, bl boolean, si smallint, t text, f real, d double precision, dt date, ts timestamp, tsz timestamptz)'); @@ -281,11 +281,11 @@ void main() { }); group('Mixing prepared statements', () { - PostgreSQLConnection connection; + late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await connection.open(); await connection.execute( 'CREATE TEMPORARY TABLE t (i1 int not null, i2 int not null)'); @@ -440,12 +440,12 @@ void main() { }); group('Failure cases', () { - var connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + var connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); setUp(() async { - connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await connection.open(); await connection.execute( 'CREATE TEMPORARY TABLE t (i int, s serial, bi bigint, bs bigserial, bl boolean, si smallint, t text, f real, d double precision, dt date, ts timestamp, tsz timestamptz)'); diff --git a/test/query_test.dart b/test/query_test.dart index 9627632..4fc66a4 100644 --- a/test/query_test.dart +++ b/test/query_test.dart @@ -4,12 +4,12 @@ import 'package:postgres/src/types.dart'; void main() { group('Successful queries', () { - var connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + var connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); setUp(() async { - connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await connection.open(); await connection.execute('CREATE TEMPORARY TABLE t ' '(i int, s serial, bi bigint, ' @@ -332,12 +332,12 @@ void main() { }); group('Unsuccesful queries', () { - var connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + var connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); setUp(() async { - connection = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await connection.open(); await connection.execute( 'CREATE TEMPORARY TABLE t (i1 int not null, i2 int not null)'); diff --git a/test/timeout_test.dart b/test/timeout_test.dart index 5ff8f32..c23d204 100644 --- a/test/timeout_test.dart +++ b/test/timeout_test.dart @@ -5,17 +5,17 @@ import 'package:test/test.dart'; import 'package:postgres/postgres.dart'; void main() { - PostgreSQLConnection conn; + late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (id INT UNIQUE)'); }); tearDown(() async { - await conn?.close(); + await conn.close(); }); test( diff --git a/test/transaction_test.dart b/test/transaction_test.dart index e588032..50ed9c6 100644 --- a/test/transaction_test.dart +++ b/test/transaction_test.dart @@ -7,17 +7,17 @@ import 'package:postgres/postgres.dart'; void main() { group('Transaction behavior', () { - PostgreSQLConnection conn; + late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (id INT UNIQUE)'); }); tearDown(() async { - await conn?.close(); + await conn.close(); }); test('Rows are Lists of column values', () async { @@ -295,17 +295,17 @@ void main() { // After a transaction fails, the changes must be rolled back, it should continue with pending queries, pending transactions, later queries, later transactions group('Transaction:Query recovery', () { - PostgreSQLConnection conn; + late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (id INT UNIQUE)'); }); tearDown(() async { - await conn?.close(); + await conn.close(); }); test('Is rolled back/executes later query', () async { @@ -396,17 +396,17 @@ void main() { }); group('Transaction:Exception recovery', () { - PostgreSQLConnection conn; + late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (id INT UNIQUE)'); }); tearDown(() async { - await conn?.close(); + await conn.close(); }); test('Is rolled back/executes later query', () async { @@ -542,17 +542,17 @@ void main() { }); group('Transaction:Rollback recovery', () { - PostgreSQLConnection conn; + late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 5432, 'dart_test', - username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 'dart_test', + port: 5432, username: 'dart', password: 'dart'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (id INT UNIQUE)'); }); tearDown(() async { - await conn?.close(); + await conn.close(); }); test('Is rolled back/executes later query', () async { From ec523df8609b4c7dab2aa0dcce3a56dbd093c3e7 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Mon, 22 Feb 2021 20:07:31 -0800 Subject: [PATCH 02/33] update travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9d14a9a..af90a1b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: dart sudo: required dart: - - stable + - beta addons: postgresql: "9.6" services: From 1ebb99f7b050f0e63a12c1b34b159ce33929ca0b Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Mon, 22 Feb 2021 20:31:56 -0800 Subject: [PATCH 03/33] update sdk requirement --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index cd24c15..8096f95 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ version: 2.2.0 homepage: https://github.com/stablekernel/postgresql-dart environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.12.0-0 <3.0.0" dependencies: buffer: ^1.1.0-nullsafety.0 From 850f475d021904bfcf51d01e434d0335bee4583e Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Mon, 22 Feb 2021 20:51:47 -0800 Subject: [PATCH 04/33] change error type from dynamic to Object --- lib/src/connection_fsm.dart | 13 ++++++------- lib/src/query.dart | 4 ++-- lib/src/query_queue.dart | 4 ++-- lib/src/transaction_proxy.dart | 2 +- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/lib/src/connection_fsm.dart b/lib/src/connection_fsm.dart index bd4b903..9a3b899 100644 --- a/lib/src/connection_fsm.dart +++ b/lib/src/connection_fsm.dart @@ -255,14 +255,13 @@ class _PostgreSQLConnectionStateBusy extends _PostgreSQLConnectionState { // print("(${query.statement}) -> $message"); if (message is ReadyForQueryMessage) { - if (message.state == ReadyForQueryMessage.StateTransactionError) { - query.completeError(returningException); - return _PostgreSQLConnectionStateReadyInTransaction( - query.transaction as _TransactionProxy); - } - if (returningException != null) { - query.completeError(returningException); + if (message.state == ReadyForQueryMessage.StateTransactionError) { + query.completeError(returningException!); + return _PostgreSQLConnectionStateReadyInTransaction( + query.transaction as _TransactionProxy); + } + query.completeError(returningException!); } else { query.complete(rowsAffected); } diff --git a/lib/src/query.dart b/lib/src/query.dart index 2c801eb..14bf95a 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -161,12 +161,12 @@ class Query { _onComplete.complete(QueryResult(rowsAffected, rows as T)); } - void completeError(dynamic error, [StackTrace? stackTrace]) { + void completeError(Object error, [StackTrace? stackTrace]) { if (_onComplete.isCompleted) { return; } - _onComplete.completeError(error as Object, stackTrace); + _onComplete.completeError(error, stackTrace); } @override diff --git a/lib/src/query_queue.dart b/lib/src/query_queue.dart index d30c40a..09812dc 100644 --- a/lib/src/query_queue.dart +++ b/lib/src/query_queue.dart @@ -20,7 +20,7 @@ class QueryQueue extends ListBase> return _inner.first; } - void cancel([dynamic error, StackTrace? stackTrace]) { + void cancel([Object? error, StackTrace? stackTrace]) { _isCancelled = true; error ??= _cancellationException; final existing = _inner; @@ -31,7 +31,7 @@ class QueryQueue extends ListBase> // synchronous. scheduleMicrotask(() { existing.forEach((q) { - q.completeError(error, stackTrace!); + q.completeError(error!, stackTrace!); }); }); } diff --git a/lib/src/transaction_proxy.dart b/lib/src/transaction_proxy.dart index 5a1f453..a375118 100644 --- a/lib/src/transaction_proxy.dart +++ b/lib/src/transaction_proxy.dart @@ -87,7 +87,7 @@ class _TransactionProxy extends Object 'that prevented this query from executing.'); _queue.cancel(err); - final rollback = Query('ROLLBACK', {}, _connection, _transaction!, + final rollback = Query('ROLLBACK', {}, _connection, _transaction, onlyReturnAffectedRowCount: true); _queue.addEvenIfCancelled(rollback); From ee5eb44cc20b93e16572ad95c29190da0853cd47 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Mon, 22 Feb 2021 20:59:38 -0800 Subject: [PATCH 05/33] update tests and set longer timeout --- lib/src/connection.dart | 6 +++--- test/decode_test.dart | 2 +- test/json_test.dart | 2 +- test/map_return_test.dart | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index 3e88aa0..43cc090 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -215,7 +215,7 @@ class PostgreSQLConnection extends Object /// default query timeout will be used. Future transaction( Future Function(PostgreSQLExecutionContext connection) queryBlock, { - int commitTimeoutInSeconds = 0, + int commitTimeoutInSeconds = 30, }) async { if (isClosed) { throw PostgreSQLException( @@ -415,7 +415,7 @@ abstract class _PostgreSQLExecutionContextMixin String fmtString, { Map substitutionValues = const {}, bool allowReuse = false, - int timeoutInSeconds = 0, + int timeoutInSeconds = 30, }) => _query( fmtString, @@ -466,7 +466,7 @@ abstract class _PostgreSQLExecutionContextMixin String fmtString, {Map substitutionValues = const {}, bool allowReuse = false, - int timeoutInSeconds = 0}) async { + int timeoutInSeconds = 30}) async { final rs = await query( fmtString, substitutionValues: substitutionValues, diff --git a/test/decode_test.dart b/test/decode_test.dart index b53adde..db07c28 100644 --- a/test/decode_test.dart +++ b/test/decode_test.dart @@ -34,7 +34,7 @@ void main() { 'VALUES (null, null, null, null, null, null, null, null, null, null, null, null, null)'); }); tearDown(() async { - await connection?.close(); + await connection.close(); }); test('Fetch em', () async { diff --git a/test/json_test.dart b/test/json_test.dart index 402363b..1e2c4c5 100644 --- a/test/json_test.dart +++ b/test/json_test.dart @@ -15,7 +15,7 @@ void main() { }); tearDown(() async { - await connection?.close(); + await connection.close(); }); group('Storage', () { diff --git a/test/map_return_test.dart b/test/map_return_test.dart index 5d7c518..074ec5d 100644 --- a/test/map_return_test.dart +++ b/test/map_return_test.dart @@ -31,7 +31,7 @@ void main() { }); tearDown(() async { - await connection?.close(); + await connection.close(); }); test('Get row map without specifying columns', () async { From 57d6e64dd3fe7029e8c7e90dbf35245fb7208d50 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Mon, 22 Feb 2021 21:24:08 -0800 Subject: [PATCH 06/33] nullable column description --- lib/src/binary_codec.dart | 2 +- lib/src/connection.dart | 28 ++++++++++++++++------------ lib/src/execution_context.dart | 4 ++-- lib/src/query.dart | 10 +++++----- test/query_test.dart | 12 ++++++------ 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/lib/src/binary_codec.dart b/lib/src/binary_codec.dart index 93aa9a4..43a93c4 100644 --- a/lib/src/binary_codec.dart +++ b/lib/src/binary_codec.dart @@ -169,7 +169,7 @@ class PostgresBinaryEncoder extends Converter { 'Invalid type for parameter value. Expected: String Got: ${value.runtimeType}'); } - final hexBytes = (value as String) + final hexBytes = value .toLowerCase() .codeUnits .where((c) => c != _dashUnit) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index 43cc090..d88f04f 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -358,13 +358,14 @@ class _OidCache { Future> _resolveTableNames( _PostgreSQLExecutionContextMixin c, - List? columns) async { + List? columns) async { if (columns == null) return []; //todo (joeconwaystk): If this was a cached query, resolving is table oids is unnecessary. // It's not a significant impact here, but an area for optimization. This includes // assigning resolvedTableName final unresolvedTableOIDs = columns - .map((f) => f.tableID) + .where((f) => f != null) + .map((f) => f!.tableID) .toSet() .where((oid) => oid > 0 && !_tableOIDNameMap.containsKey(oid)) .toList() @@ -375,7 +376,7 @@ class _OidCache { } return columns - .map((c) => c.change(tableName: _tableOIDNameMap[c.tableID])) + .map((c) => c!.change(tableName: _tableOIDNameMap[c.tableID])) .toList(); } @@ -446,12 +447,12 @@ abstract class _PostgreSQLExecutionContextMixin final queryResult = await _enqueue(query, timeoutInSeconds: timeoutInSeconds); - List? columnDescriptions = query.fieldDescriptions; + List? columnDescriptions = query.fieldDescriptions; if (resolveOids) { columnDescriptions = await _connection._oidCache ._resolveTableNames(this, columnDescriptions); } - final metaData = _PostgreSQLResultMetaData(columnDescriptions); + final metaData = _PostgreSQLResultMetaData(columnDescriptions!); return _PostgreSQLResult( queryResult.affectedRowCount, @@ -526,12 +527,15 @@ abstract class _PostgreSQLExecutionContextMixin } class _PostgreSQLResultMetaData { - final List columnDescriptions; + final List columnDescriptions; late List _tableNames; _PostgreSQLResultMetaData(this.columnDescriptions) { - _tableNames = - columnDescriptions.map((column) => column.tableName).toSet().toList(); + _tableNames = columnDescriptions + .where((column) => column != null) + .map((column) => column!.tableName) + .toSet() + .toList(); } List get tableNames { @@ -550,7 +554,7 @@ class _PostgreSQLResult extends UnmodifiableListView : super(rows); @override - List get columnDescriptions => + List get columnDescriptions => _metaData.columnDescriptions; } @@ -561,7 +565,7 @@ class _PostgreSQLResultRow extends UnmodifiableListView _PostgreSQLResultRow(this._metaData, List columns) : super(columns); @override - List get columnDescriptions => + List get columnDescriptions => _metaData.columnDescriptions; @override @@ -572,7 +576,7 @@ class _PostgreSQLResultRow extends UnmodifiableListView }); for (var i = 0; i < _metaData.columnDescriptions.length; i++) { final col = _metaData.columnDescriptions[i]; - rowMap[col.tableName]![col.columnName] = this[i]; + rowMap[col!.tableName]![col.columnName] = this[i]; } return rowMap; } @@ -582,7 +586,7 @@ class _PostgreSQLResultRow extends UnmodifiableListView final rowMap = {}; for (var i = 0; i < _metaData.columnDescriptions.length; i++) { final col = _metaData.columnDescriptions[i]; - rowMap[col.columnName] = this[i]; + rowMap[col!.columnName] = this[i]; } return rowMap; } diff --git a/lib/src/execution_context.dart b/lib/src/execution_context.dart index c5f0e0e..20e9b19 100644 --- a/lib/src/execution_context.dart +++ b/lib/src/execution_context.dart @@ -100,7 +100,7 @@ abstract class ColumnDescription { /// /// Column values can be accessed through the `[]` operator. abstract class PostgreSQLResultRow implements List { - List get columnDescriptions; + List get columnDescriptions; /// Returns a two-level map that on the first level contains the resolved /// table name, and on the second level the column name (or its alias). @@ -117,5 +117,5 @@ abstract class PostgreSQLResultRow implements List { abstract class PostgreSQLResult implements List { /// How many rows did this query affect? int get affectedRowCount; - List get columnDescriptions; + List get columnDescriptions; } diff --git a/lib/src/query.dart b/lib/src/query.dart index 14bf95a..7fd6ef8 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -39,11 +39,11 @@ class Query { CachedQuery? cache; final _onComplete = Completer>.sync(); - late List _fieldDescriptions; + List? _fieldDescriptions; - List get fieldDescriptions => _fieldDescriptions; + List? get fieldDescriptions => _fieldDescriptions; - set fieldDescriptions(List fds) { + set fieldDescriptions(List? fds) { _fieldDescriptions = fds; cache?.fieldDescriptions = fds; } @@ -135,11 +135,11 @@ class Query { } void addRow(List rawRowData) { - if (onlyReturnAffectedRowCount) { + if (onlyReturnAffectedRowCount || fieldDescriptions == null) { return; } - final iterator = fieldDescriptions.iterator; + final iterator = fieldDescriptions!.iterator; final lazyDecodedData = rawRowData.map((bd) { iterator.moveNext(); return iterator.current.converter.convert(bd); diff --git a/test/query_test.dart b/test/query_test.dart index 4fc66a4..01eb462 100644 --- a/test/query_test.dart +++ b/test/query_test.dart @@ -40,8 +40,8 @@ void main() { result = await connection.query('select t from t'); expect(result.columnDescriptions, hasLength(1)); - expect(result.columnDescriptions.single.tableName, 't'); - expect(result.columnDescriptions.single.columnName, 't'); + expect(result.columnDescriptions.single!.tableName, 't'); + expect(result.columnDescriptions.single!.columnName, 't'); expect(result, [expectedRow]); }); @@ -156,10 +156,10 @@ void main() { '01234567-89ab-cdef-0123-0123456789ab' ]; expect(result.columnDescriptions, hasLength(14)); - expect(result.columnDescriptions.first.tableName, 't'); - expect(result.columnDescriptions.first.columnName, 'i'); - expect(result.columnDescriptions.last.tableName, 't'); - expect(result.columnDescriptions.last.columnName, 'u'); + expect(result.columnDescriptions.first!.tableName, 't'); + expect(result.columnDescriptions.first!.columnName, 'i'); + expect(result.columnDescriptions.last!.tableName, 't'); + expect(result.columnDescriptions.last!.columnName, 'u'); expect(result, [expectedRow]); result = await connection.query( 'select i,s, bi, bs, bl, si, t, f, d, dt, ts, tsz, j, u from t'); From 603fa18913d11ac7fbd2a6d508f61250b43a03f1 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Mon, 22 Feb 2021 22:27:23 -0800 Subject: [PATCH 07/33] allow null key --- lib/src/connection.dart | 2 +- lib/src/execution_context.dart | 2 +- lib/src/query_queue.dart | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index d88f04f..383d1bd 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -463,7 +463,7 @@ abstract class _PostgreSQLExecutionContextMixin } @override - Future>>> mappedResultsQuery( + Future>>> mappedResultsQuery( String fmtString, {Map substitutionValues = const {}, bool allowReuse = false, diff --git a/lib/src/execution_context.dart b/lib/src/execution_context.dart index 20e9b19..1c76e8d 100644 --- a/lib/src/execution_context.dart +++ b/lib/src/execution_context.dart @@ -80,7 +80,7 @@ abstract class PostgreSQLExecutionContext { /// "company: {"name": "stable|kernel"} /// } /// ] - Future>>> mappedResultsQuery( + Future>>> mappedResultsQuery( String fmtString, {Map substitutionValues, bool allowReuse, diff --git a/lib/src/query_queue.dart b/lib/src/query_queue.dart index 09812dc..42ac683 100644 --- a/lib/src/query_queue.dart +++ b/lib/src/query_queue.dart @@ -31,7 +31,7 @@ class QueryQueue extends ListBase> // synchronous. scheduleMicrotask(() { existing.forEach((q) { - q.completeError(error!, stackTrace!); + q.completeError(error!, stackTrace); }); }); } From 3e37c2961185c2979bccac77565ae76a613bd5f8 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Mon, 22 Feb 2021 23:09:08 -0800 Subject: [PATCH 08/33] change to empty stacktrace --- lib/src/connection.dart | 5 +++-- lib/src/exceptions.dart | 8 +++++--- lib/src/query.dart | 2 +- lib/src/query_queue.dart | 2 +- lib/src/transaction_proxy.dart | 9 ++++++--- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index 383d1bd..c6e158c 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -250,7 +250,7 @@ class PostgreSQLConnection extends Object _connectionState.connection = this; } - Future _close([dynamic error, StackTrace? trace]) async { + Future _close([dynamic error, StackTrace trace = StackTrace.empty]) async { _connectionState = _PostgreSQLConnectionStateClosed(); if (_socket != null) { @@ -523,7 +523,8 @@ abstract class _PostgreSQLExecutionContextMixin } } - Future _onQueryError(Query query, dynamic error, [StackTrace? trace]) async {} + Future _onQueryError(Query query, dynamic error, + [StackTrace trace = StackTrace.empty]) async {} } class _PostgreSQLResultMetaData { diff --git a/lib/src/exceptions.dart b/lib/src/exceptions.dart index 33952e0..4f5d5a1 100644 --- a/lib/src/exceptions.dart +++ b/lib/src/exceptions.dart @@ -35,11 +35,13 @@ enum PostgreSQLSeverity { /// Exception thrown by [PostgreSQLConnection] instances. class PostgreSQLException implements Exception { PostgreSQLException(this.message, - {this.severity = PostgreSQLSeverity.error, this.stackTrace}) { + {this.severity = PostgreSQLSeverity.error, + this.stackTrace = StackTrace.empty}) { code = ''; } - PostgreSQLException._(List errorFields, {this.stackTrace}) { + PostgreSQLException._(List errorFields, + {this.stackTrace = StackTrace.empty}) { final finder = (int identifer) => (errorFields.firstWhere( (ErrorField e) => e.identificationToken == identifer, orElse: () => ErrorField(null, null))); @@ -106,7 +108,7 @@ class PostgreSQLException implements Exception { String? routineName; /// A [StackTrace] if available. - StackTrace? stackTrace; + StackTrace stackTrace; @override String toString() { diff --git a/lib/src/query.dart b/lib/src/query.dart index 7fd6ef8..8b4fb1e 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -161,7 +161,7 @@ class Query { _onComplete.complete(QueryResult(rowsAffected, rows as T)); } - void completeError(Object error, [StackTrace? stackTrace]) { + void completeError(Object error, [StackTrace stackTrace = StackTrace.empty]) { if (_onComplete.isCompleted) { return; } diff --git a/lib/src/query_queue.dart b/lib/src/query_queue.dart index 42ac683..ce9a676 100644 --- a/lib/src/query_queue.dart +++ b/lib/src/query_queue.dart @@ -20,7 +20,7 @@ class QueryQueue extends ListBase> return _inner.first; } - void cancel([Object? error, StackTrace? stackTrace]) { + void cancel([Object? error, StackTrace stackTrace = StackTrace.empty]) { _isCancelled = true; error ??= _cancellationException; final existing = _inner; diff --git a/lib/src/transaction_proxy.dart b/lib/src/transaction_proxy.dart index a375118..7fe79cd 100644 --- a/lib/src/transaction_proxy.dart +++ b/lib/src/transaction_proxy.dart @@ -70,7 +70,8 @@ class _TransactionProxy extends Object } } - Future _cancelAndRollback(dynamic object, [StackTrace? trace]) async { + Future _cancelAndRollback(dynamic object, + [StackTrace trace = StackTrace.empty]) async { if (_hasRolledBack) { return; } @@ -106,7 +107,8 @@ class _TransactionProxy extends Object } } - Future _transactionFailed(dynamic error, [StackTrace? trace]) async { + Future _transactionFailed(dynamic error, + [StackTrace trace = StackTrace.empty]) async { if (_hasFailed) { return; } @@ -117,7 +119,8 @@ class _TransactionProxy extends Object } @override - Future _onQueryError(Query query, dynamic error, [StackTrace? trace]) { + Future _onQueryError(Query query, dynamic error, + [StackTrace trace = StackTrace.empty]) { return _transactionFailed(error, trace); } } From 16700fd8199d759cf3bc64f538d13441f434fa38 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Mon, 22 Feb 2021 23:31:58 -0800 Subject: [PATCH 09/33] revert stacktrace --- lib/src/connection.dart | 5 ++--- lib/src/exceptions.dart | 8 +++----- lib/src/query.dart | 2 +- lib/src/query_queue.dart | 2 +- lib/src/transaction_proxy.dart | 9 +++------ test/connection_test.dart | 6 ++++-- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index c6e158c..383d1bd 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -250,7 +250,7 @@ class PostgreSQLConnection extends Object _connectionState.connection = this; } - Future _close([dynamic error, StackTrace trace = StackTrace.empty]) async { + Future _close([dynamic error, StackTrace? trace]) async { _connectionState = _PostgreSQLConnectionStateClosed(); if (_socket != null) { @@ -523,8 +523,7 @@ abstract class _PostgreSQLExecutionContextMixin } } - Future _onQueryError(Query query, dynamic error, - [StackTrace trace = StackTrace.empty]) async {} + Future _onQueryError(Query query, dynamic error, [StackTrace? trace]) async {} } class _PostgreSQLResultMetaData { diff --git a/lib/src/exceptions.dart b/lib/src/exceptions.dart index 4f5d5a1..33952e0 100644 --- a/lib/src/exceptions.dart +++ b/lib/src/exceptions.dart @@ -35,13 +35,11 @@ enum PostgreSQLSeverity { /// Exception thrown by [PostgreSQLConnection] instances. class PostgreSQLException implements Exception { PostgreSQLException(this.message, - {this.severity = PostgreSQLSeverity.error, - this.stackTrace = StackTrace.empty}) { + {this.severity = PostgreSQLSeverity.error, this.stackTrace}) { code = ''; } - PostgreSQLException._(List errorFields, - {this.stackTrace = StackTrace.empty}) { + PostgreSQLException._(List errorFields, {this.stackTrace}) { final finder = (int identifer) => (errorFields.firstWhere( (ErrorField e) => e.identificationToken == identifer, orElse: () => ErrorField(null, null))); @@ -108,7 +106,7 @@ class PostgreSQLException implements Exception { String? routineName; /// A [StackTrace] if available. - StackTrace stackTrace; + StackTrace? stackTrace; @override String toString() { diff --git a/lib/src/query.dart b/lib/src/query.dart index 8b4fb1e..7fd6ef8 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -161,7 +161,7 @@ class Query { _onComplete.complete(QueryResult(rowsAffected, rows as T)); } - void completeError(Object error, [StackTrace stackTrace = StackTrace.empty]) { + void completeError(Object error, [StackTrace? stackTrace]) { if (_onComplete.isCompleted) { return; } diff --git a/lib/src/query_queue.dart b/lib/src/query_queue.dart index ce9a676..42ac683 100644 --- a/lib/src/query_queue.dart +++ b/lib/src/query_queue.dart @@ -20,7 +20,7 @@ class QueryQueue extends ListBase> return _inner.first; } - void cancel([Object? error, StackTrace stackTrace = StackTrace.empty]) { + void cancel([Object? error, StackTrace? stackTrace]) { _isCancelled = true; error ??= _cancellationException; final existing = _inner; diff --git a/lib/src/transaction_proxy.dart b/lib/src/transaction_proxy.dart index 7fe79cd..a375118 100644 --- a/lib/src/transaction_proxy.dart +++ b/lib/src/transaction_proxy.dart @@ -70,8 +70,7 @@ class _TransactionProxy extends Object } } - Future _cancelAndRollback(dynamic object, - [StackTrace trace = StackTrace.empty]) async { + Future _cancelAndRollback(dynamic object, [StackTrace? trace]) async { if (_hasRolledBack) { return; } @@ -107,8 +106,7 @@ class _TransactionProxy extends Object } } - Future _transactionFailed(dynamic error, - [StackTrace trace = StackTrace.empty]) async { + Future _transactionFailed(dynamic error, [StackTrace? trace]) async { if (_hasFailed) { return; } @@ -119,8 +117,7 @@ class _TransactionProxy extends Object } @override - Future _onQueryError(Query query, dynamic error, - [StackTrace trace = StackTrace.empty]) { + Future _onQueryError(Query query, dynamic error, [StackTrace? trace]) { return _transactionFailed(error, trace); } } diff --git a/test/connection_test.dart b/test/connection_test.dart index 189855f..ceeb9b1 100644 --- a/test/connection_test.dart +++ b/test/connection_test.dart @@ -446,11 +446,13 @@ void main() { group('Network error situations', () { late ServerSocket serverSocket; - late Socket socket; + Socket? socket; tearDown(() async { await serverSocket.close(); - await socket.close(); + if (socket != null) { + await socket!.close(); + } }); test( From c17db31c5a033367be02740608a367f9c314ed97 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Mon, 22 Feb 2021 23:47:30 -0800 Subject: [PATCH 10/33] query null result --- lib/src/connection.dart | 14 +++++++++++--- lib/src/execution_context.dart | 2 +- test/connection_test.dart | 14 ++++++++------ test/decode_test.dart | 2 +- test/encoding_test.dart | 2 +- test/query_test.dart | 8 ++++---- 6 files changed, 26 insertions(+), 16 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index 383d1bd..e38c6c9 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -390,8 +390,12 @@ class _OidCache { resolveOids: false, ); + if (orderedTableNames == null) { + return; + } + final iterator = oids.iterator; - orderedTableNames.forEach((tableName) { + orderedTableNames!.forEach((tableName) { iterator.moveNext(); if (tableName.first != null) { _tableOIDNameMap[iterator.current] = tableName.first as String; @@ -412,7 +416,7 @@ abstract class _PostgreSQLExecutionContextMixin int get queueSize => _queue.length; @override - Future query( + Future query( String fmtString, { Map substitutionValues = const {}, bool allowReuse = false, @@ -425,7 +429,7 @@ abstract class _PostgreSQLExecutionContextMixin timeoutInSeconds: timeoutInSeconds, ); - Future _query( + Future _query( String fmtString, { Map substitutionValues = const {}, bool allowReuse = true, @@ -474,6 +478,10 @@ abstract class _PostgreSQLExecutionContextMixin allowReuse: allowReuse, timeoutInSeconds: timeoutInSeconds, ); + + if (rs == null) { + return Future.value(); + } return rs.map((row) => row.toTableColumnMap()).toList(); } diff --git a/lib/src/execution_context.dart b/lib/src/execution_context.dart index 1c76e8d..c888994 100644 --- a/lib/src/execution_context.dart +++ b/lib/src/execution_context.dart @@ -29,7 +29,7 @@ abstract class PostgreSQLExecutionContext { /// By default, instances of this class will reuse queries. This allows significantly more efficient transport to and from the database. You do not have to do /// anything to opt in to this behavior, this connection will track the necessary information required to reuse queries without intervention. (The [fmtString] is /// the unique identifier to look up reuse information.) You can disable reuse by passing false for [allowReuse]. - Future query(String fmtString, + Future query(String fmtString, {Map substitutionValues, bool allowReuse, int timeoutInSeconds}); diff --git a/test/connection_test.dart b/test/connection_test.dart index ceeb9b1..ccb46e4 100644 --- a/test/connection_test.dart +++ b/test/connection_test.dart @@ -445,11 +445,13 @@ void main() { }); group('Network error situations', () { - late ServerSocket serverSocket; + ServerSocket? serverSocket; Socket? socket; tearDown(() async { - await serverSocket.close(); + if (serverSocket != null) { + await serverSocket!.close(); + } if (socket != null) { await socket!.close(); } @@ -491,7 +493,7 @@ void main() { () async { serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 5433); - serverSocket.listen((s) { + serverSocket!.listen((s) { socket = s; // Don't respond on purpose s.listen((bytes) {}); @@ -515,7 +517,7 @@ void main() { () async { serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 5433); - serverSocket.listen((s) { + serverSocket!.listen((s) { socket = s; // Don't respond on purpose s.listen((bytes) {}); @@ -539,7 +541,7 @@ void main() { final openCompleter = Completer(); serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 5433); - serverSocket.listen((s) { + serverSocket!.listen((s) { socket = s; // Don't respond on purpose s.listen((bytes) {}); @@ -565,7 +567,7 @@ void main() { final openCompleter = Completer(); serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 5433); - serverSocket.listen((s) { + serverSocket!.listen((s) { socket = s; // Don't respond on purpose s.listen((bytes) {}); diff --git a/test/decode_test.dart b/test/decode_test.dart index db07c28..4a279cf 100644 --- a/test/decode_test.dart +++ b/test/decode_test.dart @@ -40,7 +40,7 @@ void main() { test('Fetch em', () async { final res = await connection.query('select * from t'); - final row1 = res[0]; + final row1 = res![0]; final row2 = res[1]; final row3 = res[2]; diff --git a/test/encoding_test.dart b/test/encoding_test.dart index a053e92..c64d15c 100644 --- a/test/encoding_test.dart +++ b/test/encoding_test.dart @@ -393,7 +393,7 @@ Future expectInverse(dynamic value, PostgreSQLDataType dataType) async { final result = await conn.query( 'INSERT INTO t (v) VALUES (${PostgreSQLFormat.id('v', type: dataType)}) RETURNING v', substitutionValues: {'v': value}); - expect(result.first.first, equals(value)); + expect(result!.first.first, equals(value)); final encoder = PostgresBinaryEncoder(dataType); final encodedValue = encoder.convert(value); diff --git a/test/query_test.dart b/test/query_test.dart index 01eb462..cab3360 100644 --- a/test/query_test.dart +++ b/test/query_test.dart @@ -39,7 +39,7 @@ void main() { expect(result, [expectedRow]); result = await connection.query('select t from t'); - expect(result.columnDescriptions, hasLength(1)); + expect(result!.columnDescriptions, hasLength(1)); expect(result.columnDescriptions.single!.tableName, 't'); expect(result.columnDescriptions.single!.columnName, 't'); expect(result, [expectedRow]); @@ -155,7 +155,7 @@ void main() { {'a': 'b'}, '01234567-89ab-cdef-0123-0123456789ab' ]; - expect(result.columnDescriptions, hasLength(14)); + expect(result!.columnDescriptions, hasLength(14)); expect(result.columnDescriptions.first!.tableName, 't'); expect(result.columnDescriptions.first!.columnName, 'i'); expect(result.columnDescriptions.last!.tableName, 't'); @@ -365,13 +365,13 @@ void main() { () async { final rs1 = await connection .query('SELECT * FROM (VALUES (\'user@domain.com\')) t1 (col1)'); - expect(rs1.first.toColumnMap(), {'col1': 'user@domain.com'}); + expect(rs1!.first.toColumnMap(), {'col1': 'user@domain.com'}); final rs2 = await connection.query( 'SELECT * FROM (VALUES (\'user@domain.com\')) t1 (col1) WHERE col1 > @u1', substitutionValues: {'u1': 'hello@domain.com'}, ); - expect(rs2.first.toColumnMap(), {'col1': 'user@domain.com'}); + expect(rs2!.first.toColumnMap(), {'col1': 'user@domain.com'}); }); test('Wrong type for parameter in substitution values fails', () async { From e0fa64fef4571e2d7909a0a6ff593ddc3d6a4b1d Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 23 Feb 2021 00:39:58 -0800 Subject: [PATCH 11/33] nullable execute --- lib/src/connection.dart | 6 +++--- lib/src/execution_context.dart | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index e38c6c9..d28e305 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -395,7 +395,7 @@ class _OidCache { } final iterator = oids.iterator; - orderedTableNames!.forEach((tableName) { + orderedTableNames.forEach((tableName) { iterator.moveNext(); if (tableName.first != null) { _tableOIDNameMap[iterator.current] = tableName.first as String; @@ -451,7 +451,7 @@ abstract class _PostgreSQLExecutionContextMixin final queryResult = await _enqueue(query, timeoutInSeconds: timeoutInSeconds); - List? columnDescriptions = query.fieldDescriptions; + var columnDescriptions = query.fieldDescriptions; if (resolveOids) { columnDescriptions = await _connection._oidCache ._resolveTableNames(this, columnDescriptions); @@ -486,7 +486,7 @@ abstract class _PostgreSQLExecutionContextMixin } @override - Future execute(String fmtString, + Future execute(String fmtString, {Map substitutionValues = const {}, int? timeoutInSeconds}) async { timeoutInSeconds ??= _connection.queryTimeoutInSeconds; diff --git a/lib/src/execution_context.dart b/lib/src/execution_context.dart index c888994..33a3997 100644 --- a/lib/src/execution_context.dart +++ b/lib/src/execution_context.dart @@ -41,7 +41,7 @@ abstract class PostgreSQLExecutionContext { /// This method returns the number of rows affected and no additional information. This method uses the least efficient and less secure command /// for executing queries in the PostgreSQL protocol; [query] is preferred for queries that will be executed more than once, will contain user input, /// or return rows. - Future execute(String fmtString, + Future execute(String fmtString, {Map substitutionValues, int timeoutInSeconds}); /// Cancels a transaction on this context. From be96021b73c6e9a601562a23c7ca3326c4060fb1 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 23 Feb 2021 18:58:10 -0800 Subject: [PATCH 12/33] nullable future --- lib/src/connection.dart | 18 ++++++++++-------- lib/src/query.dart | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index d28e305..d5380dc 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -458,12 +458,14 @@ abstract class _PostgreSQLExecutionContextMixin } final metaData = _PostgreSQLResultMetaData(columnDescriptions!); - return _PostgreSQLResult( - queryResult.affectedRowCount, - metaData, - queryResult.value! - .map((columns) => _PostgreSQLResultRow(metaData, columns)) - .toList()); + return queryResult != null + ? _PostgreSQLResult( + queryResult.affectedRowCount, + metaData, + queryResult.value! + .map((columns) => _PostgreSQLResultRow(metaData, columns)) + .toList()) + : null; } @override @@ -500,13 +502,13 @@ abstract class _PostgreSQLExecutionContextMixin onlyReturnAffectedRowCount: true); final result = await _enqueue(query, timeoutInSeconds: timeoutInSeconds); - return result.affectedRowCount; + return result != null ? result.affectedRowCount : null; } @override void cancelTransaction({String reason}); - Future> _enqueue(Query query, + Future?> _enqueue(Query query, {int timeoutInSeconds = 30}) async { if (_queue.add(query)) { _connection._transitionToState(_connection._connectionState.awake()); diff --git a/lib/src/query.dart b/lib/src/query.dart index 7fd6ef8..02c3ead 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -26,7 +26,7 @@ class Query { String? statementIdentifier; - Future> get future => _onComplete.future; + Future?> get future => _onComplete.future; final String statement; final Map substitutionValues; From 2affed04d569da6a24201db7b727e1d1d9a17bd3 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 23 Feb 2021 19:05:36 -0800 Subject: [PATCH 13/33] oops forgot --- lib/src/query.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/query.dart b/lib/src/query.dart index 02c3ead..5585058 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -38,7 +38,7 @@ class Query { CachedQuery? cache; - final _onComplete = Completer>.sync(); + final _onComplete = Completer?>.sync(); List? _fieldDescriptions; List? get fieldDescriptions => _fieldDescriptions; From daaedfe8ca6d75679af29c729322d4a933d99db7 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 23 Feb 2021 19:25:00 -0800 Subject: [PATCH 14/33] nullable tablename --- lib/src/connection.dart | 8 ++++---- lib/src/execution_context.dart | 4 ++-- lib/src/query.dart | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index d5380dc..b32b5a9 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -538,7 +538,7 @@ abstract class _PostgreSQLExecutionContextMixin class _PostgreSQLResultMetaData { final List columnDescriptions; - late List _tableNames; + late List _tableNames; _PostgreSQLResultMetaData(this.columnDescriptions) { _tableNames = columnDescriptions @@ -548,7 +548,7 @@ class _PostgreSQLResultMetaData { .toList(); } - List get tableNames { + List get tableNames { return _tableNames; } } @@ -579,8 +579,8 @@ class _PostgreSQLResultRow extends UnmodifiableListView _metaData.columnDescriptions; @override - Map> toTableColumnMap() { - final rowMap = >{}; + Map> toTableColumnMap() { + final rowMap = >{}; _metaData.tableNames.forEach((tableName) { rowMap[tableName] = {}; }); diff --git a/lib/src/execution_context.dart b/lib/src/execution_context.dart index 33a3997..f532556 100644 --- a/lib/src/execution_context.dart +++ b/lib/src/execution_context.dart @@ -93,7 +93,7 @@ abstract class ColumnDescription { String get columnName; /// The resolved name of the referenced table. - String get tableName; + String? get tableName; } /// A single row of a query result. @@ -104,7 +104,7 @@ abstract class PostgreSQLResultRow implements List { /// Returns a two-level map that on the first level contains the resolved /// table name, and on the second level the column name (or its alias). - Map> toTableColumnMap(); + Map> toTableColumnMap(); /// Returns a single-level map that maps the column name (or its alias) to the /// value returned on that position. diff --git a/lib/src/query.dart b/lib/src/query.dart index 5585058..83ae0cf 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -244,7 +244,7 @@ class FieldDescription implements ColumnDescription { final int formatCode; @override - final String tableName; + final String? tableName; FieldDescription._( this.converter, @@ -281,7 +281,7 @@ class FieldDescription implements ColumnDescription { return FieldDescription._( converter, fieldName, tableID, columnID, typeID, dataTypeSize, typeModifier, formatCode, - '', // tableName + null, // tableName ); } From 430ceb1c55734d05bd698843b192516510b00df1 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 23 Feb 2021 21:07:08 -0800 Subject: [PATCH 15/33] overwritten reuse bool error --- lib/src/connection.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index b32b5a9..c472076 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -419,7 +419,7 @@ abstract class _PostgreSQLExecutionContextMixin Future query( String fmtString, { Map substitutionValues = const {}, - bool allowReuse = false, + bool allowReuse = true, int timeoutInSeconds = 30, }) => _query( @@ -432,7 +432,7 @@ abstract class _PostgreSQLExecutionContextMixin Future _query( String fmtString, { Map substitutionValues = const {}, - bool allowReuse = true, + required bool allowReuse, int? timeoutInSeconds, bool resolveOids = true, }) async { From e8026d8aec81b3ed0cecd7a1e1bfe137e5ff15aa Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 23 Feb 2021 21:14:05 -0800 Subject: [PATCH 16/33] encoding empty string --- lib/src/binary_codec.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/binary_codec.dart b/lib/src/binary_codec.dart index 43a93c4..1ec421f 100644 --- a/lib/src/binary_codec.dart +++ b/lib/src/binary_codec.dart @@ -215,7 +215,7 @@ class PostgresBinaryDecoder extends Converter { final dataType = typeMap[typeCode]; if (value.isEmpty) { - return null; + return ''; } final buffer = From 17bac0ccccbdc7db45321adea04f0f180423426a Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 23 Feb 2021 21:22:17 -0800 Subject: [PATCH 17/33] encoding empty string --- lib/src/binary_codec.dart | 8 ++++---- lib/src/query.dart | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/src/binary_codec.dart b/lib/src/binary_codec.dart index 1ec421f..0248cd0 100644 --- a/lib/src/binary_codec.dart +++ b/lib/src/binary_codec.dart @@ -28,15 +28,15 @@ final _hex = [ 'f', ]; -class PostgresBinaryEncoder extends Converter { +class PostgresBinaryEncoder extends Converter { final PostgreSQLDataType _dataType; const PostgresBinaryEncoder(this._dataType); @override - Uint8List convert(dynamic value) { + Uint8List? convert(dynamic value) { if (value == null) { - return Uint8List.fromList([]); + return null; } switch (_dataType) { @@ -215,7 +215,7 @@ class PostgresBinaryDecoder extends Converter { final dataType = typeMap[typeCode]; if (value.isEmpty) { - return ''; + return null; } final buffer = diff --git a/lib/src/query.dart b/lib/src/query.dart index 83ae0cf..84ab0b7 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -209,8 +209,8 @@ class ParameterValue { dynamic value, PostgreSQLDataType postgresType) { final converter = PostgresBinaryEncoder(postgresType); final bytes = converter.convert(value); - final length = bytes.length; - return ParameterValue._(true, bytes, length); + final length = bytes?.length; + return ParameterValue._(true, bytes, length ?? 0); } factory ParameterValue.text(dynamic value) { From 0a981d7da53d785c728231c5b4cecb1b28178a57 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 23 Feb 2021 22:07:46 -0800 Subject: [PATCH 18/33] more encoding decoding stuff --- lib/src/binary_codec.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/binary_codec.dart b/lib/src/binary_codec.dart index 0248cd0..115d2e0 100644 --- a/lib/src/binary_codec.dart +++ b/lib/src/binary_codec.dart @@ -211,13 +211,13 @@ class PostgresBinaryDecoder extends Converter { final int typeCode; @override - dynamic convert(Uint8List value) { - final dataType = typeMap[typeCode]; - - if (value.isEmpty) { + dynamic convert(Uint8List? value) { + if (value == null || value.isEmpty) { return null; } + final dataType = typeMap[typeCode]; + final buffer = ByteData.view(value.buffer, value.offsetInBytes, value.lengthInBytes); From 62381ebf01014052507dbbe4e30173724cc0ff41 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 23 Feb 2021 23:18:45 -0800 Subject: [PATCH 19/33] linting --- test/connection_test.dart | 2 -- test/transaction_test.dart | 8 ++++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test/connection_test.dart b/test/connection_test.dart index ccb46e4..2712c0b 100644 --- a/test/connection_test.dart +++ b/test/connection_test.dart @@ -344,7 +344,6 @@ void main() { await conn.execute('CREATE TEMPORARY TABLE t (i int unique)'); await conn.execute('INSERT INTO t (i) VALUES (1)'); - //ignore: unawaited_futures conn.execute('INSERT INTO t (i) VALUES (1)').catchError((err) { // ignore }); @@ -389,7 +388,6 @@ void main() { final orderEnsurer = []; // this will emit a query error - //ignore: unawaited_futures conn.execute('INSERT INTO t (i) VALUES (1)').catchError((err) { orderEnsurer.add(1); // ignore diff --git a/test/transaction_test.dart b/test/transaction_test.dart index 50ed9c6..49d39f2 100644 --- a/test/transaction_test.dart +++ b/test/transaction_test.dart @@ -248,8 +248,12 @@ void main() { () async { final errs = []; await conn.transaction((ctx) async { - ctx.query('INSERT INTO t (id) VALUES (1)').catchError(errs.add); - ctx.query('INSERT INTO t (id) VALUES (2)').catchError(errs.add); + final errsAdd = (e) { + errs.add(e); + return null; + }; + ctx.query('INSERT INTO t (id) VALUES (1)').catchError(errsAdd); + ctx.query('INSERT INTO t (id) VALUES (2)').catchError(errsAdd); ctx.cancelTransaction(); ctx.query('INSERT INTO t (id) VALUES (3)').catchError((e) {}); }); From 39e4461cb86bcd3a645d94c0a1e2de9afe43e6b5 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Wed, 24 Feb 2021 22:00:37 -0800 Subject: [PATCH 20/33] consistency --- lib/src/query.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/query.dart b/lib/src/query.dart index 84ab0b7..18db4eb 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -209,8 +209,8 @@ class ParameterValue { dynamic value, PostgreSQLDataType postgresType) { final converter = PostgresBinaryEncoder(postgresType); final bytes = converter.convert(value); - final length = bytes?.length; - return ParameterValue._(true, bytes, length ?? 0); + final length = bytes?.length ?? 0; + return ParameterValue._(true, bytes, length); } factory ParameterValue.text(dynamic value) { From 9d0851ac53ebead57f8b7fa5b27c619ed5b49abe Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Thu, 25 Feb 2021 01:16:45 -0800 Subject: [PATCH 21/33] own worst enemy --- lib/src/binary_codec.dart | 2 +- lib/src/connection.dart | 7 ++----- lib/src/query.dart | 2 +- lib/src/server_messages.dart | 4 ++-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/src/binary_codec.dart b/lib/src/binary_codec.dart index 115d2e0..aa4c75b 100644 --- a/lib/src/binary_codec.dart +++ b/lib/src/binary_codec.dart @@ -212,7 +212,7 @@ class PostgresBinaryDecoder extends Converter { @override dynamic convert(Uint8List? value) { - if (value == null || value.isEmpty) { + if (value == null) { return null; } diff --git a/lib/src/connection.dart b/lib/src/connection.dart index c472076..6999147 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -541,11 +541,8 @@ class _PostgreSQLResultMetaData { late List _tableNames; _PostgreSQLResultMetaData(this.columnDescriptions) { - _tableNames = columnDescriptions - .where((column) => column != null) - .map((column) => column!.tableName) - .toSet() - .toList(); + _tableNames = + columnDescriptions.map((column) => column!.tableName).toSet().toList(); } List get tableNames { diff --git a/lib/src/query.dart b/lib/src/query.dart index 18db4eb..093a703 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -134,7 +134,7 @@ class Query { return null; } - void addRow(List rawRowData) { + void addRow(List rawRowData) { if (onlyReturnAffectedRowCount || fieldDescriptions == null) { return; } diff --git a/lib/src/server_messages.dart b/lib/src/server_messages.dart index 1eab22b..709a659 100644 --- a/lib/src/server_messages.dart +++ b/lib/src/server_messages.dart @@ -115,7 +115,7 @@ class RowDescriptionMessage extends ServerMessage { } class DataRowMessage extends ServerMessage { - final values = []; + final values = []; DataRowMessage(Uint8List bytes) { final reader = ByteDataReader()..add(bytes); @@ -127,7 +127,7 @@ class DataRowMessage extends ServerMessage { if (dataSize == 0) { values.add(Uint8List(0)); } else if (dataSize == -1) { - values.add(Uint8List.fromList([])); + values.add(null); } else { final rawBytes = reader.read(dataSize); values.add(rawBytes); From e741fa0a49188bc120356713f78ce26231b336c5 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sat, 27 Feb 2021 16:27:11 -0800 Subject: [PATCH 22/33] change params to nullable and revert port --- lib/src/connection.dart | 11 ++-- lib/src/connection_fsm.dart | 11 ++-- lib/src/query.dart | 10 +-- lib/src/substituter.dart | 6 +- lib/src/transaction_proxy.dart | 2 +- test/connection_test.dart | 114 ++++++++++++++++----------------- 6 files changed, 77 insertions(+), 77 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index 6999147..a0977b3 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -40,8 +40,8 @@ class PostgreSQLConnection extends Object /// [useSSL] when true, uses a secure socket when connecting to a PostgreSQL database. PostgreSQLConnection( this.host, + this.port, this.databaseName, { - this.port = 5432, this.username, this.password, this.timeoutInSeconds = 30, @@ -215,7 +215,7 @@ class PostgreSQLConnection extends Object /// default query timeout will be used. Future transaction( Future Function(PostgreSQLExecutionContext connection) queryBlock, { - int commitTimeoutInSeconds = 30, + int? commitTimeoutInSeconds, }) async { if (isClosed) { throw PostgreSQLException( @@ -418,7 +418,7 @@ abstract class _PostgreSQLExecutionContextMixin @override Future query( String fmtString, { - Map substitutionValues = const {}, + Map? substitutionValues, bool allowReuse = true, int timeoutInSeconds = 30, }) => @@ -431,7 +431,7 @@ abstract class _PostgreSQLExecutionContextMixin Future _query( String fmtString, { - Map substitutionValues = const {}, + Map? substitutionValues, required bool allowReuse, int? timeoutInSeconds, bool resolveOids = true, @@ -489,8 +489,7 @@ abstract class _PostgreSQLExecutionContextMixin @override Future execute(String fmtString, - {Map substitutionValues = const {}, - int? timeoutInSeconds}) async { + {Map? substitutionValues, int? timeoutInSeconds}) async { timeoutInSeconds ??= _connection.queryTimeoutInSeconds; if (_connection.isClosed) { throw PostgreSQLException( diff --git a/lib/src/connection_fsm.dart b/lib/src/connection_fsm.dart index 9a3b899..788e9da 100644 --- a/lib/src/connection_fsm.dart +++ b/lib/src/connection_fsm.dart @@ -255,12 +255,13 @@ class _PostgreSQLConnectionStateBusy extends _PostgreSQLConnectionState { // print("(${query.statement}) -> $message"); if (message is ReadyForQueryMessage) { + if (message.state == ReadyForQueryMessage.StateTransactionError) { + query.completeError(returningException!); + return _PostgreSQLConnectionStateReadyInTransaction( + query.transaction as _TransactionProxy); + } + if (returningException != null) { - if (message.state == ReadyForQueryMessage.StateTransactionError) { - query.completeError(returningException!); - return _PostgreSQLConnectionStateReadyInTransaction( - query.transaction as _TransactionProxy); - } query.completeError(returningException!); } else { query.complete(rowsAffected); diff --git a/lib/src/query.dart b/lib/src/query.dart index 093a703..008f4fa 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -29,7 +29,7 @@ class Query { Future?> get future => _onComplete.future; final String statement; - final Map substitutionValues; + final Map? substitutionValues; final PostgreSQLExecutionContext transaction; final PostgreSQLConnection connection; @@ -96,7 +96,7 @@ class Query { } void sendCachedQuery(Socket socket, CachedQuery cacheQuery, - Map substitutionValues) { + Map? substitutionValues) { final statementName = cacheQuery.preparedStatementName; final parameterList = cacheQuery.orderedParameters! .map((identifier) => ParameterValue(identifier, substitutionValues)) @@ -196,13 +196,13 @@ class CachedQuery { class ParameterValue { factory ParameterValue(PostgreSQLFormatIdentifier identifier, - Map substitutionValues) { + Map? substitutionValues) { if (identifier.type == null) { - return ParameterValue.text(substitutionValues[identifier.name]); + return ParameterValue.text(substitutionValues?[identifier.name]); } return ParameterValue.binary( - substitutionValues[identifier.name], identifier.type!); + substitutionValues?[identifier.name], identifier.type!); } factory ParameterValue.binary( diff --git a/lib/src/substituter.dart b/lib/src/substituter.dart index f97038a..1afc484 100644 --- a/lib/src/substituter.dart +++ b/lib/src/substituter.dart @@ -52,10 +52,10 @@ class PostgreSQLFormat { } } - static String substitute(String fmtString, Map values, + static String substitute(String fmtString, Map? values, {SQLReplaceIdentifierFunction? replace}) { final converter = PostgresTextEncoder(); - replace ??= (spec, index) => converter.convert(values[spec.name]); + replace ??= (spec, index) => converter.convert(values?[spec.name]); final items = []; PostgreSQLFormatToken? currentPtr; @@ -114,7 +114,7 @@ class PostgreSQLFormat { } else { final identifier = PostgreSQLFormatIdentifier(t.buffer.toString()); - if (!values.containsKey(identifier.name)) { + if (values != null && !values.containsKey(identifier.name)) { // Format string specified identifier with name ${identifier.name}, // but key was not present in values. return t.buffer; diff --git a/lib/src/transaction_proxy.dart b/lib/src/transaction_proxy.dart index a375118..077345f 100644 --- a/lib/src/transaction_proxy.dart +++ b/lib/src/transaction_proxy.dart @@ -30,7 +30,7 @@ class _TransactionProxy extends Object PostgreSQLExecutionContext get _transaction => this; final _TransactionQuerySignature executionBlock; - final int commitTimeoutInSeconds; + final int? commitTimeoutInSeconds; bool _hasFailed = false; bool _hasRolledBack = false; diff --git a/test/connection_test.dart b/test/connection_test.dart index 2712c0b..48c87a7 100644 --- a/test/connection_test.dart +++ b/test/connection_test.dart @@ -17,8 +17,8 @@ void main() { }); test('Connect with md5 auth required', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await conn.open(); @@ -26,8 +26,8 @@ void main() { }); test('SSL Connect with md5 auth required', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart', useSSL: true); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart', useSSL: true); await conn.open(); @@ -41,16 +41,16 @@ void main() { }); test('Connect with no auth required', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust'); await conn.open(); expect(await conn.execute('select 1'), equals(1)); }); test('SSL Connect with no auth required', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust', useSSL: true); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust', useSSL: true); await conn.open(); expect(await conn.execute('select 1'), equals(1)); @@ -58,8 +58,8 @@ void main() { test('Closing idle connection succeeds, closes underlying socket', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust'); await conn.open(); await conn.close(); @@ -74,8 +74,8 @@ void main() { test('SSL Closing idle connection succeeds, closes underlying socket', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust', useSSL: true); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust', useSSL: true); await conn.open(); await conn.close(); @@ -91,8 +91,8 @@ void main() { test( 'Closing connection while busy succeeds, queued queries are all accounted for (canceled), closes underlying socket', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust'); await conn.open(); final errors = []; @@ -118,8 +118,8 @@ void main() { test( 'SSL Closing connection while busy succeeds, queued queries are all accounted for (canceled), closes underlying socket', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust', useSSL: true); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust', useSSL: true); await conn.open(); final errors = []; @@ -147,8 +147,8 @@ void main() { late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust'); await conn.open(); }); @@ -229,8 +229,8 @@ void main() { }); test('Sending queries to opening connection triggers error', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust'); openFuture = conn.open(); try { @@ -242,8 +242,8 @@ void main() { }); test('SSL Sending queries to opening connection triggers error', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust', useSSL: true); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust', useSSL: true); openFuture = conn.open(); try { @@ -256,8 +256,8 @@ void main() { test('Starting transaction while opening connection triggers error', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust'); openFuture = conn.open(); try { @@ -272,8 +272,8 @@ void main() { test('SSL Starting transaction while opening connection triggers error', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust', useSSL: true); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust', useSSL: true); openFuture = conn.open(); try { @@ -288,8 +288,8 @@ void main() { test('Invalid password reports error, conn is closed, disables conn', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'notdart'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'notdart'); try { await conn.open(); @@ -303,8 +303,8 @@ void main() { test('SSL Invalid password reports error, conn is closed, disables conn', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'notdart', useSSL: true); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'notdart', useSSL: true); try { await conn.open(); @@ -318,8 +318,8 @@ void main() { test('A query error maintains connectivity, allows future queries', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (i int unique)'); @@ -337,8 +337,8 @@ void main() { test( 'A query error maintains connectivity, continues processing pending queries', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (i int unique)'); @@ -378,8 +378,8 @@ void main() { test( 'A query error maintains connectivity, continues processing pending transactions', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (i int unique)'); @@ -409,8 +409,8 @@ void main() { test( 'Building query throws error, connection continues processing pending queries', () async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'darttrust'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'darttrust'); await conn.open(); // Make some async queries that'll exit the event loop, but then fail on a query that'll die early @@ -458,7 +458,7 @@ void main() { test( 'Socket fails to connect reports error, disables connection for future use', () async { - final conn = PostgreSQLConnection('localhost', 'dart_test', port: 5431); + final conn = PostgreSQLConnection('localhost', 5431, 'dart_test'); try { await conn.open(); @@ -473,8 +473,8 @@ void main() { test( 'SSL Socket fails to connect reports error, disables connection for future use', () async { - final conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5431, useSSL: true); + final conn = + PostgreSQLConnection('localhost', 5431, 'dart_test', useSSL: true); try { await conn.open(); @@ -497,8 +497,8 @@ void main() { s.listen((bytes) {}); }); - final conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5433, timeoutInSeconds: 2); + final conn = PostgreSQLConnection('localhost', 5433, 'dart_test', + timeoutInSeconds: 2); try { await conn.open(); @@ -521,8 +521,8 @@ void main() { s.listen((bytes) {}); }); - final conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5433, timeoutInSeconds: 2, useSSL: true); + final conn = PostgreSQLConnection('localhost', 5433, 'dart_test', + timeoutInSeconds: 2, useSSL: true); try { await conn.open(); @@ -546,8 +546,8 @@ void main() { Future.delayed(Duration(milliseconds: 100), openCompleter.complete); }); - final conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5433, timeoutInSeconds: 2); + final conn = PostgreSQLConnection('localhost', 5433, 'dart_test', + timeoutInSeconds: 2); conn.open().catchError((e) {}); await openCompleter.future; @@ -572,8 +572,8 @@ void main() { Future.delayed(Duration(milliseconds: 100), openCompleter.complete); }); - final conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5433, timeoutInSeconds: 2, useSSL: true); + final conn = PostgreSQLConnection('localhost', 5433, 'dart_test', + timeoutInSeconds: 2, useSSL: true); conn.open().catchError((e) { return null; }); @@ -597,8 +597,8 @@ void main() { }); test('If connection is closed, do not allow .execute', () async { - final conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + final conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); try { await conn.execute('SELECT 1'); fail('unreachable'); @@ -608,8 +608,8 @@ void main() { }); test('If connection is closed, do not allow .query', () async { - final conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + final conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); try { await conn.query('SELECT 1'); fail('unreachable'); @@ -619,8 +619,8 @@ void main() { }); test('If connection is closed, do not allow .mappedResultsQuery', () async { - final conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + final conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); try { await conn.mappedResultsQuery('SELECT 1'); fail('unreachable'); @@ -632,8 +632,8 @@ void main() { test( 'Queue size, should be 0 on open, >0 if queries added and 0 again after queries executed', () async { - final conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + final conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await conn.open(); expect(conn.queueSize, 0); From 473f4dfe7b875d2002b662fe71ac7330e671b461 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sat, 27 Feb 2021 16:33:04 -0800 Subject: [PATCH 23/33] revert port on tests --- test/decode_test.dart | 4 ++-- test/encoding_test.dart | 4 ++-- test/json_test.dart | 4 ++-- test/map_return_test.dart | 4 ++-- test/notification_test.dart | 8 +++----- test/query_reuse_test.dart | 15 +++++++-------- test/query_test.dart | 14 ++++++-------- test/timeout_test.dart | 4 ++-- test/transaction_test.dart | 16 ++++++++-------- 9 files changed, 34 insertions(+), 39 deletions(-) diff --git a/test/decode_test.dart b/test/decode_test.dart index 4a279cf..f492f0b 100644 --- a/test/decode_test.dart +++ b/test/decode_test.dart @@ -4,8 +4,8 @@ import 'package:test/test.dart'; void main() { late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await connection.open(); await connection.execute(''' diff --git a/test/encoding_test.dart b/test/encoding_test.dart index c64d15c..3566d7e 100644 --- a/test/encoding_test.dart +++ b/test/encoding_test.dart @@ -14,8 +14,8 @@ late PostgreSQLConnection conn; void main() { group('Binary encoders', () { setUp(() async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await conn.open(); }); diff --git a/test/json_test.dart b/test/json_test.dart index 1e2c4c5..c045c32 100644 --- a/test/json_test.dart +++ b/test/json_test.dart @@ -5,8 +5,8 @@ void main() { late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await connection.open(); await connection.execute(''' diff --git a/test/map_return_test.dart b/test/map_return_test.dart index 074ec5d..ac2e222 100644 --- a/test/map_return_test.dart +++ b/test/map_return_test.dart @@ -7,8 +7,8 @@ void main() { late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await connection.open(); await connection.execute(''' diff --git a/test/notification_test.dart b/test/notification_test.dart index a4827b7..d12aaae 100644 --- a/test/notification_test.dart +++ b/test/notification_test.dart @@ -5,12 +5,10 @@ import 'package:test/test.dart'; void main() { group('Successful notifications', () { - var connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); - + late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await connection.open(); }); diff --git a/test/query_reuse_test.dart b/test/query_reuse_test.dart index c98bbf5..929cb6a 100644 --- a/test/query_reuse_test.dart +++ b/test/query_reuse_test.dart @@ -14,8 +14,8 @@ void main() { late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await connection.open(); await connection.execute( 'CREATE TEMPORARY TABLE t (i int, s serial, bi bigint, bs bigserial, bl boolean, si smallint, t text, f real, d double precision, dt date, ts timestamp, tsz timestamptz)'); @@ -284,8 +284,8 @@ void main() { late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await connection.open(); await connection.execute( 'CREATE TEMPORARY TABLE t (i1 int not null, i2 int not null)'); @@ -440,12 +440,11 @@ void main() { }); group('Failure cases', () { - var connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await connection.open(); await connection.execute( 'CREATE TEMPORARY TABLE t (i int, s serial, bi bigint, bs bigserial, bl boolean, si smallint, t text, f real, d double precision, dt date, ts timestamp, tsz timestamptz)'); diff --git a/test/query_test.dart b/test/query_test.dart index cab3360..8ee2244 100644 --- a/test/query_test.dart +++ b/test/query_test.dart @@ -4,12 +4,11 @@ import 'package:postgres/src/types.dart'; void main() { group('Successful queries', () { - var connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await connection.open(); await connection.execute('CREATE TEMPORARY TABLE t ' '(i int, s serial, bi bigint, ' @@ -332,12 +331,11 @@ void main() { }); group('Unsuccesful queries', () { - var connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + late PostgreSQLConnection connection; setUp(() async { - connection = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + connection = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await connection.open(); await connection.execute( 'CREATE TEMPORARY TABLE t (i1 int not null, i2 int not null)'); diff --git a/test/timeout_test.dart b/test/timeout_test.dart index c23d204..610db5f 100644 --- a/test/timeout_test.dart +++ b/test/timeout_test.dart @@ -8,8 +8,8 @@ void main() { late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (id INT UNIQUE)'); }); diff --git a/test/transaction_test.dart b/test/transaction_test.dart index 49d39f2..5bee2ef 100644 --- a/test/transaction_test.dart +++ b/test/transaction_test.dart @@ -10,8 +10,8 @@ void main() { late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (id INT UNIQUE)'); }); @@ -302,8 +302,8 @@ void main() { late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (id INT UNIQUE)'); }); @@ -403,8 +403,8 @@ void main() { late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (id INT UNIQUE)'); }); @@ -549,8 +549,8 @@ void main() { late PostgreSQLConnection conn; setUp(() async { - conn = PostgreSQLConnection('localhost', 'dart_test', - port: 5432, username: 'dart', password: 'dart'); + conn = PostgreSQLConnection('localhost', 5432, 'dart_test', + username: 'dart', password: 'dart'); await conn.open(); await conn.execute('CREATE TEMPORARY TABLE t (id INT UNIQUE)'); }); From d4b155e6cbfac97b21afb76e5b842a191874c3d7 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sat, 27 Feb 2021 16:53:29 -0800 Subject: [PATCH 24/33] revert and change incrementally --- lib/src/connection.dart | 9 +++++---- lib/src/connection_fsm.dart | 11 +++++------ lib/src/query.dart | 10 +++++----- lib/src/substituter.dart | 6 +++--- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index a0977b3..a9ef370 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -215,7 +215,7 @@ class PostgreSQLConnection extends Object /// default query timeout will be used. Future transaction( Future Function(PostgreSQLExecutionContext connection) queryBlock, { - int? commitTimeoutInSeconds, + int commitTimeoutInSeconds = 30, }) async { if (isClosed) { throw PostgreSQLException( @@ -418,7 +418,7 @@ abstract class _PostgreSQLExecutionContextMixin @override Future query( String fmtString, { - Map? substitutionValues, + Map substitutionValues = const {}, bool allowReuse = true, int timeoutInSeconds = 30, }) => @@ -431,7 +431,7 @@ abstract class _PostgreSQLExecutionContextMixin Future _query( String fmtString, { - Map? substitutionValues, + Map substitutionValues = const {}, required bool allowReuse, int? timeoutInSeconds, bool resolveOids = true, @@ -489,7 +489,8 @@ abstract class _PostgreSQLExecutionContextMixin @override Future execute(String fmtString, - {Map? substitutionValues, int? timeoutInSeconds}) async { + {Map substitutionValues = const {}, + int? timeoutInSeconds}) async { timeoutInSeconds ??= _connection.queryTimeoutInSeconds; if (_connection.isClosed) { throw PostgreSQLException( diff --git a/lib/src/connection_fsm.dart b/lib/src/connection_fsm.dart index 788e9da..9a3b899 100644 --- a/lib/src/connection_fsm.dart +++ b/lib/src/connection_fsm.dart @@ -255,13 +255,12 @@ class _PostgreSQLConnectionStateBusy extends _PostgreSQLConnectionState { // print("(${query.statement}) -> $message"); if (message is ReadyForQueryMessage) { - if (message.state == ReadyForQueryMessage.StateTransactionError) { - query.completeError(returningException!); - return _PostgreSQLConnectionStateReadyInTransaction( - query.transaction as _TransactionProxy); - } - if (returningException != null) { + if (message.state == ReadyForQueryMessage.StateTransactionError) { + query.completeError(returningException!); + return _PostgreSQLConnectionStateReadyInTransaction( + query.transaction as _TransactionProxy); + } query.completeError(returningException!); } else { query.complete(rowsAffected); diff --git a/lib/src/query.dart b/lib/src/query.dart index 008f4fa..093a703 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -29,7 +29,7 @@ class Query { Future?> get future => _onComplete.future; final String statement; - final Map? substitutionValues; + final Map substitutionValues; final PostgreSQLExecutionContext transaction; final PostgreSQLConnection connection; @@ -96,7 +96,7 @@ class Query { } void sendCachedQuery(Socket socket, CachedQuery cacheQuery, - Map? substitutionValues) { + Map substitutionValues) { final statementName = cacheQuery.preparedStatementName; final parameterList = cacheQuery.orderedParameters! .map((identifier) => ParameterValue(identifier, substitutionValues)) @@ -196,13 +196,13 @@ class CachedQuery { class ParameterValue { factory ParameterValue(PostgreSQLFormatIdentifier identifier, - Map? substitutionValues) { + Map substitutionValues) { if (identifier.type == null) { - return ParameterValue.text(substitutionValues?[identifier.name]); + return ParameterValue.text(substitutionValues[identifier.name]); } return ParameterValue.binary( - substitutionValues?[identifier.name], identifier.type!); + substitutionValues[identifier.name], identifier.type!); } factory ParameterValue.binary( diff --git a/lib/src/substituter.dart b/lib/src/substituter.dart index 1afc484..f97038a 100644 --- a/lib/src/substituter.dart +++ b/lib/src/substituter.dart @@ -52,10 +52,10 @@ class PostgreSQLFormat { } } - static String substitute(String fmtString, Map? values, + static String substitute(String fmtString, Map values, {SQLReplaceIdentifierFunction? replace}) { final converter = PostgresTextEncoder(); - replace ??= (spec, index) => converter.convert(values?[spec.name]); + replace ??= (spec, index) => converter.convert(values[spec.name]); final items = []; PostgreSQLFormatToken? currentPtr; @@ -114,7 +114,7 @@ class PostgreSQLFormat { } else { final identifier = PostgreSQLFormatIdentifier(t.buffer.toString()); - if (values != null && !values.containsKey(identifier.name)) { + if (!values.containsKey(identifier.name)) { // Format string specified identifier with name ${identifier.name}, // but key was not present in values. return t.buffer; From 3fe22bd1472a07d058adbc84a43eb6f94cc81751 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sat, 27 Feb 2021 17:04:57 -0800 Subject: [PATCH 25/33] nullable sub values --- lib/src/query.dart | 10 +++++----- lib/src/substituter.dart | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/src/query.dart b/lib/src/query.dart index 093a703..008f4fa 100644 --- a/lib/src/query.dart +++ b/lib/src/query.dart @@ -29,7 +29,7 @@ class Query { Future?> get future => _onComplete.future; final String statement; - final Map substitutionValues; + final Map? substitutionValues; final PostgreSQLExecutionContext transaction; final PostgreSQLConnection connection; @@ -96,7 +96,7 @@ class Query { } void sendCachedQuery(Socket socket, CachedQuery cacheQuery, - Map substitutionValues) { + Map? substitutionValues) { final statementName = cacheQuery.preparedStatementName; final parameterList = cacheQuery.orderedParameters! .map((identifier) => ParameterValue(identifier, substitutionValues)) @@ -196,13 +196,13 @@ class CachedQuery { class ParameterValue { factory ParameterValue(PostgreSQLFormatIdentifier identifier, - Map substitutionValues) { + Map? substitutionValues) { if (identifier.type == null) { - return ParameterValue.text(substitutionValues[identifier.name]); + return ParameterValue.text(substitutionValues?[identifier.name]); } return ParameterValue.binary( - substitutionValues[identifier.name], identifier.type!); + substitutionValues?[identifier.name], identifier.type!); } factory ParameterValue.binary( diff --git a/lib/src/substituter.dart b/lib/src/substituter.dart index f97038a..1afc484 100644 --- a/lib/src/substituter.dart +++ b/lib/src/substituter.dart @@ -52,10 +52,10 @@ class PostgreSQLFormat { } } - static String substitute(String fmtString, Map values, + static String substitute(String fmtString, Map? values, {SQLReplaceIdentifierFunction? replace}) { final converter = PostgresTextEncoder(); - replace ??= (spec, index) => converter.convert(values[spec.name]); + replace ??= (spec, index) => converter.convert(values?[spec.name]); final items = []; PostgreSQLFormatToken? currentPtr; @@ -114,7 +114,7 @@ class PostgreSQLFormat { } else { final identifier = PostgreSQLFormatIdentifier(t.buffer.toString()); - if (!values.containsKey(identifier.name)) { + if (values != null && !values.containsKey(identifier.name)) { // Format string specified identifier with name ${identifier.name}, // but key was not present in values. return t.buffer; From 45b28738cf88e5cd582a725cfa2fb0ed2c9fda3a Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sat, 27 Feb 2021 17:11:53 -0800 Subject: [PATCH 26/33] ReadyForQueryMessage transaction --- lib/src/connection_fsm.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/src/connection_fsm.dart b/lib/src/connection_fsm.dart index 9a3b899..11e939a 100644 --- a/lib/src/connection_fsm.dart +++ b/lib/src/connection_fsm.dart @@ -255,12 +255,12 @@ class _PostgreSQLConnectionStateBusy extends _PostgreSQLConnectionState { // print("(${query.statement}) -> $message"); if (message is ReadyForQueryMessage) { + if (message.state == ReadyForQueryMessage.StateTransactionError) { + query.completeError(returningException!); + return _PostgreSQLConnectionStateReadyInTransaction( + query.transaction as _TransactionProxy); + } if (returningException != null) { - if (message.state == ReadyForQueryMessage.StateTransactionError) { - query.completeError(returningException!); - return _PostgreSQLConnectionStateReadyInTransaction( - query.transaction as _TransactionProxy); - } query.completeError(returningException!); } else { query.complete(rowsAffected); From 72db712b6c919d42ea3878a3b9478e16b297b38e Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sat, 27 Feb 2021 17:20:35 -0800 Subject: [PATCH 27/33] forgot to save --- lib/src/connection.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index a9ef370..6493bfd 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -215,7 +215,7 @@ class PostgreSQLConnection extends Object /// default query timeout will be used. Future transaction( Future Function(PostgreSQLExecutionContext connection) queryBlock, { - int commitTimeoutInSeconds = 30, + int? commitTimeoutInSeconds, }) async { if (isClosed) { throw PostgreSQLException( @@ -418,7 +418,7 @@ abstract class _PostgreSQLExecutionContextMixin @override Future query( String fmtString, { - Map substitutionValues = const {}, + Map? substitutionValues, bool allowReuse = true, int timeoutInSeconds = 30, }) => @@ -431,7 +431,7 @@ abstract class _PostgreSQLExecutionContextMixin Future _query( String fmtString, { - Map substitutionValues = const {}, + Map? substitutionValues, required bool allowReuse, int? timeoutInSeconds, bool resolveOids = true, From 3a45f6c8367b9b995c6c72921a8deba5a7ce9d43 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sat, 27 Feb 2021 17:28:59 -0800 Subject: [PATCH 28/33] nullable default substitute --- lib/src/substituter.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/substituter.dart b/lib/src/substituter.dart index 1afc484..bc5938e 100644 --- a/lib/src/substituter.dart +++ b/lib/src/substituter.dart @@ -55,7 +55,8 @@ class PostgreSQLFormat { static String substitute(String fmtString, Map? values, {SQLReplaceIdentifierFunction? replace}) { final converter = PostgresTextEncoder(); - replace ??= (spec, index) => converter.convert(values?[spec.name]); + values ??= const {}; + replace ??= (spec, index) => converter.convert(values![spec.name]); final items = []; PostgreSQLFormatToken? currentPtr; From 45fd4bc7b1279e9af35840d5c7025b54bfa1bd69 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sun, 28 Feb 2021 02:31:42 -0800 Subject: [PATCH 29/33] changelog bump version --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca20fdc..08e1fa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 2.3.0 + +- Migrate to null safety + ## 2.2.0 - Supporting Unix socket connections. (Thanks to [grillbiff](https://github.com/grillbiff), diff --git a/pubspec.yaml b/pubspec.yaml index 8096f95..8de7278 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: postgres description: PostgreSQL database driver. Supports statement reuse and binary protocol. -version: 2.2.0 +version: 2.3.0 homepage: https://github.com/stablekernel/postgresql-dart environment: From fd3139296750e667d1231690107c8eca26256b36 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sun, 28 Feb 2021 02:36:55 -0800 Subject: [PATCH 30/33] oops forgot --- lib/src/connection.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/connection.dart b/lib/src/connection.dart index 6493bfd..09c8250 100644 --- a/lib/src/connection.dart +++ b/lib/src/connection.dart @@ -420,7 +420,7 @@ abstract class _PostgreSQLExecutionContextMixin String fmtString, { Map? substitutionValues, bool allowReuse = true, - int timeoutInSeconds = 30, + int? timeoutInSeconds, }) => _query( fmtString, @@ -473,7 +473,7 @@ abstract class _PostgreSQLExecutionContextMixin String fmtString, {Map substitutionValues = const {}, bool allowReuse = false, - int timeoutInSeconds = 30}) async { + int? timeoutInSeconds}) async { final rs = await query( fmtString, substitutionValues: substitutionValues, From 223283908e0f1afa250b154edd4f048b94143659 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sat, 6 Mar 2021 23:10:12 -0800 Subject: [PATCH 31/33] nullable param dataTypeStringForDataType --- lib/src/substituter.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/substituter.dart b/lib/src/substituter.dart index bc5938e..472383f 100644 --- a/lib/src/substituter.dart +++ b/lib/src/substituter.dart @@ -13,7 +13,7 @@ class PostgreSQLFormat { return '@$name'; } - static String? dataTypeStringForDataType(PostgreSQLDataType dt) { + static String? dataTypeStringForDataType(PostgreSQLDataType? dt) { switch (dt) { case PostgreSQLDataType.text: return 'text'; From 515ad44a3842026d5c0e79aa0ad91d55994aae02 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sun, 7 Mar 2021 13:51:14 -0800 Subject: [PATCH 32/33] change not caught before inheritance is weird --- lib/src/execution_context.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/execution_context.dart b/lib/src/execution_context.dart index f532556..6c21649 100644 --- a/lib/src/execution_context.dart +++ b/lib/src/execution_context.dart @@ -42,7 +42,7 @@ abstract class PostgreSQLExecutionContext { /// for executing queries in the PostgreSQL protocol; [query] is preferred for queries that will be executed more than once, will contain user input, /// or return rows. Future execute(String fmtString, - {Map substitutionValues, int timeoutInSeconds}); + {Map substitutionValues, int? timeoutInSeconds}); /// Cancels a transaction on this context. /// From 15026cad2c92013b77c44d9ae1000559ac3b7605 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sun, 7 Mar 2021 13:52:39 -0800 Subject: [PATCH 33/33] change not caught before inheritance is weird --- lib/src/execution_context.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/execution_context.dart b/lib/src/execution_context.dart index 6c21649..a37d388 100644 --- a/lib/src/execution_context.dart +++ b/lib/src/execution_context.dart @@ -32,7 +32,7 @@ abstract class PostgreSQLExecutionContext { Future query(String fmtString, {Map substitutionValues, bool allowReuse, - int timeoutInSeconds}); + int? timeoutInSeconds}); /// Executes a query on this context. ///