1.47k likes | 1.65k Views
Corso Introduttivo sui Databases. Luciano Barone, Università Roma I Matteo Boschini, Cilea Milano Domenico Della Volpe, INFN Napoli Giovanni Organtini, Università Roma I Francesco Prelz, INFN Milano Lucia Silvestris, INFN Bari. Generalità sui Database e DBMS. Introduzione.
E N D
Corso Introduttivo sui Databases Luciano Barone, Università Roma I Matteo Boschini, Cilea Milano Domenico Della Volpe, INFN Napoli Giovanni Organtini, Università Roma I Francesco Prelz, INFN Milano Lucia Silvestris, INFN Bari
Introduzione • Cosa e’ un Data-base? • E’ una collezione di dati. • Esempio1: Rubrica telefonica • Esempio2: Sistema delle tasse Italiano • Esempio3: Conto Corrente bancario Questa collezione può essere generata e gestita: • manualmente (Rubrica) • tramite l’utilizzo del computer (Rubrica o sistema delle tasse,conto corrente)
Introduzione • Quando si utilizza il computer la gestione può essere fatta: • utilizzando un insieme di programmi che sono stati scritti appositamente per la particolare applicazione • utilizzando un database management System (DBMS) (Collezione di programmi che consente all’utente di creare e mantenere un Database)
Caratteristiche dell’approccio Database • Il database System non e’ solo il database ma anche il suo catalogo. • Il catalogo contiene informazioni quali la struttura di ogni file, il tipo dei dati che devono essere immagazzinati e i vari vincoli sui dati. • Il catalogo viene utilizzato dal DBMS software. Infatti il DBMS non viene scritto per ogni specifica applicazione quindi si deve riferire al catalogo per conoscere la struttura dei dati. (Questo non e’ necessario nel caso di file processing, in quanto la definizione dei dati fa’ tipicamente parte dell’applicazione stessa. Per esempio nel caso di un programma in C++ questa parte viene fatta nella definizione delle class e nel caso del C delle structure)
Utente Database System Applicazioni DBMS Software Software per processare le queries Software per accedere e immagazzinare dati Definizione del database:catalogo e schema Databases DataBase System
Quali sono i vantaggi nell’utilizzare un DBMS • Controllo della duplicazione di dati e software • Storage persistente per gli oggetti presenti nelle applicazioni e per la struttura dei dati • Diverse interfacce che possono essere utilizzate dai diversi utenti • Possono essere immagazzinate relazioni complesse tra i dati • Backup e recovery • DataBase descrive automaticamente il formato dei dati
Quali sono le implicazioni dovute all’utilizzazione di un Database • Devono essere utilizzati degli standard per i nomi e i formati dei vari dati • Si riduce il tempo necessario per sviluppare le applicazioni • In quanto si utilizza il DBMS che costituisce un layer intermedio tra il database e l’applicazione • Aumenta la flessibilità • Nel caso in cui bisogna soddisfare una ulteriore requirement, generalmente bisogna aggiungere qualche nuovo database oppure modificare i dati in un file esistente. Questo viene gestito dal software DBMS • Disponibilità di informazioni aggiornate • Infatti tutti gli utenti hanno una visione aggiornata dei loro dati subito dopo che la transazione e’ avvenuta.
Quando usare un DBMS ? • Date le caratteristiche appena esposte, un DB e’ utile (se non necessario) quando si trattano dati “complessi” . Complessita’ dei dati • dati di per se’ semplici, ma il campione e’ molto grande(elenco fornitori di una ditta) • i dati e le applicazioni su di essi richiedono integrita’ e consistenza (conto corrente) • esistono complesse relazioni tra dati (eventi HEP)
Quale DB usare ? • La scelta e’ dettata, oltre che da fatti oggettivi quali esistenza del prodotto o precedenti esperienze, da • quantita’ dei dati da immagazzinare. • tipo di dati da immagazzinare. • complessita’ delle relazioni tra le entita’ da immagazzinare. Piu’ elevata e’ la quantita’ o la complessita’ dei dati, piu’ articolato (o complesso) deve essere il DBMS. • Rubrica: carta e penna • CC Banca: DB commerciale con ottime caratteristiche’ di integrita’ • eventi HEP: DB (commerciale…) con ottima gestione relazioni complesse
Quando non e’ necessario utilizzare un DBMS • Nonostante i tutti i vantaggi descritti nelle precedenti trasparenze l’utilizzazione di un DBMS comporta un sovrapprezzo dovuto all’iniziale investimento in termini di hardware, software e training. Pertanto nelle seguenti circostanze si consiglia di non utilizzare un DBMS: • Il Database e le sue applicazioni sono molto semplici, ben definite e non si aspetta che cambino nel tempo • Non e’ richiesto un accesso da parte di più di un utente • Ci sono delle esigenze di accesso in tempo reale che non possono essere soddisfatte a causa dell’overhead dovuto ad un DBMS
Database Relazionali • Alla base dei database relazionali c’e’ un concetto molto semplice: quello che conta e’ la descrizione dei dati fatta dall’utente (E.F. Codd) • La descrizione logica non ha NESSUN legame con la struttura fisica dei dati. • La descrizione più semplice e immediata e’ una TABELLA. • Esiste un particolare formalismo matematico (algebra relazionale) in cui le tabelle vengono dette relazioni. DB RELAZIONALE DB di TABELLE LOGICHE
Database Relazionali - tabelle, terminologia • Una tabella e’ caratterizzata da FIELDS (colonne, campi) e n-tuple (rows, righe). • Se le righe della tabella hanno almeno un valore di colonna unico in tutta la tabella, la riga viene detta ENTRY del DB. • Tale valore e’ detto PRIMARY KEY, ovvero un oggetto che identifica in maniera univoca una entry. • Le PRIMARY KEY possono ottimizzare la gestione della tabella. • Esistono diversi livelli gerarchici di key: primary, secondary, etc. • una secondary key e’ qualche cosa che identifica una parte di tabella.
Database relazionali - tabelle, terminologia RUN_NUM e’ una Primary Key RUN_TYPE e’ una Secondary Key
Database relazionali - tabelle, terminologia • Usando opportune chiavi primarie e secondarie e’ possibile normalizzare il DB. La normalizzazione e’ un concetto chiave della teorie dei RDBMS, anche se oggigiorno la maggior parte dei RDBMS la implementa in maniera automatica. NORMALIZZAZIONE BUONA DEFINIZIONE DELLA TABELLA
RUN_TYPE table PRIMARY KEY = RUN_NUM SECONDARY KEY=RUN_TYPE Questa tabella sarebbe di per se’ ben definita, ma…. RUN_TAPE table PRIMARY KEY=COMMENT 2 SECONDARY KEY (comment,tape_id). Ora abbiamo due tabelle, mentre sfruttando PRIM e SEC KEY ne potremmo avere una sola, con maggiore efficienza di uso spazio disco e tempi di manipolazione... DB relazionali - “cattiva definizione” della tabella lucia: lucia:
Database relazionali -relazioni • Le tabelle sono chiamate relazioni… • si definiscono poi delle relazioni logiche tra elementi della tabella • esiste un meccanismo per maneggiare questi tipi di relazioni…(tabelle + nessi logici) • tale formalismo e’ tradotto sul calcolatore in un linguaggio che e’ genericamente chiamato Structured Query Language (SQL)
Database relazionali -DEFINIZIONE… • Un database relazionale e’ quindi un insieme di una o più tabelle, che possono o meno avere un nesso logico tra loro. • Tali tabelle non hanno alcun nesso con la struttura fisica dei dati ma solo con quella logica. • Una tabella non può appartenere in parte a un DB e in parte ad un altro. • Più tabelle, logicamente correlate o meno, possono appartenere allo stesso DB. Il DB e’ poi dotato di un linguaggio di gestione (SQL)
SQL definizione… • SQL e’ il linguaggio per interagire con un RDBMS. • E’ standard (a meno di dialetti) • Esistono essenzialmente 2 modi per usare SQL: 1) “ambiente SQL” specie di “shell” con comandi propri. SQL>comando SQL>@script.sql 2) uso di SQL da linguaggi di alto livello (f77, C, C++) come “embeddeb SQL” o come API.
Database relazionali - caratteristiche • Controllo della duplicazione: a seconda di come si definiscono i DB e le table • persistenza: automatica (tranne che per temporary-views) • accessi contemporanei: si’ • a seconda della tipologia dell’utente (user, dba) possono solo essere letti o anche modificati. In genere si adotta WORM • dati aggiornati: si’. I dati vengono aggiornati con un commit, che, a seconda dell’applicazione, puo’ essere immediato o posticipato. • Consistenza, robustezza: si’, esistono meccanismi (roll-back, control) che implementano la reversibilita’ e la consistenza. • Auto-descrizione dei dati:si’, e’ il concetto base dei RDBMS • scalabilita’ : non e’ semplice. E’ possibile, ad esempio, aggiungere campi a una tabella definendone una nuova e facendo un merge con la vecchia. Non e’ trasparente all’utente e alle applicazioni
Database relazionali - fisicamente su una macchina ? • Come abbiamo visto, la struttura logica dei dati non ha nulla a che vedere con la struttura fisica dei dati e di come essi sono organizzati su una macchina. • Non necessariamente un DB logico (il DB di calibrazione dell’HC) corrisponde a quello che per la macchina e l’O.S. e’ il database. • In generale e’ il RDBMS stesso che si occupa di scrivere i dati su disco, e in generale non si sa esattamente dove li scriva... • Si sa che li organizza in alberi di directory • e’ quindi sufficiente conoscere la directory madre per eseguire un backup fisico del database
Database relazionali - QUERY PROCESSING Cosa posso mettere via in un DB relazionale ? Esistono vari DATATYPES che si possono usare: (es. Rubrica: Nome, Cognome, tel.,e-mail, ecc.) • Numerico (INT e FLOAT, con varia precisione) • CHAR • DATE (data, con vari formati, es:31-01-98,01-31-98) che permettono una facile gestione temporale dei dati... • BINARIO (non tutti i RDBMS) (RAW [<1kB], LRAW [<2GB], BLOB[<4GB])
Database relazionali - trattamento campi binari.…ovvero, i dati HEP... Campi BINARI (forse i campi più utili in HEP…) • in generale i RDBMS sono “pensati” per variabili alfa-numeriche, che sono le uniche direttamente “leggibili” e interpretabili da SQL. Ciò e’ dovuto essenzialmente alla filosofia stessa dei RDBMS, nati per fini gestionali. • E’ tuttavia possibile usarli con opportuni strumenti e linguaggi di alto livello (f77,C,C++) “interfacciati” con SQL
i dati HEP in RDBMS: vantaggi e svantaggi... • …va valutata attentamente l'opportunità di inserire direttamente nel DB i dati, essendo il campo binario “non-nativo”. Vantaggi: • non e’ necessaria una implementazione OO. • RDBMS sono, almeno a livello intuitivo, semplici. • I RDBMS sono ampiamente diffusi • persistenza automatica dei dati Svantaggi: • implementazione dei campi binari richiede una elevata professionalita’ • essendo tali campi non nativi, si introduce un over-head di tempi di accesso e caricamento che va valutato in funzione dell’uso che si vuole fare del DB.
Database relazionali -SQL Survival Kit A meno di “dialetti” particolari, SQL e’ ben definito. “...se si interroga [bene] in inglese il DB si hanno le risposte desiderate…”(G. Koch) • il comando generico di SQL ha tre componenti: • 1. Comando (verbo…) • 2. Tabella su cui eseguirlo (complemento oggetto…) • 3. Clausole (altri complementi..) COMANDO from/into TABELLA [where…clausola…];
Database relazionali -SQL Survival Kit COMANDI BASE: • create TABLE table_name (field def.); • select FIELD from TABLE_NAME [where…]; • insert into TABLE_NAME values [where…]; • delete from TABLE_NAME [where…]; • update TABLE_NAME set values [where…];
Database relazionali -SQL Survival Kit esempi: CREATE TABLE RUN_TAB ( date DATE, time char(6) run_num number(5), run_type char(10), beam number(5), comment char(48), tape_id char(10) ); INSERT into RUN_TAB (date, time, run_num, run_type, beam, comment, tape_id) VALUES (‘1-1-97’,01:10, 1234,pion,200,P1234);
Database relazionali -SQL Survival Kit esempi: SELECT RUN_TYPE FROM RUN_TAB where TAPE_ID=P1234; dara’ : RUN_TYPE ------------- pion pion • where e’ il nocciolo della relazionalita’… e’ la clausola where che permette di accedere ai nessi logici esistenti tra i dati…
Database relazionali -SQL Survival Kit esempi: select * from RUN_TYPE, RUN_TAPE where TAPE_ID=P1234; automaticamente cerca in entrambe le tabelle (con ovvio rallentamento) e da’: DATE | TIME | RUN_NUM | RUNTYPE | BEAM ENERGY | COMMENT | TAPE_ID | ----------------------------------------------------------------------- 1-1-97 01:10 1234 pion 200 P1234 1-1-97 01:50 1235 pion 200 HC off P1234 la relazionalita’ e’ “insita” nel fatto che SQL cerca in tabelle differenti e mette in relazione i diversi dati.
Database relazionali -SQL Survival Kit • esistono 6 operatori relazionali: • = • != • < • > • <= • >= • e 3 operatori logici: • NOT • AND • OR
Database relazionali - ORACLE • ORACLE e’ il RDBMS commerciale più diffuso al mondo. • Estremamente robusto per quanto riguarda recovery e integrità, ovvero nel preservare versioni precedenti del DB • …questo e’ (forse) anche il suo difetto in HEP: ridondanza e controlli di consistenza rallentano le operazioni di accesso e query sul DB. • E’ possibile ridurre al minimo tali meccanismi, al costo di una elevata professionalità nella gestione.
Database relazionali - ORACLE • Possiede molti strumenti di sviluppo e accesso (proprietari) che permettono di sfruttarlo al meglio. • SQL+ (SQL “puro”) • PL/SQL (SQL procedurale) • ProC, ProF77, ProC++ (SQL “puro” precompilabile in programmi C,f77,C++) • OCI- Oracle Call Interface (librerie per SQL f77, C e C++). Questo e’ lo strumento necessario per applicazioni veloci e che gestiscano DATATYPES binari.
Database relazionali - ORACLE • Esistono poi strumenti per l’interfaccia Web (Oraweb). • Esistono infine strumenti freeware per l’interfaccia utente • moduli Perl5: • DBI.pm che necessita del driver module DBD::Oracle ... use DBI; BEGIN { $ENV{ORACLE_HOME} = '/home/oracle/product/7.x.x'; $ENV{TWO_TASK} = 'DB'; } $dbh = DBI->connect('dbi:Oracle:','scott', 'tiger');
Esempio di Pro*Fortran Program Run_Query EXEC SQL BEGIN DECLARE SECTION CHARACTER*10 UID CHARACTER*10 PWD INTEGER RUN_NUM INTEGER BEAM CHARACTER*10 RUN_TYPE EXEC SQL END DECLARE SECTION EXEC SQL INCLUDE SQLCA EXEC SQL WHENEVER SQLERROR DO CALL SQLERR UID = ‘SCOTT’ PWD = ‘TIGER’ EXEC SQL CONNECT :UID IDEBTIFIED BY :PWD WRITE(6,*) ‘CONNECTED TO ORACLE AS’, UID, PWD TOTAL = 0 EXEC SQL WHENEVER NOT FOUND GOTO 7000 EXEC SQL SELECT RUN_NUM,BEAM,RUN_TYPE + INTO :RUN_NUM, :BEAM, :RUN_TYP + FROM RUN_TAB + WHERE RUN_NUM = 1234 WRITE(6,*) RUN_NUM,BEAM,RUN_TYPE 7000 CONTINUE END SUBROUTINE SQLERR EXEC SQL INCLUDE SQLCA EXEC SQL WHENEVER SQLERROR CONTINUE WRITE(6,*) ‘ORACLE ERROR:’, SQLEMC EXEC SQL ROLBACK WORK RELEASE STOP END COMPILAZIONE… > profor MODE=ANSI INAME=Run_Query.pfo DBMS=V8 run_query.f e poi si compila run_query.f come si desidera... Database relazionali - ORACLE
Esempio di OCI: /* File: popolo_jb007.c Author: M.J. Boschini (boschini@cilea.it) This programs is an upgrade of popolo_jb006.c Main difference is that now input file and output files may live in different directories. Executable may live in an other directory as well. 03-February-1999 */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include "blocks_v2.h" #define MSG_SIZE 200000 #include <oratypes.h> #include <ocidfn.h> #ifdef __STDC__ #include <ociapr.h> #else #include <ocikpr.h> #endif #include <ocidem.h> Cda_Def cda; Lda_Def lda; ub4 hda[HDA_SIZE/sizeof(ub4)]; dvoid do_exit(); dvoid oci_error(); dvoid play_msg(); typedef unsigned char my_Uchar[100000]; long le_wo; unsigned long filelen; my_Uchar data; /* <------------------- changed */ int rowind =0; int j =0; static FILE *fp1, *otfp, *oefp; char o_txt_file[56]; char o_err_file[56]; char file_name[56]; char *datto = ".txt"; char *loggo = ".err"; char *directory = "/ora_cache2/temp_load/"; main(int argc,char *argv[]) { text sql_statement[256]; register sword i; sb2 indp; ub2 retl, rcode; sword msg_id; sb4 msg_len, len, offset; ub1 *ucp; register ub1 *ucp1; ub4 ret_len; unsigned long binfilelen; char *binfile; if (argc != 4) { (void) printf("Usage: %s binfilename file_number table_name\n", argv[0]); return 0; } strncpy((char *) o_txt_file, directory, sizeof (o_txt_file) - 1); strncpy((char *) o_err_file, directory, sizeof (o_err_file) - 1); printf("file is %s\n",o_txt_file); strncpy((char *) file_name, (char *) argv[1], sizeof (o_txt_file) - 1); Database relazionali - ORACLE- OCI
/* See program description for +21 explanation..... */ strcat(o_txt_file,file_name+21); strcat(o_txt_file,datto); strcat(o_err_file,file_name+21); strcat(o_err_file,loggo); printf("file is %s\n",o_txt_file); if( (otfp = fopen(o_txt_file, "w")) == NULL) { /* output txt filed file */ printf("error opening txt file \n"); } fprintf(otfp, " Loading log for file %s\n\n", argv[1]); if( (oefp = fopen(o_err_file,"w")) == NULL ) { /* output error file */ printf("error opening error file \n"); } if(( fp1 = fopen(argv[1],"rb")) == NULL) { /* input binary file */ printf("error opening file %s\n",argv[1]); } binfilelen = file_length(fp1); rewind(fp1); rowind = (atoi(argv[2]))*1000000; /* Connect to ORACLE. */ if (olog(&lda, (ub1 *)hda, (text *) ”user/password", -1, (text *) 0, -1, (text *) 0, -1, OCI_LM_DEF)) { fputs("Cannot connect with username USER. Exiting...\n", stderr); exit(EXIT_FAILURE); } fputs("Connected to ORACLE as user USER.\n", stdout); /* Open a cursor. */ if (oopen(&cda, &lda, (text *) 0, -1, -1, (text *) 0, -1)) { fputs("Cannot open cursor. Exiting...\n", stderr); exit(EXIT_FAILURE); } while( (f_read(fp1,binfilelen, &le_wo,data)) != -2) { /*loop on entire file*/ ++rowind; ++j; sprintf(( char*)sql_statement,"INSERT INTO %s VALUES(:1,%d,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)",argv[3],rowind,head[0],head[1],head[2],head[3],head[4],head[5],head[6],head[7],head[8],head[9]); if (oparse(&cda, sql_statement, -1, FALSE, 2)) oci_error(&cda); if (obndrn(&cda, 1, data, (le_wo)*2, 24, -1, (sb2 *) 0, (text *) 0, 0, -1)) oci_error(&cda); if(j%50 == 0) { printf("row number is %d --> committed !\n",j); printf("Data inserted in table amsjb_006 = %d\n", j); if(ocom(&lda) ) oci_error(&lda); if (oexn(&cda, 1, 0)) oci_error(&cda); if(j%5000 == 0) { printf("row number is %d --> committed !\n",j); printf("Data inserted in table amsjb_006 = %d\n", j); if(ocom(&lda) ) oci_error(&lda); } fprintf(otfp,"Data inserted in table %s = %d\n", j,argv[3]); do_exit(EXIT_SUCCESS); } Database relazionali - ORACLE- OCI
dvoid oci_error(cda) Cda_Def *cda; { text msg[200]; sword n; fputs("\n-- ORACLE ERROR --\n", stderr); n = oerhms(&lda, (sb2) cda->rc, msg, 200); fprintf(stderr, "%.*s", n, msg); fprintf(stderr, "Processing OCI function %s\n", oci_func_tab[(int) cda->fc]); do_exit(EXIT_FAILURE); } dvoid do_exit(rv) sword rv; { fputs("Exiting...\n", stdout); if (oclose(&cda)) { fputs("Error closing cursor.\n", stderr); rv = EXIT_FAILURE; } if (ologof(&lda)) { fputs("Error logging off.\n", stderr); rv = EXIT_FAILURE; } exit(rv); } int file_length(fp) FILE *fp; { fseek(fp, 0, SEEK_END); printf("MJB --> filelen is %d\n",ftell(fp)); return (ub4) (ftell(fp)); } Database relazionali - ORACLE- OCI
# Example for building demo OCI programs: # # NOTE: 1. ORACLE_HOME must be either: # . set in the user's environment # . passed in on the command line # . defined in a modified version of this makefile # # 2. If the target platform support shared libraries (e.g. Solaris) # look in the platform specific documentation for information # about environment variables that need to be properly # defined (e.g. LD_LIBRARY_PATH in Solaris). # include $(ORACLE_HOME)/rdbms/lib/env_rdbms.mk RDBMSLIB=$(ORACLE_HOME)/rdbms/lib/ LDFLAGS=-L$(LIBHOME) -L$(ORACLE_HOME)/rdbms/lib LLIBPSO=`cat $(ORACLE_HOME)/rdbms/lib/psoliblist` LDSHARED=ld -G -b -o CPLPL=aCC CC=cc CFLAGS =-Ae RM=rm OPTIMIZE=+O3 OBJS = popolo_jb007.o blocks_v3.o # directory that contain oratypes.h and other oci demo program header files INCLUDE= -I$(ORACLE_HOME)/rdbms/demo -I$(ORACLE_HOME)/rdbms/public -I$(ORACLE_HOME)/plsql/public -I$(ORACLE_HOME)/network/public # CONFIG = $(ORACLE_HOME)/rdbms/lib/config.o # module to be used for linking with non-deferred option # flag for linking with non-deferred option (default is deferred mode) NONDEFER=false # libraries for linking oci programs #OCISHAREDLIBS=$(TTLIBS) $(LLIBTHREAD) OCISHAREDLIBS=$(LIBCLNTSH) $(LLIBTHREAD) OCISTATICLIBS=$(STATICTTLIBS) $(LLIBTHREAD) PSOLIBLIST=$(ORACLE_HOME)/rdbms/lib/psoliblist CLEANPSO=rm -f $(PSOLIBLIST); $(GENPSOLIB) DOLIB=$(ORACLE_HOME)/lib/liborcaccel.a DUMSDOLIB=$(ORACLE_HOME)/lib/liborcaccel_stub.a REALSDOLIB=/usr/lpp/orcaccel/liborcaccel.a PROC=$(ORACLE_HOME)/bin/proc PCCINCLUDE= include=$(ORACLE_HOME)/precomp/public PCCI=-I$(ORACLE_HOME)/precomp/public USERID=scott/tiger PCCPLSFLAGS= $(PCCINCLUDE) ireclen=132 oreclen=132 sqlcheck=full \ ltype=none user=$(USERID) LLIBSQL= -lsql PROLDLIBS= $(LLIBSQL) $(TTLIBS) DEMO_MAKEFILE = mio_jb0.mk DEMOS = popolo_jb007 .SUFFIXES: .o .cob .for demos: $(DEMOS) generate_sharedlib: $(SILENT)$(ECHO) "Building client shared library ..." $(SILENT)$(ECHO) "Calling script $$ORACLE_HOME/bin/genclntsh ..." $(GENCLNTSH) $(SILENT)$(ECHO) "The library is $$ORACLE_HOME/lib/libclntsh.so ... DONE" $(DEMOS): $(MAKE) -f $(DEMO_MAKEFILE) build EXE=$@ OBJS=$@.o $(OBJS): $(CC) $(CFLAGS) +z -c $(INCLUDE) blocks_v3.c popolo_jb007.c build: $(LIBCLNTSH) $(OBJS) $(ECHODO) $(CC) $(LDFLAGS) -o $(EXE) blocks_v3.o popolo_jb007.o $(OCISHAREDLIBS) extproc_nocallback: $(OBJS) $(LDSHARED) $(SHARED_LDFLAG) $(SHARED_LIBNAME) $(LDFLAGS) $(OBJS) extproc_callback: $(OBJS) $(LIBCLNTSH) $(LDSHARED) $(SHARED_LDFLAG) $(SHARED_LIBNAME) $(OBJS) $(LDFLAGS) $(OCISHAREDLIBS) $(LIBEXTP) clean: # $(RM) -f $(DEMOS) *.o *.so rm -f *.o *.so Database relazionali - ORACLE- OCI makefile
Database relazionali - ORACLE Esperimenti in Produzione Esperimenti in Produzione AMS AMS ha ha acquisito acquisito dati su una dati su una n n navicella shuttle della NASA navicella shuttle della NASA Fa ricerca sull’antimateria Fa ricerca sull’antimateria n n Dati circa Dati circa 110GB 110GB n n Dati Dati “ “ posizionali posizionali ” e ” e di calibrazione di calibrazione n n gia’ gia’ in in DB DB Oracle. Oracle. Eventi di fisica Eventi di fisica in in fase di fase di n n caricamento caricamento . . Tutti Tutti i i membri della collaborazione membri della collaborazione n n possono accedere ai dati possono accedere ai dati . . Formato di Formato di output output dal DB dal DB e’ e’ n n consono consono ad ad applicazioni applicazioni HEP HEP (PAW, f77) (PAW, f77)
Database relazionali - ORACLE • ORACLE e’ anche utilizzato nella gestione della amministrazione al CERN e FNAL
Databases Relazionali come Data Storage per l’HEP Database pubblici e loro applicazioni in HEP
Database Relazionali di Pubblico Dominio La gestione di esperimenti di dimensioni ridotte, di test beam, di gruppi di lavoro, può venire facilitata dall’adozione di un -semplice- sistema di gestione di database, che offre questi vantaggi: • Auto-descrizione del formato dei dati • Uniformità dell’interfaccia di accesso • Semplicità di reperimento/installazione/gestione • Facilità di interfacciamento a tool WEB • Gestione storica delle modifiche
MSQL Home page: www.hughes.com.au Sviluppato da un singolo (David Hughes) per le necessità di un gruppo di ricerca non informatica (Minerva). MySQL Home page: www.tcx.se Sviluppato da una software-house. Requisito principale: velocità di accesso ai record. Quali Database Relazionali Pubblici? • PostgreSQL Home page: www.postgresql.org sunsite.auc.dk/postgresql • Originalmente sviluppato a Berkeley dallo stesso gruppo di ricerca informatica che ha creato Ingres. Tutti disponibili senza spese per applicazioni senza fini di lucro.
MSQL msqladmin create <database> msqladmin drop <database> msqldump <database> msql <database> MySQL mysqladmin create <database> mysqladmin drop <database> mysqldump <database> mysql <database> RDBMS pubblici: funzionalità SQL simili • PostgreSQL createdb <database> destroydb <database> pg_dump -d <database> psql <database> Creazione di un database: Cancellazione di un database: Estrazione/esportazione del contenuto di un database in formato di istruzioni SQL: Interprete di comandi SQL:
RDBMS pubblici: interfacciamento WEB • A tutti i pacchetti pubblici di gestione di database è associata una vasta collezione di software di utilità collegato. • Accesso e configurazione con interfaccia grafica • Accesso da svariati linguaggi di script: • Tcl, Perl, Python, Pike, … • Accesso da linguaggi compilati, attraverso opportune librerie (spesso accessibili direttamente solo dal C: vedi più avanti per un esempio di accesso da Fortran).
Interfacciamento WEB - Esempio con PERL-DBI • Questo esempio è fornito come riferimento. Sarà più chiaro al termine della sessione sui linguaggi di script. Il contenuto di una tabella di database (esempio: coppie nome canale/ valore di calibrazione) viene estratto e restituito in formato HTML. # Esegui la query. $result = $dbi_conn->prepare($query); $result->execute or die $DBI::errstr; # Ci sono risultati? if ($result->rows < 1) { print "<Html><Title>Error: cannot find info</Title><Body>\n"; print "<H1>ERROR: Cannot find any channel value.</H1>\n"; print "</Body></Html>\n"; exit 1; } # Stampa i risultati in una tabella HTML. print "<Html><Title>Channel calibration list.</Title><Body>\n"; print "<Center><H1>List of channels.</H1></Center><P><Hr>\n"; print "<Center>"; print "<Table Border=2><Tr><Td><B>Channel</B></Td><Td><B>Value</B></Td>"; print "</Tr>\n"; for ($i=0; $i<$result->rows; $i++) { @row = $result->fetchrow_array; $channel = $row[0]; $calibr = $row[1]; # Rimuovi gli spazi bianchi al termine della stringa del risultato. $_ = $channel; s/\s+$//; $channel=$_; print "<Tr><Td>$channel</Td><Td>$calibr</Td></Tr>\n"; } # Chiudi la pagina. print "</Table></Center>\n"; print "</Body></Html>\n"; #!/usr/bin/perl use CGI; use DBI; # Inizializza il contenuto della pagina WEB con la risposta $page = new CGI; print $page->header.”\n”; # DBI puo' funzionare con ODBC, Oracle, Ingres, mSQL, DB2, Empress, Informix, # Solid, Postgres, Illustra: Scegliere qui quello desiderato #$database_engine = "Pg"; #$database_engine = "mSQL"; #$database_engine = "mysql"; # Stabilisci la connessione col database locale 'test' $dbi_conn = DBI->connect("dbi:$database_engine:dbname=test","",""); # Connessione OK? if (!($dbi_conn)) { print "<Html><Title>Error: cannot connect to $database_engine</Title><Body>\n"; print "<H1>ERROR: Cannot connect to $database_engine database.</H1>\n"; print "</Body></Html>\n"; exit 1; } SQL # Costruisci una query di SQL. $query = "SELECT channel,calibr FROM test"; # Abbiamo ricevuto un parametro (ad esempio da un form HTML) # che richiede un particolare canale? $req_channel = $page->param('channel'); if ($req_channel =~ /[^\s]+/) { $query = $query . " WHERE channel like \'%$req_channel%\'"; } # Richiedi che i risultati siano in ordine alfabetico per canale. $query = $query . " ORDER BY channel";
Interfacciamento da C/Fortran: esempio con Msql • Un altro esempio di riferimento. Viene costruita una semplice interfaccia di accesso alle routine di libreria in C, che può essere utilizzata anche da programmi in Fortran. /* Esempio di interfaccia con Msql chiamabile dal Fortran */ /* F. Prelz 4-DEC-1998 */ #include <stdio.h> #include <stdlib.h> #include <time.h> #include "msql.h" /* Stati di errore */ #define DB_OK 0 #define DB_CONNECT_FAILED 1 #define DB_SELECT_DB_FAILED 2 #define DB_QUERY_FAILED 3 #define DB_NO_RECORD_FOUND 4 #define DB_USER_ROUTINE_FAILED 5 #define DB_CANNOT_ALLOC 6 /* Definizione della dimensione dei risultati da passare al Fortran (deve essere la stessa nella routine Fortran) */ #define FIELD_LENGTH 40 #define MAX_FIELDS 50 typedef int (*db_call_t)(); int db_query_list_f(char *db_name, char *query, db_call_t routine) { char *host_name; int socket; m_result *result; m_row row; int i,j,k,retcod,n_records,n_fields; char return_strings[MAX_FIELDS][FIELD_LENGTH]; host_name = getenv("MSQL_SERVER"); if ((socket = msqlConnect(host_name))==-1) return(DB_CONNECT_FAILED); if (msqlSelectDB(socket,db_name)==-1) { msqlClose(socket); return(DB_SELECT_DB_FAILED); } if (msqlQuery(socket,query)==-1) { msqlClose(socket); return(DB_QUERY_FAILED); } result = msqlStoreResult(); n_records = msqlNumRows(result); if (n_records==0) { msqlFreeResult(result); msqlClose(socket); return(DB_NO_RECORD_FOUND); } for(i=0;i<n_records;i++) { row = msqlFetchRow(result); /* Riempi le stringhe di risultati da passare al Fortran */ n_fields = msqlNumFields(result); for (j=0;j<n_fields && j<MAX_FIELDS;j++) { for(k=0;k<strlen(row[j]) && k<FIELD_LENGTH; k++) return_strings[j][k]=row[j][k]; for(;k<FIELD_LENGTH; k++) return_strings[j][k]=' '; } /* Chiama la routine indicata dall’utente*/ retcod = (routine)(&n_fields, return_strings, FIELD_LENGTH, MAX_FIELDS); if (retcod<0) { msqlFreeResult(result); msqlClose(socket); return(DB_USER_ROUTINE_FAILED); } } msqlFreeResult(result); msqlClose(socket); return(DB_OK); }
Interfacciamento da C/Fortran: esempio con Msql (2) • Segue: ecco il wrapper chiamabile dal Fortran ed il programma di accesso in Fortran. c Esempio di accesso al Database da Fortran F.Prelz 4-DEC-1998 c Per ogni record ottenuto eseguendo la query passata in c 'Db_Query_List' viene eseguita la funzione (Fortran) "User_Call". c Program Access_DB c External User_Call Integer User_Call External Db_Query_List Integer Db_Query_List Integer Status c Status = Db_Query_List('test','SELECT * FROM test',User_Call) c Database---^ ^--- Query Write (*,*) 'Status from Db_Query_List:',Status Call Exit End c Integer Function User_Call(N_Fields, Row) c c Questa funzione viene eseguita per ogni riga estratta dal database. c Row e' un array di character che contiene la riga trovata. c Integer N_Fields Integer I Integer Count Save Count Character*(*) Row(*) c Count = Count + 1 Write (*,'(1X,A,I3)') 'Row # ',Count c Do I = 1,N_Fields Write(*,'(1X,A,I3,A,A)') 'Field # ',I,' = ',Row(I) Enddo c User_Call = 0 Return End /* Wrapper chiamabile da Fortran */ int db_query_list__(char *db_name, char *query, int *routine, int l1, int l2) { int retcod; char *db_name_c, *query_c; /* Dobbiamo formattare le stringhe per passarle al C */ db_name_c = (char *)malloc(l1+2); query_c = (char *)malloc(l2+2); if (db_name_c != NULL) { strncpy(db_name_c,db_name,l1); db_name_c[l1]='\000'; } else return(DB_CANNOT_ALLOC); if (query_c != NULL) { strncpy(query_c,query,l2); query_c[l2]='\000'; } else return(DB_CANNOT_ALLOC); /* Ed ora chiamiamo la routine principale */ retcod = db_query_list_f(db_name_c, query_c, (db_call_t)routine); free (db_name_c); free (query_c); return retcod; } Fortran
Interfacciamento WEB - Esempio Msql/Mysql+PERL • Questi esempi sono forniti come riferimento. Saranno più chiari al termine della sessione sui linguaggi di script. Il contenuto di una tabella di database (esempio: coppie nome canale/ valore di calibrazione) viene estratto e restituito in formato HTML. # Esegui la query. $result = $db_conn->query($query); # Ci sono risultati? if ($result->numrows < 1) { print "<Html><Title>Error: cannot find info</Title><Body>\n"; print "<H1>ERROR: Cannot find any channel value.</H1>\n"; print "</Body></Html>\n"; exit 1; } # Stampa i risultati in una tabella HTML. print "<Html><Title>Channel calibration list.</Title><Body>\n"; print "<Center><H1>List of channels.</H1></Center><P><Hr>\n"; print "<Center>"; print "<Table Border=2><Tr><Td><B>Channel</B></Td><Td><B>Value</B></Td>"; print "</Tr>\n"; for ($i=0; $i<$result->numrows; $i++) { @row = $result->fetchrow; $channel = $row[0]; $calibr = $row[1]; # Rimuovi gli spazi bianchi al termine del risultato. $_ = $channel; s/\s+$//; $channel=$_; # Stampa la riga con i valori print "<Tr><Td>$channel</Td><Td>$calibr</Td></Tr>\n"; } # Chiudi la pagina. print "</Table></Center>\n"; print "</Body></Html>\n"; Interfaccia comune a Msql e Mysql #!/usr/bin/perl # use CGI; use Msql; # Per Mysql: use Mysql; # Inizializza il contenuto della pagina WEB con la risposta $page = new CGI; print $page->header; # Stabilisci la connessione col database locale di Msql 'test' # Per Mysql: $db_conn = Mysql->connect("","test"); $db_conn = Msql->connect("","test"); # Connessione OK? if (!($db_conn)) { print "<Html><Title>Error: cannot connect to MSQL/MYSQL</Title><Body>\n"; print "<H1>ERROR: Cannot connect to MSQL/MYSQL database.</H1>\n"; print "</Body></Html>\n"; exit 1; } SQL # Costruisci una query di SQL. $query = "SELECT channel,calibr FROM test"; # Abbiamo ricevuto un parametro (ad esempio da un form HTML) # che richiede un particolare canale? $req_channel = $page->param('channel'); if ($req_channel =~ /[^\s]+/) { $query = $query . " WHERE channel like \'%$req_channel%\'"; } # Richiedi che i risultati siano in ordine alfabetico per canale. $query = $query . " ORDER BY channel";