/* * Det här är filen "esql-test-1.esc". * Den innehåller ett C-program med ESQL (embedded SQL). * Programmet visar hur man kan anropa INGRES från C med hjälp av ESQL, * genom att ställa två enkla frågor mot demo-databasen. * * I det här programmet använder vi "cursors", * som ingår i standarden för ESQL. * INGRES erbjuder också en utvidgning utöver standard-ESQL, * s. k. "SELECT-loopar" (se programmet "esql-test-2.esc"). * * Thomas Padron-McCarthy IDA (tpm@ida.liu.se) * 30 december 1992 * * Instruktioner: * Kopiera filen till ditt eget directory: * cp ~di-c/kursbibliotek/esql-test-1.esc esql-test-1.esc * Studera programmet. * Kör filen genom C-ESQL-preprocessorn med kommandot * esqlc -p esql-test-1.esc * Då får du en C-fil som heter "esql-test-1.c". * Kompilera och länka ihop programmet (skriv det här som EN rad): * gcc -o esql-test-1 esql-test-1.c * /usr/local/ingres/ingres/lib/libingres.a -lm * Kör programmet: * esql-test-1 * * Alla satser i programmet som börjar med EXEC SQL är ESQL-satser, * och översätts av ESQL-preprocessorn till vanlig C-kod. * ESQL skrivs med ungefär (inte exakt!) samma syntax som SQL. * Läs i övrigt kommentarerna. * * Lite om C: * Funktionen "main" i C mostvarar huvudprogrammet i Pascal. * När programmet startas anropas main, och när man lämnar main * avslutas programmet. * Tecknen { och } motsvarar BEGIN och END i Pascal. * Variabeldeklarationerna står i början av varje sådant BEGIN-END-block. * Observera att C (men inte ESQL) skiljer på stora och små bosktäver! * */ #include /* Den här satsen anger att vi ska använda INGRES' * "SQL communications area", vilket är något * som behövs för INGRES' felhantering - t. ex. WHENEVER-satsen. */ EXEC sql include sqlca; int main(void) { /* Först kommer en deklarations-sektion för ESQL. * Den innehåller deklarationer av variabler som * gäller för både ESQL och C samtidigt! */ EXEC SQL begin declare section; char this_name[20 + 1]; /* En sträng. Obs: dimension = längd + 1 */ int this_salary; char part_name[20 + 1]; char supplier_name[15 + 1]; EXEC SQL end declare section; printf("\nVälkommen till ESQL-TEST-1!\n\n"); /* Vanlig C-kod */ EXEC SQL connect esql_demo; /* Ett ESQL-anrop. Gissa vad det gör. */ /* Här kommer en SELECT-operation uttryckt i ESQL: * Skriv ut namn och lön för alla anställda. * I vanlig SQL skulle man skrivit: * select name, salary from employee * Här använder vi en cursor, kallad "emp_cursor", * som "stegas igenom" tabellen employee * (egentligen: resultatet av SELECT-frågan). * I FETCH-satsen anger vi vilka variabler resultatet ska hamna i. * Koden inuti while-loopen (printf-satsen) utförs för varje tupel som * finns i relationen. Variablerna this_salary och this_name * sätts till de värden som attributen SALARY och NAME har i den tupeln. * WHENEVER-satsen gör att när vi försöker hämta en tupel (med FETCH) * efter att tabellen är slut, så hoppar vi till labeln "close_emp_cursor". */ EXEC SQL declare emp_cursor cursor for select name, salary from employee; EXEC SQL open emp_cursor; EXEC SQL whenever not found goto close_emp_cursor; while (1) { EXEC SQL fetch emp_cursor into :this_name, :this_salary; printf("Personen som heter %s har %d dollar i lön.\n", this_name, this_salary); } /* while */ close_emp_cursor: EXEC SQL close emp_cursor; /* Slut på den första SELECT-operationen */ printf("\n"); /* Vanlig C-kod: Skriv ut en tom rad */ /* En SELECT-operation till: * 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.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; /* I frågan ovan använde vi en WHENEVER-sats för att hoppa ur while-loopen * när det inte fanns fler tupler att hämta med FETCH. * Vi kan få samma effekt genom att titta på fältet "sqlcode" * i posten "sqlca", som 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å den andra 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 */