ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Discussion of open issues, suggestions and bugs regarding ODAC (Oracle Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
kithran
Posts: 13
Joined: Wed 05 Oct 2005 08:20

ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by kithran » Thu 08 May 2014 09:05

While a function called via TOraStoredProc now appears to work correctly with most result types there is an issue if the result is a boolean. An example of the problem can be seen with these two sql monitors, the first with an older version of ODAC that works correctly and the second with 9.3.8:

Code: Select all

78      08:59:09  SQL Prepare: declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;
79      08:59:09  :PCUSTOMERID(INTEGER,IN)=<NULL> 
:RESULT(BOOLEAN,OUT)=<NULL>
80      08:59:09  SQL Execute: declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;
81      08:59:09  :PCUSTOMERID(INTEGER,IN)=0 
:RESULT(BOOLEAN,OUT)=<NULL>

Code: Select all

78      16:24:35  SQL Prepare: declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;
79      16:24:35  :PCUSTOMERID(INTEGER,IN)=<NULL> 
:RESULT(BOOLEAN,OUT)=<NULL>
80      16:24:35  SQL Unprepare: declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;
81      16:24:35  :PCUSTOMERID(INTEGER,IN)=0 
:RESULT(BOOLEAN,OUT)=<NULL>
82      16:24:35  SQL Unprepare: declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;
83      16:24:35  :PCUSTOMERID(INTEGER,IN)=0 
:RESULT(BOOLEAN,OUT)=<NULL>
84      16:24:35  SQL Prepare: declare
  v_RESULT boolean;
begin
  P_CUSTOMER.ISCONTAINER(:PCUSTOMERID, v_RESULT);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;
85      16:24:35  :PCUSTOMERID(INTEGER,IN)=0 
:RESULT(BOOLEAN,OUT)=<NULL>
86      16:24:35  SQL Execute: declare
  v_RESULT boolean;
begin
  P_CUSTOMER.ISCONTAINER(:PCUSTOMERID, v_RESULT);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;
87      16:24:35  :PCUSTOMERID(INTEGER,IN)=0 
:RESULT(BOOLEAN,OUT)=<NULL>
88      16:24:35  Error: ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'ISCONTAINER'
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored
Do you have a timescale for this to be fixed?

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by AlexP » Thu 08 May 2014 14:36

We can't reproduce the problem on the latest ODAC version 9.3.8.
For the function

Code: Select all

CREATE OR REPLACE FUNCTION SP_BOOL_RET(A_VALUE IN NUMBER) RETURN BOOLEAN AS
BEGIN
  RETURN  A_VALUE = 0;
END;
the correct call is generated:

Code: Select all

declare
  v_RESULT boolean;
begin
  v_RESULT := SP_BOOL_RET(:A_VALUE);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;
and the function runs with no errors.

kithran
Posts: 13
Joined: Wed 05 Oct 2005 08:20

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by kithran » Thu 08 May 2014 15:05

The SQL monitor output I posted initially is from the same delphi form - the only difference is the successful call is with ODAC 8.2.7 and the unsuccessful call is with ODAC 9.3.8.

I have also been able to reproduce this with another delphi form calling a different function in a different oracle package that returns a boolean result with the form working with ODAC 5.80.0.42 and failing with ODAC 9.3.8. - see the following sql monitor output:

5.80.0.42

Code: Select all

455     15:59:59  SQL Execute: declare
  v_RESULT boolean;
begin
  v_RESULT := fleetware.P_BO_VEHICLE.ISDRIVERREGKEEPER(:PDRIVERID, :PFMVEHICLEID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;
456     15:59:59  :PDRIVERID(INTEGER,IN)=52 
:PFMVEHICLEID(VARCHAR[2],IN)='93' 
:RESULT(BOOLEAN,OUT)=<NULL>
9.3.8

Code: Select all

669     16:02:03  SQL Execute: declare
  v_RESULT boolean;
begin
  fleetware.P_BO_VEHICLE.ISDRIVERREGKEEPER(:PDRIVERID, :PFMVEHICLEID, v_RESULT);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;
670     16:02:03  :PDRIVERID(INTEGER,IN)=52 
:PFMVEHICLEID(VARCHAR[2],IN)='93' 
:RESULT(BOOLEAN,OUT)=<NULL>
671     16:02:03  Error: ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'ISDRIVERREGKEEPER'
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

paulzip
Posts: 37
Joined: Mon 02 Oct 2006 13:13

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by paulzip » Fri 09 May 2014 14:12

Just a hunch (seems pretty obvious to me), the fix to TOraStoredProc calling ...
1. Stored functions with return type boolean (WORKS)
2. Package functions with return type boolean. (FAILS)

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by AlexP » Mon 12 May 2014 12:06

Hello,

We couldn't reproduce the problem on neither separate functions nor packages. Please send a script for creating function/package, and the OraStoredProc declaration text in the *.dfm file.

kithran
Posts: 13
Joined: Wed 05 Oct 2005 08:20

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by kithran » Mon 12 May 2014 14:51

I've just found another issue that seems to indicate its a general issue with Boolean parameters (whether they are results or not).

The following procedure is in a package:

Code: Select all

  procedure GetTotalPayments(
    ContractID    Varchar2,
    DueDateFrom   Date := null,
    DueDateTo     Date := null,
    InvDateFrom   Date := null,
    InvDateTo     Date := null,
    Posted        boolean := null,
    PaymentType   char := null,
    pCount    out PLS_Integer,
    Finance   out Number,
    Services  out Number,
    Insurance out Number);
A SQL monitor shows the following:

Code: Select all

48      15:38:29  SQL Execute: declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(v_POSTED, :CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;
49      15:38:29  :POSTED(BOOLEAN,IN)=True 
:CONTRACTID(VARCHAR[5],IN)='103/A' 
:DUEDATEFROM(DATE,IN)=<NULL> 
:DUEDATETO(DATE,IN)=<NULL> 
:INVDATEFROM(DATE,IN)=<NULL> 
:INVDATETO(DATE,IN)=<NULL> 
:PAYMENTTYPE(CHAR[0],IN)=<NULL> 
:PCOUNT(INTEGER,OUT)=<NULL> 
:FINANCE(FLOAT,OUT)=<NULL> 
:SERVICES(FLOAT,OUT)=<NULL> 
:INSURANCE(FLOAT,OUT)=<NULL>
50      15:38:29  Error: ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'GETTOTALPAYMENTS'
ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'GETTOTALPAYMENTS'
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

The declaration from the DFM is as follows:

Code: Select all

  object sprTotalPayments: TOraStoredProc
    StoredProcName = 'P_FM_CONTRACT.GETTOTALPAYMENTS'
    Session = frmMDIMain.dbMain
    SQL.Strings = (
      'declare'
      '  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);'
      'begin'
      
        '  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUE' +
        'DATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUN' +
        'T, :FINANCE, :SERVICES, :INSURANCE);'
      'end;')
    Left = 712
    Top = 440
    ParamData = <
      item
        DataType = ftBoolean
        Name = 'POSTED'
        ParamType = ptInput
      end
      item
        DataType = ftString
        Name = 'CONTRACTID'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'DUEDATEFROM'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'DUEDATETO'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'INVDATEFROM'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'INVDATETO'
        ParamType = ptInput
      end
      item
        DataType = ftFixedChar
        Name = 'PAYMENTTYPE'
        ParamType = ptInput
      end
      item
        DataType = ftInteger
        Name = 'PCOUNT'
        ParamType = ptOutput
      end
      item
        DataType = ftFloat
        Name = 'FINANCE'
        ParamType = ptOutput
      end
      item
        DataType = ftFloat
        Name = 'SERVICES'
        ParamType = ptOutput
      end
      item
        DataType = ftFloat
        Name = 'INSURANCE'
        ParamType = ptOutput
      end>
  end
For some reason the new version of ODAC thinks the boolean parameter is the first parameter rather than the 6th parameter it actually is (and the DFM says it is).

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by AlexP » Tue 13 May 2014 13:09

Most probably, this parameter was first in your procedure, therefore it was the first to be written in the dfm. Then the procedure was edited, and the dfm wasn't updated, the error occurs due to this. If you recreate the procedure, parameters will be written correctly in the dfm - and there will be no error.

kithran
Posts: 13
Joined: Wed 05 Oct 2005 08:20

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by kithran » Wed 14 May 2014 08:57

AlexP wrote:Most probably, this parameter was first in your procedure, therefore it was the first to be written in the dfm. Then the procedure was edited, and the dfm wasn't updated, the error occurs due to this. If you recreate the procedure, parameters will be written correctly in the dfm - and there will be no error.
Thanks to our source control system I can say the procedure in the package and the component on the dfm were both added over 8 years ago and have never been changed - when added the boolean parameter was the 6th parameter in the procedure definition and the 6th parameter of the dfm as shown in the examples above.

Yet for some reason only with ODAC 9.3.8 when the call to the procedure is actually made the boolean parameter is being treated as the first parameter as shown in the sql monitor output above.

paulzip
Posts: 37
Joined: Mon 02 Oct 2006 13:13

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by paulzip » Wed 14 May 2014 09:08

AlexP wrote:Most probably, this parameter was first in your procedure, therefore it was the first to be written in the dfm. Then the procedure was edited, and the dfm wasn't updated, the error occurs due to this. If you recreate the procedure, parameters will be written correctly in the dfm - and there will be no error.
This is definitely an ODAC bug and I have a few examples of the same problem, I can replicate it too :

1. Set up TOraStoredProc pointing to a stored proc with a boolean parameter in the middle of a list of parameters, such as an OUT parameter in Kithrin's example.
2. In Delphi Object Inspector, click TOraStoredProc.Params property. The params form will be invoked.
3. The params will parsed and added to the DFM in the correct order. Click OK.
4. Perform step 2. again, the params will be parsed but now any boolean parameter will be added as the first parameters in the list, (developer won't be aware params order has changed and will click OK). This is because ODAC has re-written the calling code as

Code: Select all

declare
  v_BOOLPARAM1 boolean := sys.DIUTIL.INT_TO_BOOL(:BOOLPARAM1);
  v_BOOLPARAM2 boolean := sys.DIUTIL.INT_TO_BOOL(:BOOLPARAM2); 
begin
  ...
end;
to work around boolean treatment. Now at runtime the stored proc will blow up because the binding of the TOraParamDesc params which seems to work off index will be broken by ODAC's bug. This is a VERY DANGEROUS bug and has certainly caused me some headaches. Perhaps the binding code should work on param name, rather than index - regardless, this needs to be addressed.

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by AlexP » Wed 14 May 2014 10:38

On the latest version, doing the provided steps and executing the Kithrin's sample - the problem is not reproduced. Please make sure you have completely deleted the previous ODAC version.

paulzip
Posts: 37
Joined: Mon 02 Oct 2006 13:13

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by paulzip » Wed 14 May 2014 11:02

AlexP wrote:On the latest version, doing the provided steps and executing the Kithrin's sample - the problem is not reproduced. Please make sure you have completely deleted the previous ODAC version.
You're completely missing the point here! In new versions of ODAC, if the params in the DFM are not ordered to match the :APARAM place holder index in the stored proc, it blows up with ORA-06550, PLS-00306: wrong number or types of arguments in call to .... I'm demonstrating how the param order can end up incorrect - down to a bug in ODAC. Bear in mind, Kithran and I are still using an older version of ODAC, because we are having these issues trying to move to a newer version.

Old versions of ODAC don't exhibit this problem, so you've changed something and it's broken things. It seems to relate to how you rewrite and parse boolean parameters and parameter binding indexing. I suspect that internally, your parameter binding or Oracle param type allocation is done by index, it SHOULD be by name, it's EXACTLY why they have names and avoids such dangers and problems as Kithran and I are experiencing trying to upgrade to newer versions of ODAC.

paulzip
Posts: 37
Joined: Mon 02 Oct 2006 13:13

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by paulzip » Wed 14 May 2014 12:38

The problem seems to be in OraClasses.TOCICommand.CreateProcCall or InternalCreateProcCall methods when constructing the anonymous block SQL for the stored proc call. Interestingly, you're aware of this EXACT issue in the 5.80.x source (which doesn't exhibit the bug), see the comment in your code below which says "Prevent updating ParamDescs. Otherwise parameter order will be incorrect in case of boolean parameters..". So it looks like you've removed a fix you put in ages ago!

Code: Select all

procedure TOraDataSet.InternalCreateProcCall(Name: string; Overload: integer;
  NeedDescribe: boolean);
var
  ProcCallSQL: string;
begin
  CheckConnection;

  if not NeedDescribe then
    TOraSQL(FCommand).WriteParams(False);
  ProcCallSQL := FICommand.CreateProcCall(PChar(Name), Overload, NeedDescribe);
  if NeedDescribe then
    TOraSQL(FCommand).CreateParams;

  // Prevent updating ParamDescs. Otherwise parameter order will be incorrect
  // in case of boolean parameters.
  FICommand.SetProp(prDisableParamScan, True);
  try
    FCommand.SQL.Text := ProcCallSQL;
  finally
    FICommand.SetProp(prDisableParamScan, False);
  end;
end;

AlexP
Devart Team
Posts: 5530
Joined: Tue 10 Aug 2010 11:35

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by AlexP » Thu 15 May 2014 14:17

If you create a package from http://forums.devart.com/viewtopic.php? ... 28#p101282 , the problem is not reproduced performing your steps. Please provide a package reproducing the problem.

paulzip
Posts: 37
Joined: Mon 02 Oct 2006 13:13

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by paulzip » Fri 16 May 2014 16:45

Here's a test to prove that 9.3.8 is broken in regards to stored procs with boolean variables.

Dummy package matching Kithran's example :

Code: Select all

create or replace package P_FM_CONTRACT as

procedure GetTotalPayments(
  ContractID    Varchar2,
  DueDateFrom   Date := null,
  DueDateTo     Date := null,
  InvDateFrom   Date := null,
  InvDateTo     Date := null,
  Posted        boolean := null,
  PaymentType   char := null,
  pCount    out PLS_Integer,
  Finance   out Number,
  Services  out Number,
  Insurance out Number);   
  
end;
/

create or replace package body P_FM_CONTRACT as
procedure GetTotalPayments(
  ContractID    Varchar2,
  DueDateFrom   Date := null,
  DueDateTo     Date := null,
  InvDateFrom   Date := null,
  InvDateTo     Date := null,
  Posted        boolean := null,
  PaymentType   char := null,
  pCount    out PLS_Integer,
  Finance   out Number,
  Services  out Number,
  Insurance out Number) is
begin
  null;
end;

end;
/  
Form Pas Code (Note the param order to the InternalCreateProcCall method differs between ODAC 5.80.x and ODAC 9.3.8. Only errors are shown, calls which succeed log no error line )

Code: Select all

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, MemDS, DBAccess, Ora, StdCtrls;

type
  TOps = (opDefault, opPrepare, opCreateProcCall,
          opInternalCreateProcCallNoDescr, opInternalCreateProcDescr);
  TOraStoredProcHack = class(TOraStoredProc);
  TForm1 = class(TForm)
    OraSession1: TOraSession;
    sprGetTotalPayment: TOraStoredProc;
    Memo1: TMemo;
    btnRunTests: TButton;
    procedure FormShow(Sender: TObject);
    procedure btnRunTestsClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    DefaultSQLText : string;
    DefaultParams : TOraParams;
    procedure DoLog(const Str: string);
    function ParamsAsString(Params: TOraParams): string;
    procedure ResetStoredProc(ClearParams: boolean);
    procedure ProcessTest(Info: string; ClearParams: boolean);
    procedure DoClearDataSetParams(Params: TParams; SetBound: boolean);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  TypInfo;

procedure TForm1.FormShow(Sender: TObject);
begin
  Memo1.Lines.Clear;
  DefaultSQLText := sprGetTotalPayment.SQL.Text;
  DefaultParams := TOraParams.Create(nil);
  DefaultParams.Assign(sprGetTotalPayment.Params);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  DefaultParams.Free;
end;

procedure TForm1.DoLog(const Str : string);
begin
  Memo1.Lines.Add(Str);
end;

function TForm1.ParamsAsString(Params : TOraParams) : string;
var
  m : integer;
begin
  for m := 0 to Params.Count - 1 do
    Result := Result + Params[m].Name + ', ';
end;

procedure TForm1.ResetStoredProc(ClearParams : boolean);
begin
  if sprGetTotalPayment.Prepared then
    sprGetTotalPayment.UnPrepare;
  sprGetTotalPayment.SQL.Text := DefaultSQLText;
  if ClearParams then
    sprGetTotalPayment.Params.Clear
  else
    sprGetTotalPayment.Params.Assign(DefaultParams);
end;

procedure TForm1.DoClearDataSetParams(Params : TParams; SetBound : boolean);
var
  i:integer;
begin
  for i := 0 to Params.Count-1 do
  begin
    Params[i].Clear;
    if SetBound then
      Params[i].Bound := True;
  end;
end;

procedure TForm1.ProcessTest(Info : string; ClearParams : boolean);
const
  SEP  = '-----------------------------------------------';
  SEP2 = '===============================================';
  CONTRNO = '103/A';
var
  n : TOps;
  procedure LogInfo(AOp : TOps; ASQL : string);
  begin
    DoLog(GetEnumName(TypeInfo(TOps), integer(AOp)) + ': ' + #13#10);
    DoLog('Params Order : ' + ParamsAsString(sprGetTotalPayment.Params) + #13#10);
    DoLog(ASQL);
    try
      DoClearDataSetParams(sprGetTotalPayment.Params, True);
      sprGetTotalPayment.ParamByName('ContractID').AsString := ContrNo;
      sprGetTotalPayment.ParamByName('Posted').AsBoolean := True;
      sprGetTotalPayment.ExecProc;
    except
      on E:Exception do
        DoLog(E.Message);
    end;
    DoLog(SEP);
  end;
begin
  DoLog(Info);
  for n := Low(TOps) to High(TOps) do
  begin
    ResetStoredProc(ClearParams);
    case n of
      opPrepare :
        sprGetTotalPayment.Prepare;
      opCreateProcCall :
        sprGetTotalPayment.CreateProcCall(sprGetTotalPayment.StoredProcName, 0);
      opInternalCreateProcCallNoDescr, opInternalCreateProcDescr :
        TOraStoredProcHack(sprGetTotalPayment).InternalCreateProcCall(sprGetTotalPayment.StoredProcName, 0, n = opInternalCreateProcDescr); // Version 5.80
//      TOraStoredProcHack(sprGetTotalPayment).InternalCreateProcCall(sprGetTotalPayment.StoredProcName, n = opInternalCreateProcDescr);    // Version 9.3.8        
    end;
    LogInfo(n, sprGetTotalPayment.SQL.Text);
  end;
  DoLog(SEP2);
end;

procedure TForm1.btnRunTestsClick(Sender: TObject);
begin
  ProcessTest('Params From DFM', False);
  ProcessTest('Params Cleared', True);
end;

end.
The Form DFM code : (Note the stored procedure params have been viewed once from the Object Inspector params editor in ODAC 5.80 and saved). This DFM is used for both tests, because we are going from ODAC 5.80 to 9.3.8 and we will not be re-invoking all our 10000s of stored proc param lists in our real life enterprise app.

Code: Select all

object Form1: TForm1
  Left = 319
  Top = 124
  Width = 1305
  Height = 750
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnDestroy = FormDestroy
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object Memo1: TMemo
    Left = 352
    Top = 8
    Width = 633
    Height = 681
    ScrollBars = ssBoth
    TabOrder = 0
    WordWrap = False
  end
  object btnRunTests: TButton
    Left = 88
    Top = 272
    Width = 75
    Height = 25
    Caption = 'Run Tests'
    TabOrder = 1
    OnClick = btnRunTestsClick
  end
  object OraSession1: TOraSession
    Username = 'PAULZIP'
    Password = 'PAULZIP'
    Server = 'CURRENT'
    Connected = True
    Left = 136
    Top = 56
  end
  object sprGetTotalPayment: TOraStoredProc
    StoredProcName = 'P_FM_CONTRACT.GETTOTALPAYMENTS'
    Session = OraSession1
    SQL.Strings = (
      'declare'
      '  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);'
      'begin'
      
        '  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUE' +
        'DATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUN' +
        'T, :FINANCE, :SERVICES, :INSURANCE);'
      'end;')
    Left = 200
    Top = 56
    ParamData = <
      item
        DataType = ftBoolean
        Name = 'POSTED'
        ParamType = ptInput
      end
      item
        DataType = ftString
        Name = 'CONTRACTID'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'DUEDATEFROM'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'DUEDATETO'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'INVDATEFROM'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'INVDATETO'
        ParamType = ptInput
      end
      item
        DataType = ftFixedChar
        Name = 'PAYMENTTYPE'
        ParamType = ptInput
      end
      item
        DataType = ftInteger
        Name = 'PCOUNT'
        ParamType = ptOutput
      end
      item
        DataType = ftFloat
        Name = 'FINANCE'
        ParamType = ptOutput
      end
      item
        DataType = ftFloat
        Name = 'SERVICES'
        ParamType = ptOutput
      end
      item
        DataType = ftFloat
        Name = 'INSURANCE'
        ParamType = ptOutput
      end>
  end
end
Output for ODAC 5.80.x

Code: Select all

Params From DFM
opDefault: 

Params Order : POSTED, CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

-----------------------------------------------
opPrepare: 

Params Order : POSTED, CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

-----------------------------------------------
opCreateProcCall: 

Params Order : CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, POSTED, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

-----------------------------------------------
opInternalCreateProcCallNoDescr: 

Params Order : POSTED, CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(v_POSTED, :CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'GETTOTALPAYMENTS'
ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'GETTOTALPAYMENTS'
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

-----------------------------------------------
opInternalCreateProcDescr: 

Params Order : CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, POSTED, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

-----------------------------------------------
===============================================
Params Cleared
opDefault: 

Params Order : 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

Parameter 'ContractID' not found
-----------------------------------------------
opPrepare: 

Params Order : 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

Parameter 'ContractID' not found
-----------------------------------------------
opCreateProcCall: 

Params Order : CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, POSTED, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

-----------------------------------------------
opInternalCreateProcCallNoDescr: 

Params Order : 

begin
  P_FM_CONTRACT.GETTOTALPAYMENTS;
end;

Parameter 'ContractID' not found
-----------------------------------------------
opInternalCreateProcDescr: 

Params Order : CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, POSTED, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

-----------------------------------------------
===============================================
Output for ODAC 9.3.8

Code: Select all

Params From DFM
opDefault: 

Params Order : POSTED, CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'GETTOTALPAYMENTS'
ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'GETTOTALPAYMENTS'
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

-----------------------------------------------
opPrepare: 

Params Order : POSTED, CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'GETTOTALPAYMENTS'
ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'GETTOTALPAYMENTS'
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

-----------------------------------------------
opCreateProcCall: 

Params Order : CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, POSTED, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

-----------------------------------------------
opInternalCreateProcCallNoDescr: 

Params Order : POSTED, CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'GETTOTALPAYMENTS'
ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'GETTOTALPAYMENTS'
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

-----------------------------------------------
opInternalCreateProcDescr: 

Params Order : CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, POSTED, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

-----------------------------------------------
===============================================
Params Cleared
opDefault: 

Params Order : 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

Parameter 'ContractID' not found
-----------------------------------------------
opPrepare: 

Params Order : CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, POSTED, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

-----------------------------------------------
opCreateProcCall: 

Params Order : CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, POSTED, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

-----------------------------------------------
opInternalCreateProcCallNoDescr: 

Params Order : 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

Parameter 'ContractID' not found
-----------------------------------------------
opInternalCreateProcDescr: 

Params Order : CONTRACTID, DUEDATEFROM, DUEDATETO, INVDATEFROM, INVDATETO, POSTED, PAYMENTTYPE, PCOUNT, FINANCE, SERVICES, INSURANCE, 

declare
  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);
begin
  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUEDATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUNT, :FINANCE, :SERVICES, :INSURANCE);
end;

-----------------------------------------------
===============================================
Hopefully you can now replicate the issues and fix 9.3.8.

paulzip
Posts: 37
Joined: Mon 02 Oct 2006 13:13

Re: ODAC 9.3.8 Issue with Boolean Results on TOraStoredProc

Post by paulzip » Mon 19 May 2014 15:46

I've altered the test to include Kithran's boolean function issue too.

Code: Select all

create or replace package P_CUSTOMER as  
function  IsContainer(pCustomerID number) return boolean;  
end;
/

create or replace package body P_CUSTOMER as

function  IsContainer(pCustomerID number) return boolean is
begin
  return true;
end;

end;
/ 
New form pas with radio buttons to select which boolean params stored proc test to perform :

Code: Select all

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, MemDS, DBAccess, Ora, StdCtrls;

type
  TOps = (opDefault, opPrepare, opCreateProcCall,
          opInternalCreateProcCallNoDescr, opInternalCreateProcDescr);
  TOraStoredProcHack = class(TOraStoredProc);
  TForm1 = class(TForm)
    OraSession1: TOraSession;
    sprGetTotalPayment: TOraStoredProc;
    Memo1: TMemo;
    btnRunTests: TButton;
    sprIsContainer: TOraStoredProc;
    radGetTotalPayment: TRadioButton;
    radIsContainer: TRadioButton;
    procedure FormShow(Sender: TObject);
    procedure btnRunTestsClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Memo1DblClick(Sender: TObject);
  private
    { Private declarations }
    DefaultSQLText : string;
    DefaultParams : TOraParams;
    procedure DoLog(const Str: string);
    function ParamsAsString(Params: TOraParams): string;
    procedure ResetStoredProc(AStoredProc: TOraStoredProc; ClearParams: boolean);
    procedure DoClearDataSetParams(Params: TParams; SetBound: boolean);
    procedure DefaultsForStoredProc(AStoredProc: TOraStoredProc);
    procedure ProcessTest(AStoredProc: TOraStoredProc; Info: string;
      ClearParams: boolean);
    procedure RunTests(AStoredProc: TOraStoredProc);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  TypInfo;

procedure TForm1.FormShow(Sender: TObject);
begin
  Memo1.Lines.Clear;
  DefaultParams := TOraParams.Create(nil);
end;

procedure TForm1.DefaultsForStoredProc(AStoredProc : TOraStoredProc);
begin
  DefaultSQLText := AStoredProc.SQL.Text;
  DefaultParams.Assign(AStoredProc.Params);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  DefaultParams.Free;
end;

procedure TForm1.DoLog(const Str : string);
begin
  Memo1.Lines.Add(Str);
end;

function TForm1.ParamsAsString(Params : TOraParams) : string;
var
  m : integer;
begin
  for m := 0 to Params.Count - 1 do
    Result := Result + Params[m].Name + ', ';
end;

procedure TForm1.ResetStoredProc(AStoredProc : TOraStoredProc; ClearParams : boolean);
begin
  if AStoredProc.Prepared then
    AStoredProc.UnPrepare;
  AStoredProc.SQL.Text := DefaultSQLText;
  if ClearParams then
    AStoredProc.Params.Clear
  else
    AStoredProc.Params.Assign(DefaultParams);
end;

procedure TForm1.DoClearDataSetParams(Params : TParams; SetBound : boolean);
var
  i:integer;
begin
  for i := 0 to Params.Count-1 do
  begin
    Params[i].Clear;
    if SetBound then
      Params[i].Bound := True;
  end;
end;

procedure TForm1.ProcessTest(AStoredProc : TOraStoredProc; Info : string; ClearParams : boolean);
const
  SEP  = '-----------------------------------------------';
  SEP2 = '===============================================';
  CONTRNO = '103/A';
var
  n : TOps;
  procedure LogInfo(AOp : TOps; ASQL : string);
  var
    ABoolean : boolean;
  begin
    DoLog(GetEnumName(TypeInfo(TOps), integer(AOp)) + ': ' + #13#10);
    DoLog('Params Order : ' + ParamsAsString(AStoredProc.Params) + #13#10);
    DoLog(ASQL);
    try
      DoClearDataSetParams(AStoredProc.Params, True);
      if AStoredProc = sprGetTotalPayment then
      begin
        AStoredProc.ParamByName('ContractID').AsString := ContrNo;
        AStoredProc.ParamByName('Posted').AsBoolean := True;
      end
      else
        AStoredProc.ParamByName('PCUSTOMERID').AsInteger := 0;
      AStoredProc.ExecProc;
      if AStoredProc = sprIsContainer then
        ABoolean := AStoredProc.ParamByName('RESULT').AsBoolean;
    except
      on E:Exception do
        DoLog(E.Message);
    end;
    DoLog(SEP);
  end;
begin
  DoLog(Info);
  for n := Low(TOps) to High(TOps) do
  begin
    ResetStoredProc(AStoredProc, ClearParams);
    case n of
      opPrepare :
        AStoredProc.Prepare;
      opCreateProcCall :
        AStoredProc.CreateProcCall(AStoredProc.StoredProcName, 0);
      opInternalCreateProcCallNoDescr, opInternalCreateProcDescr :
        TOraStoredProcHack(AStoredProc).InternalCreateProcCall(AStoredProc.StoredProcName, 0, n = opInternalCreateProcDescr); // Version 5.80
//        TOraStoredProcHack(AStoredProc).InternalCreateProcCall(AStoredProc.StoredProcName, n = opInternalCreateProcDescr);    // Version 9.3.8
    end;
    LogInfo(n, AStoredProc.SQL.Text);
  end;
  DoLog(SEP2);
end;

procedure TForm1.RunTests(AStoredProc : TOraStoredProc);
begin
  DefaultsForStoredProc(AStoredProc);
  ProcessTest(AStoredProc, 'Params From DFM', False);
  ProcessTest(AStoredProc, 'Params Cleared', True);
  ResetStoredProc(AStoredProc, False);
end;


procedure TForm1.btnRunTestsClick(Sender: TObject);
begin
  if radGetTotalPayment.Checked then
    RunTests(sprGetTotalPayment)
  else
    RunTests(sprIsContainer);
end;

procedure TForm1.Memo1DblClick(Sender: TObject);
begin
  Memo1.SelectAll;
  Memo1.CopyToClipboard;
end;

end.
The Form DFM code : (Note the stored procedure params have been viewed once from the Object Inspector params editor in ODAC 5.80 and saved).

Code: Select all

object Form1: TForm1
  Left = 319
  Top = 124
  Width = 1305
  Height = 750
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnDestroy = FormDestroy
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object Memo1: TMemo
    Left = 352
    Top = 8
    Width = 633
    Height = 681
    ScrollBars = ssBoth
    TabOrder = 0
    WordWrap = False
    OnDblClick = Memo1DblClick
  end
  object btnRunTests: TButton
    Left = 88
    Top = 272
    Width = 75
    Height = 25
    Caption = 'Run Tests'
    TabOrder = 1
    OnClick = btnRunTestsClick
  end
  object radGetTotalPayment: TRadioButton
    Left = 72
    Top = 152
    Width = 113
    Height = 17
    Caption = 'GetTotalPayment'
    Checked = True
    TabOrder = 2
    TabStop = True
  end
  object radIsContainer: TRadioButton
    Left = 72
    Top = 176
    Width = 113
    Height = 17
    Caption = 'IsContainer'
    TabOrder = 3
  end
  object OraSession1: TOraSession
    Username = 'PAULZIP'
    Password = 'PAULZIP'
    Server = 'CURRENT'
    Connected = True
    Left = 136
    Top = 56
  end
  object sprGetTotalPayment: TOraStoredProc
    StoredProcName = 'P_FM_CONTRACT.GETTOTALPAYMENTS'
    Session = OraSession1
    SQL.Strings = (
      'declare'
      '  v_POSTED boolean := sys.DIUTIL.INT_TO_BOOL(:POSTED);'
      'begin'
      
        '  P_FM_CONTRACT.GETTOTALPAYMENTS(:CONTRACTID, :DUEDATEFROM, :DUE' +
        'DATETO, :INVDATEFROM, :INVDATETO, v_POSTED, :PAYMENTTYPE, :PCOUN' +
        'T, :FINANCE, :SERVICES, :INSURANCE);'
      'end;')
    Left = 200
    Top = 56
    ParamData = <
      item
        DataType = ftBoolean
        Name = 'POSTED'
        ParamType = ptInput
      end
      item
        DataType = ftString
        Name = 'CONTRACTID'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'DUEDATEFROM'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'DUEDATETO'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'INVDATEFROM'
        ParamType = ptInput
      end
      item
        DataType = ftDateTime
        Name = 'INVDATETO'
        ParamType = ptInput
      end
      item
        DataType = ftFixedChar
        Name = 'PAYMENTTYPE'
        ParamType = ptInput
      end
      item
        DataType = ftInteger
        Name = 'PCOUNT'
        ParamType = ptOutput
      end
      item
        DataType = ftFloat
        Name = 'FINANCE'
        ParamType = ptOutput
      end
      item
        DataType = ftFloat
        Name = 'SERVICES'
        ParamType = ptOutput
      end
      item
        DataType = ftFloat
        Name = 'INSURANCE'
        ParamType = ptOutput
      end>
  end
  object sprIsContainer: TOraStoredProc
    StoredProcName = 'P_CUSTOMER.ISCONTAINER'
    Session = OraSession1
    SQL.Strings = (
      'declare'
      '  v_RESULT boolean;'
      'begin'
      '  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);'
      '  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);'
      'end;')
    Left = 200
    Top = 88
    ParamData = <
      item
        DataType = ftInteger
        Name = 'PCUSTOMERID'
        ParamType = ptInput
      end
      item
        DataType = ftBoolean
        Name = 'RESULT'
        ParamType = ptOutput
      end>
  end
end
The test was run with IsContainer selected. Here are the results, which again demonstrate inconsistencies between v 5.80.x and v9.3.8

v5.80

Code: Select all

Params From DFM
opDefault: 

Params Order : PCUSTOMERID, RESULT, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

-----------------------------------------------
opPrepare: 

Params Order : PCUSTOMERID, RESULT, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

-----------------------------------------------
opCreateProcCall: 

Params Order : RESULT, PCUSTOMERID, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

-----------------------------------------------
opInternalCreateProcCallNoDescr: 

Params Order : PCUSTOMERID, RESULT, 

declare
  v_RESULT boolean;
begin
  P_CUSTOMER.ISCONTAINER(:PCUSTOMERID, v_RESULT);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'ISCONTAINER'
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

-----------------------------------------------
opInternalCreateProcDescr: 

Params Order : RESULT, PCUSTOMERID, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

-----------------------------------------------
===============================================
Params Cleared
opDefault: 

Params Order : 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

Parameter 'PCUSTOMERID' not found
-----------------------------------------------
opPrepare: 

Params Order : 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

Parameter 'PCUSTOMERID' not found
-----------------------------------------------
opCreateProcCall: 

Params Order : RESULT, PCUSTOMERID, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

-----------------------------------------------
opInternalCreateProcCallNoDescr: 

Params Order : 

begin
  P_CUSTOMER.ISCONTAINER;
end;

Parameter 'PCUSTOMERID' not found
-----------------------------------------------
opInternalCreateProcDescr: 

Params Order : RESULT, PCUSTOMERID, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

-----------------------------------------------
===============================================
v9.3.9

Code: Select all

Params From DFM
opDefault: 

Params Order : PCUSTOMERID, RESULT, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'ISCONTAINER'
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

-----------------------------------------------
opPrepare: 

Params Order : PCUSTOMERID, RESULT, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'ISCONTAINER'
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

-----------------------------------------------
opCreateProcCall: 

Params Order : RESULT, PCUSTOMERID, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

-----------------------------------------------
opInternalCreateProcCallNoDescr: 

Params Order : PCUSTOMERID, RESULT, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

ORA-06550: line 4, column 3:
PLS-00306: wrong number or types of arguments in call to 'ISCONTAINER'
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored

-----------------------------------------------
opInternalCreateProcDescr: 

Params Order : RESULT, PCUSTOMERID, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

-----------------------------------------------
===============================================
Params Cleared
opDefault: 

Params Order : 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

Parameter 'PCUSTOMERID' not found
-----------------------------------------------
opPrepare: 

Params Order : RESULT, PCUSTOMERID, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

-----------------------------------------------
opCreateProcCall: 

Params Order : RESULT, PCUSTOMERID, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

-----------------------------------------------
opInternalCreateProcCallNoDescr: 

Params Order : 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

Parameter 'PCUSTOMERID' not found
-----------------------------------------------
opInternalCreateProcDescr: 

Params Order : RESULT, PCUSTOMERID, 

declare
  v_RESULT boolean;
begin
  v_RESULT := P_CUSTOMER.ISCONTAINER(:PCUSTOMERID);
  :RESULT := sys.DIUTIL.BOOL_TO_INT(v_RESULT);
end;

-----------------------------------------------
===============================================


Post Reply