Skip to content

7.9.1

Choose a tag to compare

@madorin madorin released this 09 Oct 06:18
· 194 commits to master since this release

Added

Character sets

  • Text goes through the code page of its column's charset (fields, parameters,
    text BLOBs, dataset fields, array elements, SQL text, object names), not only
    UTF-8 or the system code page: e.g. WIN1251 data on a Western Windows no
    longer comes as ? or mojibake.
    • Unit FIBCharSets (FirebirdCharSetCodePage, FirebirdCharSetName,
      DecodeString, EncodeString); TFIBDatabase.Capabilities: AttachmentCharSetID,
      CodePage, MetadataCodePage, TextCodePage, BlobCodePage;
      TFIBDatabase.ConnectionSerial; TFIBCustomDataSet.StringFieldCharSetID,
      StringFieldCodePage, BlobFieldCodePage.
  • Unlike FireDAC and IBDAC (UTF-8 or the system code page only): any Firebird
    charset, per column also on NONE connections; NONE/OCTETS columns kept as
    bytes on UTF8 connections; array elements in the column charset; DDL and
    names in UTF-8 on NONE; an error instead of ? for characters the charset
    can't hold.

Packages

  • FIBPlusFMX runtime package for Delphi 13 with the FireMonkey login dialog
    FIB_FMX_DBLoginDlg, which was in no package. Its name has no version
    suffix: the BPL gets one through {$LIBSUFFIX AUTO} (FIBPlusFMX370.bpl).

Timeouts

Firebird 4+ statement and idle timeouts; details in Docs/guide/timeouts.md.

  • TFIBDatabase.Session: StatementTimeout (ms, every statement of the
    attachment) and IdleTimeout (s), sent after connect and when changed.
    Apply sends them again (e.g. after ALTER SESSION RESET);
    ActualStatementTimeout / ActualIdleTimeout read them from the server.
    IdleTimeout is not sent at design time.
  • TFIBQuery.StatementTimeout and TpFIBDataSet.StatementTimeout (ms, through
    fb_dsql_set_timeout) replace the session value for one statement;
    FIBNoStatementTimeout opts a statement out of it.
  • For a SELECT the timer runs until the last row is fetched, so a dataset
    browsed in a grid can fail on a later scroll. In interactive applications set
    the timeouts per query, or opt the browsing datasets out.
  • A non-zero value the server or the client library can't apply raises
    EFIBClientError (feFeatureNotSupported); 0 never raises. A value stored in
    a DFM makes Open fail on Firebird 3 and older (Open(False) returns with
    Connected = False). Capabilities.SessionTimeouts and
    Capabilities.StatementTimeout tell what is available.
  • EFIBError.ErrorCodes, HasErrorCode and IsStatementTimeout;
    keStatementTimeout and keCancelled in TKindIBError. An idle timeout
    arrives as a lost connection.

Read consistency

Firebird 4+ read committed transactions where every statement reads one
snapshot taken at its start.

  • read_consistency in TRParams (isc_tpb_read_consistency).
  • TpFIBTransaction.TPBMode tpbReadConsistency sends write, nowait,
    read_committed and read_consistency; on a server older than Firebird 4
    StartTransaction raises EFIBClientError (feFeatureNotSupported).
    tpbReadCommitted stays the default: with the server default
    ReadConsistency = 1 it already runs in this mode on Firebird 4+.
  • Capabilities.ReadConsistency and TFIBDatabase.RequireReadConsistency;
    IsReadCommitedTransaction also recognizes read_consistency.
  • A ReadConsistency kind in the transaction editor.

Parallel workers

Firebird 5+ parallel workers for sweep, index creation, backup and restore; the
server limits them with MaxParallelWorkers in firebird.conf (default 1).

  • parallel_workers in DBParams and the typed ConnectParams.ParallelWorkers
    (0 removes the line). The parameter is sent to Firebird only; Firebird 3 and 4
    ignore it.
  • ParallelWorkers on TpFIBBackupService, TpFIBRestoreService and
    TpFIBValidationService (sweep, sent only with SweepDB). It is sent only
    when greater than 0; a Firebird 3 or 4 server rejects it.

