I have this procedure:
create or replace PROCEDURE MyProc
(
<some-parameters>
)
AS
BEGIN
if(<some-condition>) then
RAISE_APPLICATION_ERROR('my custom error message');
end if;
END;
When calling it from C#:
try
{
<call procedure>
}
catch(OracleException x)
{
lblMessage.Text = x.Message;
}
I am getting error message like:
ORA-28008: my custom error message ORA-06512: at blah, line blah ORA-06512: at line blah
I want only:
my custom error message
There is no innerException. Errors collection don't help. Same situation when use Exception instead of OracleException.
What am I missing?
I can use string manipulation but how fixed is format of error message?
I use return parameters to capture with php. I recon the same technique will be useful in .net.
(I assume it's possible to catch the custom message in the exception handling and re-raising only that custom message, but underneath method works for sure. :)
create or replace PROCEDURE MyProc (p_result out varchar2)
is
...
begin
...
if error then
p_result := 'my custom error message';
return; -- exit procedure
end if;
p_result := 'ok';
end;
Try
PKG_MSG.RAISE_ERROR( 0,null,'my custom error message',null,null,null,null,null,null,null,null,null,null );
instead of
RAISE_APPLICATION_ERROR('my custom error message');
Related
This is a pascal program that returns factor . rate is the input which is given by the user.
This program is throwing me error.
please do have a look and help.
I want to rectify the error.
I'm not able to find out the error since im very new to pascal and im trying to learn
program Mss;
var
rate,factor:integer;
begin
readln(rate);
case rate of
1..2:begin
factor:=(2*rate)-1;
writeln(factor);
end
3:begin throws error here
factor:=(3*rate)-1;
writeln(factor);
end
4:begin
factor:=(4*rate)-1;
writeln:=(factor);
end
5:begin
factor:=(3*rate)-1;
writeln(factor);
end
6..8:begin
factor:=rate-2;
writeln(factor);
end
else begin
writeln(rate);
end
end;
This is a switch case which returns factor. rate is the input from user.
this throws me an error.
Fatal: Syntax error, ";" expected but "ordinal const" found
You have a few syntax errors. Your begin/end blocks need to be followed by ;.
writeln:=(factor) should be writeln(factor).
And you need an end. to finish the program.
program Mss;
var
rate,factor:integer;
begin
readln(rate);
case rate of
1..2:begin
factor:=(2*rate)-1;
writeln(factor);
end;
3:begin
factor:=(3*rate)-1;
writeln(factor);
end;
4:begin
factor:=(4*rate)-1;
writeln(factor);
end;
5:begin
factor:=(3*rate)-1;
writeln(factor);
end;
6..8:begin
factor:=rate-2;
writeln(factor);
end;
else begin
writeln(rate);
end
end
end.
Also, please note that ; in Pascal is a separator, so you could write code like:
6..8:begin
factor:=rate-2;
writeln(factor);
end;
As:
6..8:begin
factor:=rate-2;
writeln(factor)
end;
I have this code (that runs under iOS with Delphi Tokyo):
procedure TMainForm.Button1Click(Sender: TObject);
var aData: NSData;
begin
try
try
aData := nil;
finally
// this line triggers an exception
aData.release;
end;
except
on E: Exception do begin
exit;
end;
end;
end;
Normally the exception should be caught in the except end block, but in this case it is not caught by the handler and it is propagated to the Application.OnException handler.
Access violation at address 0000000100EE9A8C, accessing address
0000000000000000
Did I miss something?
This is a bug (actually, a feature) on iOS and Android platforms (possibly on others with LLVM backend - though they are not explicitly documented).
Core issue is that exception caused by virtual method call on nil reference constitutes hardware exception that is not captured by nearest exception handler and it is propagated to the next exception handler (in this case to Application exception handler).
Use a Function Call in a try-except Block to Prevent Uncaught Hardware Exceptions
With compilers for iOS devices, except blocks can catch a hardware
exception only if the try block contains a method or function call.
This is a difference related to the LLVM backend of the compiler,
which cannot return if no method/function is called in the try block.
The simplest code that exhibits the issue on iOS and Android platform is:
var
aData: IInterface;
begin
try
aData._Release;
except
end;
end;
Executing above code on Windows platform works as expected and the exception is caught by exception handler. There is no nil assignment in above code, because aData is interface reference and they are automatically nilled by compiler on all platforms. Adding nil assignment is redundant and does not change the outcome.
To show that exceptions are caused by virtual method calls
type
IFoo = interface
procedure Foo;
end;
TFoo = class(TInterfacedObject, IFoo)
public
procedure Foo; virtual;
end;
procedure TFoo.Foo;
var
x, y: integer;
begin
y := 0;
// division by zero causes exception here
x := 5 div y;
end;
In all following code variants, exception escapes exception handler.
var
aData: IFoo;
begin
try
aData.Foo;
except
end;
end;
var
aData: TFoo;
begin
try
aData.Foo;
except
end;
end;
Even if we change Foo method implementation and remove all code from it, it will still cause escaping exception.
If we change Foo declaration from virtual to static, exception caused by division to zero will be properly caught because call to static methods on nil references is allowed and call itself does not throw any exceptions - thus constitutes function call mentioned in documentation.
type
TFoo = class(TInterfacedObject, IFoo)
public
procedure Foo;
end;
TFoo = class(TObject)
public
procedure Foo;
end;
Another static method variant that also causes exception that is properly handled is declaring x as TFoo class field and accessing that field in Foo method.
TFoo = class(TObject)
public
x: Integer;
procedure Foo;
end;
procedure TFoo.Foo;
var
x: integer;
begin
x := 5;
end;
Back to the original question that involved NSData reference. NSData is Objective-C class and those are represented as interfaces in Delphi.
// root interface declaration for all Objective-C classes and protocols
IObjectiveC = interface(IInterface)
[IID_IObjectiveC_Name]
end;
Since calling methods on interface reference is always virtual call that goes through VMT table, in this case behaves in similar manner (exhibits same issue) as virtual method call invoked directly on object reference. The call itself throws an exception and is not caught by nearest exception handler.
Workarounds:
One of the workarounds in code where reference might be nil is checking it for nil before calling virtual method on it. If needed, in case of nil reference we can also raise regular exception that will be properly caught by enclosing exception handler.
var
aData: NSData;
begin
try
if Assigned(aData) then
aData.release
else
raise Exception.Create('NSData is nil');
except
end;
end;
Another workaround as mentioned in documentation is to put code in additional function (method)
procedure SafeCall(const aData: NSData);
begin
aData.release;
end;
var
aData: NSData;
begin
try
SafeCall(aData);
except
end;
end;
I am trying to find a way to detect the error no in objfpc, what I tried is shown below:
Program ErrorHandling;
{$R+}
{$MODE objfpc}
Uses
SysUtils, crt;
Var
intvar: 1 .. 100;
Begin
Try
clrscr;
writeln( 'enter intvar: ');
readln(intvar);
Except
on
e: Exception
Do
Begin
writeln('In Exception, IOResult: ',IOResult);
Case IOResult Of
201: writeln('Range intvar out of range 1-100!'); {How can we find that Error no is 201}
Else
writeln('Unkown Error!'); readln;
End
End
End;
writeln('intvar: ' , intvar);
readln;
End.
But How can we find if the 201 Range Error occurs. I tried using IOResult command but it always shows "Unknown Error" string of my case statement.
Using exceptions you can check error type by type of exception itself.
The classic way is:
try
clrscr;
writeln('enter intvar: ');
readln(intvar);
except
on e: ERangeError do // Executes when raised exception is ERangeError
begin
Writeln('Range intvar out of range 1-100!');
end;
on e: Exception do // Executes for any other exceptions
begin
Writeln(e.ClassName); // Shows exception class you can use at the "on e:" constuction
Writeln(e.Message);
end;
end;
Look at The try...except statement in the official documentation.
There are little bit problem.
I have an exception like this one
"Project project1 raised exception class 'External: SIGSEGV'.
In file '.\include\control.inc' at line 3251:
GetTextMethod := TMethod(#Self.GetTextBuf);
Code, which trigger exception:
procedure load_translation(language: string);
var
iit: integer;
begin
Form1.Caption:='Form 1';
Form2.Caption:='Form 2'; //as well as Unit2.Form2.Caption:='Form 2';
end;
procedure TForm1.Image1Click(Sender: TObject);
begin
language:='en';
load_translation(language);
end; `
I have a second Form, which already designed (not in runtime), so Exception raised when setting Text property of TEdit in custom component (Lazarus) not applicable in my case.
debug output:
<-stack-list-arguments 1 0 0>
^done,stack-args=[frame={level="0",args=[{name="this",value="<error reading variable>"},{name="result",value="0x0"}]}]
(gdb)
<-stack-list-locals 1>
^done,locals=[{name="LEN",value="5987780"},{name="GETTEXTMETHOD",value="{CODE = 0xc, DATA = 0x3676c0}"},{name="GETTEXT",value="0x25cf9d8"},{name="RESULT",value="0x25cf9d8"}]
(gdb)
I have a function in PL/SQL:
FUNCTION do_something
RETURN BOOLEAN
IS
...
BEGIN
...
END
This function can be called as such:
DECLARE
answer BOOLEAN;
BEGIN
answer := do_something();
END
Now, there are cases, where I don't need the returned boolean. If I don't want to get it and just write:
do_something();
I get PLS-00306 (wrong number of types of arguments in call to DO_SOMETHING)
Is there a way to call it without declaring and setting a new boolean, which I will never use in this case?
Very simple: create a procedure which covers this function
PROCEDURE do_something
IS
dummy boolean;
BEGIN
dummy := do_something();
END;
Sorry, but this is the only way in PL/SQL. This language is very strict in definitions of procedure and function and you cannot make a function call without handling the result. But you can make a procedure as it is shown in example above.
It will define automatically where to choose the function and where the procedure.
EDIT
As far as there are people who do not trust me (sometimes I really tell bad things so doubts are allowed :) ) this is the test:
declare
myresult boolean;
function do_something return boolean
is
begin
return true;
end;
procedure do_something
is
dummy boolean;
begin
dummy := do_something();
end;
begin
myresult := do_something();
do_something();
end;
works well.
Here is a useful alternative to assigning a dummy variable:
DECLARE
FUNCTION f_yes RETURN boolean IS
BEGIN
return true;
END f_yes;
BEGIN
IF f_yes THEN
null;
END IF;
END;
This is slightly more helpful when there are functions of different return types you want to call without using their results. It's also helpful for writing empty IF statements, which could be useful to to simplify code by eliminating possibilities for the real condition you want to match in a later ELSIF.
I'm in the same situation and the shortest solution I've come up is wrapping it in an IF statement:
if do_something then
null;
end if;