0

I'm beginning with Pro*C and have a program that reads in records and prints out grouped by an identifying value (guests). In order to get all the information printed, I used a break from the for loop to control what goes where. It compiles but it's not following the printing scheme and actually goes into an infinite loop. The last break at the end is to stop the infinite loop, and it's not hitting any of the conditionals for some reason (even with a default else). There's limited debugging on the remote database server it's executing on (dbx is not available).

While not end of cursor (ie. sqlcode = 0) If PrevSaleItem Not = Cursor.Item_ID Write The Subtotals for the Item Initialize ItemQty and ItemTotal to 0 Set PrevSaleItem to Cursor.Item_ID End if Print Out Detail Line Add Cursor.Quantity to ItemQty Add Cursor.calc_tax to ItemTotal and GuestTotal Fetch next record in cursor End While Print the Subtotals for the last item Print the Grand totals

exec sql open dbGuest;
exec sql fetch dbGuest into :sLastName, :sFirstName, :nItemID, :sItemName, :nQuantity, :nUnitPrice, :sTransDate, :sHotelName, :nHotelID, :sTaxable, :nCalcTax;
/* Lets check the status of the OPEN statement before proceeding , else exceptions would be suppressed */
if(sqlca.sqlcode !=0)  // If anything went wrong or we read past eof, stop the loop
 {
    printf("Error while opening Cursor <%d><%s>\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
    break;
 }
int PrevSaleItem = 0;
int ItemQty = 0;
double ItemTotal = 0.0;
double GuestTotal = 0.0;
for(;;)
{
    printf("%s %s %s %s %d\n","Charge Summary for:", sFirstName.arr, sLastName.arr, " Guest_ID:", nGuest_ID);
    printf("%s %d %s %s \n", "Sales_Item: ", nItemID, " - ", sItemName.arr);
    // Do the crazy stuff to end the C-Strings
    sLastName.arr[sLastName.len] = 0;
    sFirstName.arr[sFirstName.len] = 0;
    sItemName.arr[sItemName.len] = 0;
    sTransDate.arr[sTransDate.len] = 0;
    sHotelName.arr[sHotelName.len] = 0;
    sTaxable.arr[sTaxable.len] = 0;
    // initialize
    PrevSaleItem = nItemID;
    ItemQty = 0;
    ItemTotal = 0.0;
    GuestTotal = 0.0;
    //While not end of cursor (ie. sqlcode = 0)
    /* Check for No DATA FOUND */
    if (sqlca.sqlcode == 0)
    {
        if(PrevSaleItem != nItemID)
        {
            printf("ItemQty: %f \t ItemTotal: %f",ItemQty,ItemTotal);
            ItemTotal = 0.0;
            GuestTotal = 0.0;
            PrevSaleItem = nItemID;
        }
        printf("GuestTotal \t\t %f",GuestTotal);
        ItemQty += nQuantity;
        ItemTotal += nCalcTax;
        GuestTotal += nCalcTax;
    }
    else if(sqlca.sqlcode == 100 || sqlca.sqlcode == 1403)  // If anything went wrong or we read past eof, stop the loop
    {
        printf("CURSOR is empty after all fetch");
        PrevSaleItem = -1;
        break;
    }
    /* Check for other errors */
    else if(sqlca.sqlcode != 0)
    {
         printf("Error while fetching from Cursor <%d><%s>\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
         break;
    }
    else {printf("HIT ELSE"); break;}
    break;
}
// close the cursor and end the program
exec sql close dbGuest ;

The logic that should be happening is as follows:

Assume the break mechanism is within an outer for loop (not shown). It should open the cursor, fetch the 1st record, and then print the heading for the guest and the sales item. It then initializes the totals and break variables by setting the values. While not the end of cursor (sqlcode is 0, and instead of while just used for loop with break) if the previous item != the item id then it prints subtotals, initializes item quantities and totals to 0 and sets the previous item to item id (then breaks the if conditional). Item quantity is increased by the quantity in the table, and the calc_tax is added to the item and guest totals. The next record is fetched, the totals for that last item are printed, and then the grand totals for that guest are printed.

It's not printing the amounts where it should be and is in infinite loop, and after I tried breaks in all the conditionals, I'm at a loss to explain how it's happening. I'm sure it's a beginner mistake, so maybe a jr Oracle developer (but a pro would be great) has a moment to get me back on track here.

stackuser
  • 869
  • 16
  • 34
  • First, since you've got a break before the `}` which terminates the `for(;;)` loop, I don't see how this could be in an infinite loop. But, despite this - there's no fetch of the cursor inside the loop, so you never read another row from the cursor, and thus you'll never get to the end of the data fetched by the cursor. Share and enjoy. – Bob Jarvis - Слава Україні Feb 22 '14 at 20:45
  • Thanks, I'll put the fetch inside the loop. As for the infinite loop, in the middle of my 1st paragraph in post I said that the last `break` is there intentionally to stop the infinite loop. Maybe I should've written that clearer, but my intention was to remark on that last `break` and then leave it in the code so that I wouldn't cause anyone else the infinite loop suffering that I'd gone through -- don't want to discourage people from helping :) – stackuser Feb 22 '14 at 21:00
  • As a rule you should post the code in the form that exhibits the problems you're describing. – Bob Jarvis - Слава Україні Feb 22 '14 at 23:38

1 Answers1

2

Your fetch is outside the for loop. You go into the loop after the first fetch. If sqlca.sqlcode is zero after that first fetch, it isn't reaching any of the breaks because of the nested if and else, so it goes round the loop again. Becuase there is not a second fetch, you still have a good sqlcode, so it keeps going. I think.... Anyway, moving your fetch into the loop looks like what you want to happen?

It does look like that final break should kick in, but yesterday you posted code you'd modified so I'm not sure if that's the case here too.

If you reformat your code and introduce braces and nesting for the else conditions you can see they don't line up. The final { you showed isn't for the for, it's for one of the branches.

for(;;)
{
    if (sqlca.sqlcode == 0)
    {
        if(PrevSaleItem != nItemID)
        {
            ...
        }
        ....
    }
    else
    {
        if(sqlca.sqlcode == 100 || sqlca.sqlcode == 1403)
        {
            break;
        }
        else
        {
            if(sqlca.sqlcode != 0)
            {
                break;
            }
            else
            {
                printf("HIT ELSE");
                break;
            }
            break;
        }
       // close the cursor and end the program
       exec sql close dbGuest ;

The else if(sqlca.sqlcode != 0) is redundant; at this point sqlca.sqlcode has to be something other than 0, 100 or 1403. So it can't reach the next else either.

Alex Poole
  • 183,384
  • 11
  • 179
  • 318
  • Thanks! I see what you're saying that the fetch should be in the loop. It's still not printing the final totals or the item totals. I don't want to trouble you anymore, but I just realized that I'd asked for what I was doing wrong in printing out the totals as well. I think it's not really part of the question, so if it's ok with you I'll accept your answer and then post a different question as to why it's not printing properly within the loops. – stackuser Feb 22 '14 at 21:33