Changed

  • FIBRelease is renamed to FIBPatchVersion.
  • FIBBuildDate is renamed to FIBVersionDate and uses the ISO date format.
  • Version constants are untyped and can be used in {$IF} directives.
  • TFIBDatabase.AttachmentID is Int64, read with isc_portable_integer
    (the attachment ID is BIGINT in Firebird 3+), and is 0 instead of -1 when
    not connected (#34).
  • TFIBSQLLogger.CreateStatisticsTable creates FIB$APP_STATISTICS.ATTACHMENT_ID
    as BIGINT in dialect 3. An existing table can be updated with
    ALTER TABLE FIB$APP_STATISTICS ALTER ATTACHMENT_ID TYPE BIGINT.
  • Protected fields of TFIBDatabase and TFIBTransaction are renamed from the
    v prefix to F: FInternalTransaction, FAfterConnectEvents,
    FBeforeDisconnectEvents, FBeforeDestroyEvents,
    FBeforeStartTransactionEvents, FAfterStartTransactionEvents,
    FBeforeEndTransactionEvents, FAfterEndTransactionEvents,
    FDatabaseTRParams, FDatabaseTPBs.
  • The protected TpFIBDatabase.CreateRCTimer is renamed to
    CreateRestoreConnectTimer.
  • A character the target code page can't hold raises "Cannot transliterate
    character between character sets" (values and SQL text) instead of being
    sent as ? or a look-alike, e.g. ș/ț with comma (Romanian Standard
    keyboard) on WIN1250/WIN1252: use UTF8 or the Romanian Legacy keyboard.
  • NONE connections decode a column with its declared charset, so text written
    in another code page (e.g. cp1250 into a WIN1252 column) shows as stored.
    Repair by reinterpreting the bytes:
    cast(cast(C as varchar(n) character set OCTETS) as varchar(n) character set WIN1250).
  • ISO8859_1/ISO8859_9 go through code pages 1252/1254 (€ “ ” … instead of
    the C1 controls), ASCII through the system code page.
  • TFIBStringField.AsAnsiString (Delphi 2009+) returns the column bytes with
    their code page set; calculated and lookup ftString fields use the system
    code page.
  • TFIBDatabase.FBAttachCharsetID is a deprecated function, use
    Capabilities.AttachmentCharSetID (read once at connect, -1 when not
    connected or on InterBase); IsKOI8Connect is deprecated.
  • IIBClientLibrary.ClientVersion and ClientMinorVersion are deprecated
    functions instead of properties, so using them gives a warning; use Version.
    Classes implementing the interface must add them.
  • The default client library is fbclient.dll instead of gds32.dll
    (TFIBDatabase.LibraryName, TpFIBServices.LibraryName). The global
    IBASE_DLL is renamed to CLIENT_DLL. When fbclient.dll without a path
    can't be loaded, gds32.dll is loaded, so applications shipped with
    gds32.dll keep working. Forms saved with the old default don't store
    LibraryName and get the new one.
  • The default SQLDialect is 3 instead of 1: in TFIBDatabase created in code,
    for new components dropped at design time (DefSQLDialect; a value saved in
    the preferences is kept), and in the SQL editor without a database. Forms
    always store SQLDialect, so they keep their value. On a dialect 1 database
    the dialect is lowered to 1 at connect, as before.
  • The packages for Delphi 2007 and later write DCU files to
    $(BDSCOMMONDIR)\Dcu\FIBPlus\$(Platform)\$(Config) instead of
    .\$(Platform)\$(Config): the folder next to the packages was shared by all
    Delphi versions, so they overwrote each other's DCU files.

Removed

  • SUPPORT_KOI8_CHARSET and StdFuncs.ConvertToCodePage/ConvertFromCodePage.
  • SqlTxtRtns.IBStdCharacterSets, IBStdCharSetsCount and
    IBStdCollationsCount: use FIBCharSets.FirebirdCharSetName.

Fixed

  • TFIBSQLLogger.StatisticsParams had no effect. The parameters left out are
    not written by SaveStatisticsToFile, and SaveStatisticsToDB writes NULL
    in their columns (MAXTIME_PARAMS follows fspMaxTimeExecute).
  • TFIBSQLLogger.SaveStatisticsToDB and CreateStatisticsTable roll back
    when a statement fails, instead of committing the rows inserted before it
    or leaving the transaction active.
  • Array fields kept the descriptor of a previous connection.
  • TpFIBScripter: CONNECT, CREATE DATABASE and DROP DATABASE replaced
    the LibraryName of the database with the default library. It is changed
    only by SET CLIENTLIB.
  • Locate, filters, sorting and bookmarks on string fields of a non-system code
    page; lookup fields with a Unicode result field.
  • UseExecuteBlock: apostrophes in literals not doubled, non-ASCII text sent
    in the system code page.
  • UseExecuteBlock: dates, times and timestamps are written as ISO literals
    (they depended on the locale); TIME / TIMESTAMP WITH TIME ZONE values keep
    their zone (they were moved to the session zone); memo, GUID and emulated
    BOOLEAN values and memo text of a column charset on a NONE connection are
    written correctly. More than 255 records, or a block over 64K bytes (counted
    in bytes, not characters), failed with "Token unknown". A record posted without
    changes with UpdateOnlyModifiedFields failed with "Token unknown"; an insert
    without values writes DEFAULT VALUES. Deleted records stayed pending after
    the apply. OnUpdateError was called twice for a failed block, and the records
    of a skipped block lost their pending state. A record that does not fit in a
    block, and array and binary BLOB fields, now raise a clear error.
  • Text BLOB parameters set before Prepare sent without their charset; NONE
    and OCTETS text BLOBs decoded as UTF-8 on UTF8 connections.
  • A string parameter replaced by AsInteger before Prepare sent the string.
  • Multi-byte charset values (SJIS, GBK, ...) cut in the middle of a character.
  • DisableEncodingSQLText sent queries with parameters with an empty SQL text.
  • CharacterSet returned UNKNOWN for KOI8R/U, WIN1258, TIS620, GBK, CP943C
    and GB18030.
  • GetExportDataScript wrote ftFMTBcd values with the locale decimal
    separator.
  • GetExportDataScript wrote dates in the locale format, left memo values
    unquoted and GUID values as text instead of the 16 bytes of the column.
  • StrUtil.FastCopy read before the string for Index < 1; it now calls
    Copy on Delphi 2009+.
  • The FIBPlus_XE3 package did not compile: it contained the XML export units,
    which are not in the repository.
  • TpFIBScripter skipped the session SET statements (STATEMENT TIMEOUT,
    SESSION IDLE TIMEOUT, BIND, TIME ZONE, DECFLOAT, ROLE, TRUSTED ROLE, OPTIMIZE, SEARCH_PATH) without an error; it now sends them to the
    server, so an old script that contains them now runs them. They have the new
    TStmtType value sSetSession.
  • Locate with a Currency key on NUMERIC(10..18) columns with a scale did not
    find values above 2^53 (e.g. 12345678901234.5678).
  • pfImportDefaultValues: CURRENT_TIME(n), CURRENT_TIMESTAMP(n),
    LOCALTIME(n) and LOCALTIMESTAMP(n) defaults failed with a conversion error
    on insert. The value keeps the fractional digits of the default, as the
    server does: CURRENT_TIME and LOCALTIME without a precision no longer get
    milliseconds.
  • A BOOLEAN parameter set with AsString := 'true' / 'false' before Prepare
    raised "Invalid data conversion".
  • AsQuad assigned after a long AsString was replaced by the string at the
    execute.
  • User transaction kinds saved in the transaction editor shifted to another
    kind when a predefined kind was added.
  • DBParamByDPB with a code above 83 (such as isc_dpb_config) read an empty
    value and wrote a parameter with a name out of the table range.
  • TpFIBDatabase: an alias did not read back its CLIENT_LIB into
    LibraryName. Aliases saved by earlier versions usually hold gds32.dll,
    see the upgrading guide.
  • TpFIBDatabase.OnErrorRestoreConnect got an uninitialized DoRaise.
  • TpFIBDatabase.InRestoreConnect stayed True after a successful restore or
    a reconnect during the wait, and TransactionID returned 0 for transactions
    started after it. It was cleared while the timer waited again after a failed
    attempt, and the timer kept running when OnErrorRestoreConnect chose to
    stop.
  • TpFIBDatabase.ApplyUpdates raised an access violation for an empty array
    and read invalid memory for a dataset that is not a TFIBCustomDataSet.
  • TpFIBDatabase saved the schema cache (AutoSaveToFile) on ForceClose
    when not connected.
  • TpFIBDatabase.WaitForRestoreConnect read 0 and laWaitRestore did nothing
    until code assigned the property; the default 30000 now applies. Forms
    saved by earlier versions without a value set store
    WaitForRestoreConnect = 0, which keeps the timer off.
  • TpFIBNRestoreService.Restore read one element past the end of the file
    array.
  • TpFIBBackupService and TpFIBRestoreService: a name=length line sent a
    length cut to as many digits as the name has characters.
  • Service Params entries (ServiceParamBySPB, login dialog) were looked up
    case-sensitively, and password also matched password_enc.
  • FixLimboTransactionErrors raised an access violation after
    FetchLimboTransactionInfo returned entries. LimboTransactionInfoCount
    and UserInfoCount returned -1 for an empty list; LimboTransactionInfo
    and UserInfo raise EListError for an index out of range instead of
    returning nil.
  • FixLimboTransactionErrors rolled back the transactions with
    RecoverTwoPhaseGlobal; it now sends them to two-phase recovery.
  • TpFIBSecurityService: SecAdmin was sent only when its value changed, so
    setting it again on the next AddUser or ModifyUser had no effect, and a
    failed call cleared the properties. Setting SecAdmin is now always sent;
    the properties, SecAdmin included, are cleared only after a successful
    call.
  • TpFIBQuery.ExecProcedure wrote two spaces between EXECUTE and PROCEDURE.
  • BatchOutputRawFile ignored its Version argument and always wrote version 3.
  • TFIBTimeField and TFIBDateTimeField with ShowMsec wrote milliseconds
    without leading zeros: 5 ms showed as .5 instead of .005.
  • RecordFieldAsFloat read past the last record for RecNumber = RecordCount,
    and on a filtered dataset for a visible number past the end; it returns 0.
  • TBlobSwapSupport could not be assigned (TFIBDatabase.BlobSwapSupport).
  • AutoUpdateOptions.Assign did not copy UseExecuteBlock, UseReturningFields
    and UseRowsClause, and left KeyFieldList empty. Assigning the
    AutoUpdateOptions property replaced the object instead of copying it, which
    leaked the old one and freed the shared one twice.
  • CharacterSet of a text BLOB column returned the charset with the BLOB
    subtype as ID (OCTETS), and numeric columns returned NONE, OCTETS or
    ASCII; columns that are not CHAR, VARCHAR or text BLOB return UNKNOWN.
  • TFIBSQLMonitor.Release raised an access violation before the first traced
    event, and the monitor was never freed while no monitor reader was active.
    Queries traced from several threads could free the SQL monitor writer thread
    while another thread used it; freeing the last monitor could hang; messages
    left at shutdown leaked.
  • SQL monitor: the fields of a fetch trace are on separate indented lines, as
    the parameters of an execute trace; a failed prepare names the query with
    its full owner path, as a failed execute.
  • TpFibErrorHandler: assigning ErrorLexems did not copy Exception and
    At; lexems of another length than the default cut the exception message
    in the wrong place; ExceptionName kept the value of an earlier exception.
  • Database.SQLLogger := nil left the logger attached, so statistics were
    still collected; moving a logger to another database left it on the first.
  • TSIBfibEventAlerter: the error for too long event names said they were
    truncated; they are not.
  • TpFIBScripter: StopStatementNo was not set by a pause at the last
    statement and kept the value of an earlier run; ExecuteScript(0) raised an
    access violation.
  • TpFIBScripter: OnExecuteError got an undefined DoRollBack for
    CONNECT, CREATE DATABASE and COMMIT, and was not called for
    DROP DATABASE; a failed COMMIT is kept when the handler sets DoRollBack
    to False.
  • TpFIBScripter: a resumed run lost the INSERT used by REINSERT,
    SET SQL DIALECT and SET NAMES; a pause set before INPUT was ignored.
  • TpFIBScripter with UseExecBlockForDML: an error in the last
    EXECUTE BLOCK always propagated, without OnExecuteError.
  • TpFIBScripter with UseExecBlockForDML: OnExecuteError and
    AfterStatementExecute of a block reported the statement after the block,
    which ran even when Stop was set; they report the last statement of the
    block, and AfterStatementExecute is called once per block.
  • TpFIBScripter with UseExecBlockForDML: after a pause, and after
    ExecuteStatement outside a run, the pending block was sent only by the next
    run, even of another script.
  • TpFIBScripter with UseExecBlockForDML: a statement too long for a block
    was dropped; EXECUTE BLOCK and EXECUTE PROCEDURE statements were nested
    into a block.
  • TpFIBClientDataSet.TransactionIsActive always raised "Invalid argument":
    TpFIBDataSet did not return the transaction state to the client. After a
    failed Commit or RollBack, the next execute without a command text ran
    the commit or rollback again instead of the dataset's SQL.