mysql catch all error handling - mysql

is there any way to capture all the errors the same way we can do with exceptions e.g. exceptions can be caught like
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
`#failurecode` = RETURNED_SQLSTATE, `#failuremsg` = MESSAGE_TEXT;
SELECT 'FAILURE' AS RESULT, `#failurecode` AS RESULTCODE,
`#failuremsg` AS RESULTMESSAGE;
END;
can all the errors be caught in one statement?

Related

how to execute next try on E exception

try
try //try1
//if error happen
except
on E: Exception do
begin
how to execute next try below
end;
end;
try //try2
...
except
on E: Exception do
begin
*and so on*
end;
end;
finally
...
end;
How if I want to execute "try2" when "try1" run to exception?
I have tried to use "Next" but it straight to "finally" in exception

Dec Ada & exception

I have this code in one modules:
PROCEDURE Get (File: IN Ada.Text_IO.File_Type; Item : OUT Rational) IS
N: Integer;
D: Integer;
Dummy: Character;
BEGIN -- Get
LOOP
BEGIN
Ada.Integer_Text_IO.Get(File => File, Item => N);
Ada.Text_IO.Get (File => File, Item => Dummy);
Ada.Integer_Text_IO.Get(File => File, Item => D);
Item := N/D;
if Dummy /= '/' then
........;
end if;
EXIT;
EXCEPTION
when other =>
Ada.Text_IO.Put_Line(" here is exception ");
END;
END LOOP;
END Get;
What is differences with this second code.
The main of my question is if I don't put raise in body of statement of exception what is happen?
PROCEDURE Get (File: IN Ada.Text_IO.File_Type; Item : OUT Rational) IS
N: Integer;
D: Integer;
Dummy: Character;
BEGIN -- Get
LOOP
BEGIN
Ada.Integer_Text_IO.Get(File => File, Item => N);
Ada.Text_IO.Get (File => File, Item => Dummy);
Ada.Integer_Text_IO.Get(File => File, Item => D);
Item := N/D;
if Dummy /= '/' then
........;
end if;
EXIT;
EXCEPTION
when other =>
Ada.Text_IO.Put_Line(" here is exception ");
**raise;**
END;
END LOOP;
END Get;
The main of my question is if I don't put raise in body of statement of exception what is happen???
Thank you very much.
The only difference between both code modules is that the exception (if any is raised during execution of Get) is reraised, i.e. the exception is propagated to the caller of Get.
Whether this is the desired behaviour depends on your needs, i.e. does the caller of Get need to know that an exception occurred?
In your example several kinds of exceptions may occur, e.g.
not reading the correct/expected input (the file to read from does not start with a number)
trying to read from a file that has not been opened
reading D as 0 (thus resulting in a division by 0)
All of these are handled in the same manner by printing "here is exception". The first implementation of Get then silently returns control to the caller (who will not know that anything strange happened). The second implementation, however, will inform the caller by reraising the exception.
For more information see the Ada LRM ยง11.3 (Raise Statements).

mysql error handling with signal/resignal

I would like to have a check for valid load types. If a load type passed into my procedure is invalid, I want to throw an error message via SIGNAL. I also want to have a generic EXIT handler for any other unexpected errors which will rollback any changes. The problem is the generic EXIT handler is taking precedence over my custom SIGNAL and all I get is 'SQLException encountered'. Unless i remove the generic EXIT handler, in which case I get 'Load type is incorrect'.
code:
DECLARE incorrect_load_type CONDITION FOR SQLSTATE '22012';
DECLARE EXIT HANDLER FOR incorrect_load_type
RESIGNAL SET MESSAGE_TEXT = 'Load type is incorrect';
DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING
begin
SELECT 'SQLException encountered';
rollback;
end;
IF(v_load_type != 'CORRECT TYPE') THEN
SIGNAL incorrect_load_type;
END IF;
Try this
DECLARE incorrect_load_type CONDITION FOR SQLSTATE '22012';
DECLARE EXIT HANDLER FOR incorrect_load_type
begin
SELECT 'Load type is incorrect';
end;
DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING
begin
SELECT 'SQLException encountered';
rollback;
end;
IF (v_load_type != 'CORRECT TYPE') THEN
SIGNAL incorrect_load_type;
END IF;
What I would do is this:
DECLARE custom_exception CONDITION FOR SQLSTATE '45000';
DECLARE EXIT HANDLER FOR SQLEXCEPTION begin
rollback;
resignal;
end;
IF v_load_type != 'CORRECT TYPE' THEN
SIGNAL custom_exception set message_text = 'Load type is incorrect';
END IF;
Notice that I've created a generic custom exception, and set the message text when it is signaled. This allows the generic SQLEXCEPTION exit handler to catch it and propagate that error message.
Next, I have deleted the handler for the custom exception.
Lastly, I have removed SQLWARNING from the exit handler. This is to avoid catching harmless warnings that ends up aborting the execution (since the "exit" handler would have caught it had SQLWARNING been included) but would yet totally mask out the reason (likely bcoz warnings aren't signaled, I'm guessing. And hence, despite the "resignal", there is nothing to resignal, so nothing is resignaled! And what ends up happening is: A warning (eg. data truncation) is caught and execution aborted, with no indication of this having happened!)
This is what I seem to be seeing from my experience.
Coming from an Oracle background, I can positively state that exception handling in MySQL grossly sucks!

Error converting varchar to int?

