ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Creating a prefixed-DS based on a specific Record Format

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

  • Creating a prefixed-DS based on a specific Record Format

    COBOL'er posting in the RPG area (no surprise there...lol).

    I'm trying to define a work area laid out identically to an inbound file I am reading. The physical file is named IV021F and its record format name is RIV021F. All of the fields are named I21field01, I21field02, I21field03, etc. etc. etc.

    So after looking at the manual...it seemed simple enough. Use the LIKEREC keyword to define a DS that is identical to the record layout and then use the PREFIX keyword to change all of the field names from I21xxxx to Z21xxxx.

    Unfortunately...this doesn't work...I'm receiving an error in SEU indicating that this is not allowed (The keyword is not allowed following keyword LIKEREC; keyword is ignored).

    Does anyone have a smarter way to do this?

  • #2
    Well the "smarter" way might be to use the keyword QUALIFIED on the DS definition so that the DS name is the "prefix". Personally I find this the best approach as it is very obvious where all the fields are defined.

    There are other approaches - like adding the PREFIX keyword to the file specification - but without knowing _why_ you want to prefix the field in the first place it is difficult to make a recommendation.

    Comment


    • #3
      Thanks Jon for the feedback...I will probably go with qualification. I was trying to avoid it because the length of the field names would be larger...

      I wanted to use the record layout for "control break" fields. Using a copy of the record with different field names would allow me to specify one or more of them as a "break" field (and hold their contents). In the future, should I desire to alter the break variable...there would be no need to create a new specific variable in the "D" specs as it would already exist

      In COBOL this would be dead simple:

      01 Break-Area.
      copy ddr-RIV021F of IV021F
      prefix by 'Break-'.

      OK...I got this to work so that I now have a data structure with renamed fields:

      D Save_IV021F E DS ExtName(IV021F) Prefix('X':1)

      Hooray! Unfortunately, is doesn't appear that you can do a move/assignment with the input record:

      Save_IV021F = RIV021F;

      Sheesh...back to the drawing board
      Last edited by Terry Wincheste; December 7, 2017, 12:17 PM.

      Comment


      • #4
        Actually it is easier in RPG.

        dcl-ds record LikeRec(xxxxxRec) Dim(2);

        Read xxxxxFile record(c); // where c = 1 or 2 (flip flop the current image)

        And then compare the fields for the level break. You do still have to use qualified names but the fact that you see that as a problem just means you need to move to RDi <grin> or use a short DS name!

        The RPG approach is faster in operation because no data copying is required. RPG just unpacks the fields directly into the appropriate DS.

        There are a few instances still where COBOL may be easier than RPG - but for the most part RPG is the better language. even if I don't count subprocedures in the equation.

        Comment


        • #5
          Interesting, but I'm getting an error when I put the dcl-ds statement into my /FREE area. So I surrounded it by a /FREE and /END-FREE and put it into the D-Spec area and it still fails. We're running at V6R1 so maybe this style is not applicable to our compiler version.

          I thought my goal was simple but its turning out to be a PITA...lol

          1. Read a record (MyRcd)
          2. Move the contents of MyRcd to a SaveRcd
          3. Establish/Check any break values I desire
          4. When my key break values change...move MyRcd into SaveRcd again
          5. Rinse and Repeat until EOF()

          On a side note, I quit entering periods at the end of COBOL sentences *years* ago so I have been hesitant to move to the /FREE version of RPGLE and then have to go back to being forced into punctuating...every...line...of...code...

          Comment


          • #6
            V6R1 doesn't support the new free-form D specs so they'll need to be declared the "old fashioned" way.

            Comment


            • #7
              Originally posted by Terry Wincheste View Post
              Interesting, but I'm getting an error when I put the dcl-ds statement into my /FREE area. So I surrounded it by a /FREE and /END-FREE and put it into the D-Spec area and it still fails. We're running at V6R1 so maybe this style is not applicable to our compiler version.
              Ah well - if you are seeking help when using a severely obsolete version of the OS it is always a good idea to mention it.

              Just switch to D-specs. Works the same. You _may_ have to specify *INPUT on the LIKEREC - can't recall when the rules were relaxed on that but pretty certain it was post V6.1.

              So just
              Code:
              D record         DS              LikeRec(xxxxxRec: *Input)  Dim(2)
              The read is unchanged.

              Comment


              • #8
                Thanks Jon. A little searching led me to this solution and I am posting this just in case someone else gets in the same predicament ;-)

                First, I defined two Data Structures to hold the contents of the record with the second definition having its fields prefixed by X.

                D RecdBufr E DS ExtName(IV021F)
                D SaveBufr E DS ExtName(IV021F) Prefix('X':1)

                Relying on RPG's unique characteristic that allows the same field to be defined multiple times, I simply moved the input record in RECDBUFR to a holding area (SAVEBUFR) so that I would have a copy of the last entry that was read from the physical file.

                /End-Free
                C MOVEL RECDBUFR SAVEBUFR
                /Free

                It works good. Production is happy so I am happy...lol This may have been done easier, but it only cost me 5 lines of code,,,not bad

                (we just upgraded our D/R system to V7R2 and are slated to do the main Production system during the first quarter or 2018...we're getting there...lol)

                Comment


                • #9
                  Not sure why you did it the hard way <grin> but glad you got something working.

                  But ... it is 2017 (almost 2018) - why oh why oh why are you coding in fixed form?

                  Comment


                  • #10
                    Actually, the program is in free-form but I used MOVEL to move data between the data structures...was having too much of a problem the other way.

                    It was an older piece of code that I stumbled across...and it worked fine

                    Comment


                    • #11
                      Originally posted by Terry Wincheste View Post
                      Actually, the program is in free-form but I used MOVEL to move data between the data structures...was having too much of a problem the other way.

                      It was an older piece of code that I stumbled across...and it worked fine
                      EVAL would have done the same thing. Just SavedBufr = RecdBufr; // Does the same as MOVEL becuase the structures are identical

                      It would also have had the added advantage that it wouldn't confuse the heck out of anyone who learnt RPG in the last 10+ years. There's a reason you had to resort to fixed form to do a MOVEL - it is because it was deprecated some 16+ years ago.

                      Also - while I know that for some reason you wanted to avoid qualified names - it still seems more confusing to me for someone to have to understand that when you code If XField = Field; that a comparison is being made between a current and a saved value. Had you simply made the save image qualified then it would have been If SavedBufr.Field = Field; and one pretty much knows what is going on without even the need for a comment.

                      P.S. I don't have a downer on PREFIX - I was the one who "invented" it when the RPG IV compiler was being designed. I just think that in this case there is a better more obvious approach.

                      P.P.S. OK - down off soapbox - no more preaching.
                      Last edited by JonBoy; December 12, 2017, 12:32 PM.

                      Comment


                      • #12
                        Terry, I'm going to climb up onto Jon's abandoned soapbox :-D

                        From your PREFIX('X':1), where you're replacing the first character of the names with 'X', I assume that the first character of the real field names is already sort of a prefix.

                        If you used qualified data structures, and stripped of that 1st character for both data structures, and you used 1-character names for your data structures, you'd only be adding one extra character to your references, X.name vs Xname.

                        Say your file fields are ZNAME and ZADDR. Use PREFIX('' : 1) to remove the first character of the names. With data structure names R and S, the subfields would be R.name, R.addr, X.name, X.addr. Vs Zname, Zaddr, Xname, Xaddr if you use unqualified names. Even with semi-meaningless 1-character data structure names, I think R.name and S.name are clearer than Zname and Xname.

                        Code:
                         * Record
                        D R             E DS                  ExtName(IV021F)
                        D                                     Qualified Prefix('' : 1)
                         * Saved record
                        D X               DS                  LikeDs(R)
                         /free
                            Eval-Corr X = R;
                            ...
                            If X.name <> R.name;
                              ...
                        A bonus of using qualified names is that you can use EVAL-CORR (Eval Corresponding) to assign the data structures. EVAL-CORR differs from MOVE or EVAL in that it also assigns any null-indicators associated with the subfields. If the data structures are related through LIKEDS, EVAL-CORR is as fast as MOVE or EVAL, assigning the contents of the data structures all at once, rather than subfield by subfield.

                        Comment


                        • #13
                          Thanks Barbara. I will try this as soon as I get a chance. But have vacation days to burn before EOY

                          Comment

                          Working...
                          X