sponsored links



No announcement yet.

Any way to dynamically reference variables?

  • Filter
  • Time
  • Show
Clear All
new posts

  • Any way to dynamically reference variables?

    I have some existing code I have to modify and am trying to improve some code readability and efficiency in the process. I have a various number of fields that all reference the same field in a table. The naming convention for these fields is as such: field1, field2, ... field10, where each variable has the same name with an additional numeric value appended to its end.

    After these fields are populated, the code performs the exact same IF check on every field. I was wondering if there was some way I could reference this variable name dynamically, so I could instead add these IF statements to a loop. Maybe there is some way to reference a variable by using a string?

    Note: I cannot use arrays for the existing fields, due to the existing data structure and SQL used to populate it.

  • #2
    Your limitations pretty much rule out all of the easy approaches. The easiest of which would have been to define all the fields in a DS and then redefine the field as an array.

    Only other method I can think of would be to do something like this:

    Dcl-ds  fieldAddresses;
      pField1  pointer  int(%addr(Field1));
      pField2  pointer  int(%addr(Field2));
      pFieldn  pointer  int(%addr(Fieldn));
      pFields  pointer  dim(nn)  Pos(1);
    Dcl-s  Field  Based(pField);
    For i =1 to %Elem(pFields);
       pField = pFields(i);
    //  Now perform all tasks on Field.
    Hopefully that makes sense. Not pretty but ...

    Another "cleaner" approach would be to define a subprocedure that performs all the processing on these fields and then simply code 10 (or however many there are) calls to the subproc passing each version of the field in turn.


    • #3
      Assuming all of the fields are in the same data structure... in this case OrigDS

             Dcl-DS Fields_new QUALIFIED;
               Field1      Like(Field1);
               Field2      Like(Field1);
               Field3      Like(Field1);
               Field4      Like(Field1);
               Field5      Like(Field1);
               Field6      Like(Field1);
               Field7      Like(Field1);
               Field8      Like(Field1);
               Field9      Like(Field1);
               Field10     Like(Field1);
               Fields      Like(Field1) DIM(10) Pos(1);
             Dcl-S  i          Int(3);
         EVAL-CORR Fields_New = Origds;
        For i = 1 to %Elem(Fields_New.Fields);
               .... do whatever to Felds_New.Field(i)
        Eval-Cor OrigDS = Fields_New;
      This puts Field1 through Field10 into a qualified data structure Fields_New - do whatever to those fields and then moves that back into the original fields.


      • ryanweeks
        ryanweeks commented
        Editing a comment
        Yea I should have probably explained the original structure a bit better. The fields were all next to each other, but there were also many other fields in that data structure. Building an array after the SQL populates this DS is fine, but importing directly into an array would have been infeasible.

      • JonBoy
        JonBoy commented
        Editing a comment
        Actually if the fields are contiguous in the original DS all you have do it add this to that DS:
        fieldArray  Like(field1)  Dim(xx)  SamePos(field1);

      • Rocky
        Rocky commented
        Editing a comment
        If they are together in the original DDS you can overlay the array right in the DS. No change to the SQL is necessary as the array will reflect the fields automatically. Jonboy shows the syntax but the beauty if that by doing this there isn't a need to move data back and forth.If they were NOT contiguous but have the same charactaristics then you need to move in and out.

        DCL-DS datastructure;
        keyfld char(10);
        descr char(30);
        field1 char(10);
        field2 char(10);
        field3 char(10);
        field4 char(10);
        field5 char(10);
        field6 char(10);
        field7 char(10);
        field8 char(10);
        field9 char(10);
        field10 char(10);
        fields char(10) dim(10) samepos(field1);
        ssn char(10);

        EXEC SQL SELECT * INTO :datastructure FROM datafile WHERE KEYFLD ='abc';

        Fields will reflect FIELD1-FIELD10 in an array - no special coding of your SQL needed.

    • #4
      Knowing that sampos keyword is a fairly new addition to ILE RPG - here's an alternative solution.

        Dcl-DS Field_DS;                                  
          otherfield1 char(10);                           
          otherfield2 char(10);                           
          otherfield3 char(10);                           
          Field1      Char(10) Inz('1');                  
          Field2      Char(10) Inz('2');                  
          Field3      Char(10) Inz('3');                  
          Field4      Char(10) Inz('4');                  
          Field5      Char(10) Inz('5');                  
          Field6      Char(10) Inz('6');                  
          Field7      Char(10) Inz('7');                  
          Field8      Char(10) Inz('8');                  
          Field9      Char(10) Inz('9');                  
          Field10     Char(10) Inz('10');                 
          othersyet1   char(10);                           
          othersyet2   char(10);                           
          othersyet3   char(10);                           
         Dcl-S Fields Char(10) Dim(10) Based(pFields);
         Dcl-S pFields Pointer Inz(%Addr(Field1));
      Fields array refers to Field1-Field10. You change fields(5) you change field5 in the data structure - no change in SQL whatsoever.


      • #5
        Have you considered writing embeddeed dynamic sql? You build a string then execute. If you do this, definitely consider sql injection scenarios.