ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

I think I've discovered a compiler bug, can anyone verify?

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

  • I think I've discovered a compiler bug, can anyone verify?

    In short - in a CCSID37 SQLRPGLE source file, if there is a hex 05 tab character before a component line of an Exec SQL statement, it can cause the compiler/SQL precompiler to silently ignore that source line. The line is even omitted from the diagnostic check source listing spool.

    The bug was noticed in v7.3, and today we updated test to v7.4 and the bug is still present. I was unable to reproduce the bug on pub400.com even when targeting v7.3, so there may be some other subtleties of job/compile setup that have an effect.

    It's also not as simple as "tab character causes line to be ignored", because in my test case I have two lines with tab characters and only one is ignored. This is also the reason for the complex SQL example, as it is designed to mimic the original program where the bug was found as closely as possible due to the "flakiness" of the bug.

    Source member is CCSID37, jobs are CCSID 65535 with default CCSID 37.

    My test code is transcribed below.

    Code:
           ctl-Opt option(*srcstmt:*nodebugio:*nounref) optimize(*basic)
                    dftActGrp(*no) actGrp(*caller) extBinInt(*yes)
                    bndDir('HCBNDDIR':'CMBNDDIR') main(SQLBUGTST1);
    
            dcl-proc SQLBUGTST1;
    
              dcl-c MAX_RECORDS const(100);
    
              dcl-ds record extname('WSPEEDJ/SQLBUGTST2') qualified template inz
                     end-ds;
    
              dcl-ds records likeDs(record) dim(MAX_RECORDS) inz(*likeDs);
    
              dcl-s outTxt varchar(50);
              dcl-s rp char(1);
    
              reset records;
              SQLER3 = 0;
    
              exec sql
                declare csr1 cursor for
                  select * from WSPEEDJ/SQLBUGTST2 nsl
                   where nsl.COL1 = 'TEST01' and nsl.COL4 <= 1210506
                     and (nsl.COL5 >= 1210506 or nsl.COL5 = 0)
                     and nsl.COL4 = (Select max(nsl2.COL4)
                                         from WSPEEDJ/SQLBUGTST2 nsl2
                                        where nsl2.COL1 = nsl.COL1 and
                                           nsl2.COL2 = nsl.COL2 and
                                           nsl2.COL3 =  nsl.COL3 and
                                        (nsl2.COL5 >= 1210506 or nsl2.COL5 = 0)
                     and nsl2.COL4 <= 1210506)
                   order by nsl.COL1, nsl.COL2, nsl.COL3, nsl.COL4 desc;
              exec sql open csr1;
              exec sql fetch csr1 for :MAX_RECORDS rows into :records;
              outTxt = outTxt + %char(SQLER3)+'; ';
              exec sql close csr1;
              // The above csr1 SQL has a hex '05' character in position 6 in
              // source lines 0028.00 and 0029.00
              //      nsl2.COL2 = nsl.COL2 and
              //      nsl2.COL3 =  nsl.COL3 and
              // It returns 50 rows
              // It should return 52, but it acts like line 0028.00
              //      nsl2.COL2 = nsl.COL2 and
              // is not there.
    
    
              exec sql
                declare csr2 cursor for
                  select * from WSPEEDJ/SQLBUGTST2 nsl
                   where nsl.COL1 = 'TEST01' and nsl.COL4 <= 1210506
                     and (nsl.COL5 >= 1210506 or nsl.COL5 = 0)
                     and nsl.COL4 = (Select max(nsl2.COL4)
                                         from WSPEEDJ/SQLBUGTST2 nsl2
                                        where nsl2.COL1 = nsl.COL1 and
                                        nsl2.COL2 = nsl.COL2 and
                                        nsl2.COL3 =  nsl.COL3 and
                                        (nsl2.COL5 >= 1210506 or nsl2.COL5 = 0)
                     and nsl2.COL4 <= 1210506)
                   order by nsl.COL1, nsl.COL2, nsl.COL3, nsl.COL4 desc;
              exec sql open csr2;
              exec sql fetch csr2 for :MAX_RECORDS rows into :records;
              outTxt = outTxt + %char(SQLER3)+'; ';
              exec sql close csr2;
              // The above csr2 SQL is identical to the csr1 sql except it does not
              // have the hex '05' characters.
              // It returns  the correct 52 rows
    
    
              exec sql
                declare csr9 cursor for
                  select * from WSPEEDJ/SQLBUGTST2 nsl
                   where nsl.COL1 = 'TEST01' and nsl.COL4 <= 1210506
                     and (nsl.COL5 >= 1210506 or nsl.COL5 = 0)
                     and nsl.COL4 = (Select max(nsl2.COL4)
                                         from WSPEEDJ/SQLBUGTST2 nsl2
                                        where nsl2.COL1 = nsl.COL1 and
                               //       nsl2.COL2 = nsl.COL2 and
                                        nsl2.COL3 =  nsl.COL3 and
                                        (nsl2.COL5 >= 1210506 or nsl2.COL5 = 0)
                     and nsl2.COL4 <= 1210506)
                   order by nsl.COL1, nsl.COL2, nsl.COL3, nsl.COL4 desc;
              exec sql open csr9;
              exec sql fetch csr9 for :MAX_RECORDS rows into :records;
              outTxt = outTxt + %char(SQLER3)+'; ';
              exec sql close csr9;
              // The above csr9 SQL is identical to the csr2 sql except it does not
              // have the hex '05' characters, and the source line
              //      nsl2.COL2 = nsl.COL2 and
              // is commented out.
              // It produces the same 50 rows as csr1 does, thus suggesting that
              // the hex '50' characters in csr1 are causing it to ignore this line
    
              dsply outTxt '' rp;
    
              *inlr = *on;
    
            end-Proc;​
    Table SQLBUGTST2 columns:
    COL1 char(6)
    COL2 char(2)
    COL3 char(2)
    COL4 decimal(7)​
    COL5 decimal(7)​

  • #2
    Table SQLBUGTST2​ data 1:
    Code:
    COL1    COL2    COL3    COL4    COL5
    ----    ----    ----    ----    ----
    
    TEST01    22    02    1060601    0
    TEST01    22    03    1140701    0
    TEST01    22    03    1041001    1140701
    TEST01    22    05    1041001    0
    TEST01    22    06    1041001    0
    TEST01    22    25    1131201    0
    TEST01    22    25    1060601    0
    TEST01    22    72    1140701    0
    TEST01    22    75    1140701    0
    TEST01    23    AJ    1120601    0
    TEST01    23    04    1120601    0
    TEST01    23    04    1080201    1120601
    TEST01    23    04    1060601    0
    TEST01    23    07    1121101    0
    TEST01    23    08    1121101    0
    TEST01    23    09    1121101    0
    TEST01    23    10    1121101    0
    TEST01    23    11    1121101    0
    TEST01    23    12    1041001    0
    TEST01    23    13    1041001    0
    TEST01    23    14    1041001    0
    TEST01    23    17    1041001    0
    TEST01    23    18    1060601    0
    TEST01    23    19    1041001    0
    TEST01    23    20    1060601    0
    TEST01    23    21    1060601    0
    TEST01    23    22    1060601    0
    TEST01    23    23    1041001    0
    TEST01    23    24    1060601    0
    TEST01    23    25    1060601    0
    TEST01    23    26    1060601    0
    TEST01    23    27    1060601    0
    TEST01    23    28    1060601    0
    TEST01    23    29    1041001    0
    TEST01    23    30    1041001    0
    TEST01    23    31    1131201    0
    TEST01    23    31    1080201    1080201
    TEST01    23    31    1060601    1080131

    Comment


    • #3
      Table SQLBUGTST2​ data 2 (could not include the whole thing in one post for some reason):
      Code:
      COL1    COL2    COL3    COL4    COL5
      ----    ----    ----    ----    ----
      
      TEST01    23    32    1041001    0
      TEST01    23    33    1041001    0
      TEST01    23    34    1041001    0
      TEST01    23    35    1041001    0
      TEST01    23    4A    1140701    0
      TEST01    23    4B    1140701    0
      TEST01    23    4C    1140701    0
      TEST01    23    47    1060601    1060601
      TEST01    23    48    1060601    1060601
      TEST01    23    49    1080201    1080201
      TEST01    23    49    1060601    0
      TEST01    23    50    1080201    1080201
      TEST01    23    50    1060601    0
      TEST01    23    53    1131201    0
      TEST01    23    58    1080201    1080201
      TEST01    23    59    1080201    1080201
      TEST01    23    60    1080201    1080201
      TEST01    23    61    1080201    1080201
      TEST01    23    62    1080201    1080201
      TEST01    23    63    1080201    1080201
      TEST01    23    64    1080201    1080201
      TEST01    23    66    1080201    1080201
      TEST01    23    71    1120601    0
      TEST01    23    75    1120601    0
      TEST01    23    76    1120601    0
      TEST01    23    83    1131201    0
      TEST01    25    36    1060601    0
      TEST01    25    37    1041001    0
      TEST01    25    38    1041001    0
      TEST01    25    39    1041001    0
      TEST01    25    40    1060601    0
      TEST01    25    55    1120601    0
      TEST01    25    65    1080201    1080201

      Comment


      • #4
        P.S. you can delete bndDir('HCBNDDIR':'CMBNDDIR') from the ctl-opt

        Comment


        • #5
          I can't reproduce your problem here on a 7.3 machine with QCCSID=1147, with SRCF CCSID any of 37, 1147 or 65535 and JOB ccsid any of 1147, 37 or 65535. (it always gives DSPLY 52; 52; 50; )
          How did you put the source in the PUB400 SRCF, save/restore or copy/paste ?

          if you run DMPSYSOBJ OBJ(SQLBUGTST1) CONTEXT(yourlib) OBJTYPE(*PGM)
          then find DECLARE CSR1 in the spool that it produced you will see the SQL query that is run, uppercased, formatted with no linebreak.
          Do you see the conditions of line 28 and 29 there ?
          If yes is it preceeded by x'05' ?
          Nicolas

          Comment


          • #6
            Hi, thanks for checking.

            To reproduce on pub400 I had to retype the source by hand - I cannot access pub400 from work.

            I'm not authorised to DMPSYSOBJ, I will see if I can find someone who is who is willing to run it for me. What exactly does it do?

            Comment


            • #7
              P.S. I forgot to specify, I don't know if the tab character would survive copy/pasting from the forum. I added the tab character in my source member by directly modifying it using SQL, with an ALIAS object to target the member within the source file

              Comment


              • #8
                DMPSYSOBJ stands for Dump System Object, it produces a spool file that shows object attributes (those which are shown by DSPOBJD like TEXT, USAGE and object specific commands) and some content of an object in a context. .
                A type of context is a library, DMPSYSOBJ will show a list of system pointers to the objects it contains. With a PF will contain a list pointers to members and formats.

                When CRTSQLRPGI, it produces an intermediate source that contains calls with a statement number that refers to a statement that is put in a secondary associated space of the member produced. Then the object ic created and the data in the space is copied to the associated space of the object, where RPGLE debug data is also.

                DMPSYSOBJ of the program compile with your source is 146 pages long

                Here is what I can fin on page 5
                Code:
                0018C0   40400000 00000000 00000000 00000000   C4C5C3D3 C1D9C540 C3E2D9F1 40C3E4D9  *                DECLARE CSR1 CUR*    
                0018E0   E2D6D940 C6D6D940 E2C5D3C5 C3E3405C   40C6D9D6 D440E2D8 D3C2E4C7 E3E2E3F2  *SOR FOR SELECT * FROM SQLBUGTST2*    
                001900   40D5E2D3 40E6C8C5 D9C540D5 E2D3404B   40C3D6D3 F1407E40 7DE3C5E2 E3F0F17D  * NSL WHERE NSL . COL1 = 'TEST01'*    
                001920   40C1D5C4 40D5E2D3 404B40C3 D6D3F440   4C7E40F1 F2F1F0F5 F0F640C1 D5C4404D  * AND NSL . COL4 <= 1210506 AND (*    
                001940   40D5E2D3 404B40C3 D6D3F540 6E7E40F1   F2F1F0F5 F0F640D6 D940D5E2 D3404B40  * NSL . COL5 >= 1210506 OR NSL . *    
                001960   C3D6D3F5 407E40F0 405D40C1 D5C440D5   E2D3404B 40C3D6D3 F4407E40 4D40E2C5  *COL5 = 0 ) AND NSL . COL4 = ( SE*    
                001980   D3C5C3E3 40D4C1E7 404D40D5 E2D3F240   4B40C3D6 D3F4405D 40C6D9D6 D440E2D8  *LECT MAX ( NSL2 . COL4 ) FROM SQ*    
                0019A0   D3C2E4C7 E3E2E3F2 40D5E2D3 F240E6C8   C5D9C540 D5E2D3F2 404B40C3 D6D3F140  *LBUGTST2 NSL2 WHERE NSL2 . COL1 *    
                0019C0   7E40D5E2 D3404B40 C3D6D3F1 40C1D5C4   40D5E2D3 F2404B40 C3D6D3F2 407E40D5  *= NSL . COL1 AND NSL2 . COL2 = N*    
                0019E0   E2D3404B 40C3D6D3 F240C1D5 C440D5E2   D3F2404B 40C3D6D3 F3407E40 D5E2D340  *SL . COL2 AND NSL2 . COL3 = NSL *    
                001A00   4B40C3D6 D3F340C1 D5C4404D 40D5E2D3   F2404B40 C3D6D3F5 406E7E40 F1F2F1F0  *. COL3 AND ( NSL2 . COL5 >= 1210*    
                001A20   F5F0F640 D6D940D5 E2D3F240 4B40C3D6   D3F5407E 40F0405D 40C1D5C4 40D5E2D3  *506 OR NSL2 . COL5 = 0 ) AND NSL*    
                001A40   F2404B40 C3D6D3F4 404C7E40 F1F2F1F0   F5F0F640 5D40D6D9 C4C5D940 C2E840D5  *2 . COL4 <= 1210506 ) ORDER BY N*    
                001A60   E2D3404B 40C3D6D3 F1406B40 D5E2D340   4B40C3D6 D3F2406B 40D5E2D3 404B40C3  *SL . COL1 , NSL . COL2 , NSL . C*    
                001A80   D6D3F340 6B40D5E2 D3404B40 C3D6D3F4   40C4C5E2 C3404000 00000000 00000000  *OL3 , NSL . COL4 DESC           *    
                001AA0   D6D70000 00000000 00000000 69880000   00000000 00000000 00000000 00000730  *OP          Ñh                  *    
                001AC0   00050000 00000000 10000000 00020000   00000000 046C0000 00000000 00000000  *                     %          *    
                001AE0   00000000 04600000 04680000 00000000   00000000 00000000 00000000 00000000  *     -   Ç                      *    ​​


                I also had to use an alias to check.

                Is the member RCDLEN 112 ?

                If you can post here the source member, the program object and maybe the temporary SRCF (qsqltemp1 for example) as objects in a SAVF ?
                Nicolas

                Comment


                • #9
                  I am making enquiries to see what I will be allowed to share.

                  The source file is RCDLEN 132

                  This temporary SRCF you've asked for, is that something produced by DMPSYSOBJ?

                  Comment


                  • vazymimil
                    vazymimil commented
                    Editing a comment
                    Well I'm not sure It will help more than tell you if your objects behave the same here.

                    Probably opening a ticket at IBM support is a better option.

                    No CRTSQLRPGI produces the temporary file/member
                Working...
                X