Msg 245, Level 16, State 1, Line 89
Conversion failed when converting the varchar value 'There was an error creating the System.DirectoryServices assembly. ' to data type int.
This error is caused by the statement below:
begin try print ' - Preparing to create System.DirectoryServices assembly with UNSAFE_ACCESS permission'
create assembly [System.DirectoryServices] from 'c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.DirectoryServices.dll'
with permission_set = unsafe
print ' - System.DirectoryServices assembly created'
end try
begin catch
print 'There was an error creating the System.DirectoryServices assembly. '+Error_number()+Error_Severity()
end catch
This is coming from your concatenation of number to string in the catch block. This is not allowed without casting as it tries to convert the string to number rather than vice versa and as your string literal is not numeric this attempt is doomed to fail!
You can use RAISERROR with severity 0 to print the message with the values substituted in or the alternative is to concatenate the string yourself using explicit casts.
begin catch
declare #num int = Error_number()
declare #sev int = Error_Severity()
raiserror('There was an error creating the System.DirectoryServices assembly. %d %d ',0,1, #num,#sev)
end catch

TDataSet Descendant

I have a very good DirectMySQL unit, which is ready to be used and i want it to be a TDataset descendant so i can use it with QuickReport, i just want MySQL Query with DirectMySQL which descendant from TDataset.
Everything was ok until i tried to access a big table with 10.000 rows and more. It was unstable, the error was unpredictable and not always shown but it likely happened after you played with other tables.
It happened in GetFieldData(Field: TField; Buffer: Pointer): boolean; which used to get the field value from MySQL rows.
Here's the code,
function TMySQLQuery.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
var
I, CT: Integer;
Row: TMySQL_Row;
TBuf: PChar;
FD: PMySQL_FieldDef;
begin
UpdateCursorPos; ------------> This code is after i got the error but no result
Resync([]); ------------> This code is after i got the error but no result
Result := false;
Row := oRecordset.CurrentRow;
I := Field.FieldNo-1;
FD := oRecordset.FieldDef(I);
if Not Assigned(FD) then
FD := oRecordset.FieldDef(I);
TBuf := PP(Row)[i];
Try
CT := MySQLWriteFieldData(fd.field_type, fd.length, fd.decimals, TBuf, PChar(Buffer));
Result := Buffer <> nil;
Finally
Row := nil; ------------> This code is after i got the error but no result
FD := nil; ------------> This code is after i got the error but no result
TBuf := nil; ------------> This code is after i got the error but no result
Buffer := nil; ------------> This code is after i got the error but no result
End;
end;
{
These codes below are to translate the data type
from MySQL Data type to a TDataset data type
and move mysql row (TBuf) to TDataset buffer to display.
And error always comes up from this function
when moving mysql row to buffer.
}
function TMySQLQuery.MySQLWriteFieldData(AType: byte;
ASize: Integer; ADec: cardinal; Source, Dest: PChar): Integer;
var
VI: Integer;
VF: Double;
VD: TDateTime;
begin
Result := MySQLDataSize(AType, ASize, ADec);
case AType of
FIELD_TYPE_TINY, FIELD_TYPE_SHORT, FIELD_TYPE_LONG, FIELD_TYPE_LONGLONG,
FIELD_TYPE_INT24:
begin
if Source <> '' then
VI := StrToInt(Source)
else
VI := 0;
Move(VI, Dest^, Result);
end;
FIELD_TYPE_DECIMAL, FIELD_TYPE_NEWDECIMAL:
begin
if source <> '' then
VF := internalStrToCurr(Source)
else
VF := 0;
Move(VF, Dest^, Result);
end;
FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE:
begin
if Source <> '' then
VF := InternalStrToFloat(Source)
else
VF := 0;
Move(VF, Dest^, Result);
end;
FIELD_TYPE_TIMESTAMP:
begin
if Source <> '' then
VD := InternalStrToTimeStamp(Source)
else
VD := 0;
Move(VD, Dest^, Result);
end;
FIELD_TYPE_DATETIME:
begin
if Source <> '' then
VD := InternalStrToDateTime(Source)
else
VD := 0;
Move(VD, Dest^, Result);
end;
FIELD_TYPE_DATE:
begin
if Source <> '' then
VD := InternalStrToDate(Source)
else
VD := 0;
Move(VD, Dest^, Result);
end;
FIELD_TYPE_TIME:
begin
if Source <> '' then
VD := InternalStrToTime(Source)
else
VD := 0;
Move(VD, Dest^, Result);
end;
FIELD_TYPE_STRING, FIELD_TYPE_VAR_STRING,
FIELD_TYPE_ENUM, FIELD_TYPE_SET:
begin
if Source = nil then
Dest^ := #0
else
Move(Source^, Dest^, Result);
end;
Else
Result := 0;
Raise EMySQLError.Create( 'Write field data - Unknown type field' );
end;
end;
My guess for now is it's memory related problem.
I am stacked. Anyone could help?
I also need TDataset documentation which list availlable descendant function and how to use it, or how to descendant from TDataset. anyone have them? I am lack of this kind of doumentation.
GetFieldData cannot have UpdateCursorPos and Resync calls. Otherwise you may get unpredicatable errors.
FD := oRecordset.FieldDef(I) ... FD := oRecordset.FieldDef(I); - looks strange. Second assigment is not needed.
finally ... end with local variables reset is not needed.
I have no idea what returns MySQLDataSize. For example, MySQLDataSize may return size in Delphi data type representation units, or may return length of data returned by MySQL. But depending on that MySQLWriteFieldData may be correct or may be not.
I dont know how DirectMySQL works. If it uses raw TCP/IP to talk to MySQL, then the problem may be there. For example, it incorrectly handles a sequence of packets.
And finally - what are the errors you are getting ? What is your Delphi version ? What is your MySQL client and server versions ?
And so on ....
IOW, that will be really hard to say, what is wrong. To do so, I for example, will need to get all sources, sit at Delphi IDE debugger and analyze many details of what is going on - sorry, no time :)
It's solved now by adding #0 at the end of the line... Thanks so much to all who replied to my problem.