How to I make the execution of the code return to the place from where it started executing an exception? - exception

here is a sample code
DECLARE
A number := 10;
B number := &x; ---- input a negative value
res number;
My-Exception EXCEPTION;
BEGIN
IF B < 0 THEN
RAISE myExp;
END IF;
---- how to make the code execute here after executing exception
res := A/B;
EXCEPTION
WHEN myExp THEN
DBMS_OUTPUT.PUT_LINE('cannot be negative');
B := B*(-1);
res := A/B;
DBMS_OUTPUT.PUT_LINE(res);
END;
/
how to make the code execute the commented area after finishing executing the exception

Related

ORA-30625 - JSON_OBJECT_T

I have the following procedure
CREATE OR REPLACE PROCEDURE GetAddress(P_JSON_CLOB_IN IN CLOB, P_JSON_OBJECT_OUT OUT JSON_OBJECT_T)
AS
V_JSON_OBJ JSON_OBJECT_T := JSON_OBJECT_T.parse(P_JSON_CLOB_IN);
V_ID CUSTOMERS.ID%TYPE;
V_TYPE ADDRESSES.TYPE%TYPE;
V_ADR ADDRESSES%ROWTYPE;
BEGIN
V_ID := V_JSON_OBJ.GET_STRING('id');
V_TYPE := V_JSON_OBJ.GET_STRING('type');
SELECT a.* INTO V_ADR FROM ADDRESSES a
INNER JOIN CUSTOMERS c ON c.ID=a.PEOPLEID
WHERE c.ID = V_ID
AND a.TYPE = V_TYPE;
P_JSON_OBJECT_OUT.put('address1',TO_CHAR(V_ADR.ADDRESS1));
P_JSON_OBJECT_OUT.put('address2',TO_CHAR(V_ADR.ADDRESS2));
P_JSON_OBJECT_OUT.put('zipmask',TO_CHAR(V_ADR.ZIPMASK));
P_JSON_OBJECT_OUT.put('city',TO_CHAR(V_ADR.CITY));
P_JSON_OBJECT_OUT.put('countryCode',TO_CHAR(V_ADR.COUNTRYCODE));
EXCEPTION
WHEN NO_DATA_FOUND THEN
P_JSON_OBJECT_OUT.put('error','NO DATA FOUND');
END;
It compiles successfully, however when invoked returns oracle exception
"ORA-30625 Method dispatch on NULL SELF argument is disallowed" on line 21.
I assume the error occurs because parameter P_JSON_OBJECT_OUT needs to be initialized prior to adding a key/value? How do I achieve this?
Thanks
I Found the solution. Simply add the following line in the start of the block:
P_JSON_OBJECT_OUT := new JSON_OBJECT_T;

Call by result Example

Is there any proper example for explaining call-by-result ? (not pseudocode)
I have learned that ALGOL 68, Ada could use this way,
but I cannot find any clear example of Call-by-Result.
I just made by myself.
pseudocode
begin
integer n;
procedure p(k: integer);
begin
n := n+1;
k := k+4;
print(n);
end;
n := 0;
p(n);
print(n);
end;
Implement using Ada Language
call.adb
with Gnat.Io; use Gnat.Io;
procedure call is
x : Integer;
Procedure NonSense (A: in out integer) is
begin
x := x + 1;
A := A + 4;
Put(x);
end NonSense;
begin
x := 0;
NonSense (x);
Put(" ");
Put(x);
New_Line;
end call;
Since Ada uses call-by-result way, result should be 1 4. (It could be checked by entering this code into online-Ada-compiler "http://www.tutorialspoint.com/compile_ada_online.php")
And, other result applied different passing parameter types should be...
call by value: 1 1
call by reference: 5 5
(compare > call by value-result: 1 4)

Run functions recursively

I have 2 function function1 and function2.
Now I'm wondering how to run them recursively.
Maybe I will describe it:
Input of function1 is table of array from function2 output. Output of function1 is also table of array which is input for function2 and so on.
While function1 is returning some values then function2 should be execute with that values.
When function2 return some values then function1 should be execute.
Function1 and function2 should be execute until one of them return null. Is it possible to do in pl/sql? Could you give me some tips? How to correctly convey the variables?
EDIT:
Generally it should looks:
declare
tab2 num_array;
v_Return NUM_ARRAY;
v_Return2 NUM_ARRAY;
BEGIN
select ID bulk collect into tab2 from account;
v_Return := function1(tab2);
if v_return is not null then
v_return2 :=function2(v_return);
--and now iteration:
if v_return2.count>0 then
v_Return := function1(v_return2);
if v_return.count>0 then
v_return2 :=function2(v_return);
if v_return2.count>0 then
v_Return := function1(v_return2);
if v_return..count>0 then
v_return2 :=function2(v_return);
-- and so on
END;
Of course I want to avoid doing something like that, can it be dynamically?
----edit 2
while(num=1)
loop
if v_return.count>0 then
num := 1;
v_return2 :=function2(v_return);
if v_return2.count>0 then
num :=1;
v_Return := function1(v_return2);
else num :=0;
end if;
else num :=0;
end if;
end loop;
END;
How about using a simple loop?
loop
v_return2 := function2(v_return);
exit when v_return2.count = 0;
v_return := function1(v_return2);
exit when v_return.count = 0;
end loop;

Lazarus Pascal parameterized query causing segfault! Why?

