/* * Det här är filen "esql-test-3.esc". * Den innehåller ett C-program med ESQL (embedded SQL). * Programmet visar hur man kan anropa en egen felhanteringsrutin * om det uppstår ett INGRES-fel. * Felet som uppstår i det här programmet är ett "statiskt" fel * (felstavning av ett attributnamn), men även "dynamiska" fel, * t. ex. att en databas inte gick att öppna, kan hanteras. * * Thomas Padron-McCarthy IDA (tpm@ida.liu.se) * 30 december 1992 * * Instruktioner: * Kopiera filen till ditt eget directory: * cp ~di-c/kursbibliotek/esql-test-3.esc esql-test-3.esc * Studera programmet. * Kör filen genom C-ESQL-preprocessorn med kommandot * esqlc -p esql-test-3.esc * Då får du en C-fil som heter "esql-test-3.c". * Kompilera och länka ihop programmet (skriv det här som EN rad): * gcc -o esql-test-3 esql-test-3.c * /usr/local/ingres/ingres/lib/libingres.a -lm * Kör programmet: * esql-test-3 * */ #include EXEC sql include sqlca; /* Den här funktionen ska anropas om det uppstår ett fel i en SQL-sats: */ int my_ingres_error_handler(void) { int c; EXEC SQL begin declare section; char the_error_message[1000]; /* Felmedelanden kan vara långa! */ EXEC SQL end declare section; EXEC SQL inquire_ingres (:the_error_message = ERRORTEXT); printf("\n"); printf("*** Tråkigt nog har det uppstått ett INGRES-fel.\n"); printf("Så här ser felmeddelandet från INGRES ut:\n"); printf("%s", the_error_message); printf("\n"); /* Vi avslutar först INGRES-körningen, och sen programmet: */ EXEC SQL disconnect; /* Här skulle vi alltså egentligen bara avsluta programmet: * exit(1); * Fast vi gör det lite mer avancerat i stället: */ do { printf("Vill du avsluta programmet (skriv 'j' eller 'n')? "); c = getchar(); while (getchar() != '\n') ; if (c == 'j') { printf("Jaha. Tack och adjö.\n"); exit(1); } else if (c == 'n') { printf("Nähä. Då kör vi vidare!\n\n"); } else { printf("\007"); printf("Nej! Fel! Skriv 'j' eller 'n' först på raden!\n"); } } while (c != 'j' && c != 'n'); } /* my_ingres_error_handler */ int main(void) { EXEC SQL begin declare section; char part_name[20 + 1]; char supplier_name[15 + 1]; EXEC SQL end declare section; printf("\nVälkommen till ESQL-TEST-3!\n\n"); /* Den här satsen talar om att funktionen "my_ingres_error_handler" * ska anropas om det uppstår ett fel i en SQL-sats: */ EXEC SQL whenever sqlerror call my_ingres_error_handler; EXEC SQL connect esql_demo; /* En SELECT-operation: * Ta fram alla PARTS som varje SUPPLIER levererat, * tillsammans med SUPPLIERs namn. * I vanlig SQL skulle man skrivit: * select parts.pname, supplier.name * from parts, supplier, supply * where supplier.number = supply.snum * and supply.pnum = parts.pnum */ EXEC SQL declare cursor2 cursor for select parts.pname, supplier.name from parts, supplier, supply where supplier.number = supply.nums /* FEL! "nums" ska egentligen vara "snum"! */ and supply.pnum = parts.pnum; EXEC SQL open cursor2; /* Stäng av felhanteringen när tuplerna tar slut: */ EXEC SQL whenever not found continue; /* Fältet "sqlcode" i posten "sqlca" anger "senaste felkod". * Så länge den är 0 har vi inte kommit till slutet av relationen. */ while (sqlca.sqlcode == 0) { EXEC SQL fetch cursor2 into :part_name, :supplier_name; if (sqlca.sqlcode == 0) { printf("Prylen %s har levererats av %s.\n", part_name, supplier_name); } } /* while */ EXEC SQL close cursor2; /* Slut på SELECT-operationen */ printf("\n"); /* Avsluta INGRES-körningen */ EXEC SQL disconnect; /* Nu är det bara vanlig C-kod kvar: */ printf("Slut i rutan.\n"); return 0; } /* main */