postgres_fork 3.0.0
postgres_fork: ^3.0.0 copied to clipboard
PostgreSQL database driver. Supports statement reuse and binary protocol.
Changelog #
3.0.0 #
-
DecodingSettings:IntervalDecoding.text(the server's interval text,'1 day 02:03:04'),ExtendedTypeDecoding.textnow also coverspoint('(1,2)'), andnullableArrays: truemakes every array aList<T?>(by default an array without NULL is aList<T>and one with NULL aList<T?>, so the type of a column changes with its content). Arrays of the types decoded as text areList<String>. -
Performance: the data type of a column is looked up once, not for every value (
typeMapwas aMaplookup per value), and text values (text,varchar,name,char(n),"char",xml) are decoded before any other check.char(n)had no fast path and went through every check of the less common types. A 1000-row result of int/char/timestamp columns decodes about 5% faster than 2.8.5. -
Bug fix: geometric types (
lseg,box,line,path,polygon,circle),bit/varbit,tsvector, ranges and their arrays came back as their binary bytes or, when those happened to be valid UTF-8, as garbage ('ab'for the tsvector'a' 'b',''for the int4range[1,5)). They are now the server's text ('(3,4),(1,2)','101',"'a' 'b'",'[1,5)'); arrays are lists of texts. Arrays of user-defined types (enum[]) are the array literal ('{ok,sad}'); they were bytes. Atstzrangebound is printed in UTC (+00). -
Breaking change:
intervalvalues (andinterval[]elements) are now always decoded asPgInterval(months, days, microseconds;==,hashCode,toDuration(), andtoString()equal to the server's text with the defaultIntervalStylepostgres). Previously the default wasDuration, and any interval with days or months ('1 day') failed withUnimplementedError.DecodingSettings(interval: IntervalDecoding.duration)restores the old behavior.DurationandPgIntervalare both accepted as parameters, now also without a type (@x,?, simple protocol). -
macaddr,macaddr8(and their arrays) are decoded to the server's canonical text ('08:00:2b:01:02:03'); previously the binary bytes came back as a garbageString.money(andmoney[]) is decoded to the exact amount as a decimalStringwith 2 fraction digits ('12.34','-0.05','0.00'), without the currency symbol; previously the raw bytes. The scale ofmoneyfollowslc_monetaryon the server; 2 is the PostgreSQL default for practically all locales. The text path (simple protocol) still returns the server's text (formoney, the locale text, e.g.R$ 12,34). -
oidand thereg*types (regclass,regtype...),xid,cid,oid[],oidvectorandint2vector(e.g.pg_index.indkey) are decoded asints; previously aString(orUint8List) with the binary bytes. -
Bug fix: a connection terminated by the server (
pg_terminate_backend, shutdown) while a query of atransaction()was running left that query, the transaction's queued queries and the transaction itself waiting for the query timeout. All queued callers now fail at once with the server's error (57P01); callers outside a transaction also get that error instead of a generic "connection closing" message. -
Bug fix: a transaction queued when the connection was closed produced an extra unhandled asynchronous error.
-
Bug fix: the statement cache was never refreshed: after
ALTER TABLEchanged a cached query's result (0A000, "cached plan must not change result type"), or after the prepared statement was removed (DEALLOCATE,DISCARD ALL, a pooler;26000), every later execution of that SQL failed. The failing statement is now dropped from the cache (the next execution prepares it again), andDISCARD ALL/DEALLOCATE ALLrun on the connection clear the cache. -
Bug fix:
query()(with the defaultallowReuse) of a command without rows (INSERTwithoutRETURNING,UPDATE,DELETE, DDL,SET...) prepared a new named statement on the server at every call (they were never cached), leaking prepared statements. -
Bug fix:
query(..., useSimpleQueryProtocol: true)with several statements mixed the rows of all of them with the column description of the last one (toColumnMap()threwRangeError). The result is now the last result set, as in libpq (affectedRowCountwas already the last one's). -
Bug fix:
PostgreSQLConnection.settingswas not updated after the connection was opened; it now followsParameterStatusmessages (SET application_name,SET TimeZone, ...). -
Bug fix: non-ASCII column names were decoded byte by byte (
"descrição"came back as"descrição"), in both APIs. -
Bug fix:
mappedResultsQueryassociated table names by position: when a result had a column of a view (or another relation that is not a plain table) with a smaller OID, the names of the tables were shifted. -
Bug fix:
numericvalues between -1 and 0 were decoded without the leading zero ('-0.5'came back as'-.5'). -
Bug fix: a
dateparameter (@d:date) was encoded from the UTC date, truncated towards zero: before 2000 any time after midnight became the next day (1999-12-31 12:00→2000-01-01), and a localDateTimecould become another day. The date of theDateTimeitself is used (as in the text path). -
Bug fix: text encoding of parameters and of values written into the SQL (untyped
@x,?and the simple protocol):NaN/Infinitywere sent as'nan'(with quotes) and rejected (22P02), also inside arrays;- BC dates were one year off (
DateTimeyear -43, i.e. 44 BC, was sent as 43 BC) and year 0 (1 BC) was rejected; - in the SQL text, negative numbers are now parenthesized:
5-@xwithx = -1became the comment5--1, and@x::int2with -32768 was out of range;-0.0keeps its sign ('-0'::float8); - lists and
PgPointwritten into the SQL were not quoted (syntax error / read as a record); nullelements of lists were not supported:['a', null]was sent as{"\"a\"","null"}(wrong data); they are nowNULL;Durationwithout a type failed with "Could not infer type".
-
Bug fix:
@x::type1::type2(more than one cast after a placeholder) became$1::type1type2. -
Bug fix: the error severity is read from the non-localized
Vfield (PostgreSQL 9.6+), solc_messagestranslations (e.g.FEHLER,PÂNICO) no longer make errorsunknownandFATAL/PANICare always recognized. -
Bug fix:
PostgreSQLConnection(encoding: ascii)sentclient_encodingascii, which the server rejects; it now sendsSQL_ASCII. A server message that the connection's encoding cannot decode no longer throws an unhandled exception from the socket listener (leaving queries waiting): the connection is closed with that error. Error messages that cannot be decoded fall back to lenient UTF-8. -
Bug fix (v3 experimental API):
- a query with several statements (
execute('SELECT 1; SELECT 2'), or DDL followed byINSERT) threw an unhandled "Future already completed"; rows of all statements are returned (each with its own schema) andaffectedRowsis the last statement's; - a parameter that cannot be encoded (e.g. a
Stringfor anint) threw an unhandled error and the call never completed (the prepared statement also leaked); the call now fails with theFormatException; - queries without parameters (simple protocol, text format) failed with
UnimplementedErrorfordate,timestamptz,numeric,uuid,json, arrays,intervaland other types without a text decoder; those values are now returned as the server's text; execute()/prepare()called right beforeclose()failed with "connection was closed" instead of running first.
- a query with several statements (
-
Bug fix: a
TZDateTime(what non-UTC zones decode to) could not be sent back as a parameter: the text encoder appended an offset totoIso8601String(), which already ends with one ('2024-01-15T12:34:56.789123-0300-03:00', error 22009). The value is now encoded from its fields. Offsets between -01:00 and 00:00 (e.g. -00:30) also kept a+sign. -
Tests:
non_ascii_connection_strings_test.dartis skipped withPOSTGRES_TEST_NO_DOCKER=1(it needs its own containers). -
Removed the runtime dependencies
buffer,crypto,collection,sasl_scram(and its transitivesaslprep/unorm_dart),stream_channel,async,charcode,meta,pool,stack_traceandenough_convert. The needed functionality is now implemented inlib/src/utilswith the same behavior (verified by the parity tests independency_parity/). -
Breaking change (v3 experimental API):
PgSessionSettings.transformernow uses theStreamChannelTransformer/StreamSinkTransformerclasses exported bypackage:postgres_fork/postgres_v3_experimental.dartinstead of the ones frompackage:stream_channel/package:async. -
The
windows-1252client encoding is now detected byEncoding.name, so any codec namedwindows-1252(not onlyWindows1252Codecfromenough_convert) is sent to the server asWIN1252. -
Removed the
pg_timezonedependency. The time zone runtime (TZDateTime,Location,TimeZone) is now part of the package and exported bypackage:postgres_fork/timezone.dart. The embedded database is generated from the IANA tz database (currently 2026e) byscripts/update_tzdb.dart, which uses a Dart port of the IANAziccompiler (scripts/tzdb/zic.dart). -
New
TimeZoneSettings.databaseVariant:TimeZoneDatabaseVariant.full(new default): all IANA zones and links (e.g.Brazil/East,US/Eastern) with the complete history and explicit transitions up to 2100, like PostgreSQL itself.TimeZoneDatabaseVariant.reduced: the previouspg_timezonedatabase (431 common locations, transitions limited to 5 years around the generation date).
-
Bug fix: decoding
timestamptzwithforceDecodeTimestamptzAsUTC: falsecould return a value shifted by the daylight saving time difference between the value's date and the current date (for example, a January timestamp inAmerica/New_Yorkdecoded during summer came back one hour off). The decoded value now always represents the same instant as the server value, with the local fields computed using the offset in force at that date. Non-UTC time zones now always return aTZDateTime(previously zones whose current offset was zero returned a UTCDateTime). -
Fixes for issue #2 (type decoding and lost connections):
- A value that cannot be decoded no longer closes the connection: the query fails with the decoding error and the connection stays usable (v2 and v3 APIs, also inside transactions).
- Arrays:
NULLelements are decoded asnull(previouslyint[]withNULLfailed and closed the connection, andtext[]returned''). Lists withoutNULLkeep the element type (List<int>); lists withNULLareList<int?>. Multi-dimensional arrays are decoded as nested lists. New array types:date[],timestamp[],timestamptz[],numeric[],int2[],float4[],bytea[],name[],bpchar[],uuid[],json[],point[],interval[],time[],timetz[],inet[]andcidr[]. - New
DecodingSettings(PostgreSQLConnection(decodingSettings: ...)andPgSessionSettings.decodingSettings):interval:IntervalDecoding.pgInterval(default, newPgIntervalclass with months, days and microseconds) orIntervalDecoding.duration(the previousDuration; intervals with months or days throwUnimplementedErrorwith an explanatory message).extendedTypesfortime,timetz,inetandcidr(previously raw bytes, andcidrreturned an invalid string):ExtendedTypeDecoding.objects(default:PgTime,PgTimeTz,PgInet),.text(same text as PostgreSQL) or.bytes(raw bytes).
PgInterval,PgTime,PgTimeTzandPgInetare accepted as query parameters (andPgIntervalfor@x:interval).
-
Authentication fixes:
- MD5: the hash is now computed over the UTF-8 bytes of the password and the user name (as libpq does). Previously non-ASCII passwords failed.
- SCRAM-SHA-256: passwords rejected by SASLprep (e.g. containing control characters) are used as is (as libpq does) instead of throwing.
-
New features (v2 API,
PostgreSQLConnection):COPY:copyFrom(sql, Stream<List<int>>)(COPY ... FROM STDIN, with flow control),copyTo(sql, onData)(COPY ... TO STDOUT) andcopyRows(table, columns, rows), which writes Dart values in the COPY text format (much faster thanINSERTfor many rows).PgCopyencodes rows and values (encodeTextRows,encodeTextValue) and decodes text rows (decodeTextRow). An error in the data stream or in the server aborts the COPY (nothing is written) and the connection stays usable. They are also available in transactions through an extension onPostgreSQLExecutionContext. ACOPY ... FROM STDINsent throughqueryorexecutenow fails with a clear error (previously the connection hung).- Savepoints:
ctx.savepoint((sp) async { ... })insidetransaction. An error inside the block rolls back only the savepoint (ROLLBACK TO SAVEPOINT) and is rethrown; the transaction can continue and be committed. Savepoints can be nested. - Session parameters sent in the startup message:
applicationNameandstartupParameters(e.g.search_path,statement_timeout), avoidingSETround trips after connecting (alsoPgSessionSettingsin v3). cancelQuery()sends aCancelRequest(as libpq). WithcancelQueryOnTimeout: true, a query that times out is also cancelled on the server, so the connection is released right away.maxPreparedStatements: limits the prepared statements kept by the connection (least recently used ones are closed on the server). Default: no limit (unchanged).sslMode(PgSslMode.disable,prefer,require,verifyFull). When null,useSSLdecides as before.listen,unlisten,notifyandnotificationsForforLISTEN/NOTIFY.DecodingSettings.timestamp:TimestampDecoding.localWallClockdecodestimestampanddateas localDateTimes with the same fields stored in the database.PgErrorCodewith common SQLSTATE codes (uniqueViolation,foreignKeyViolation,serializationFailure,deadlockDetected,queryCanceled, ...) to compare withPostgreSQLException.code.PostgresTextEncodable: application types can define their own text representation for query parameters.- Connection pool:
PostgreSQLPool(() => PostgreSQLConnection(...), settings: PostgreSQLPoolSettings(...)), which implementsPostgreSQLExecutionContextand addsrun,runTx,withConnection,queryStream,copyFrom/copyTo/copyRows,statusandclose. Settings:maxConnectionCount,maxConnectionAge,maxSessionUse,maxErrorCount,maxUseCount,idleTestThreshold,acquireTimeout,onOpenandretryOptions. Sessions wait in arrival order; a connection is closed instead of returned when it was closed, the session timed out, a transaction was left open or a limit was reached. Ordinary SQL errors do not close the connection. - Server-side cursors:
queryStream(sql, fetchSize: ...)returns the rows as aStream, fetched in batches only when the consumer asks for more (pausing the subscription stops fetching; cancelling closes the cursor). Available on the connection, insidetransactionand on the pool. PgDecimal: arbitrary precision decimal (thenumerictype, includingNaNandInfinity) with the same arithmetic, scale and rounding rules as PostgreSQL (verified against the server with random values).DecodingSettings(numeric: NumericDecoding.decimal)decodesnumericandnumeric[]asPgDecimal(default:NumericDecoding.string, unchanged).PgDecimalis accepted as a query parameter and in COPY.
-
New features (v3 experimental API):
PgSessionExecutor.runandrunTx(with optionalPgRetryOptions, which retry on serialization failures and deadlocks by default);PgPool.openis now implemented (it threwUnimplementedError;PgPool.preparethrowsUnsupportedError, usewithConnection);PgConnectionImplementation.isClosed;TypeMessage.typeNamein logical replication. -
PgRetryOptionsis exported by both libraries.PostgreSQLRollbacknow implementsException(PostgreSQLPool.runTxthrows it when the transaction is cancelled and the return type does not accept it). -
connection_config.dartgathers the connection configuration types (PgSslMode,ReplicationMode,DecodingSettings,TimeZoneSettings);ReplicationModeis still exported from the same libraries. -
Bug fixes:
execute(timeoutInSeconds: ...)ignored the given timeout and always used the connection'squeryTimeoutInSeconds.- Simple query protocol (
execute,useSimpleQueryProtocol: true): aNULLvalue threw an error that closed the connection; it is nownull. - Queries with more than 65535 parameters now fail with a clear error before being sent, and the connection stays usable (previously the parameter count overflowed and the connection broke).
Uint8Listparameters without a type are sent asbytea(hex format) instead of being encoded as an array of numbers.- In connections that are not in replication mode,
COPY ... TO STDOUTdata starting withkorwwas parsed as a replication message (which could close the connection). numericvaluesInfinityand-Infinity(PostgreSQL 14+) were decoded as'0'; the strings'Infinity'/'-Infinity'were rejected as typednumericparameters.- Closing the connection (or losing it) during a transaction left the transaction's queries waiting until their timeout, and the rollback then waited another 30 seconds; they now fail immediately.
- v3 API: booleans in results of the simple query protocol (queries
without parameters) were always
false. - v3 API: when the server closed the connection (e.g.
pg_terminate_backend), the running operation and the next ones never completed, the socket error was unhandled and an unsolicitedFATALerror could throwBad state: Cannot add event after closing. They now fail withPostgreSQLException.
-
Fixed a bug inherited from the
bufferpackage: when the received byte chunks were views of a larger buffer, reading across chunks could read past the end of a chunk, losing messages or throwingRangeError. -
Performance (measured against 2.8.5, AOT, local PostgreSQL 16): no regression in queries, inserts, transactions or decoding (CPU-only decoding and encoding benchmarks are ~1% faster); arrays are ~9% faster; SCRAM connections ~18% faster; decoding
timestamptzwith a non-UTC time zone is ~40x faster (the location lookup is cached until the next zone transition). -
Requires Dart SDK 3.6 (
sdk: ^3.6.0).
2.8.5 #
- fix decode server Error Response Message
2.8.4 #
- fix decode timestamp without timezone as local DateTime, ignore past timezone transitions
2.8.3 #
- fix init Location By default with UTC
2.8.2 #
- add more flexibility on how date, timestamp and timestaptz types are decoded by adding flags to the TimeZoneSettings class
2.8.1 #
- change timezone to external pkg
- makes the timeZone parameter of PostgreSQLConnection more flexible to be compatible with String or TimeZoneSettings instance
2.8.0 #
-
Breaking change: decode timestamp without timezone as local DateTime and decode timestamp with timezone respecting the timezone defined in the connection
-
Breaking change: timeZone option in PostgreSQLConnection is now a TimeZoneSettings type instead of String
2.7.0 #
-
Support has been implemented to change the character encoding for the connection, this makes it possible to change the default encoding from utf8 to win1252, iso8859, among others.
-
implemented executing a prepared statement with question mark placeholder style similar to PHP PDO
final results = await connection.query(
' SELECT * FROM public.table_example LIMIT ?',
substitutionValues: [2000], placeholderIdentifier:
PlaceholderIdentifier.onlyQuestionMark);
2.6.0 #
- Updated to
package:lints. - Adding lowerCase values to
AuthenticationScheme. - Add new
package:postgres/postgres_v3_experimental.dartlibrary as a preview. It exposes the postgres client under a new API that will replace the current one in version3.0.0of this package. At the moment, the new library is experimental and not fully implemented. Until the actual3.0.0release, the new APIs might change without a breaking version.
2.5.2 #
2.5.0 #
- Added Support for Streaming Replication Protocol which included the following changes:
- Replication Mode Messages Handling. #58 by osaxma
- Add new message types for replication. #57 by osaxma
- Add connection configuration for Streaming Replication Protocol. #56 by osaxma
- Raise the min sdk version to support enhanced enums. #55 by osaxma
- Add LSN type and time conversion to and from ms-since-Y2K. #53 by osaxma
- Fix affected rows parsing in CommandCompleteMessage. #52 by osaxma
- Introduced new APIs to
PostgreSQLConnection:addMessageto send client messages,messagesstream to listen to server messages &useSimpleQueryProtocoloption inquerymethod. #51 by osaxma
2.4.6 #
2.4.5 #
- Added support for boolean arrays. #41 by slightfoot.
2.4.4 #
- Added support for varchar arrays. #39 by paschalisp.
2.4.3 #
- Support for clear text passwords using a boolean parameter in connection as 'allowClearTextPassword' to activate / deactivate the feature. #20.
2.4.2 #
- Include original stacktrace when query fails. (#15 by davidmartos96)
2.4.0 #
2.3.2 #
- Expose
ColumnDescription.typeId.
2.3.1 #
2.3.0 #
- Finalized null-safe release.
2.3.0-null-safety.2 #
- Fixing query API optional parameters.
2.3.0-null-safety.1 #
- Updated public API to always return non-nullable results.
- BREAKING CHANGE: unknown mapped table name is no longer
null, it is empty string ('').
2.3.0-null-safety.0 #
2.2.0 #
2.1.1 #
- Fix
RuneIterator.currentuse, which no longer returnsnullin 2.8 SDK.
2.1.0 #
- Missing substitution value no longer throws
FormatException. More details in the GitHub issue.
2.0.0 #
- Fixed startup packet length when username is null (#111).
- Finalized dev release.
2.0.0-dev1.0 #
- Restricted field access on [PostgreSQLConnection].
- Connection-level default query timeout.
- Option to specify timeout for the transaction's
"COMMIT"query. - Optimized byte buffer parsing and construction with
package:buffer. - Hardened codebase with
package:pedanticand additional lints. - Updated codebase to Dart 2.2.
PostgreSQLResultandPostgreSQLResultRowas the return value of a query.- Returned lists are protected with
UnmodifiableListView. - Exposing column metadata through
ColumnDescription. - row-level
toTableColumnMapandtoColumnMap
- Returned lists are protected with
PostgreSQLConnectionand_TransactionProxyshare the OID cache.- default value for
query(allowReuse = true)is set only in the implementation method.
Breaking behaviour
- Table OIDs are always resolved to table names (and not only with mapped queries).
1.0.2 #
- Add connection queue size
1.0.1 #
- Prevent the table name resolution of OIDs <= 0.
1.0.0 #
- Adds support for Dart 2
0.9.9 #
- Add full support for
UUIDcolumns.
0.9.8 #
- Preserve error stacktrace on various query or transaction errors.
- Read support for
BYTEAcolumns.
0.9.7 #
- Adds
Connection.mappedResultsQueryto return query results as aMapwith keys for table and column names.
0.9.6 #
- Adds
Connection.notificationsto listen forNOTIFYevents (thanks @andrewst) - Adds better error reporting.
- Adds support for JSONB columns.
- Fixes issue when encoding UTF16 characters (thanks @andrewst)
0.9.5 #
- Allow connect via SSL.
0.9.4 #
- Fixed issue with buffer length
0.9.3 #
- Fixed issue with UTF8 encoding
0.9.2 #
- Bump for documentation
0.9.1 #
- Added transactions: PostgreSQLConnection.transaction and PostgreSQLConnection.cancelTransaction.
0.9.0 #
- Initial version