I've only just started learning Pascal so please excuse my ineptitude if I've missed something glaringly obvious.
I have a program that connects to a DB, retrieves a list of accounts and displays them in a StringGrid. I am now trying to extend the program so that selecting a row in the grid will perform a further search using parameters returned from the grid.
I have the grid setup correctly (I think!), I've managed to write the accountID value into a variable and am using it to construct a query.
When the time comes to run the query a segfault is issued and I don't understand why, the error message is
Project SQLConnect raised exception class 'External: SIGSEGV' at address 583166
The Assembler window shows the following gobbledygook:
00583166 8b09 mov (%ecx),%ecx
Here are the procedures I'm using to return data
Initial return before selecting row, this works - on its own:
procedure TForm1.sendQueryClick(Sender: TObject);
begin
CreateConnection;
CreateTransaction;
try
Query := GetQuery;
Query.SQL.Text := 'SELECT * FROM tbl_accounts LEFT JOIN tbl_properties ON tbl_accounts.ClientID = tbl_properties.PropertyID LEFT JOIN tbl_clients ON tbl_accounts.ClientID = tbl_clients.ClientID ORDER BY tbl_accounts.AccountID DESC';
AConnection.Open;
Query.Open;
while not Query.Eof do
begin
accID := Query.FieldByName('AccountID').AsString;
accountNo := Query.FieldByName('AccountNumber').AsString;
mortgagors := Query.FieldByName('Mortgagors').AsString;
address := Query.FieldByName('Address').AsString;
accResults.RowCount := accResults.RowCount + 1;
accResults.Cells[0, accResults.RowCount - 1] := accID;
accResults.Cells[1, accResults.RowCount - 1] := accountNo;
accResults.Cells[2, accResults.RowCount - 1] := mortgagors;
accResults.Cells[3, accResults.RowCount - 1] := address;
Query.Next;
end;
finally
Query.Close;
AConnection.Close;
Query.Free;
ATransaction.Free;
AConnection.Free;
end;
end;
This is the row select query, which causes the segfault:
procedure TForm1.accResultsSelectCell(Sender: TObject; aCol, aRow: Integer; var CanSelect: Boolean);
begin
// Hide Account ID Column
accResults.ColWidths[0] := 0;
CurrCol := 0;
CurrRow := aRow;
// Grab Account ID value from cell
CellValue := accResults.Cells[CurrCol, CurrRow];
selectedRow.Text := CellValue;
// Setup Query
try
TestQuery := GetQuery;
TestQuery.SQL.Text := 'SELECT * FROM tbl_accounts LEFT JOIN tbl_properties ON tbl_accounts.ClientID = tbl_properties.PropertyID LEFT JOIN tbl_clients ON tbl_accounts.ClientID = tbl_clients.ClientID WHERE AccountID = :AccID';
TestQuery.Params.ParamByName('AccID').AsString := CellValue;
// Open Database connection
AConnection.Open;
TestQuery.Open;
begin
end;
finally
TestQuery.Close;
AConnection.Close;
TestQuery.Free;
ATransaction.Free;
AConnection.Free;
end;
end;
IIRC: Make sure that the type of the parameter is not ftunknown.

Return value of stored functions in MyDAC

I am working with Devart's MyDac and MySQL Server 5.0.41. Here is a section from the documentation on executing stored procedures with TMyConnection.ExecProc:
Note: Stored functions unlike stored procedures return result values that are obtained internally through the RESULT parameter. You will no longer have to provide anonymous value in the Params array to describe the result of the function. The stored function result is obtained from the Params[0] indexed property or with the ParamByName('RESULT') method call.
They also give an example on how to execute a stored function:
aStringVariable1 := TMyConnection.ExecProc('StoredFunctionName',['Param1','Param2']);
aStringVariable2 := TMyConnection.ParamByName('Result').AsString;
By Following these examples, my execution of the stored functions are returning Param1 in the variable aStringVariable2.The execution of the functions in the Query Browser returns the right results. Any pointers on the right way to execute stored functions in MyDAC with TMyConnection or TMyStoredProc will be appreciated.
Thanks in advance.
Here is the code we use to call stored procedures - hope it helps
function TDbControl.DatabaseStoredProc(FConnectionsAddr: integer; SpName: string;var Params: TDAParams): boolean;
var
MyStoredProc: TMyStoredProc;
PramsTxt: String;
Idx, Idx2: Integer;
begin
result := False;
MyStoredProc := nil;
try
try
MyStoredProc := TMyStoredProc.Create(nil);
MyStoredProc.Connection := TMyConnection(FConnectionsAddr);
MyStoredProc.StoredProcName := SpName;
MyStoredProc.ParamCheck := False;
if assigned(Params) then
begin
for Idx := 0 to Params.Count - 1 do
begin
MyStoredProc.ParamByName(Params[Idx].Name).DataType := Params[Idx].DataType;
MyStoredProc.ParamByName(Params[Idx].Name).Value := Params[Idx].Value;
end;
end;
MyStoredProc.Execute;
if assigned(Params) then
begin
for Idx := 0 to Params.Count - 1 do
begin
if (Params[Idx].ParamType = ptOutput ) then
Params[Idx].Value := MyStoredProc.ParamByName(Params[Idx].Name).Value;
end;
end;
result := True;
except
on E: Exception do
begin
PramsTxt := '';
if assigned(Params) then
begin
for Idx2 := 0 to Params.Count - 1 do
begin
PramsTxt := PramsTxt + Params.Items[Idx2].Name + '=' + Params[Idx2].AsString + ',';
end;
end;
LogText(FConnectionsAddr, 'DatabaseStoredProc Err:' + E.Message + ' SpName:' + SpName + ' Prams:' + PramsTxt);
raise ;
end;
end;
finally
FreeAndNil(MyStoredProc);
end;
end;