Z cyklu ciekawostki #FireDAC
Na wstępie chciałbym uniknąć zbędnej dyskusji, że delphi umarło itd. Załączam jedynie jako ciekawostkę / info jeśli ktoś korzysta.
Mam kawałek kodu, który bierze DDL obiektu oracle (procedura/funkcja/pakiet/trigger itp.) z pliku i wgrywa ją na docelowe środowisko. Jak to w przypadku oracle bywa jak coś jest nie tak to status obiektu jest invalid i np w przypadku pakietów gdzie wgrywany jest np tylko header pakietu to wymagana jest kompilacja body tegoż pakietu bo automatycznie wchodzi w stan invalid.
W związku z powyższym po wgraniu czegokolwiek na bazkę uruchomiłem poniższy kod:
BEGIN
FOR CUR IN (SELECT * FROM ALL_OBJECTS
WHERE OWNER = :USER
and STATUS = 'INVALID'
and OBJECT_TYPE <> 'JAVA CLASS'
and OBJECT_NAME = :OBJECT_NAME) LOOP
BEGIN
IF CUR.OBJECT_TYPE = 'PACKAGE BODY' THEN
EXECUTE IMMEDIATE 'ALTER PACKAGE "'||CUR.OWNER||'"."'||CUR.OBJECT_NAME||'" COMPILE BODY';
ELSE
EXECUTE IMMEDIATE 'ALTER '||CUR.OBJECT_TYPE||' "'||CUR.OWNER||'"."'||CUR.OBJECT_NAME||'" COMPILE';
END IF;
END;
END LOOP;
END;
który automatycznie kompiluje mi dany obiekt/obiekty.
Wywołanie natomiast powyższego kodu wygląda tak:
for var k: integer := 0 to FFilList.Count - 1 do
begin
if TdmMainModule.Instance.LoadScriptFromFileFD(FFilList[k].value) then
try
TdmMainModule.Instance.qScript.ExecuteAll;
if ((FFilList[k].objectType <> TObjectEnum.oeOthers) and (pAutoCompile)) then
TryCompileObject(FFilList[k].value); //tu jest execute powyższego PL/SQL'a
if Assigned(fOnGetText) then
fOnGetText('OK: ' + FFilList[k].value + ' ' + sAddInfo);
except
on e: Exception do
if Assigned(fOnGetText) then
fOnGetText('Fail: ' + FFilList[k].value + ' ' + e.Message);
end;
end;
No i mam wszystko OK
Co ciekawe na bazie jest status pakietu INVALID no i rozkmina dlaczego. Odpaliłem PL/SQL'a z toad i zwrócił mi:
ORA-24344: Success with Compilation Error
niby jakiś tam ORA ale do exceptiona nie wchodzi .... i tu niestety bez wczytania się w kody FireDAC nie dało rady. Najpierw FireDac.Phys.OracleCli.pas
OCI_SUCCESS = 0; // maps to SQL_SUCCESS of SAG CLI
OCI_SUCCESS_WITH_INFO = 1; // maps to SQL_SUCCESS_WITH_INFO
OCI_RESERVED_FOR_INT_USE = 200; // reserved
OCI_NO_DATA = 100; // maps to SQL_NO_DATA
OCI_ERROR = -1; // maps to SQL_ERROR
OCI_INVALID_HANDLE = -2; // maps to SQL_INVALID_HANDLE
OCI_NEED_DATA = 99; // maps to SQL_NEED_DATA
OCI_STILL_EXECUTING = -3123; // OCI would block error
następnie FireDAC.Phys.OracleWrapper.pas
procedure TOCIError.Check(ACode: sword; AInitiator: TObject = nil);
begin
if FIgnoreErrors then
Exit;
case ACode of
OCI_SUCCESS:
;
OCI_NEED_DATA,
OCI_INVALID_HANDLE,
OCI_STILL_EXECUTING,
OCI_CONTINUE:
FDException(AInitiator, EOCINativeException.Create(Self, ACode, '')
{$IFDEF FireDAC_Monitor}, Env.Tracing {$ENDIF});
OCI_SUCCESS_WITH_INFO:
begin
ClearInfo;
FInfo := EOCINativeException.Create(Self);
end;
OCI_NO_DATA,
OCI_ERROR:
FDException(AInitiator, EOCINativeException.Create(Self)
{$IFDEF FireDAC_Monitor}, Env.Tracing {$ENDIF});
else
;
end;
end;
Jak widać OCI_SUCCESS_WITH_INFO jest jedynym exceptionem, który nie tworzy FDException ... no taaa logiczne przecież
@robertos7778: za długo trwa dlatego wyszukuję tylko obiekty rozkompilowane, które wgrywałem :)