Re: SQL UDF to call RPG without service program
Vern Hamberg via RPG400-L <[email protected]> Tue, 3 Mar 2026 10:46:12 -0600
| Newsgroups | gmane.comp.lang.as400.rpg |
|---|---|
| Message-ID | <[email protected]> |
Ah, mea culpa! So a question, as I've not done this kind of thing - if one were to use the default practice of simply calling a program in some SQL context, it's fine if you don't want to know anything back, that the program is basically a procedure that only takes some action, and all parameters are really input. But if you wanted to have a result come back, something in the SQL context would have to be able to use some parameter's value. *Regards* *Vern Hamberg* IBM Champion 2025 <cid:[email protected]> CAAC (COMMON Americas Advisory Council) IBM Influencer 2023 On 3/3/2026 9:28 AM, Charles Wilt wrote: > No, CREATE FUNCTION... > > Here's an quick (AI generated) example... > > CREATE OR REPLACE FUNCTION MYLIB.GET_TOTAL_PGM ( > qty INT, > unit_price DECIMAL(9, 2) > ) RETURNS DECIMAL(11, 2)LANGUAGE RPGLE > PARAMETER STYLE SQLDETERMINISTICNO EXTERNAL ACTIONEXTERNAL NAME > 'MYLIB/TOTALPGM' -- Points to *PGM object > PROGRAM TYPE MAIN > > RPG code: > > **FREE > ctl-opt dftactgrp(*no) actgrp(*caller); > > dcl-pi *n; > -- 1. Input Parameters (Matched to SQL types) > inQty int(10) const; > inPrice packed(9: 2) const; > -- 2. Result Parameter (This is where you "return" the value) > outTotal packed(11: 2); > -- 3. Input Indicators (2-byte integers) > indQty int(5) const; > indPrice int(5) const; > -- 4. Result Indicator > indTotal int(5); > -- 5. Housekeeping (Mandatory for Style SQL) > sqlState char(5); > fName varchar(139) const; > specName varchar(128) const; > diagMsg varchar(70); > end-pi; > > -- Logic > sqlState = '00000'; > indTotal = 0; > > if (indQty < 0 or indPrice < 0); > indTotal = -1; > else; > outTotal = inQty * inPrice; > endif; > > return; > > > > > On Tue, Mar 3, 2026 at 7:55 AM Vern Hamberg via RPG400-L < > [email protected]> wrote: > >> Hi Charles >> >> In this technique, are you using CREATE PROCEDURE? I had posted that one >> could simply call a program, but it is PARAMETER STYLE GENERAL and all >> parameters are INOUT - does that line up with your knowledge? >> >> *Regards* >> >> *Vern Hamberg* >> >> IBM Champion 2025<cid:[email protected]> CAAC >> (COMMON Americas Advisory Council) IBM Influencer 2023 >> >> >> On 3/3/2026 8:45 AM, Charles Wilt wrote: >>> You can use a MAINLINE RPG program as an external scalar SQL UDF. >>> You simply need to use PARAMETER STYLE SQL. (note the 3rd line below, >>> emphasis mine) >>> >>> All applicable parameters are passed. The parameters are defined to be in >>> the following order: >>> n parameters for the input parameters that are specified for the >> function. >>> ****A parameter for the result of the function.**** >>> n parameters for indicator variables for the input parameters. >>> A parameter for the indicator variable for the result. >>> A CHAR(5) output parameter for SQLSTATE. The SQLSTATE returned indicates >>> the success or failure of the function. The SQLSTATE returned can either >> be: >>> the SQLSTATE from the last SQL statement executed in the external >> program, >>> an SQLSTATE that is assigned by the external program. >>> The user may set the SQLSTATE to any valid value in the external program >> to >>> return an error or warning from the function. >>> >>> >>> A VARCHAR(517) input parameter for the fully qualified function name >>> A VARCHAR(128) input parameter for the specific name. >>> A VARCHAR(1000) output parameter for the message text. >>> When control is returned to the invoking program, the message text can be >>> found in the 6th token of the SQLERRMC field of the SQLCA. Only a portion >>> of the message text is available. For information on the layout of the >>> message data in the SQLERRMC, see the replacement data descriptions for >>> message SQL0443 in message file QSQLMSG. The complete message text can be >>> retrieved using the GET DIAGNOSTICS statement. For more information, see >>> GET DIAGNOSTICS. >>> >>> >>> Zero to three optional parameters: >>> A structure (consisting of an INTEGER followed by a CHAR(n)) input and >>> output parameter for the scratchpad, if SCRATCHPAD was specified on the >>> CREATE FUNCTION statement. >>> An INTEGER input parameter for the call type, if FINAL CALL was specified >>> on the CREATE FUNCTION statement. >>> A structure for the dbinfo structure, if DBINFO was specified on the >> CREATE >>> FUNCTION statement. >>> >>> >>> Yes, the interface is more complex, but you gain a lot of control. >>> Personally, I've gotten to the point of always using PARAMETER STYLE SQL. >>> >>> Of course, assuming an existing program called from other places, you >> could >>> add the additional parms as *OMIT and modify the code to see if the >>> additional parms where passed or not; thus allowing the program to >>> determine if it was called from RPG or SQL. When called from SQL, you >> can >>> do the extra work to the additional parms, >>> >>> Charles >>> >>> On Mon, Mar 2, 2026 at 4:43 PM Reeve<[email protected]> wrote: >>> >>>> Rob, "regular" RPG programs (with a mainline, I guess) can't return a >>>> value. A function implicitly returns a single value. Service programs >>>> (ctl-opt *NOMAIN) can return a value. >>>> >>>> Two ideas: >>>> 1) Read up on parameter passing and overloading. If the attributes of >> the >>>> caller's parameter list don't fit with the called parameter list, you >> get a >>>> Not Found; I think a returned value is not considered in signature >>>> matching. >>>> 2) Set up a dummy service program named GETUPCHARGEFUNC and see if your >>>> code works with it. If so, your SQL is good. >>>> >>>> --reeve >>>> >>>> On Mon, Mar 2, 2026 at 12:28 PM Robert Rogerson<[email protected]> >>>> wrote: >>>> >>>>> Hi Reeve, >>>>> >>>>> I may be missing something but why not just call the RPG from the >>>>> function? I'm not sure of the purpose of the procedure and if it's >>>> needed. >>>>> Here's an example of a function calling an RPG program. >>>>> >>>>> CREATE FUNCTION MYLIB.GETUPCHARGEFUNC ( >>>>> WHSENBR NUMERIC(3, 0) , >>>>> ITEMNBR NUMERIC(6, 0) ) >>>>> RETURNS NUMERIC(7, 2) >>>>> LANGUAGE RPGLE >>>>> SPECIFIC MYLIB.GETUPCHARGEFUNC >>>>> NOT DETERMINISTIC >>>>> MODIFIES SQL DATA >>>>> CALLED ON NULL INPUT >>>>> NOT FENCED >>>>> EXTERNAL NAME 'MYLIB/GETUPCHRGF' >>>>> PARAMETER STYLE SQL ; >>>>> >>>>> To call >>>>> SELECT >>>>> ivwhid AS "Warehouse", >>>>> ivitm# AS "Item Number", >>>>> GETUPCHARGEFUNC(ivwhid, ivitm#) AS "Up Charge" >>>>> FROM invmasp >>>>> WHERE ivwhid = 90 >>>>> AND ivitm# = 5 >>>>> ORDER BY 1, 2; >>>>> >>>>> HTH, >>>>> >>>>> Rob >>>>> >>>>> On Mon, Mar 2, 2026 at 2:43 PM Reeve<[email protected]> wrote: >>>>> >>>>>> External name is FUNC00001A: shouldn't you be calling that object? >>>>>> >>>>>> On Mon, Mar 2, 2026 at 11:20 AM Eric Wesson<[email protected]> >>>>> wrote: >>>>>>> I am trying to create an SQL function that effectively calls an RPG >>>>>>> program and returns the result. I've read you can do it by creating a >>>>>>> service program and calling it but I'm trying to do it without the >>>>>> service >>>>>>> program. >>>>>>> >>>>>>> I have successfully created an sql stored procedure that calls the >>>> RPG >>>>>>> program and I've created a function that calls the stored procedure. >>>>>>> >>>>>>> When i try to use the function, I get an error saying "FUN0001 not >>>>>> found". >>>>>>> I can successfully call the function directly using "CALL >>>>>>> APPSTRPROC.FUNC0001(12345, 0)". >>>>>>> I've beat my head against the wall on this one. Any ideas? >>>>>>> >>>>>>> >>>>>>> Code that creates procedure and function >>>>>>> // Stored procedure to call rpg >>>>>>> Exec sql >>>>>>> Create or replace Procedure Appstrproc.FUNC0001( >>>>>>> in SystemSku dec(15), >>>>>>> out Retail dec(9,2)) >>>>>>> Language RPGLE >>>>>>> Called on null input >>>>>>> Not deterministic >>>>>>> No external action >>>>>>> Reads sql data >>>>>>> External name FUNC00001A >>>>>>> Parameter style general; >>>>>>> >>>>>>> // Function to call stored procedure >>>>>>> Exec Sql >>>>>>> Create or Replace Function >>>>>>> Appstrproc.f_SkuGetCurrentRetail(SystemSku dec(15)) >>>>>>> Returns Decimal(9,2) >>>>>>> Language SQL >>>>>>> Return Appstrproc.FUNC0001(SystemSku, 0); >>>>>>> >>>>>>> Thanks, >>>>>>> Eric >>>>>>> -- >>>>>>> This is the RPG programming on IBM i (RPG400-L) mailing list >>>>>>> To post a messageemail:[email protected] >>>>>>> To subscribe, unsubscribe, or change list options, >>>>>>> visit:https://lists.midrange.com/mailman/listinfo/rpg400-l >>>>>>> oremail:[email protected] >>>>>>> Before posting, please take a moment to review the archives >>>>>>> athttps://archive.midrange.com/rpg400-l. >>>>>>> >>>>>>> [email protected] for any subscription >>>>> related >>>>>>> questions. >>>>>>> >>>>>>> >>>>>> -- >>>>>> This is the RPG programming on IBM i (RPG400-L) mailing list >>>>>> To post a messageemail:[email protected] >>>>>> To subscribe, unsubscribe, or change list options, >>>>>> visit:https://lists.midrange.com/mailman/listinfo/rpg400-l >>>>>> oremail:[email protected] >>>>>> Before posting, please take a moment to review the archives >>>>>> athttps://archive.midrange.com/rpg400-l. >>>>>> >>>>>> [email protected] for any subscription >>>> related >>>>>> questions. >>>>>> >>>>>> >>>>> -- >>>>> This is the RPG programming on IBM i (RPG400-L) mailing list >>>>> To post a messageemail:[email protected] >>>>> To subscribe, unsubscribe, or change list options, >>>>> visit:https://lists.midrange.com/mailman/listinfo/rpg400-l >>>>> oremail:[email protected] >>>>> Before posting, please take a moment to review the archives >>>>> athttps://archive.midrange.com/rpg400-l. >>>>> >>>>> [email protected] for any subscription >> related >>>>> questions. >>>>> >>>>> >>>> -- >>>> This is the RPG programming on IBM i (RPG400-L) mailing list >>>> To post a messageemail:[email protected] >>>> To subscribe, unsubscribe, or change list options, >>>> visit:https://lists.midrange.com/mailman/listinfo/rpg400-l >>>> oremail:[email protected] >>>> Before posting, please take a moment to review the archives >>>> athttps://archive.midrange.com/rpg400-l. >>>> >>>> [email protected] for any subscription related >>>> questions. >>>> >>>> >> -- >> This is the RPG programming on IBM i (RPG400-L) mailing list >> To post a message email:[email protected] >> To subscribe, unsubscribe, or change list options, >> visit:https://lists.midrange.com/mailman/listinfo/rpg400-l >> or email:[email protected] >> Before posting, please take a moment to review the archives >> athttps://archive.midrange.com/rpg400-l. >> >> Please [email protected] for any subscription related >> questions. >> >> -- This is the RPG programming on IBM i (RPG400-L) mailing list To post a message email: [email protected] To subscribe, unsubscribe, or change list options, visit: https://lists.midrange.com/mailman/listinfo/rpg400-l or email: [email protected] Before posting, please take a moment to review the archives at https://archive.midrange.com/rpg400-l. Please contact [email protected] for any subscription related questions.