Delphi UIBDatabase nem csatlakozik vissza

Delphi UIBDatabase nem csatlakozik vissza
2019-09-07T17:37:28+02:00
2019-09-13T12:29:08+02:00
2022-12-06T03:15:54+01:00
PizzaProgram
A napokban frissítettem az UIB adatbázis kezelőt (mert a régiben rossz a LockTimeout).
Azóta ha megszakad az adatbázis kapcsolat (pl. rossz wifi miatt) egyszerűen nem enged visszacsatlakozni.
 
Hiába próbálom zárni előbb uDB.IsConnected:=False; vagy akár uDB.CancelAbort; paranccsal, amint megpróbálok újra csatlakozni, azt írja, hogy:

Project ...exe raised exception class EUIBError with message 'invalid statement handle Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements GDS Code: 335544485 - SQL Code: -901 - Error Code: 165'. Process stopped. Use Step or Run to continue.
Mutasd a teljes hozzászólást!
uiblib.pas fájlban javítandó:
 1. LockTimeout paraméter integer legyen
 2. paraméterezési eljárást felül kell írni a begin résztől ezzel a kóddal:

function CreateTRParams(Options: TTransParams; const LockRead, LockWrite: string{$IFDEF FB20_UP}; LockTimeout: integer{$ENDIF}): RawByteString; ... begin {$IFDEF FB20_UP} if LockTimeout = 0 then Exclude(Options, tpLockTimeout) else begin // -1 = infinite, 1..2048M = seconds Exclude(Options, tpnoWait); Include(Options, tpWait ); Include(Options, tpLockTimeout); end; {$ENDIF} if Options = [tpConcurrency,tpWait,tpWrite] then result := '' else begin Result := isc_tpb_version3; for tp := Low(TTransParam) to High(TTransParam) do if (tp in Options) then begin case tp of tpLockRead : ParseStrOption(tpc[tp], AnsiString(LockRead)); tpLockWrite : ParseStrOption(tpc[tp], AnsiString(LockWrite)); {$IFDEF FB20_UP} tpLockTimeout : //old code: PAnsiChar(@LockTimeout)[0] + PAnsiChar(LockTimeout)[1]; << [1] causing AV error case LockTimeout of -1 : Result := Result + tpc[tp] + #4#127#255#255#255; // 0 : Result := Result + tpc[tp] + #1#0; // this would be invalid 1..255: Result := Result + tpc[tp] + #1 + AnsiChar(Byte( LockTimeout and $FF)); else //256..32k Result := Result + tpc[tp] + #2 + AnsiChar(Byte((LockTimeout div $FF) and $FF)) + AnsiChar(Byte(LockTimeout and $FF)); end; {$ENDIF} else Result := Result + tpc[tp]; end; end; end; end;
...
Mutasd a teljes hozzászólást!

  • A probléma 2 részből adódott össze:

    1.) Véletlenül elgépeltem egy fontos helyen a paramétereket: tpConcurrency helyett tpConsistency -t írtam.
    Ettől persze LOCK-olta az egész táblát, így természetesen nem tudott "visszacsatlakozni" ahhoz a táblához már.
    (Azt persze fel nem tudom fogni, miért volt jó ennyire hasonló hangzású paraméterneveket kitalálni? Pl.: tpPreventConcurrent , tpAllowConcurrent túl egyértelmű lett volna?)

    2.) Túlságosan megbíztam az UIB jelenlegi fejlesztőiben. Ez szintén hatalmas hiba volt.
    Az általuk "átírt" LockTimeout funkciót inkább csak még jobban elrontották, mint az UIB 2.5-ben volt.
    Néhány éve én magam javítottam ki az UIB 2.5 kódjában a paraméterezést, ezt most újra meg kellett tennem, és így már STABILAN fut mindenhol a program.

    Az ő kódjuk több sebből vérzik, mivel:
    - hiába állít be az ember LockTimeout értéket a tranzakciónak, mert már az elején kilép, ha külön nem adta hozzá a tpLockTimeout paramétert az .Options -höz.

    if Options = [tpConcurrency,tpWait,tpWrite] then result := ''
    - amint ezt valaki kiküszöbölte, rögtön előugrik egy újabb hiba:

    PAnsiChar(@LockTimeout)[0] + PAnsiChar(LockTimeout)[1];
    A [1] rész kapásból Access Viola hibával elszáll.

    - ... és még volt pár érdekesség, de nem ragozom, inkább idemásolom a KÉSZ, javított kódot

    FONTOS még, hogy a Word típust vissza kell írni integer-nek, különben nem kezel -1 értéket! (Ami "infinite"-nek, azaz végtelen időnek felel meg.
    Mutasd a teljes hozzászólást!
  • uiblib.pas fájlban javítandó:
     1. LockTimeout paraméter integer legyen
     2. paraméterezési eljárást felül kell írni a begin résztől ezzel a kóddal:

    function CreateTRParams(Options: TTransParams; const LockRead, LockWrite: string{$IFDEF FB20_UP}; LockTimeout: integer{$ENDIF}): RawByteString; ... begin {$IFDEF FB20_UP} if LockTimeout = 0 then Exclude(Options, tpLockTimeout) else begin // -1 = infinite, 1..2048M = seconds Exclude(Options, tpnoWait); Include(Options, tpWait ); Include(Options, tpLockTimeout); end; {$ENDIF} if Options = [tpConcurrency,tpWait,tpWrite] then result := '' else begin Result := isc_tpb_version3; for tp := Low(TTransParam) to High(TTransParam) do if (tp in Options) then begin case tp of tpLockRead : ParseStrOption(tpc[tp], AnsiString(LockRead)); tpLockWrite : ParseStrOption(tpc[tp], AnsiString(LockWrite)); {$IFDEF FB20_UP} tpLockTimeout : //old code: PAnsiChar(@LockTimeout)[0] + PAnsiChar(LockTimeout)[1]; << [1] causing AV error case LockTimeout of -1 : Result := Result + tpc[tp] + #4#127#255#255#255; // 0 : Result := Result + tpc[tp] + #1#0; // this would be invalid 1..255: Result := Result + tpc[tp] + #1 + AnsiChar(Byte( LockTimeout and $FF)); else //256..32k Result := Result + tpc[tp] + #2 + AnsiChar(Byte((LockTimeout div $FF) and $FF)) + AnsiChar(Byte(LockTimeout and $FF)); end; {$ENDIF} else Result := Result + tpc[tp]; end; end; end; end;
    ...
    Mutasd a teljes hozzászólást!
  • Annyit még hozzátennék a megoldáshoz, hogy ezen javítások után sem "csatlakozik vissza".
    Tehát egyenlőre azt tudom tenni, hogy:
    - megsemmisítem a kapcsolatot, a tranzakciót, mindent (.free)
    - és újra létrehozom az egészet.
    Mindez kevesebb, mint 1ms idő, cserébe garantáltan működik.

    Nekem sem tetszik, de amíg valaki nem mond valami okosabbat, addig ez van, ezt kell szeretni.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd