ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Passing Data Structure Arrays

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Passing Data Structure Arrays

    I always seem to have trouble with this... I've created a service program procedure that has the following definitions. I'm able to populate the CLIENT ds, but I can't seem to "eval" ouCLIENTS equal to CLIENTS so that the values are passed back.

    Compiler doesn't like ouCLIENTS = CLIENT

    I know there has to be something wrong with my definition of CLIENT_T .

    Code:
       dcl-pi *n;
         inUser              varchar(10) const;
         ouClients           likeds(client_t);
       end-pi;
    
       dcl-ds Client         qualified dim(100);
         nbr                 varchar(3);
         name                varchar(30);
         type                varchar(4);
       end-ds;
    
    
    ... FROM MY /COPY MEMBER
        dcl-ds  client_t           qualified template dim(100);
           Nbr                     varchar(3);
           Name                    varchar(30);
           Type                    varchar(4);
        end-ds;

  • #2
    What error do you get when you try the assignment? Saying you can't populate the variables isn't useful.

    FYI, the LikeDS declaration will only create the field definitions, it will not make this an array so you will need to specifically define the DIM statement on ouClients if you require this to be an array.

    Comment


    • #3
      Without knowing what error you get it is hard to diagnose but ...

      This to my way of thinking is what the code should look like;

      Code:
         dcl-pi *n;
           inUser              varchar(10) const;
           ouClients           likeds(client_t)  Dim(100);
         end-pi;
      
      //  This DS is not needed. 
      //  dcl-ds Client         qualified dim(100);
       //    nbr                 varchar(3);
       //    name                varchar(30);
       //    type                varchar(4);
       //  end-ds;
      Then you directly populate ouClients( index).fieldName - then there''s no need to copy anything.

      However, if I was coding this I would return the array rather than pass it as a parm and use RTNPARM to avoid any performance hit. Like so:

      Code:
         dcl-pi *n  likeDS(client_t)  Dim(100)  RTNPARM;
           inUser              varchar(10) const;
         end-pi;
      
        returnDS  likeDS(client_t)  Dim(100);
      
       // build results in returnDS then
      
      Return returnDS;
      Build the data the same way
      Does it always return 100 elements? If not, wouldn't be a bad idea to modify the DS to include a count.

      Comment


      • #4
        Originally posted by john.sev99 View Post
        What error do you get when you try the assignment? Saying you can't populate the variables isn't useful.

        FYI, the LikeDS declaration will only create the field definitions, it will not make this an array so you will need to specifically define the DIM statement on ouClients if you require this to be an array.
        Thanks!

        That was the problem. Sorry for not including the error. I had tried so many different things not realizing that the PI didn't contain an array (my errors were all about omitted elements/indexes).

        JohnBoy - thanks for the suggestion to clean it up. I started out without a separate definition, but added it to try to eliminate unknowns.

        The end result is for this procedure to be a SQL UDF. So am I better off returning an array as you defined, or leaving it with two parameters?

        Comment


        • #5
          Originally posted by gwilburn View Post

          The end result is for this procedure to be a SQL UDF. So am I better off returning an array as you defined, or leaving it with two parameters?
          Interestingly the RTNPARM approach actually results in two parms being passed - the return value being the first one. RPG just does the "translation" under the covers. This makes it possible to use the routine in RPG in the preferred way i.e. results = myProcedure ( inUser ); But also to call it with two parms from languages that don't understand RTNPARM - such as SQL UDEs. So if it will only _ever_ be called from SQL there's no point in using RTNPARM but if it is used from RPG and SQL then that is the way to go.

          Comment


          • #6
            So I tried to invoke my UDTF - the RPGLE pgm is defined as a function

            Code:
               dcl-proc VLF_ClientList   Export;
            
               dcl-pi *n             likeds(client_t) dim(100) rtnparm;
                 inUser              varchar(10) const;
               end-pi;
            
              dcl-ds  client_t           qualified template;
                 Nbr                     varchar(3);
                 Name                    varchar(30);
                 Type                    varchar(4);
              end-ds;
            I defined:
            Input as varchar(10)
            Output as TABLE varchar(3), varchar(30), and varchar(4)

            select * from table(MYLIB.VLF_CLIENTLIST('GWILBURN ')) as u;

            I get an error (in the joblog): RNX0115: Length of varying length variable is out of range.

            Not sure what I'm doing wrong.

            edit: I placed the service pgm in debug, and the INUSER parameter is blank.
            Last edited by gwilburn; May 7, 2019, 09:43 AM.

            Comment


            • #7
              I've never seen a UDTF coded this way. Are you sure that's legitimate?

              Comment


              • #8
                Originally posted by Scott Klement View Post
                I've never seen a UDTF coded this way. Are you sure that's legitimate?
                No it is not correct... I just found your article. I may want to write this a purely an SQL UDTF since nearly all the code in the RPG procedure is SQL anyway. I've just never written one.

                Comment

                Working...
                X