Plan zajęć
- Biblioteka libpq
- Połączenie z bazą danych PostgreSQL
- Obsługa błędów
- Zapytania do bazy danych
- Kursory
Programy z wbudowanym językiem SQL wymagają dwóch etapów kompilacji. Początkowo przetwarzamy progam przy pomocy preprocesora, który przetwarza polecenia SQL na odpowiednie funkcje w języku gospodarza. Następnie kompilujemy z wykorzystaniem odpowiedniego kompilatora, na koniec dołączamy odpowiednie biblioteki związane z bazą danych.
ecpg program.pqc gcc -g -I/usr/include/postgresql program.c -o program -lecpg
Plik prog1.pqc ( [listing dokumentu] [link do dokumentu] )
#include <stdio.h>
#include "test.h"
EXEC SQL BEGIN DECLARE SECTION;
char dbname[1024];
char db[15];
char usr[15];
char pas[15];
EXEC SQL END DECLARE SECTION;
int
main()
{
strncpy(db,dbase,15);
strncpy(usr,user,15);
strncpy(pas,pass,15);
EXEC SQL CONNECT TO :db AS con1 USER :usr USING :pas;
EXEC SQL SELECT current_database() INTO :dbname;
printf("current database=%s \n", dbname);
EXEC SQL DISCONNECT ALL;
return 0;
}
Zadanie: Zmodyfikować program dodając odczytanie również bieżącego użytkownika ( current_user ).
W ramach ćwiczenia zapoznamy się z odczytem danych z tablicy oraz obsługą błędów.
Do obsługi błędów zwracanych przez bazę danych do aplikacji dostępna jest struktura sqlca, która jest dostępna w kodzie aplikacji po dołączeniu pliku sqlca.h. Opis struktury przedstawiono poniżej.
struct
{ char sqlcaid[8];
long sqlabc;
long sqlcode;
struct
{
int sqlerrml;
char sqlerrmc[SQLERRMC_LEN]; } sqlerrm;
char sqlerrp[8];
long sqlerrd[6];
char sqlwarn[8];
char sqlstate[5];
} sqlca;
Plik prog2.pqc ( [listing dokumentu] [link do dokumentu] )
#include <stdio.h>
#include "test.h"
EXEC SQL BEGIN DECLARE SECTION;
char db[15];
char usr[15];
char pas[15];
char dbname[1024];
int id;
char fname[20];
char lname[20];
EXEC SQL END DECLARE SECTION;
int
main()
{
strncpy(db,dbase,15);
strncpy(usr,user,15);
strncpy(pas,pass,15);
EXEC SQL CONNECT TO :db AS con1 USER :usr USING :pas;
EXEC SQL SELECT current_database() INTO :dbname;
printf("current database=%s \n", dbname);
EXEC SQL SELECT id_uczestnik, imie, nazwisko INTO :id, :fname, :lname FROM kurs.uczestnik LIMIT 1;
printf("%i %s %s\n",id,fname,lname);
EXEC SQL DISCONNECT ALL;
return 0;
}
Plik prog2d.pqc ( [listing dokumentu] [link do dokumentu] )
#include <stdio.h>
#include "test.h"
EXEC SQL BEGIN DECLARE SECTION;
char db[15];
char usr[15];
char pas[15];
char dbname[1024];
int id;
char fname[20];
char lname[20];
EXEC SQL END DECLARE SECTION;
int
main()
{
strncpy(db,dbase,15);
strncpy(usr,user,15);
strncpy(pas,pass,15);
ECPGdebug(1,stderr);
EXEC SQL CONNECT TO :db AS con1 USER :usr USING :pas;
EXEC SQL SELECT current_database() INTO :dbname;
printf("current database=%s \n", dbname);
EXEC SQL SELECT id_uczestnik, imie, nazwisko INTO :id, :fname, :lname FROM kurs.uczestnik LIMIT 1;
printf("%i %s %s\n",id,fname,lname);
EXEC SQL DISCONNECT ALL;
return 0;
}
Plik prog2e.pqc ( [listing dokumentu] [link do dokumentu] )
#include <stdio.h>
#include "test.h"
EXEC SQL BEGIN DECLARE SECTION;
char db[15];
char usr[15];
char pas[15];
char dbname[1024];
int id;
char fname[20];
char lname[20];
EXEC SQL END DECLARE SECTION;
int
main()
{
strncpy(db,dbase,15);
strncpy(usr,user,15);
strncpy(pas,pass,15);
ECPGdebug(1,stderr);
EXEC SQL CONNECT TO :db AS con1 USER :usr USING :pas;
EXEC SQL SELECT current_database() INTO :dbname;
printf("current database=%s \n", dbname);
EXEC SQL SELECT id_uczestnik, imie, nazwisko INTO :id, :fname, :lname FROM kurs.uczestnik ;
printf("%i %s %s\n",id,fname,lname);
EXEC SQL DISCONNECT ALL;
return 0;
}
Plik prog2em1.pqc ( [listing dokumentu] [link do dokumentu] )
#include <stdio.h>
#include "test.h"
EXEC SQL BEGIN DECLARE SECTION;
char db[15];
char usr[15];
char pas[15];
char dbname[1024];
int id;
char fname[20];
char lname[20];
EXEC SQL END DECLARE SECTION;
int
main()
{
strncpy(db,dbase,15);
strncpy(usr,user,15);
strncpy(pas,pass,15);
ECPGdebug(1,stderr);
EXEC SQL CONNECT TO :db AS con1 USER :usr USING :pas;
EXEC SQL SELECT current_database() INTO :dbname;
printf("current database=%s \n", dbname);
EXEC SQL SELECT id_uczestnik, imie, nazwisko INTO :id, :fname, :lname FROM kurs.uczestnik ;
if (sqlca.sqlcode == 0 )
printf(" %i %s %s\n",id,fname,lname);
else
{ printf(" SQLCA.SQLCODE: %i\n", sqlca.sqlcode);
printf(" SQLCA.SQLSTATE: %s\n", sqlca.sqlstate);
printf(" SQLCA.SQLERRM: %i %s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); }
EXEC SQL DISCONNECT ALL;
return 0;
}
Plik prog2em2.pqc ( [listing dokumentu] [link do dokumentu] )
#include <stdio.h>
#include "test.h"
EXEC SQL include sqlca;
EXEC SQL whenever sqlwarning sqlprint;
EXEC SQL whenever sqlerror do Prnt();
void Prnt()
{
fprintf(stderr, "*******************************************\n");
fprintf(stderr, "Fatal Error\n");
sqlprint();
fprintf(stderr, "*******************************************\n");
}
EXEC SQL BEGIN DECLARE SECTION;
char db[15];
char usr[15];
char pas[15];
char dbname[1024];
int id;
char fname[20];
char lname[20];
EXEC SQL END DECLARE SECTION;
int
main()
{
strncpy(db,dbase,15);
strncpy(usr,user,15);
strncpy(pas,pass,15);
ECPGdebug(1,stderr);
EXEC SQL CONNECT TO :db AS con1 USER :usr USING :pas;
EXEC SQL SELECT current_database() INTO :dbname;
printf("current database=%s \n", dbname);
EXEC SQL SELECT id_uczestnik, imie, nazwisko INTO :id, :fname, :lname FROM kurs.uczestnik ;
if (sqlca.sqlcode == 0 )
printf(" %i %s %s\n",id,fname,lname);
else
{ printf(" SQLCA.SQLCODE: %i\n", sqlca.sqlcode);
printf(" SQLCA.SQLSTATE: %s\n", sqlca.sqlstate);
printf(" SQLCA.SQLERRM: %i %s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); }
EXEC SQL DISCONNECT ALL;
return 0;
}
Plik prog3.pqc ( [listing dokumentu] [link do dokumentu] )
#include <stdio.h>
#include "test.h"
EXEC SQL BEGIN DECLARE SECTION;
char db[15];
char usr[15];
char pas[15];
char dbname[1024];
int id;
char fname[20];
char lname[20];
EXEC SQL END DECLARE SECTION;
int
main()
{
strncpy(db,dbase,15);
strncpy(usr,user,15);
strncpy(pas,pass,15);
/* ECPGdebug(1,stderr); */
EXEC SQL CONNECT TO :db AS con1 USER :usr USING :pas;
EXEC SQL SELECT current_database() INTO :dbname;
printf("current database=%s \n", dbname);
EXEC SQL DECLARE c1 CURSOR FOR SELECT * FROM kurs.uczestnik ;
EXEC SQL OPEN c1;
EXEC SQL FETCH c1 INTO :id, :fname, :lname;
printf("%i %s %s\n",id,fname,lname);
EXEC SQL CLOSE c1;
EXEC SQL DISCONNECT ALL;
return 0;
}
Zadanie: Wykorzystując cursor zwrócić zawartość dowolnej tabeli relacyjnej.
Plik prog4ei.pqc ( [listing dokumentu] [link do dokumentu] )
#include <stdio.h>
#include "test.h"
EXEC SQL BEGIN DECLARE SECTION;
char dbname[1024];
char db[15];
char usr[15];
char pas[15];
char insertStmt[100];
EXEC SQL END DECLARE SECTION;
static void handle_error(void);
int main()
{
EXEC SQL WHENEVER SQLERROR DO handle_error();
ECPGdebug(1,stderr);
strncpy(db,dbase,15);
strncpy(usr,user,15);
strncpy(pas,pass,15);
EXEC SQL CONNECT TO :db AS con1 USER :usr USING :pas;
strncpy(insertStmt,"INSERT INTO kurs.uczesnik VALUES(45, 'Adrian', 'Zawadzki')",50);
EXEC SQL EXECUTE IMMEDIATE :insertStmt;
EXEC SQL COMMIT;
fprintf(stderr, "ok\n");
return 0;
}
static void handle_error(void)
{
fprintf(stderr, "%s\n", sqlca.sqlerrm.sqlerrmc);
EXEC SQL WHENEVER SQLERROR CONTINUE;
/* EXEC SQL ROLLBACK RELEASE; */
}
Plik prog4pe.pqc ( [listing dokumentu] [link do dokumentu] )
#include <stdio.h>
#include "test.h"
EXEC SQL BEGIN DECLARE SECTION;
char dbname[1024];
char db[15];
char usr[15];
char pas[15];
char insertStmt[100];
char sqlStmt[100];
int par_val;
EXEC SQL END DECLARE SECTION;
static void handle_error(void);
int main()
{
EXEC SQL WHENEVER SQLERROR DO handle_error();
ECPGdebug(1,stderr);
strncpy(db,dbase,15);
strncpy(usr,user,15);
strncpy(pas,pass,15);
EXEC SQL CONNECT TO :db AS con1 USER :usr USING :pas;
/* strncpy(insertStmt,"INSERT INTO osoba VALUES(5, 'Adrian', 'Zawadzki')",50);
EXEC SQL EXECUTE IMMEDIATE :insertStmt;
EXEC SQL COMMIT;*/
strncpy(sqlStmt,"SELECT id_uczestnik, imie, nazwisko FROM kurs.uczestnik WHERE id_uczestnik = ?", 50);
EXEC SQL PREPARE s1 FROM :sqlStmt;
par_val = 1;
EXEC SQL EXECUTE s1 INTO :id, :fname, :lname USING :par_val;
fprintf(stderr, "ok\n");
return 0;
}
static void handle_error(void)
{
fprintf(stderr, "%s\n", sqlca.sqlerrm.sqlerrmc);
EXEC SQL WHENEVER SQLERROR CONTINUE;
/* EXEC SQL ROLLBACK RELEASE; */
}