POLITECNICO DI MILANO DIPARTIMENTO DI INGEGNERIA CIVILE E AMBIENTALE CORSO DI LAUREA SPECIALISTICA IN INGEGNERIA PER L'AMBIENTE E IL TERRITORIO PROGETTAZIONE E IMPLEMENTAZIONE DI CONTROLLI DI CONSISTENZA SU UN GEODATABASE DI DATI STORICI Tesi di laurea di: Emiliano Costantini, matr 735167 Relatrice: Prof.ssa Federica Migliaccio Correlatore: Ing. Guido Minini ANNO ACCADEMICO 2012/2013 Ai miei genitori Indice generale Introduzione.....................................................................................................................................5 Premessa...........................................................................................................................5 Il progetto «Geografie dell’Italia Medievale (XIII­XV sec.)»..............................................5 Obiettivi del presente lavoro.............................................................................................7 Struttura della tesi............................................................................................................8 CAPITOLO 1 - I dati......................................................................................................................9 1.1 La struttura tabellare originaria.................................................................................9 1.2 Geodatabase del progetto «Geografie dell’Italia Medievale (XIII­XV sec.)»..............13 1.2.1 Schema logico del geodatabase...................................................................................16 CAPITOLO 2 - Il DBMS PostgreSQL.....................................................................................22 2.1 Cenni all'evoluzione dei DBMS..................................................................................22 2.1.1 Il modello relazionale..................................................................................................23 2.1.2 I modelli a oggetti........................................................................................................24 2.2 Il linguaggio SQL.......................................................................................................25 2.3 Il software PostgreSQL..............................................................................................26 2.3.1 L'estensione PostGIS....................................................................................................31 2.3.2 I trigger........................................................................................................................32 2.4 Il software libero.......................................................................................................34 2.4.1 Problematiche del software proprietario......................................................................37 2.4.2 Normativa italiana sul Software Libero nella Pubblica Amministrazione....................39 CAPITOLO 3 - Implementazione dei controlli di consistenza........................................40 3.1 Definizione di “consistenza”.....................................................................................40 3.2 Controlli tematici......................................................................................................42 3.2.1 Vincolo sulle date.........................................................................................................42 3.2.2 Prevenzione della ridondanza nella tabella Luogo......................................................47 3.2.3 Verifica della lunghezza delle stringhe........................................................................58 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 3/109 3.2.4 Prevenzione di refusi tipografici nella tabella “ufficiale”.............................................61 3.3 Controlli geografici...................................................................................................63 3.3.1 Controllo Bounding Box...............................................................................................63 3.3.2 Controllo su toponimi e poligoni nella tabella Luogo..................................................70 3.3.2.1 Verifica sui Comuni..........................................................................................78 3.3.2.2 Verifica sulle Province......................................................................................86 CAPITOLO 4 - Considerazioni finali......................................................................................89 4.1 Considerazioni sul lavoro svolto...............................................................................89 4.2 Sviluppi futuri...........................................................................................................90 4.3 Aspetti critici.............................................................................................................91 BIBLIOGRAFIA..............................................................................................................................92 SITOGRAFIA..................................................................................................................................94 INDICE DELLE TABELLE............................................................................................................99 INDICE DELLE FIGURE............................................................................................................101 SOFTWARE UTILIZZATI.........................................................................................................102 APPENDICE A – Descrizione esaustiva dei campi della struttura tabellare............103 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 4/109 Introduzione Introduzione Premessa Negli ultimi decenni si è assistito ad un ingente incremento dell'utilizzo di informazione geografica e territoriale, in buona parte dovuto alla disponibilità di tecnologie capaci di fornire a basso costo dati georeferenziati, cioè connessi a posizioni spaziali espresse da coordinate. Da sempre fondamentale in ambiti scientifici quali la cartografia, l'indagine geologica, la progettazione ingegneristica, la pianificazione agricola e territoriale, l'utilizzo di informazione geografica ha ormai cominciato ad assumere rilevanza anche in ambiti di matrice umanistica quali la sociologia, la tutela dei beni culturali, la ricerca storica ed archeologica. L'ampliamento dei settori d'impiego, e in generale dell'utilizzo, dei geodati ha costituito un significativo impulso allo sviluppo di applicazioni informatiche dedicate, generalmente indicate con l'acronimo inglese GIS (Geographic Information System). Ormai insostituibili nelle analisi territoriali, i software GIS permettono di conservare, organizzare, manipolare, analizzare e rappresentare l'informazione geografica, oltre a poter gestire informazione di altri tipi. Negli applicativi GIS confluiscono aspetti relativi alle tecniche di rappresentazione grafica, alle metodologie di indagine statistica ed alla gestione delle basi di dati. Il progetto «Geografie dell’Italia Medievale (XIII-XV sec.)» Il presente lavoro di tesi si colloca nell'ambito della Ricerca Storica, all'interno del Progetto di Ricerca «Organizzazione del territorio, occupazione del suolo e percezione dello spazio nel Mezzogiorno medievale (secoli XIII – XV). Sistemi informativi per una nuova cartografia storica» (PRIN1 2009), il cui principale obiettivo consiste nell’approfondimento del nesso “potere ­ territorio” nell’area del Mezzogiorno mediante lo studio dei linguaggi politici e dei documenti 1 Programma di Ricerca di Rilevante Interesse Nazionale Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 5/109 Introduzione antichi (Carrion e Migliaccio, 2009). Il progetto vede la partecipazione di quattro Unità di ricerca, di cui tre di storia medievale (l’Università Federico II di Napoli, capofila del progetto, l’Università del Salento e l’Università di Bologna), e la quarta costituita dall'Unità di ricerca del Politecnico di Milano, il cui obiettivo è potenziare gli strumenti di studio e di indagine dei dati storici, al fine di mettere in grado le altre tre Unità di sviluppare nuova conoscenza a partire dall'informazione ad oggi disponibile (Zambrano, 2013). Nell'ambito della Ricerca Storica lo studio delle geografie politiche permette spesso di estrarre consistenti quantità di dati georeferenziati, in genere derivanti da una molteplicità di fonti. La classe di software costituzionalmente più idonea a favorire analisi storiche spaziali e spazio­temporali su tali dati è rappresentata dai GIS; tali applicativi sono infatti progettati per permettere di immagazzinare, organizzare, analizzare e rappresentare l'informazione geografica. L'impiego di un GIS richiede tuttavia una preventiva strutturazione dei dati in schemi uniformi, con l'eliminazione di qualsiasi ambiguità riguardo a formati, unità di misura, significati; svolto questo lavoro preliminare diventa possibile effettuare controlli, correlazioni, sovrapposizioni e condivisioni di dati. La rigorosa strutturazione dei dati aveva costituito la prima fase del progetto «Geografie e linguaggi politici alla fine del Medioevo» (PRIN 2006), durante il quale le due Unità di ricerca dell'Università del Salento e del Politecnico di Milano avevano identificato una struttura tabellare idonea a descrivere la geografia insediativa, amministrativa ed economica del territorio (Carrion et al., 2008). In accordo al modello di dato messo a punto, l'Università del Salento aveva trascritto sotto forma di tabelle i dati storici tratti dal Quaternus Declaracionum di Francesco Agello, registro contabile degli ingressi e delle uscite tributarie dello Stato Orsiniano redatto sul finire del Basso Medioevo, georeferenziando ove possibile l'informazione mediante coordinate planimetriche (Est,Nord) ed attribuendo alle coordinate stesse un grado di affidabilità espresso mediante coefficiente numerico intero (Carrion et al., 2008). La successiva evoluzione del progetto, portata avanti dall'Unità di Ricerca del Politecnico di Milano nel corso della tesi di dottorato «Progettazione e realizzazione del Sistema Informativo Territoriale “Geografie dell’Italia Medievale (XIII­XV sec.)”», è consistita nello strutturare i dati Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 6/109 Introduzione del Quaternus in un geodatabase il cui modello fosse riconducibile all'originaria struttura tabellare; la nuova organizzazione dell'informazione ha permesso di sfruttare le potenzialità caratteristiche dei database relazionali, tra cui la possibilità di svolgere interrogazioni(query), incrociare e confrontare dati tratti da diverse fonti, verificare e salvaguardare la consistenza dell'informazione memorizzata (Zambrano, 2013). Onde permettere di sfruttare appieno l'opera di georeferenziazione effettuata, ed al contempo consentire la condivisione dei dati fra le diverse Unità di Ricerca, il database è stato collegato ad un geoservizio web chiamato «Geografie Medievali (XIII­ XV sec.)» (in fase di imminente pubblicazione), realizzato in modo tale da permettere l'accesso ai dati in due distinte modalità: ▶ sotto forma di tabelle relazionali e viste; ▶ mediante interfaccia GIS, in modo da poter visualizzare i dati georeferenziati su supporto cartografico. Obiettivi del presente lavoro La tutela dell'integrità e della consistenza dei dati rientra tra le principali funzioni affidate ad un DBMS2; tale compito consiste essenzialmente nel porre sotto controllo le operazioni di inserimento e modifica dell'informazione nella base di dati, al fine di minimizzare la probabilità che nel database siano presenti errori, contraddizioni e assurdità. Tra i più importanti costrutti disponibili nel modello logico relazionale per tutelare la consistenza si annoverano vincoli di chiave primaria, vincoli di valore univoco, vincoli sui valori nulli, e vincoli di integrità referenziale; tali vincoli vengono definiti a livello di schema logico sulle tabelle che compongono il database. Questo tipo di controlli da solo non è però in grado di prevenire alcune tipologie di errore, tra cui vincoli sulle date, refusi tipografici 3, inconsistenze nella georeferenziazione. Il presente lavoro di tesi specialistica, ponendosi a valle del lavoro svolto nel corso dei due PRIN, si propone di integrare lo schema logico del geodatabase sviluppato nel PRIN «Progettazione e realizzazione del Sistema Informativo 2 3 DataBase Management System, software di gestione di una base di dati. A meno che non si verifichino su campi vincolati, secondo una modalità tale da attivare il vincolo. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 7/109 Introduzione Territoriale “Geografie dell’Italia Medievale (XIII­ XV sec.)» con controlli di consistenza avanzati, pur nella consapevolezza che intercettare tutte le possibili inconsistenze, data la complessità dello schema, costituisce sostanzialmente un limite non raggiungibile. Struttura della tesi Il lavoro di Tesi è articolato in quattro capitoli: ▶ nel primo capitolo, dedicato ai dati, viene ripercorso lo sviluppo del progetto su cui è basato il presente lavoro, partendo dalla struttura tabellare realizzata nel corso del progetto «Geografie e linguaggi politici alla fine del Medioevo» (PRIN 2006), per arrivare al geodatabase implementato nel corso del progetto «Geografie e linguaggi politici alla fine del Medioevo» (PRIN 2006). Particolare rilievo viene dato alla descrizione dei dati tabellari e dello schema logico del geodatabase. ▶ nel secondo capitolo, dedicato al Database Management System PostgreSQL, viene descritta l'evoluzione dei DBMS, ed in particolare i modelli logici Relazionale ed Object­Relational. Viene quindi presentato nei suoi tratti essenziali il linguaggio SQL, ed illustrato in dettaglio l'applicativo PostgreSQL, dedicando un paragrafo ai trigger e all'estensione PostGIS, deputata alla gestione dell'informazione geografica. Viene infine velocemente ripercorsa la storia del Software Libero, con accenni alle controindicazioni del software proprietario e alla normativa italiana in materia di Software Libero nella Pubblica Amministrazione. ▶ nel terzo capitolo, dedicato ai controlli di consistenza, vengono riportati il codice e la descrizione in linguaggio naturale dei controlli di consistenza implementati; vengono avanzate proposte di modifica allo schema logico della base di dati in vista di possibili ristrutturazioni/ampliamenti futuri; vengono infine analizzate le inconsistenze presenti in parte dell'informazione geografica attualmente memorizzata nel database; ▶ nel quarto capitolo, dedicato alle conclusioni, si riassume il lavoro svolto, evidenziandone vantaggi e limiti, e si delineano possibili sviluppi futuri. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 8/109 CAPITOLO 1 - I dati CAPITOLO 1 ­ I dati 1.1 La struttura tabellare originaria Come precedentemente accennato, il nucleo originario di informazioni su cui è basata l'applicazione è costituito dai dati contenuti nel Quaternus Declaracionum di Francesco Agello, registro storico degli ingressi e delle uscite esattoriali dello Stato Orsiniano negli anni 1448 e 1460 (i territori interessati dallo studio sono riportati in Figura 1.1). Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 9/109 CAPITOLO 1 - I dati I dati del Quaternus, desunti dalle fonti originali dall'Unità di Ricerca dell'Università del Salento, sono stati inseriti in una struttura tabellare concepita con l'obiettivo di catturare e descrivere la configurazione urbanistica, burocratica ed economica del territorio ai tempi dello Stato Orsiniano (Carrion e Migliaccio, 2009). La struttura tabellare di archiviazione dei dati 4, progettata in collaborazione con l'Unità di Ricerca del Politecnico di Milano e memorizzata in un foglio di calcolo, si presenta come una matrice di dati con 47 campi, tra i quali: 4 ▶ toponimo del centro preso in considerazione, così come riportato dalla fonte ▶ numero di fuochi soggetti al pagamento dell’imposta diretta ▶ distretto erariale ▶ località sede di tesoreria generale ▶ località sede di capitanato ▶ località sede di castellania ▶ località sede di dogana ▶ località sede di fondaco ▶ nome dell’erario generale ▶ nome dell’erario locale ▶ nome del tesoriere generale ▶ nome del tesoriere locale ▶ nome del capitano ▶ nome del castellano ▶ importo versato da ciascun centro per il pagamento dell’imposta diretta ▶ importo versato da ciascun centro per il pagamento del focatico ▶ importo versato da ciascun centro per il pagamento delle collette ▶ quantitativo di tomoli di sale11 acquistato ▶ importo versato per il mantenimento delle condotte militari del re ▶ importo versato da ciascun centro per il diritto di platea ▶ importo versato da ciascun centro per il diritto di affida La cui descrizione completa ed esaustiva è riportata in APPENDICE A – Descrizione esaustiva dei campi della struttura tabellare. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 10/109 CAPITOLO 1 - I dati Ciascuno dei centri inseriti nella tabella (uno stralcio della quale è riportato in Figura 1.2) è stato georeferenziato mediante una coppia di coordinate piane (Est,Nord), il cui grado di affidabilità è stato espresso mediante un coefficiente numerico intero variabile tra 1 e 5: il valore 5 contrassegna luoghi ben identificabili, come chiese o conventi; il valore 4 identifica piccoli agglomerati urbani; e così via, secondo un livello decrescente di precisione del posizionamento (Carrion et al., 2008). La decisione di ricorrere a geometrie di tipo puntuale invece che areale, raggiunta dopo un confronto tra le diverse Unità di Ricerca, è da considerarsi cautelativa; in futuro non è da escludersi il passaggio a geometrie poligonali, in grado di rappresentare un'informazione più ricca (Zambrano, 2013). L'opera di schedatura delle fonti e sistematizzazione dei dati in tabelle svolta dall'Unità di Ricerca di Lecce ha consentito di connettere a ciascuna località le informazioni ad essa relative, specificando in particolare la fonte da cui ciascun dato è tratto e l'anno di riferimento. Come si può osservare in Figura 1.2, il computo del tempo nel Quaternus Declaracionum è di tipo indizionale5. 5 Nei documenti medievali l'indizione è la componente della data che indica l'anno all'interno di un ciclo di anni numerati progressivamente da 1 all'ultimo anno del ciclo a conclusione del quale il conto riprende da 1, ossia il primo anno del nuovo ciclo. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 11/109 CAPITOLO 1 - I dati Progettazione dei controlli di consistenza sul GeoDatabase del progetto «Geografie dell’Italia Medievale (XIII – XV sec.)» Pag 12/109 CAPITOLO 1 - I dati 1.2 Geodatabase del progetto «Geografie dell’Italia Medievale (XIII-XV sec.)» L'organizzazione in forma tabellare ha rappresentato un importante punto di svolta nella gestione dell'informazione; la mera strutturazione in file6 tuttavia presentava rilevanti limitazioni strutturali: se da una parte, infatti, permetteva di memorizzare in maniera persistente l'informazione su supporti digitali, dall'altra non offriva strumenti per tutelare la consistenza dei dati, né consentirne la condivisione e l'accesso concorrente tra diversi utenti/applicazioni. La consapevolezza dei limiti dell'approccio file­ based ha pertanto spinto l'Unità di Ricerca del Politecnico di Milano, in collaborazione con le altre Unità di Ricerca, a creare un sistema di gestione dei dati più complesso, basato sull'utilizzo di un DBMS (DataBase Management System, sistema di gestione di basi di dati) (Zambrano, 2013). Tra i principali vantaggi dei DBMS si possono citare i seguenti: ▶ capacità di operare secondo logiche transazionali, in grado di garantire alle operazioni le cosiddette proprietà acide7 (Atzeni et al., 1999); ▶ gestione dell'accesso concorrente ad informazione condivisa: la gestione centralizzata dei dati permette di ridurre la ridondanza, una tra le principali cause di inconsistenza (Atzeni et al., 1999); 6 7 8 ▶ privatezza, implementata mediante opportuna gestione dei privilegi; ▶ efficienza8 nell'accesso ai dati, anche nel caso di database di grandi dimensioni. Contenitori di informazioni/dati in formato digitale. Dall'inglese ACID, acronimo per: • Atomicity: un blocco di diverse istruzioni costituenti un'unica transazione viene integralmente (indivisibilmente, come un atomo) eseguito nel caso in cui la transazione si concluda con un COMMIT, oppure nessuna delle singole istruzioni viene eseguita nel caso in cui la transazione si concluda con un ROLLBACK. • Consistency: terminata una transazione il database deve trovarsi in uno stato consistente, ovvero la sua istanza non deve violare vincoli di integrità, com'era in precedenza. • Isolation: le transazioni devono essere eseguite in maniera indipendente una dall'altra – in particolare, il fallimento di una non deve compromettere la corretta esecuzione delle restanti. • Durability: la proprietà di persistenza garantisce che i risultati prodotti dalle transazioni correttamente eseguite non possano andar persi a causa di malfunzionamenti o errori. Condizionata dalle scelte effettuate in fase progettuale. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 13/109 CAPITOLO 1 - I dati Il processo di realizzazione del geodatabase è avvenuto secondo una metodologia di progettazione standard, articolata nelle seguenti fasi: I. Raccolta ed analisi dei requisiti: descrizione –generalmente informale o semi­formalizzata– dei dati che il sistema deve poter gestire, e delle funzionalità da fornire agli utenti; II. Analisi di fattibilità: stima di costi, tempi, e priorità di realizzazione delle varie componenti del sistema, per ciascuna delle possibili alternative identificate. III. Progettazione del database: implementazione vera e propria del DBMS, effettuata secondo una procedura ormai consolidata che prevede tre fasi sequenziali (Jardine, 1977): 1. Progettazione concettuale: formalizzazione delle specifiche sui dati raccolte in fase di analisi dei requisiti, effettuata secondo uno specifico modello concettuale dei dati e realizzata indipendentemente dalla successiva implementazione (Chen, 1976). Nel caso del progetto «Geografie dell’Italia Medievale (XIII­XV sec.)» il modello concettuale prescelto è il modello Entità­Relazione, ed il risultante schema concettuale9 è illustrato nelle Figure 1.3 e 1.4. 2. Progettazione logica: conversione del modello concettuale in modello logico, realizzata tenendo conto delle applicazioni che dovranno operare sul sistema e degli indici di prestazione10 attesi (Atzeni et al., 1999). All'approfondimento dello schema logico del progetto, sul quale si innesta il presente lavoro di tesi, è dedicato paragrafo 1.2.1. 3. Progettazione fisica: realizzazione vera e propria del database e del relativo sistema di gestione, effettuata in funzione delle previsioni sul carico applicativo (Atzeni et al., 2003). In questa fase avviene la creazione delle strutture­dati e degli indici, il popolamento della base di dati, la scrittura del codice delle applicazioni. IV. Validazione: verifica del corretto funzionamento del sistema. La descrizione approfondita dello schema Entity­ Relationship del progetto esula dagli obiettivi del presente lavoro, e può essere reperita in (Zambrano, 2013). 10 Costo di un'operazione, occupazione di memoria 9 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 14/109 CAPITOLO 1 - I dati Figura 1.3: Schema Concettuale – Entità georeferenziate (Zambrano, 2013) Figura 1.4: Schema Concettuale – Entità prive di georeferenziazione (Zambrano, 2013) Progettazione dei controlli di consistenza sul GeoDatabase del progetto «Geografie dell’Italia Medievale (XIII – XV sec.)» Pag 15/109 CAPITOLO 1 - I dati 1.2.1 Schema logico del geodatabase La scelta del modello da utilizzare per la creazione dello schema logico è ricaduta sul Modello Relazionale, abbinato al linguaggio d'interrogazione SQL (a cui è dedicato il paragrafo 2.2). Proposto per la prima volta da (Codd, 1970), il modello relazionale è essenzialmente basato su due concetti, tabella (table) e relazione (relation), il primo dei quali di immediata comprensione, mentre il secondo mutuato dalla Teoria degli Insiemi. La combinazione di intuitività e di una robusta base teorica a supporto hanno portato il Modello Relazionale ad una lenta ma decisa affermazione nel settore dei database, al punto da risultare oggi il modello logico più utilizzato, soppiantando i modelli Gerarchico ed Reticolare (Atzeni et al., 1999). Una descrizione più approfondita del modello relazionale verrà fornita nel capitolo 2.1.1. Lo schema logico del database del progetto «Geografie dell’Italia Medievale (XIII – XV sec.)» risulta articolato in 15 tabelle, 9 delle quali derivanti da conversione diretta delle entity dello schema concettuale, mentre le restanti 6, dette tabelle­ponte, istituite con l'unico obiettivo di collegare dati connessi distribuiti su più tabelle. Sebbene una descrizione esaustiva dello schema logico 11 esuli dagli obiettivi del presente lavoro, si ritiene opportuno riportare parte del codice SQL di creazione delle tabelle relazionali (v. Tab. 1, 2, 3, 4 e 5), unitamente ad un breve commento sullo schema stesso. ­­ Table: personaggio CREATE TABLE personaggio ( id_personaggio integer NOT NULL, nome_funz_lat character varying(75), nome_funz_ita character varying(75), CONSTRAINT personaggio_pk PRIMARY KEY (id_personaggio) ) Tab. 1: Tabella relazionale personaggio ­ codice SQL 11 Reperibile in (Zambrano, 2013). Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 16/109 CAPITOLO 1 - I dati ­­ Table: ufficiale CREATE TABLE ufficiale ( id_ufficiale integer NOT NULL, id_personaggio integer, id_fonte character varying(20), id_distretto_erariale integer, id_unita_fiscale integer, id_ufficio integer, anno integer, nome_funz_lat character varying(75), nome_funz_ita character varying(75), nome_da_fonte character varying(75), soci boolean, erario_generale boolean, erario_locale boolean, baiulo boolean, capitano boolean, vicario boolean, tesoriere_rif boolean, tesoriere boolean, castellano boolean, esattore_affida boolean, doganiere boolean, num_doganieri integer, CONSTRAINT ufficiale_pk PRIMARY KEY (id_ufficiale), CONSTRAINT distretto_erariale_ufficiale_fk FOREIGN KEY (id_distretto_erariale) REFERENCES distretto_erariale (id_distretto_erariale) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT fonte_ufficiale_fk FOREIGN KEY (id_fonte) REFERENCES fonte (id_fonte) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT personaggio_ufficiale_fk FOREIGN KEY (id_personaggio) REFERENCES personaggio (id_personaggio) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION ) Tab. 2: Tabella relazionale ufficiale ­ codice SQL ­­ Table: imposte CREATE TABLE imposte ( id_imposte integer NOT NULL, id_fonte character varying(20), id_unita_fiscale integer, focatico integer, colletta integer, tomoli_sale double precision, stoppelli_sale double precision, tassa_milizie integer, donativo integer, taberna integer, bagliva integer, platea integer, affida_parziale double precision, affida_totale double precision, CONSTRAINT imposte_pk PRIMARY KEY (id_imposte), CONSTRAINT fonte_imposte_fk FOREIGN KEY (id_fonte) REFERENCES fonte (id_fonte) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION ) Tab. 3: Tabella relazionale imposte ­ codice SQL Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 17/109 CAPITOLO 1 - I dati ­­ Table: luogo CREATE TABLE luogo ( id_luogo character varying(12) NOT NULL, id_luogo_attuale bigint, id_fonte character varying(20), id_distretto_erariale integer, toponimo_lat character varying(75), toponimo_ita character varying(45), comune_attuale character varying(45), provincia character varying(2), est_x double precision, nord_y double precision, grado_affidabilita integer, anno integer, mese integer, giorno integer, tipo_anno integer, indizione integer, fuochi_fiscali integer, fuochi_paganti integer, geom geometry, CONSTRAINT luogo_pk PRIMARY KEY (id_luogo ), CONSTRAINT distretto_erariale_luogo_fk FOREIGN KEY (id_distretto_erariale) REFERENCES distretto_erariale (id_distretto_erariale) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT fonte_luogo_fk FOREIGN KEY (id_fonte) REFERENCES fonte (id_fonte) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT luogo_attuale_luogo_fk FOREIGN KEY (id_luogo_attuale) REFERENCES luogo_attuale (id_luogo_attuale) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT enforce_dims_geom CHECK (st_ndims(geom) = 2), CONSTRAINT enforce_geotype_geom CHECK (geometrytype(geom) = 'POINT'::text OR geom IS NULL), CONSTRAINT enforce_srid_geom CHECK (st_srid(geom) = 32633) ) Tab. 4: Tabella relazionale luogo ­ codice SQL Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 18/109 CAPITOLO 1 - I dati ­­ Table: ufficio CREATE TABLE ufficio ( id_ufficio integer NOT NULL, id_luogo character varying(12) NOT NULL, id_fonte character varying(20), id_distretto_erariale integer, anno integer, est_x double precision, nord_y double precision, castellania boolean, centro_capitaneale boolean, centro_giurisdizionale boolean, tesoreria boolean, centro_vicaria boolean, dogana boolean, fondaco boolean, centro_affida boolean, geom geometry, CONSTRAINT ufficio_pk PRIMARY KEY (id_ufficio ), CONSTRAINT distretto_erariale_ufficio_fk FOREIGN KEY (id_distretto_erariale) REFERENCES distretto_erariale (id_distretto_erariale) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT fonte_ufficio_fk FOREIGN KEY (id_fonte) REFERENCES fonte (id_fonte) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT luogo_ufficio_fk FOREIGN KEY (id_luogo) REFERENCES luogo (id_luogo) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT enforce_dims_geom CHECK (st_ndims(geom) = 2), CONSTRAINT enforce_geotype_geom CHECK (geometrytype(geom) = 'POINT'::text OR geom IS NULL), CONSTRAINT enforce_srid_geom CHECK (st_srid(geom) = 32633) ) Tab. 5: Tabella relazionale ufficio ­ codice SQL Come già menzionato in precedenza, e come si può comprendere osservando le Tab. 1, 2, 3, 4 e 5 appena riportate, lo schema logico effettua una riarticolazione del contenuto dell'originaria struttura tabellare, e la sua struttura è stata progettata con l'intento esplicito di potersi ricondurre ad essa (Zambrano, 2013). Si può tuttavia osservare come in alcune tabelle (tra cui la 4 e la 5) sia presente un campo geom, di tipo geometry, assente nella struttura tabellare. Il tipo geometry costituisce un'estensione rispetto ai tipi­di­dato (data types) standard del linguaggio SQL, introdotta per permettere l'archiviazione e l'elaborazione di dati geografici e territoriali. Le estensioni verranno riprese ed approfondite nei paragrafi 2.3 e 2.3.1, con riferimento al DBMS PostgreSQL; per il momento si ricorda che i geodati presenti nel database del progetto «Geografie dell’Italia Medievale (XIII – XV sec.)» sono costituiti da primitive geometriche puntuali, le cui coordinate piane (Est,Nord) sono espresse nel Sistema di Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 19/109 CAPITOLO 1 - I dati Riferimento WGS84/UTM, zona 33N (codice EPSG: 32633). Una rappresentazione grafica dello schema logico nel suo complesso viene riportata in Figura 1.5. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 20/109 CAPITOLO 1 - I dati Figura 1.5: Schema logico relazione del geodatabase. In verde le tabelle ponte, in grassetto le chiavi primarie delle tabelle relazionali (Zambrano, 2013) Progettazione dei controlli di consistenza sul GeoDatabase del progetto «Geografie dell’Italia Medievale (XIII – XV sec.)» Pag 21/109 CAPITOLO 2 - Il DBMS PostgreSQL CAPITOLO 2 ­ Il DBMS PostgreSQL Nel corso dell'elaborato i termini “dato” e “informazione” sono spesso stati usati come sinonimi. La differenza tra i due vocaboli è sottile, ed invero i termini possono il più delle volte essere scambiati senza incorrere in errore; tuttavia, soprattutto in ambito informatico, è importante essere consapevoli della differenza tra i due concetti. In tal senso un aiuto può venire dal dizionario12: ▶ Dato: ciò che è immediatamente presente alla conoscenza, prima di ogni elaborazione; (in informatica) elementi di informazione costituiti da simboli che devono essere elaborati. ▶ Informazione: notizia, dato o elemento che consente di avere conoscenza più o meno esatta di fatti, situazioni o modi di essere. In pratica i dati da soli non hanno alcun significato ma, una volta interpretati e correlati opportunamente, essi diventano informazioni, e permettono di arricchire la conoscenza (Atzeni et al., 1999). 2.1 Cenni all'evoluzione dei DBMS Sebbene l'attenzione ai dati caratterizzi da sempre le applicazioni dell'informatica, lo sviluppo di applicativi espressamente dedicati alla gestione dei dati –chiamati DBMS, Database Management System– è cominciato soltanto verso la fine degli anni '60. Da allora state proposte diverse classi di DBMS, ciascuna contraddistinta dal modello dei dati utilizzato. Un modello dei dati è un insieme di concetti utilizzati per organizzare i dati e descriverne la struttura in modo che essa risulti comprensibile all'elaboratore; il modello dei dati è pertanto la base sulla quale vengono implementate le caratteristiche di qualsiasi DBMS. I principali modelli dei dati sono quattro, ciascuno caratterizzato da una natura ben distinta (Pratesi, 2007): 12 Vocabolario della lingua italiana. Istituto della Enciclopedia Italiana, 1987. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 22/109 CAPITOLO 2 - Il DBMS PostgreSQL ▶ Il modello gerarchico, basato sull'uso di strutture ad albero (e quindi gerarchiche, da cui il nome), definito nella prima fase di sviluppo dei DBMS (anni Sessanta), e tuttora utilizzato in un ristretto numero di ambiti applicativi. ▶ Il modello reticolare (detto anche modello CODASYL, dal comitato di standardizzazione che lo definì con precisione), basato sull'uso di grafi, sviluppato successivamente al modello gerarchico (inizio anni Settanta). ▶ Il modello relazionale, in cui la definizione dei tipi avviene mediante il costruttore relazione, che prevede la strutturazione dei dati in insiemi di record a struttura fissa (anni Settanta). ▶ Il modello a oggetti, sviluppato negli anni Ottanta come evoluzione del modello relazionale, che estende alle basi di dati il paradigma della programmazione a oggetti. Quasi tutti i DBMS in commercio si basano su uno di questi modelli dei dati, detti anche modelli logici poiché, come appena detto, le strutture utilizzate da questi modelli, pur essendo astratte, riflettono una particolare organizzazione: ad alberi, a grafi, a tabelle o ad oggetti. 2.1.1 Il modello relazionale Benché ancora utilizzati in una minoranza di ambiti applicativi, i database fondati sui modelli gerarchico e reticolare concettualmente appartengono ormai di fatto alla storia dell'informatica. La maggioranza dei sistemi di gestione di basi di dati attualmente presenti sul mercato è basata sul modello relazionale, proposto da Codd nel 1970 con l'obiettivo di superare le limitazioni dei modelli gerarchico e reticolare, strutturalmente incapaci di realizzare la proprietà di indipendenza dei dati, già riconosciuta fondamentale (Atzeni et al., 1999). Il modello relazionale prevede l'organizzazione dei dati in insiemi (relazioni) di record a struttura fissa: in altre parole all'interno di una relazione, rappresentabile mediante una tabella, ciascun record (o tupla) deve avere un numero fisso di attributi (o campi), visualizzabili come colonne della tabella stessa. Affinché all'interno di ciascuna tabella Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 23/109 CAPITOLO 2 - Il DBMS PostgreSQL relazionale non possano coesistere due record identici, al momento di creare una table occorre dichiarare una combinazione di campi, definita primary key, i cui valori congiunti non possano presentarsi in più di un record della tabella. Questa limitazione, volta ad evitare la ridondanza (una tra le principali cause di potenziale inconsistenza), prende il nome di vincolo di chiave primaria. Il collegamento tra informazioni attinenti ripartite in tabelle diverse viene realizzato mediante valori dei dominî13 che compaiono nelle tuple stesse: per questa ragione il modello relazionale è detto “basato sui valori”, in opposizione ai modelli gerarchico e reticolare, che sono invece “basati su record e puntatori” (Atzeni et al., 1999). Il modello relazionale rappresenta uno stadio fondamentale nell'evoluzione dei DBMS: i database relazionali (RDBMS) infatti, oltre a consentire un'implementazione efficace ed efficiente delle applicazioni gestionali, permettono di garantire proprietà di fondamentale importanza quali la persistenza, l'affidabilità, la portabilità e la condivisione dell'informazione. Ulteriori pregi del paradigma relazionale sono rappresentati dalla possibilità di effettuare interrogazioni(query) arbitrariamente complesse, espresse mediante linguaggi dichiarativi (essenzialmente SQL, approfondito nel paragrafo 2.2), e dalla capacità di garantire transazioni concorrenti sulla stessa base di dati (v paragrafo 1.2). 2.1.2 I modelli a oggetti Come già detto, i RDBMS permettono di manipolare in maniera arbitrariamente complessa dati a struttura semplice, di tipo numerico/simbolico. La velocità dell'evoluzione tecnologica, tuttavia, ha rapidamente prodotto ambiti applicativi nuovi, caratterizzati dall'esigenza di gestire dati di tipo strutturato, finendo con l'evidenziare i limiti strutturali del modello relazionale. Il tentativo di rispondere alle nuove esigenze ha spinto, verso l'inizio degli anni '80, ad introdurre nell'ambito dei modelli logici nozioni provenienti dal paradigma della programmazione a oggetti; da questa contaminazione è nata una nuova classe di DBMS, detta ODBMS (Object Database Management System, sistemi di gestione di basi di dati ad oggetti) (Atzeni et al., 2003). 13 Il dominio di un campo è l'insieme dei valori che possono essere assegnati a tale campo all'interno di un record. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 24/109 CAPITOLO 2 - Il DBMS PostgreSQL Inizialmente si sono delineati due differenti approcci all'introduzione del paradigma a oggetti nelle basi di dati, da cui son derivate due distinte categorie di DBMS: ▶ i sistemi di gestione di basi di dati “orientati agli oggetti” (OODBMS, Object­ Oriented Database Management System), concepiti con l'obiettivo di estendere i DBMS a partire dalle caratteristiche dei linguaggi di programmazione ad oggetti. Caratterizzati da un approccio tendenzialmente rivoluzionario, gli OODBMS risultavano in gran parte incompatibili con il paradigma relazionale; ▶ i sistemi di gestione di basi di dati “relazionali a oggetti” (ORDBMS, Object­ Relational Database Management System), concepiti con l'obiettivo di estendere i DBMS integrando il concetto di oggetto all'interno del paradigma relazionale. I due approcci, apparentemente assai conflittuali all'inizio degli anni '90, si sono poi dimostrati nei fatti abbastanza convergenti; attualmente la maggioranza dei DBMS commerciali presenti sul mercato è basata sul modello di dati a oggetti (Atzeni et al., 2003). La scelta del DBMS per il progetto «Geografie dell’Italia Medievale (XIII – XV sec.)» è ricaduta su PostgreSQL, un applicativo open source di livello enterprise appartenente alla classe degli ORDBMS, la cui descrizione verrà approfondita nel paragrafo 2.3. Ulteriori approfondimenti sul linguaggio SQL, da cui il DMBS trae in parte il nome, vengono invece riportati nel paragrafo 2.2. 2.2 Il linguaggio SQL Le origini del linguaggio SQL risalgono al 1974, con lo sviluppo di un linguaggio prototipale di interrogazione per DBMS relazionali chiamato SEQUEL. Sviluppato presso i laboratori IBM dai ricercatori Raymond Boyce e Donald Chamberlin, SEQUEL costituì la base per lo sviluppo di quello che, nel 1977, sarebbe diventato SQL. Inizialmente il linguaggio SQL veniva utilizzato da IBM solamente per usi interni e con alcuni partner; le sue potenzialità, tuttavia, cominciarono ben presto ad attirare l'interesse di un numero crescente di società commerciali, che iniziarono a sviluppare prodotti basati su di esso. Nel 1983 IBM rilasciò il primo DBMS Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 25/109 CAPITOLO 2 - Il DBMS PostgreSQL relazionale ad utilizzare compiutamente il linguaggio SQL, chiamato DB2, ancora oggi uno dei massimi competitor nel mercato dei DBMS relazionali ad oggetti. Pochi anni dopo la sua comparsa, SQL era già diventato lo standard industriale de facto per i DBMS basati sul modello di dati relazionale. La fortuna di SQL è dovuta, tra le altre ragioni, all'intenso processo di standardizzazione effettuato da ANSI14 ed ISO15, iniziato nella prima metà degli anni Ottanta e tuttora in atto. Tale processo ha consentito a sviluppatori e utenti di poter contare nel tempo su diverse versioni dello standard SQL, sempre più complete e sofisticate. Attualmente SQL è più di un semplice linguaggio di interrogazione: comprende infatti comandi per la definizione dello schema logico (raggruppati nella categoria DDL, Data Definition Language) e comandi per l'interrogazione e la modificare dell'istanza di una base di dati (raggruppati nella categoria DML, Data Manipulation Language). Lo standard SQL­3, in particolare, ha normato la codifica di alcune funzionalità derivanti dall'evoluzione più recente della tecnologia delle basi di dati, tra cui le viste ricorsive, il supporto per il paradigma ad oggetti, i trigger (Atzeni et al., 1999). Ai trigger, particolarmente rilevanti ai fini del presente lavoro, è dedicato il paragrafo 2.3.2. 2.3 Il software PostgreSQL La storia di PostgreSQL comincia nel 1970 presso l'Università della California di Berkeley, con lo sviluppo di un database relazionale chiamato Ingres (Interactive Graphics Retrieval System). Nato come progetto di ricerca universitario sotto la guida del docente di Berkeley Michael Stonebraker, nel volgere di pochi anni Ingres venne convertito in un sistema commerciale dalla società Relational Technologies, che in seguito cambiò nome in Ingres Corporation, per poi essere assorbita dalla Computer Associates. Verso la metà degli anni '80 Stonebraker, che alcuni anni prima aveva abbandonato lo sviluppo attivo di Ingres per curarne la commercializzazione, decise di tornare a Berkeley per dare vita ad un nuovo progetto, chiamato Postgres (Post Ingres). L'obiettivo del progetto era creare un 14 American National Standards Institute, Istituto Nazionale Americano di Standardizzazione. 15 International Organization for Standardization, Organizzazione Internazionale per la Standardizzazione. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 26/109 CAPITOLO 2 - Il DBMS PostgreSQL database innovativo, in particolare nel supporto ai tipi di dati complessi e alla gestione degli UDF16. Per fare questo il team di Postgres decise di creare un fork17 di Ingres, nel quale integrare nozioni e concetti derivanti dalla programmazione ad oggetti: l'ORDBMS risultante, rilasciato con licenza libera BSD (Berkeley Software Distribution), venne chiamato Postgres, e da quel momento la sua evoluzione avvenne in maniera del tutto indipendente da Ingres. Come il suo “antenato”, dopo poco tempo anche Postgres fu convertito in un sistema commerciale, ad opera della Illustra Information Technologies18, compagnia costituita da Stonebraker stesso, Gary Morgenthaler ed alcuni studenti ed ex­studenti di Berkeley. Durante questa prima fase, tuttavia, il ciclo di sviluppo di Postgres fu caratterizzato da estrema lentezza: nei cinque anni compresi tra il 1988, anno di rilascio della prima versione stabile, e il 1993 i rilasci furono soltanto quattro. Nel corso del 1993 il progetto venne ufficialmente abbandonato. La licenza libera del codice, tuttavia, nel 1994 consentì ad Andrew Yu e Jolly Chen, allora dottorandi di Berkeley, di accedere e modificare i sorgenti di Postgres sostituendo il linguaggio di interrogazione POSTQUEL, risalente ad Ingres ed ormai inattuale, con un moderno interprete SQL. Il nuovo DBMS venne quindi rilasciato sul web con il nome di Postgres95. Nel 1996, al fine di pubblicizzarne la rinascita ed enfatizzare il passaggio al linguaggio SQL, il progetto venne ribattezzato PostgreSQL. Da allora la gestione del progetto è affidata ad un'attiva comunità globale di sviluppatori –non soltanto volontari– che si coordina attraverso Internet. Al primo rilascio stabile di PostgreSQL, avvenuto nel Gennaio 1997, ne sono seguiti altri venti (v. Figura 2.1), ciascuno dei quali ha apportato migliorie, aggiunto funzionalità, corretto bug19 del codice. L'attuale20 versione di sviluppo è la 9.3.1. 16 User Defined Types, tipi di dato definiti dall'utente 17 Nell'ambito dell'ingegneria del software il termine fork (o branch) indica lo sviluppo di un nuovo software a partire dal codice sorgente di un software già esistente. Generalmente i fork avvengono nell'ambito di progetti di software libero e open source: l'uso di licenze libere, infatti, rende possibile modificare i codici sorgenti senza bisogno di autorizzazioni esplicite. 18 Illustra venne poi venduta nel 1997 alla Informix Corporation, a sua volta assorbita da IBM nel 2005. 19 In informatica il termine bug indica errori nel codice sorgente che causano malfunzionamenti o instabilità. 20 (Dicembre 2013) Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 27/109 CAPITOLO 2 - Il DBMS PostgreSQL Figura 2.1: Successione temporale dei rilasci di PostgreSQL (fonte: Wikipedia) Tra le principali caratteristiche di PostgreSQL è possibile elencare le seguenti (Pratesi, 2007): ▶ Elevata conformità agli standard: la sintassi utilizzata è conforme alla maggior parte delle direttive degli standard SQL­2 ed SQL­3. ▶ FLOSS21: dal 1996 il mantenimento e lo sviluppo del progetto è affidato ad una rete globale di sviluppatori. L'internazionalizzazione del progetto ha prodotto, tra le altre conseguenze, la traduzione dell'applicativo in più di dieci lingue diverse22. ▶ Integrità referenziale: PostgreSQL implementa completamente l'integrità referenziale supportando le relazioni tra chiavi esterne e primarie, così come i trigger (a cui è dedicato il paragrafo 2.3.2). 21 Acronimo per Free Libre and Open Source Software, cioè software libero. Al software libero è dedicato il paragrafo 2.4. 22 Per verificare l'avanzamento dei lavori di traduzione nelle diverse diverse lingue si può consultare il sito ufficiale del progetto, all'indirizzo http://babel.postgresql.org/. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 28/109 CAPITOLO 2 - Il DBMS PostgreSQL ▶ Estrema varietà di tipi di dato: in aggiunta ai tipi previsti dai vari standard SQL, sono disponibili tipi geometrici, booleani, tipi specificatamente progettati per gestire indirizzi di rete, dati in formato XML, JSON, ed altro23. ▶ Object­Relational: in PostgreSQL ciascuna tabella definisce una classe; viene implementata l'ereditarietà fra tabelle; funzioni e operatori sono polimorfici. ▶ Transaction Model: i dati vengono protetti e gli accessi concorrenti multiutente/multiapplicazione vengono coordinati attraverso le transazioni. Il Transaction Model utilizzato da PostgreSQL si basa sul modello MVCC (Multi­Version Concurrency Control), che garantisce elevate prestazioni anche dal punto di vista dei tempi di esecuzione. ▶ Linguaggi procedurali multipli: trigger e procedure possono essere scritti in diversi linguaggi procedurali. Il codice lato server generalmente è scritto in PL/pgSQL 24, ma il codice server­side può essere sviluppato anche in Tcl, Perl e persino Bash, shell utilizzata nei sistemi operativi Unix­like. ▶ Supporto multiplo per API lato client: le applicazioni lato client possono essere scritte in diversi linguaggi di programmazione, tra cui C, C++, Perl, PHP, Tcl/Tk e Python. ▶ Estensibilità: una delle caratteristiche più interessanti di PostgreSQL è la possibilità, qualora si necessiti di funzionalità non presenti nell'applicativo nativamente, di aggiungerle con relativa facilità. È possibile, tra le altre cose, aggiungere tipi di dati, funzioni, operatori, procedure, linguaggi di programmazione lato client. Attualmente in Internet è possibile reperire innumerevoli estensioni di PostgreSQL: ai fini del presente elaborato la più interessante di esse è sicuramente PostGIS, che consente a PostgreSQL di gestire i tipi di dati geografici (a PostGIS è dedicato il paragrafo 2.3.1). Le caratteristiche appena elencate rivelano indubbiamente un DBMS dalle potenzialità non comuni; la peculiarità più rilevante di PostgreSQL, tuttavia, consiste probabilmente 23 Un elenco dei tipi di dato supportati da PostgreSQL è reperibile sul sito ufficiale del progetto, all'indirizzo http://www.postgresql.org/docs/9.3/static/datatype.html. 24 Linguaggio procedurale molto simile a Oracle PL/SQL, a cui si ispira fin dal nome. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 29/109 CAPITOLO 2 - Il DBMS PostgreSQL nell'efficacia con cui riesce a sfruttare la propria natura object­relational. Non è infatti un'operazione semplice riuscire a conciliare i concetti della programmazione ad oggetti con un linguaggio dichiarativo come SQL. I DBMS relazionali puri prevedono che l'informazione d'interesse venga recuperata dall'utente tramite query SQL, che possono risultare estremamente macchinose qualora l'informazione sia ripartita in maniera molto articolata su più table. Questo approccio risulta profondamente diverso dalla gestione dei dati nei linguaggi di programmazione ad oggetti, nei quali l'utilizzo di strutture complesse consente di aggregare i dati in elementi completi, permettendo di gestire la complessità in maniera significativamente più agevole. Adattare un sistema SQL­ based ad operare secondo logiche più vicine al “naturale” utilizzo dei dati non è in generale un obiettivo di facile realizzazione; la principale difficoltà da questo punto di vista è dovuta al fatto che i due paradigmi utilizzano modelli di organizzazione dei dati molto differenti. Questo problema, indicato in ambito informatico come object­relational impedance mismatch25, può arrivare a costituire uno dei problemi principali nello sviluppo di un progetto. Per ovviare al problema sono state implementate diverse soluzioni di object­ relational mapping26, che tuttavia risultano in genere gravate da pesanti controindicazioni, tra cui una forte riduzione delle prestazioni e l'obbligo di utilizzare il linguaggio supportante la mappatura per accedere ai dati (Pratesi, 2007). PostgreSQL risolve gran parte di questi problemi permettendo di sfruttare l'ampia gamma di dominî e tipi built­ in per creare UDT27 arbitrariamente complessi, rendendo così possibile la gestione nativa di tipi complessi da parte del DBMS. Viene inoltre supportata l'ereditarietà dei tipi, concetto derivante dalla programmazione a oggetti. Ad esempio, è possibile definire un tipo “CodicePostale”, e derivare da esso un tipo “Cap_IT”, codice di avviamento postale valido per l'Italia, e un tipo “Cap_ES” (analogo per la Spagna): gli indirizzi nel database potrebbero quindi accettare entrambi i tipi, e regole specifiche potrebbero validare i dati in entrambi i 25 Approssimativamente traducibile come “discrepanza di impedenza relazionale­a oggetti” 26 Tecniche di programmazione tese a consentire l'integrazione di RDBMS con sistemi software aderenti al paradigma della programmazione a oggetti. 27 User Defined Types, nuovi tipi di dato definiti dall'utente. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 30/109 CAPITOLO 2 - Il DBMS PostgreSQL casi. Queste ed altre caratteristiche, tra cui il poliformismo di funzioni e operatori, rendono PostgreSQL uno dei DBMS commerciali attualmente più avanzati dal punto di vista della programmabilità (Pratesi, 2007). 2.3.1 L'estensione PostGIS Tra le numerose tipologie di dati supportate da PostgreSQL rientra a pieno titolo l'informazione geografica. La gestione dei dati georeferenziati richiede l'utilizzo dell'estensione PostGIS, sviluppata dalla società commerciale canadese Refractions Research, e rilasciata pubblicamente per la prima volta nel 2001 con licenza libera GNU General Public License. La prima versione stabile (1.0) dell'applicativo risale all'Aprile 2005; ad essa sono seguiti altri sei rilasci stabili. La versione 2.2 di PostGIS, attualmente in sviluppo, vede Refractions Research tuttora capofila e principale contributor del progetto. Tra le principali caratteristiche dell'estensione si possono elencare le seguenti: ▶ supporto alle primitive geometriche (o feature): point, linestring28, polygon, multipoint29, multilinestring, multipolygon30, e geometrycollection31; ▶ possibilità di importare dati vettoriali in formato shapefile; ▶ determinazione delle relazioni topologiche (connessione, adiacenza, sovrapposizione, contenimento) mediante matrice Egenhofer 3✕332; ▶ funzioni spaziali per la misura di aree, distanze, lunghezze e perimetri; ▶ funzioni spaziali32 per implementare operazioni di unione, differenza, intersezione, differenza simmetrica e buffer; ▶ indici spaziali di tipo R­tree­over­GiST (albero di ricerca generalizzato) per ottimizzare le interrogazioni spaziali; 28 29 30 31 32 Spezzata poligonale Pluralità di punti singoli trattati come un oggetto unico Detta anche face o “poligono bucato” Insieme di una o più primitive geometriche, non necessariamente dello stesso tipo. Funzioni disponibili tramite libreria GEOS. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 31/109 CAPITOLO 2 - Il DBMS PostgreSQL ▶ supporto alla selezione tramite indici, per ottimizzare le interrogazioni miste spaziali/non spaziali; ▶ strumento PostGIS Raster, per implementare intersezioni tra dati vettoriali di tipo polygon e coverage raster molto estese (integrato a partire da PostGIS 2.0+). 2.3.2 I trigger I trigger, detti anche regole attive, sono procedure definite a livello di schema logico che vengono eseguite in maniera automatica al verificarsi di un determinato evento – tipicamente l'inserimento, la modifica o la cancellazione di un record in una delle tabelle relazionali. La creazione dei trigger fa parte del DDL33, e costituisce una delle funzionalità più significative dei moderni DBMS relazionali (Atzeni et al., 1999). La specifica di un trigger avviene secondo il paradigma ECA (Event­Condition­ Action): il trigger viene attivato dal verificarsi di uno specifico evento e, se risulta soddisfatta una determinata condizione, esegue un'azione prestabilita (Atzeni et al., 1999): ▶ gli eventi sono costituiti da operazioni di aggiornamento dell'istanza della base di dati, ovvero insert/delete su tabelle e update su singoli attributi; ▶ la condizione –che può anche mancare, ossia essere sempre verificata– è un predicato booleano espresso in SQL. Nella valutazione della condizione è possibile utilizzare una coppia di variabili predefinite, old e new, che permettono di far riferimento rispettivamente alla nuova e alla vecchia versione della tupla oggetto del comando di insert, update o delete; ▶ l'azione è una successione di generiche primitive SQL, talvolta arricchite da un linguaggio di programmazione integrato nel DBMS (ad esempio PL/pgSQL in PostgreSQL); anche nell'ambito dell'azione è possibile referenziare le variabili predefinite old e new. In genere i trigger fanno riferimento ad una tabella relazionale, detta target, in quanto rispondono ad eventi relativi a tale tabella (Atzeni et al., 2003). 33 Data Definition Language, v. paragrafo 2.2. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 32/109 CAPITOLO 2 - Il DBMS PostgreSQL Tra le applicazioni più frequenti dei trigger rientra la tutela di vincoli di consistenza non esprimibili mediante costrutti predefiniti (vincoli di chiave primaria, vincoli di valore univoco, vincoli sui valori nulli, e vincoli di integrità referenziale). In questi casi il trigger si attiva ad ogni evento potenzialmente lesivo della consistenza dei dati e, qualora la violazione risulti verificata, agisce attivamente34 per emendarla secondo la procedura prevista. In questo senso la capacità di implementare azioni complesse –cioè non limitate al mero impedimento delle modifiche– costituisce il vero potenziale del costrutto trigger e la sua differenza rispetto ai vincoli predefiniti del linguaggio SQL. La principale criticità dell'utilizzo di regole attive è legata alla caratteristica dei trigger di reagire agli eventi di modifica dell'istanza del database qualunque sia la loro origine – ossia anche nel caso in cui la modifica sia il risultato dell'azione di un altro trigger. Il rischio è quindi l'innesco di una catena di attivazioni, che può degenerare in un loop infinito qualora i trigger si attivino mutuamente in modo ciclico. L'analisi di queste situazioni è particolarmente difficile, ed in pratica richiede impegno ed intúito da parte del progettista (Atzeni et al., 1999). La logica implementativa di PostgreSQL prevede che un trigger al momento dell'attivazione invochi una funzione, detta funzione­trigger, che dev'essere definita a livello di schema logico prima del trigger stesso. La sintassi prevista per le funzioni­trigger è riportata in forma semplificata in Tab. 6, mentre la sintassi per i trigger veri e propri in Tab. 7. 34 Da cui la denominazione “regola attiva”. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 33/109 CAPITOLO 2 - Il DBMS PostgreSQL CREATE [ OR REPLACE ] FUNCTION function_name() RETURNS TRIGGER AS $body$ DECLARE ­­ Dichiarazione di eventuali variabili BEGIN ­­ (blocco di primitive nel linguaggio indicato nella clausola language) RETURN NEW; END; $body$ language linguaggio_di_programmazione; Tab. 6: Forma semplificata della sintassi PL/pgSQL per la creazione di una funzione­ trigger CREATE [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] } ON table [ FROM referenced_table_name ] { NOT DEFERRABLE | [ DEFERRABLE ] { INITIALLY IMMEDIATE | INITIALLY DEFERRED } } [ FOR [ EACH ] { ROW | STATEMENT } ] [ WHEN ( condition ) ] EXECUTE PROCEDURE function_name ( arguments ) Tab. 7: Sintassi PL/pgSQL per la creazione di un trigger 2.4 Il software libero La possibilità di disporre liberamente e gratuitamente di un applicativo del livello di PostgreSQL potrebbe in prima battuta sorprendere, e sollevare interrogativi. Si ritiene quindi opportuno ripercorrere brevemente la storia del Software Libero, in seno al quale PostgreSQL è nato e tuttora continua a svilupparsi, al pari di progetti come il kernel Linux, Android, Apache web server, Mozilla Firefox, LibreOffice, QGIS, R statistics, Octave, Blender, VLC, BitTorrent e molti altri. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 34/109 CAPITOLO 2 - Il DBMS PostgreSQL Il Software Libero, internazionalmente noto come Free Software35, Open Source Software36, FOSS, F/OSS, o FLOSS37, è il risultato di 30 anni di sviluppo, conferenze e progetti portati avanti da singoli sviluppatori, imprese, compagnie e agenzie internazionali, università ed istituti di ricerca (Casagrande et al., 2012). Il concetto di software libero in realtà non è una novità in ambito informatico. I primi elaboratori avevano un costo talmente elevato che soltanto pochi centri di ricerca potevano affrontarne l'acquisto e la manutenzione. Il software (l'insieme di istruzioni che consente agli elaboratori di operare) presente in questi sistemi veniva normalmente distribuito gratuitamente sotto forma di codice sorgente, e condiviso tra sviluppatori e utenti; questi ultimi, in particolare, avevano la possibilità di modificare i sorgenti correggendo errori e aggiungendo funzionalità, rendendo poi liberamente disponibili ad altri utenti le modifiche (Casagrande et al., 2012). Con la diffusione dei computer all'esterno degli ambiti di ricerca e sviluppo, avvenuta tra la metà degli anni Settanta e la metà degli anni Ottanta, la considerazione del software da parte dei produttori mutò: da semplice accessorio dell'elaboratore, cominciò ad essere considerato esso stesso un prodotto. Il nuovo paradigma prevedeva la definizione di diritti di proprietà sul software, ed il diritto da parte del proprietario di vendere copie dell'applicativo agli utenti dietro sottoscrizione di licenze che definivano i termini di utilizzo. L'introduzione del nuovo modello, fondato sull'accesso esclusivo ai sorgenti da parte del produttore, fu causa di disagio per programmatori e ricercatori, che fino ad allora avevano sempre avuto la possibilità di visionare il codice, correggerlo, ed in generale adattarlo alle proprie necessità. In caso di problemi, il nuovo paradigma prevedeva di poter accedere al codice soltanto dietro accettazione di un accordo di non­divulgazione (Non­ Disclosure Agreement, NDA), che vietava agli sviluppatori di utilizzare il proprio contributo in altri ambiti e, soprattutto, di condividere le modifiche apportate (Casagrande et al., 2012). Fu in questo contesto che Richard Stallman, al tempo ricercatore presso il laboratorio di intelligenza artificiale del Massachusetts Institute of Technology (MIT), decise di intraprendere 35 Da non confondere con Freeware, software proprietario rilasciato gratuitamente. 36 Letteralmente “software con codice sorgente aperto” 37 Rispettivamente acronimi per Free and Open Source Software e Free Libre and Open Source Software Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 35/109 CAPITOLO 2 - Il DBMS PostgreSQL un progetto finalizzato a garantire a tutti una maggiore libertà nello sviluppo e nella fruizione del software. Nel 1984 Stallman fondò la Free Software Foundation (FSF), con l'obiettivo di sviluppare un sistema operativo corredato da strumenti di programmazione che permettessero di creare altro software. Per fornire copertura legale al software prodotto la Free Software Foundation, in collaborazione con un pool di legali tra cui l'accademico Eben Moglen, ideò un sistema di licenze che utilizzava il copyright per tutelare sia gli sviluppatori che gli utenti (Casagrande et al., 2012). Nei testi delle licenze pubblicate dalla Free Software Foundation viene sempre riportato un elenco delle “quattro libertà fondamentali” che un software deve garantire ai propri utenti per poter essere considerato free software: ▶ la libertà di essere utilizzato per qualsiasi scopo, in tutte le sue funzionalità (libertà 0); ▶ la libertà di studiarne il funzionamento, e adattarlo alle proprie necessità (libertà 1); affinchè ciò possa avvenire, l'accesso al codice sorgente è un prerequisito necessario; ▶ la libertà di copiarlo, distribuirlo ed installarlo illimitatamente (libertà 2), in modo da aiutare il prossimo; ▶ la libertà di apportare modifiche ai sorgenti e condividere le modifiche (libertà 3), in modo che l'intera comunità possa beneficiarne; affinchè ciò possa avvenire, l'accesso al codice sorgente è un prerequisito necessario. La denominazione Open Source nacque nel 1997, ad opera dell'informatico statunitense Bruce Perens. Nel 1998 Perens ed Eric Raymond fondarono la Open Source Initiative (OSI), organizzazione i cui fini principali erano la promozione e la certificazione del software libero negli ambiti commerciali statunitensi, inizialmente assai diffidenti delle licenze libere e delle idee di Stallman. A partire dal 2007 la diffusione del termine F/OSS ingloba il lavoro e le visioni della FSF e della OSI38 (Casagrande et al., 2012). La licenza BSD39 di PostgreSQL può senz'altro esser considerata una licenza libera, in quanto certificata tale sia dalla OSI che dalla FSF 40. 38 Sebbene, a rigore, le idee di FSF ed OSI non coincidano totalmente dal punto di vista filosofico, politico ed etico, esse risultano quasi sempre compatibili dal punto di vista operativo. 39 Acronimo per Berkeley Software Distribution 40 Sebbene quest'ultima ne sconsigli l'uso –perlomeno nella sua forma non modificata– in quanto non Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 36/109 CAPITOLO 2 - Il DBMS PostgreSQL 2.4.1 Problematiche del software proprietario In generale, nella scelta del software per un'applicazione, è necessario considerare tutte le voci di costo ad essa connesse, avendo cura di estendere l'analisi all'intero ciclo di vita del sistema. Nel caso di soluzioni proprietarie, in particolare, occorre considerare alcuni aspetti problematici connessi al controllo esclusivo dei sorgenti da parte del produttore, tra cui: ▶ vendor lock­in, pratica commerciale che prevede la 'fidelizzazione' dell'utenza principalmente attraverso l'utilizzo di formati proprietati per la codifica dei dati, generando, tra le altre, le seguenti conseguenze: difficoltà (o impossibilità) di migrare ad altre soluzioni, nel frattempo magari divenute più vantaggiose, senza perdita parziale (o totale) dei dati; difficoltà (o impossibilità) di scambiare dati con altri utenti/sistemi41; possibile introduzione in versioni successive degli applicativi di nuovi formati proprietari non retrocompatibili, abbinata al ritiro dal mercato delle precedenti versioni; se a ciò poi si aggiungesse –come a volte avviene– l'impossibilità di salvare i dati nei vecchi formati, l'utente potrebbe trovarsi costretto ad aggiornare contemporaneamente tutte le installazioni dell'applicativo per mantenere l'interoperabilità interna del sistema; ▶ portabilità e scalabilità ridotte. In particolare, la decisione commerciale di rilasciare versioni successive dell'applicativo soltanto per versioni successive del sistema operativo potrebbe costringere l'utente all'acquisto del nuovo sistema operativo – decisione a sua compatibile con la GNU General Public License. 41 Problema noto in ambito informatico come interoperabilità. Si osservi, al riguardo, che scegliere software proprietari che utilizzano formati aperti standardizzati non costituisce di per sé alcuna garanzia; è infatti ormai documentato l'utilizzo consapevole di tecniche EEE (Embrace, Extend and Extinguish) da parte di alcune tra le maggiori software house, con l'obiettivo esplicito di vanificare nella sostanza gli effetti del vincolo, mantenendone però al contempo il rispetto formale. Sulla questione dei formati aperti nei software proprietari sono particolarmente interessanti le considerazioni di Rob Wier, dipendente IBM e ai tempi sviluppatore OpenOffice, circa l'implementazione del formato Open Document Format in Microsoft™ Office®: «it is not particularly difficult or clever to take an adverse reading of a standard to make an incompatible, non­interoperable product. Take HTML, for example. It does not define the attributes of unstyled (default) text. So I could create a perfectly conformant browser implementation that makes all default text be 4­point Zapf Dingbats [tipo di font, N.d.A.], white text on a white background. It would conform with the standard, but it would be perfectly unusable by anyone. If you try hard enough you can create 100% conformant, but non­interoperable, implementations of almost most standards. Standards are voluntary, written to help coordinate multiple parties in their desires for interoperability. Standards are not written to compel interoperability by parties who do not wish to be interoperable.»(fonte: http://www.robweir.com/blog/2009/05/update­on­odf­spreadsheet­interoperability.html ). Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 37/109 CAPITOLO 2 - Il DBMS PostgreSQL volta gravata da conseguenze quali: possibile necessità di acquisto di nuove licenze per gli altri software proprietari eventualmente utilizzati nel sistema; ▶ possibile necessità di requisiti hardware superiori, con relativi esborsi; minore controllo sui sistemi: essendo ignoto il reale funzionamento del software –spesso attivamente occultato mediante divieti espliciti di reverse engineering– risulta impossibile accertarsi che le operazioni svolte non comprendano azioni indesiderate, che possono andare dall'aggiornamento non richiesto alla violazione della privacy degli utenti42; Nel caso in cui il sistema informatico venga realizzato da un soggetto pubblico, poi, vi sono probabilmente anche aspetti di natura socio­economica ed ambientale da considerare, tra cui i seguenti: ▶ la rinuncia ad avvalersi di competenze tecnologico­informatiche locali presenta un costo­opportunità, in termini di mancato sviluppo di professionalità, difficile da stimare ma reale; ▶ le risorse pubbliche investite nell'acquisto di licenze software da multinazionali estere sono risorse sottratte al sistema produttivo locale; ▶ l'innaturale obsolescenza dell'hardware indotta dal software, sempre più avido di requisiti, solleva questioni etiche legate alla dismissione di hardware ancora in perfetta efficienza, nonché problemi ambientali connessi allo smaltimento43. Si può considerare come nel caso del progetto «Geografie dell’Italia Medievale (XIIIXV sec.)» la scelta di un applicativo open source consolidato e molto diffuso come PostgreSQL sia risultata particolarmente appropriata: oltre a soddisfare pienamente le esigenze attuali del progetto, infatti, essa consentirà, nel momento in cui se ne presentasse l'esigenza, di integrare in 42 Particolarmente interessanti, a questo proposito, risultano le notizie pubblicate sui giornali decenni prima dello scandalo PRISM, quali ad esempio http://edition.cnn.com/TECH/computing/9909/03/windows.nsa/. 43 Si consideri, per contro, il caso del kernel open source Linux, adattato nel corso del tempo per operare su classi di dispositivi che vanno dai giocattoli agli elettrodomestici, dagli smartphone ai server di Borsa, dai sistemi domotici agli space shuttle. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 38/109 CAPITOLO 2 - Il DBMS PostgreSQL maniera flessibile e modulare nuove funzionalità e nuovi dati, senza doversi preoccupare dei costi relativi a licenze ed aggiornamenti (Zambrano, 2013). 2.4.2 Normativa italiana sul Software Libero nella Pubblica Amministrazione Nell'ambito di un più generale piano di razionalizzazione delle risorse pubbliche, nel 2012 il Governo Italiano ha modificato il proprio Codice d'Amministrazione Digitale (CAD) 44, imponendo il Software Libero come prima scelta per la Pubblica Amministrazione. La nuova formulazione dell’art. 68 del CAD, entrata in vigore il 12 Agosto 2012, recita: Le pubbliche amministrazioni acquisiscono programmi informatici o parti di essi a seguito di una valutazione comparativa di tipo tecnico ed economico tra le seguenti soluzioni disponibili sul mercato: a) software sviluppato per conto della pubblica amministrazione; b) riutilizzo di software o parti di esso sviluppati per conto della pubblica amministrazione; c) software libero o a codice sorgente aperto; d) software combinazione delle precedenti soluzioni. Solo quando la valutazione comparativa di tipo tecnico ed economico dimostri l’impossibilità di accedere a soluzioni open source o già sviluppate all’interno della pubblica amministrazione a un prezzo inferiore, è consentita l’acquisizione di programmi informatici di tipo proprietario mediante ricorso a licenza d’uso. La valutazione di cui al presente comma è effettuata secondo le modalità e i criteri definiti dall’Agenzia per l’Italia Digitale che, a richiesta di soggetti interessati, esprime altresì parere circa il loro rispetto. La considerazione di questo ulteriore aspetto conferma la lungimiranza della scelta di PostgreSQL in luogo di soluzioni proprietarie. 44 Corpo organico di disposizioni che presiede all'uso dell'informatica come strumento privilegiato nei rapporti tra la Pubblica Amministrazione italiana e i cittadini dello Stato. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 39/109 CAPITOLO 3 - Implementazione dei controlli di consistenza CAPITOLO 3 ­ Implementazione dei controlli di consistenza 3.1 Definizione di “consistenza” Nell'ambito dei database garantire la “consistenza” dell'informazione significa tutelare le proprietà di coerenza, conformità, non contradditorietà, affidabilità dei dati. Questo aspetto della gestione, in generale molto importante, in alcuni contesti applicativi assume una rilevanza paradigmatica: esempi classici in questo senso sono la gestione di un sistema bancario, o di un ospedale. Esistono tuttavia ambiti in cui l'acquisizione stessa dei dati costituisce la principale voce di costo dell'intero sistema informativo, ed anche in questi casi la tutela dell'integrità dei dati risulta cruciale, poiché eventuali perdite di informazione si tradurrebbero immediatamente in ingenti danni economici; di questa categoria fanno parte, tra gli altri, i Sistemi Informativi Territoriali. La qualità dell'informazione presente in un database può essere valutata in funzione di diversi parametri (tra cui l'accuratezza, la consistenza logica e la completezza45), nonché di indicatori improntati alla specificità della base di dati (Migliaccio, 2008). La completezza, intesa come assenza di errori di omissione all'interno della base di dati, può essere di due tipi: ▶ completezza dei dati, rispettata se la base di dati contiene le informazioni relative a tutti gli oggetti definiti nelle specifiche; ▶ completezza del modello, rispettata se le specifiche progettuali della base di dati risultano appropriate rispetto alle esigenze di una particolare applicazione (Migliaccio, 2008). La consistenza, intesa come assenza di errori e contraddizioni nei dati, si articola invece in una serie di requisiti, tra i quali: 45 Formalizzati dallo standard ISO 19113 come parametri di riferimento per la valutazione di qualità dei database. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 40/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ▶ presenza del tipo di dato corretto in tutti i campi di ciascuna tabella; ▶ assenza di valori nulli su attributi che non li prevedono; ▶ rispetto di eventuali relazioni/vincoli matematici o logici fra i dati; ▶ (nel caso di un geodatabase) rispetto di vincoli geometrici e topologici quali, ad esempio: assenza di coincidenza o sovrapposizione tra due o più elementi mutuamente esclusivi; assenza di intersezione tra due primitive linea, se non in corrispondenza di un nodo; confinamento entro un determinato range di valori ammissibili delle coordinate che definiscono elementi geometrici; chiusura delle spezzate poligonali corrispondenti ai perimetri di primitive polygon. Nel caso del progetto «Geografie dell’Italia Medievale (XIII­XV sec.)» tra i principali parametri di riferimento per la valutazione della qualità del geodatabase rientrano l'accuratezza dell'informazione tematica e del posizionamento 46, la consistenza logica e la completezza. L'obiettivo del presente lavoro di tesi è rafforzare la tutela della consistenza dei dati mediante l'implementazione dei seguenti controlli automatici: ▶ ▶ controlli di tipo tematico: vincolo sulle date, descritto nel paragrafo 3.2.1; controllo di ridondanza sulla tabella luogo, descritto nel paragrafo 3.2.2; controllo sulla lunghezza delle stringhe, descritto nel paragrafo 3.2.3; controllo sui refusi tipografici, descritto nel paragrafo 3.2.4; controlli di tipo geografico: vincolo Bounding Box sulle coordinate, descritto nel paragrafo 3.3.1; controllo su toponimi e poligoni nella tabella luogo, descritto nel paragrafo 3.3.2. 46 L'accuratezza del posizionamento risulta espressa mediante il grado di affidabilità descritto nel paragrafo 1.1 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 41/109 CAPITOLO 3 - Implementazione dei controlli di consistenza 3.2 Controlli tematici 3.2.1 Vincolo sulle date Il primo controllo di consistenza è definito sulle date presenti nelle tabelle relazionali ufficiale, luogo, distretto_erariale, unita_fiscale e ufficio. L'obiettivo del controllo è definire un range di ammissibilità della data, rifiutando l'inserimento qualora il vincolo non sia rispettato, e al contempo fornendo all'utente informazioni quanto più possibili circostanziate sul problema verificatosi, in modo da facilitarne la correzione. L'implementazione del controllo ha richiesto l'ampliamento dello schema logico con una tabella relazionale ausiliaria, chiamata variabili_numeriche_integer, nella quale memorizzare in maniera persistente i valori massimo e minimo previsti per l'anno. La tabella ausiliaria per il momento è stata popolata con valori scelti arbitrariamente e, nell'intento di semplificare l'interazione con il sistema ad eventuali utenti non tecnici, sono state create quattro funzioni ausiliarie per consentire la modifica e il recupero dei valori senza bisogno di ricorrere a vere e proprie query SQL. Il codice PL/pgSQL47 relativo viene riportato in Tab. 8. 47 PL/pgSQL è il linguaggio procedurale predefinito di PostgreSQL, integrato di default sulle versioni 9.0+ Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 42/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ Creazione della tabella ausiliaria variabili_numeriche_integer, in cui memorizzare variabili di tipo integer: CREATE TABLE variabili_numeriche_integer ( codice_variabile SERIAL PRIMARY KEY, nome_variabile CHARACTER VARYING(45) UNIQUE, valore_variabile INTEGER ); ­­ Popolamento della tabella variabili_numeriche_integer appena creata con i valori Minimo e Massimo dell'anno: INSERT INTO variabili_numeriche_integer (nome_variabile , valore_variabile) VALUES ( 'AnnoMin' , 1100 ); INSERT INTO variabili_numeriche_integer (nome_variabile , valore_variabile) VALUES ( 'AnnoMax' , 1550 ); ­­ PER CAMBIARE GLI ESTREMI SARÀ NECESSARIO ANDARE A MODIFICARE QUESTI DUE RECORD MEDIANTE LE FUNZIONI cambiaAnnoMin e cambiaAnnoMax ­­ Creazione della funzione ausiliaria cambiaAnnoMin: CREATE OR REPLACE FUNCTION cambiaAnnoMin(nuovoValoreAnno INTEGER) RETURNS INTEGER AS $$ BEGIN UPDATE variabili_numeriche_integer SET valore_variabile=nuovoValoreAnno WHERE nome_variabile='AnnoMin'; RETURN NULL; END; $$ LANGUAGE plpgsql; ­­ Creazione della funzione ausiliaria cambiaAnnoMax: CREATE OR REPLACE FUNCTION cambiaAnnoMax(nuovoValoreAnno INTEGER) RETURNS INTEGER AS $$ BEGIN UPDATE variabili_numeriche_integer SET valore_variabile=nuovoValoreAnno WHERE nome_variabile='AnnoMax'; RETURN NULL; END; $$ LANGUAGE plpgsql; ­­ Creazione della funzione ausiliaria Estrai_valore_anno_Min: CREATE OR REPLACE FUNCTION Estrai_valore_anno_Min ( OUT parametro_di_output INTEGER ) AS $$ DECLARE BEGIN SELECT variabili_numeriche_integer.valore_variabile INTO parametro_di_output FROM variabili_numeriche_integer WHERE variabili_numeriche_integer.nome_variabile = 'AnnoMin'; RETURN; END; $$ LANGUAGE plpgsql; ­­ Creazione della funzione ausiliaria Estrai_valore_anno_Max: CREATE OR REPLACE FUNCTION Estrai_valore_anno_Max ( OUT parametro_di_output INTEGER ) AS $$ DECLARE BEGIN SELECT variabili_numeriche_integer.valore_variabile INTO parametro_di_output Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 43/109 CAPITOLO 3 - Implementazione dei controlli di consistenza FROM variabili_numeriche_integer WHERE variabili_numeriche_integer.nome_variabile = 'AnnoMax'; RETURN; END; $$ LANGUAGE plpgsql; Tab. 8: Creazione delle strutture ausiliarie per il controllo delle date ­ codice PL/pgSQL Definite le strutture ausiliare è stato possibile creare la funzione­ trigger ed i trigger48 veri e propri, riportati in Tab. 9: 48 I trigger sono stati descritti nel paragrafo 2.3.2. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 44/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ CREAZIONE DELLA FUNZIONE­TRIGGER UNIVERSALE ControllaAnno() ­­ ATTENZIONE: LA FUNZIONE­TRIGGER È IN GRADO DI FUNZIONARE “UNIVERSALMENTE” SOLO SE IL RECORD CHE LE VIENE PASSATO PER IL CONTROLLO CONTIENE UN CAMPO CHE SI CHIAMA “ANNO” ­­ IN CASO CONTRARIO FALLISCE. CREATE OR REPLACE FUNCTION ControllaAnno() RETURNS TRIGGER AS $ControllaAnno$ DECLARE ­­ Dichiarazione delle variabili AnnoMinimo INTEGER ; AnnoMassimo INTEGER ; BEGIN ­­ Corpo della Funzione SELECT estrai_valore_anno_min INTO AnnoMinimo FROM (SELECT Estrai_valore_anno_Min()) AS tempTable1; ­­ AnnoMinimo := estrai_valore_anno_min FROM (SELECT Estrai_valore_anno_Min() ) AS tempTable1; ­­ AnnoMinimo := ( SELECT valore_variabile FROM variabili_numeriche_integer WHERE nome_variabile = 'AnnoMin' ); SELECT estrai_valore_anno_max INTO AnnoMassimo FROM (SELECT Estrai_valore_anno_Max()) AS tempTable2; ­­ AnnoMassimo := estrai_valore_anno_max FROM (SELECT Estrai_valore_anno_Max() ) AS tempTable2; ­­ AnnoMassimo := ( SELECT valore_variabile FROM variabili_numeriche_integer WHERE nome_variabile = 'AnnoMax' ); IF NEW.anno < AnnoMinimo then raise exception 'L_inserimento non può essere effettuato: il valore numerico dell''anno (%) è inferiore al limite minimo consentito (%)' , NEW.anno , AnnoMinimo; ELSEIF NEW.anno > AnnoMassimo then raise exception 'L_inserimento non può essere effettuato: il valore numerico dell''anno (%) supera il limite massimo consentito (%)' , NEW.anno , AnnoMassimo; END IF; RETURN NEW; END; $ControllaAnno$ language plpgsql; ­­ CREAZIONE DEL TRIGGER VERO E PROPRIO ­­ ATTENZIONE: SE VIENE CAMBIATO NOME ALL'ATTRIBUTO “ANNO” DELLA TABELLA DIVENTA IMPOSSIBILE UTILIZZARE LA FUNZIONE­TRIGGER UNIVERSALE ControllaAnno(), E DIVENTA NECESSARIO DEFINIRE UNA FUNZIONE­TRIGGER AD HOC CREATE TRIGGER ControllaAnnoUfficiale BEFORE INSERT OR UPDATE ON ufficiale FOR EACH ROW EXECUTE PROCEDURE ControllaAnno( ) ; ­­ CREAZIONE DEL TRIGGER VERO E PROPRIO ­­ ATTENZIONE: SE VIENE CAMBIATO NOME ALL'ATTRIBUTO “ANNO” DELLA TABELLA DIVENTA IMPOSSIBILE UTILIZZARE LA FUNZIONE­TRIGGER UNIVERSALE ControllaAnno(), E DIVENTA NECESSARIO DEFINIRE UNA FUNZIONE­TRIGGER AD HOC CREATE TRIGGER ControllaAnnoLuogo Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 45/109 CAPITOLO 3 - Implementazione dei controlli di consistenza BEFORE INSERT OR UPDATE ON luogo FOR EACH ROW EXECUTE PROCEDURE ControllaAnno( ) ; ­­ CREAZIONE DEL TRIGGER VERO E PROPRIO ­­ ATTENZIONE: SE VIENE CAMBIATO NOME ALL'ATTRIBUTO “ANNO” DELLA TABELLA DIVENTA IMPOSSIBILE UTILIZZARE LA FUNZIONE­TRIGGER UNIVERSALE ControllaAnno(), E DIVENTA NECESSARIO DEFINIRE UNA FUNZIONE­TRIGGER AD HOC CREATE TRIGGER ControllaAnnoDistretto_erariale BEFORE INSERT OR UPDATE ON distretto_erariale FOR EACH ROW EXECUTE PROCEDURE ControllaAnno( ) ; ­­ CREAZIONE DEL TRIGGER VERO E PROPRIO ­­ ATTENZIONE: SE VIENE CAMBIATO NOME ALL'ATTRIBUTO “ANNO” DELLA TABELLA DIVENTA IMPOSSIBILE UTILIZZARE LA FUNZIONE­TRIGGER UNIVERSALE ControllaAnno(), E DIVENTA NECESSARIO DEFINIRE UNA FUNZIONE­TRIGGER AD HOC CREATE TRIGGER ControllaAnnoUnita_fiscale BEFORE INSERT OR UPDATE ON unita_fiscale FOR EACH ROW EXECUTE PROCEDURE ControllaAnno( ) ; ­­ CREAZIONE DEL TRIGGER VERO E PROPRIO ­­ ATTENZIONE: SE VIENE CAMBIATO NOME ALL'ATTRIBUTO “ANNO” DELLA TABELLA DIVENTA IMPOSSIBILE UTILIZZARE LA FUNZIONE­TRIGGER UNIVERSALE ControllaAnno(), E DIVENTA NECESSARIO DEFINIRE UNA FUNZIONE­TRIGGER AD HOC CREATE TRIGGER ControllaAnnoUfficio BEFORE INSERT OR UPDATE ON ufficio FOR EACH ROW EXECUTE PROCEDURE ControllaAnno( ) ; Tab. 9: Creazione della funzione­ trigger e dei trigger per il controllo delle date ­ codice PL/pgSQL Infine, il controllo di consistenza è stato validato; l'esito positivo della validazione nel caso di inserimento nella tabella distretto_erariale viene riportato in Tab. 10. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 46/109 CAPITOLO 3 - Implementazione dei controlli di consistenza SELECT Estrai_valore_anno_Min() ­­RISULTATO: '1250' ­­ primo tentativo di forzare il trigger: INSERT INTO distretto_erariale (id_distretto_erariale , Anno , sede_erario ) VALUES ( 77778 , 1050 , 'nomeSede' ); ­­RISULTATO: ­­ ERRORE: L_inserimento non può essere effettuato: il valore numerico dell'anno (1050) è inferiore al limite minimo consentito (1250) ­­ secondo tentativo di forzare il trigger: INSERT INTO distretto_erariale (id_distretto_erariale , Anno , sede_erario ) VALUES ( 77779 , 1950 , 'nomeSede' ); ­­RISULTATO: ­­ ERRORE: L_inserimento non può essere effettuato: il valore numerico dell'anno (1950) supera il limite massimo consentito (1550) Tab. 10: Validazione del controllo di consistenza sulla data ­ codice PL/pgSQL 3.2.2 Prevenzione della ridondanza nella tabella Luogo Data la sua importanza e complessità, una particolare attenzione è stata riservata alla tabella relazionale luogo, la cui struttura (riportata integralmente in Tab. 4) è composta dai diciannove campi id_luogo, id_luogo_attuale, id_fonte, id_distretto_erariale, toponimo_lat, toponimo_ita, comune_attuale, provincia, est_x, nord_y, grado_affidabilita, anno, mese, giorno, tipo_anno, indizione, fuochi_fiscali, fuochi_paganti, geom. Le possibili cause generatrici di inconsistenza, nel caso di una tabella di questa complessità, risultano essere molteplici; alcune di queste, relative agli aspetti geografici, verranno trattate nei paragrafi 3.3.1 e 3.3.2. La problematica affrontata nel presente paragrafo è la ridondanza che si può generare nel momento in cui nuovi record vengono inseriti nella tabella. Il vincolo di chiave primaria, definito sul campo id_luogo, tecnicamente è sufficiente ad impedire la compresenza di due record identici nella tabella relazionale. Si consideri però il caso di inserimento in tabella di un nuovo record, identico in tutto ad un record già presente nella tabella tranne che per il valore id_luogo; l'indesiderabilità di questa situazione risulta Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 47/109 CAPITOLO 3 - Implementazione dei controlli di consistenza evidente, poiché si tratterebbe di una duplicazione dei dati 49. Il solo vincolo di chiave primaria, tuttavia, non è in grado impedire l'inserimento. Si consideri ora un secondo caso, in cui il nuovo record, invece di essere diverso soltanto rispetto al campo id_luogo, lo sia anche rispetto al campo giorno; considerata la specificità dei dati, la probabilità che il valore del campo giorno sia dovuto ad un errore tipografico sarebbe forte, e il rischio di un nuovo duplicato elevato. In questo caso, come nel precedente, sarebbe opportuno decidere se consentire l'inserimento, impedirlo, o quantomeno segnalare all'utente la possibile anomalia. Teoricamente per contrastare la ridondanza sarebbe necessario considerare tutte le possibili combinazioni di valori identici sui vari campi, identificare quelle critiche, e per ciascuna di esse predisporre una strategia di risposta. Il problema è che, a parte il campo id_luogo, la tabella luogo presenta ben diciotto campi: volendo considerare per ogni nuovo inserimento il confronto tra ciascun campo ed il corrispondente nei record presenti in memoria, e volendo assegnare a ciascuno dei 18 confronti il valore 1 in caso di identità ed il valore 0 in caso di differenza, le combinazioni possibili sarebbero 218=262144, ciascuna da analizzare singolarmente per verificarne il livello di rischio. Qualora poi oltre a vero (1) e falso (0) si volesse considerare anche un terzo possibile valore di verità, unknown, risultante da un confronto con (almeno uno dei) due attributi nulli, le possibili combinazioni salirebbero a 318=387420489. Dal momento che l'approccio esaustivo non risulta percorribile, la strategia implementata prevede di identificare i campi significativi ai fini del rischio ridondanza, ed ove possibile aggregare gli attributi affini in “supercampi” (chiamati bunch). In questo modo sono stati identificati sei supercampi, di cui tre (id_fonte, grado_affidabilita, id_distretto_erariale) composti da un unico attributo e tre (bunchCoordinate, bunchToponimi, bunchTempo) effettivamente compositi: ▶ id_fonte 49 E quindi di ridondanza, una delle principali cause di potenziale inconsistenza (Atzeni et al., 1999). Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 48/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ▶ grado_affidabilita ▶ id_distretto_erariale ▶ bunchCoordinate ▶ bunchToponimi: ▶ est_x & nord_y toponimo_ita & toponimo_lat bunchTempo: anno & mese & giorno & tipo_anno & indizione La fase successiva è consistita nell'analizzare le combinazioni di confronti sui supercampi potenzialmente a rischio ridondanza, e per ciascuna di essere predisporre una strategia di risposta; una rappresentazione grafica dell'analisi è riportata nelle Figure 3.1 e 3.2. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 49/109 CAPITOLO 3 - Implementazione dei controlli di consistenza (Est ,Nord) grado_afdabilita bunchTempo bunchToponimi id_distretto_erariale 1 1 1 1 1 1 Impedire inserimento: record già presente all'interno del DB 1 1 1 1 1 0 Warning: esiste record che differisce soltanto per il campo Distretto_Erariale 1 1 1 1 0 1 Warning: esiste record che differisce soltanto per il campo bunchToponimi 1 1 1 1 0 0 Warning: esiste record che differisce soltanto per il campo bunchToponimi e Distretto_erariale 1 1 1 0 1 1 Warning: esiste record che differisce soltanto per il campo bunchTempo 1 1 1 0 1 0 NoAction 1 1 1 0 0 1 NoAction 1 1 1 0 0 0 NoAction AZIONE id_fonte 1 := campi IDENTICI (← potenziale conflitto) 0 := campi DIVERSI 1 1 0 1 1 1 Warning: esiste record che differisce soltanto per il campo grado_affidabilita 1 1 0 1 1 0 Warning: esiste record che differisce soltanto per grado_affidabilita e distretto_erariale 1 1 0 1 0 1 NoAction (?) 1 1 0 1 0 0 NoAction 1 1 0 0 1 1 NoAction 1 1 0 0 1 0 NoAction 1 1 0 0 0 1 NoAction 1 1 0 0 0 0 1 0 1 1 1 1 NoAction Warning: esiste record che differisce soltanto per le coordinate (Est,Nord) 1 0 1 1 1 0 NoAction 1 0 1 1 0 1 NoAction 1 0 1 1 0 0 NoAction 1 0 1 0 1 1 NoAction 1 0 1 0 1 0 NoAction 1 0 1 0 0 1 NoAction 1 0 1 0 0 0 NoAction 1 0 0 1 1 1 NoAction 1 0 0 1 1 0 NoAction 1 0 0 1 0 1 NoAction 1 0 0 1 0 0 NoAction 1 0 0 0 1 1 NoAction 1 0 0 0 1 0 NoAction 1 0 0 0 0 1 NoAction 1 0 0 0 0 0 NoAction Figura 3.1: Identificazione delle combinazioni di confronti sui supercampi potenzialmente in grado di generare ridondanza, e corrispondenti azioni (pt 1/2) Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 50/109 id_fonte (Est ,Nord) grado_afdabilita bunchTempo bunchToponimi id_distretto_erarial e AZIONE CAPITOLO 3 - Implementazione dei controlli di consistenza 0 1 1 1 1 1 Warning: esiste record che differisce soltanto per id_fonte 0 1 1 1 1 0 NoAction 0 1 1 1 0 1 NoAction 0 1 1 1 0 0 NoAction 0 1 1 0 1 1 NoAction 0 1 1 0 1 0 NoAction 0 1 1 0 0 1 NoAction 0 1 1 0 0 0 NoAction 0 1 0 1 1 1 NoAction 0 1 0 1 1 0 NoAction 0 1 0 1 0 1 NoAction 0 1 0 1 0 0 NoAction 0 1 0 0 1 1 NoAction 0 1 0 0 1 0 NoAction 0 1 0 0 0 1 NoAction 0 1 0 0 0 0 NoAction 0 0 1 1 1 1 NoAction 0 0 1 1 1 0 NoAction 0 0 1 1 0 1 NoAction 0 0 1 1 0 0 NoAction 0 0 1 0 1 1 NoAction 0 0 1 0 1 0 NoAction 0 0 1 0 0 1 NoAction 0 0 1 0 0 0 NoAction 0 0 0 1 1 1 NoAction 0 0 0 1 1 0 NoAction 0 0 0 1 0 1 NoAction 0 0 0 1 0 0 NoAction 0 0 0 0 1 1 NoAction 0 0 0 0 1 0 NoAction 0 0 0 0 0 1 NoAction 0 0 0 0 0 0 NoAction Figura 3.2: Identificazione delle combinazioni di confronti sui supercampi potenzialmente in grado di generare ridondanza, e corrispondenti azioni (pt 2/2). Come si può osservare in Figura 3.2, l'esito negativo del confronto sul campo id_fonte è stato considerato sempre sufficiente a disinnescare il trigger, tranne qualora id_fonte stesso costituisca l'unica differenza rispetto ad un record già presente nella tabella. L'analisi prodotta è quindi stata convertita in codice PL/pgSQL, sotto forma della funzione­trigger e del trigger riportati in Tab. 11: Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 51/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ TEMPLATE DEL WARNING /* ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ ELSEIF 0 < count FROM ( SELECT count (*) FROM luogo WHERE ( id_fonte=NEW.id_fonte ) AND ( est_x=NEW.est_x AND nord_y=NEW.nord_y) ­­bunchCoordinate AND ( grado_affidabilita=NEW.grado_affidabilita) AND ( anno=NEW.anno AND mese=NEW.mese AND giorno=NEW.giorno AND tipo_anno=NEW.tipo_anno AND indizione=NEW.indizione ) ­­bunchTempo AND ( toponimo_ita=NEW.toponimo_ita AND toponimo_lat=NEW.toponimo_lat ) ­­bunchToponimi AND ( id_distretto_erariale=NEW.id_distretto_erariale ) ) AS myTable1 THEN RAISE NOTICE 'XXX'; */ ­­CREAZIONE DELLA FUNZIONE­TRIGGER CREATE OR REPLACE FUNCTION integritaLuogo() RETURNS TRIGGER AS $integritaLuogo$ ­­ DECLARE ­­ la funzione non prevede variabili BEGIN ­­ Corpo della funzione IF 0 < count FROM ( SELECT count (*) FROM luogo WHERE ( id_fonte=NEW.id_fonte ) AND ( est_x=NEW.est_x AND nord_y=NEW.nord_y) ­­bunchCoordinate AND ( grado_affidabilita=NEW.grado_affidabilita) AND ( anno=NEW.anno AND mese=NEW.mese AND giorno=NEW.giorno AND tipo_anno=NEW.tipo_anno AND indizione=NEW.indizione ) ­­bunchTempo AND ( toponimo_ita=NEW.toponimo_ita AND toponimo_lat=NEW.toponimo_lat ) ­­bunchToponimi AND ( id_distretto_erariale=NEW.id_distretto_erariale ) ) AS myTable1 THEN RAISE EXCEPTION 'Inserimento non consentito. Motivazione: nella tabella Luogo esiste già almeno un record con valori identici sui campi "id_fonte" , "bunchCoordinate" , "grado_affidabilità" , "bunchTempo" , "bunchToponimi" , "distretto_erariale"'; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ ELSEIF 0 < count FROM ( SELECT count (*) FROM luogo WHERE ( id_fonte=NEW.id_fonte ) AND ( est_x=NEW.est_x AND nord_y=NEW.nord_y) ­­bunchCoordinate AND ( grado_affidabilita=NEW.grado_affidabilita) AND ( anno=NEW.anno AND mese=NEW.mese AND giorno=NEW.giorno AND Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 52/109 CAPITOLO 3 - Implementazione dei controlli di consistenza tipo_anno=NEW.tipo_anno AND indizione=NEW.indizione ) ­­bunchTempo AND ( toponimo_ita=NEW.toponimo_ita AND toponimo_lat=NEW.toponimo_lat ) ) AS myTable1 ­­bunchToponimi ­­AND ­­( id_distretto_erariale=NEW.id_distretto_erariale ) THEN RAISE NOTICE 'WARNING: nella tabella Luogo esiste già almeno un record con valori identici sui campi "id_fonte" , "bunchCoordinate" , "grado_affidabilità" , "bunchTempo" , "bunchToponimi"'; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ ELSEIF 0 < count FROM ( SELECT count (*) FROM luogo WHERE ( id_fonte=NEW.id_fonte ) AND ( est_x=NEW.est_x AND nord_y=NEW.nord_y) ­­bunchCoordinate AND ( grado_affidabilita=NEW.grado_affidabilita) AND ( anno=NEW.anno AND mese=NEW.mese AND giorno=NEW.giorno AND tipo_anno=NEW.tipo_anno AND indizione=NEW.indizione ) ­­bunchTempo ­­AND ­­( toponimo_ita=NEW.toponimo_ita AND toponimo_lat=NEW.toponimo_lat ) ­­bunchToponimi AND ( id_distretto_erariale=NEW.id_distretto_erariale ) ) AS myTable1 THEN RAISE NOTICE 'WARNING: nella tabella Luogo esiste già almeno un record con valori identici sui campi "id_fonte" , "bunchCoordinate" , "grado_affidabilità" , "bunchTempo" , "distretto_erariale"'; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ ELSEIF 0 < count FROM ( SELECT count (*) FROM luogo WHERE ( id_fonte=NEW.id_fonte ) AND ( est_x=NEW.est_x AND nord_y=NEW.nord_y) ­­bunchCoordinate AND ( grado_affidabilita=NEW.grado_affidabilita) AND ( anno=NEW.anno AND mese=NEW.mese AND giorno=NEW.giorno AND tipo_anno=NEW.tipo_anno AND indizione=NEW.indizione ) ) AS myTable1 ­­bunchTempo ­­AND ­­( toponimo_ita=NEW.toponimo_ita AND toponimo_lat=NEW.toponimo_lat ) ­­bunchToponimi ­­AND ­­( id_distretto_erariale=NEW.id_distretto_erariale ) THEN RAISE NOTICE 'WARNING: nella tabella Luogo esiste già almeno un record con valori identici sui campi "id_fonte" , "bunchCoordinate" , "grado_affidabilità" , "bunchTempo"'; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ ELSEIF 0 < count FROM ( SELECT count (*) FROM luogo WHERE ( id_fonte=NEW.id_fonte ) AND ( est_x=NEW.est_x AND nord_y=NEW.nord_y) ­­bunchCoordinate AND ( grado_affidabilita=NEW.grado_affidabilita) ­­AND ­­( anno=NEW.anno AND mese=NEW.mese AND giorno=NEW.giorno AND tipo_anno=NEW.tipo_anno AND indizione=NEW.indizione ) ­­bunchTempo AND ( toponimo_ita=NEW.toponimo_ita AND toponimo_lat=NEW.toponimo_lat ) ­­bunchToponimi Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 53/109 CAPITOLO 3 - Implementazione dei controlli di consistenza AND ( id_distretto_erariale=NEW.id_distretto_erariale ) ) AS myTable1 THEN RAISE NOTICE 'WARNING: nella tabella Luogo esiste già almeno un record con valori identici sui campi "id_fonte" , "bunchCoordinate" , "grado_affidabilità" , "bunchToponimi" , "distretto_erariale"'; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ ELSEIF 0 < count FROM ( SELECT count (*) FROM luogo WHERE ( id_fonte=NEW.id_fonte ) AND ( est_x=NEW.est_x AND nord_y=NEW.nord_y) ­­bunchCoordinate ­­AND ­­( grado_affidabilita=NEW.grado_affidabilita) AND ( anno=NEW.anno AND mese=NEW.mese AND giorno=NEW.giorno AND tipo_anno=NEW.tipo_anno AND indizione=NEW.indizione ) ­­bunchTempo AND ( toponimo_ita=NEW.toponimo_ita AND toponimo_lat=NEW.toponimo_lat ) ­­bunchToponimi AND ( id_distretto_erariale=NEW.id_distretto_erariale ) ) AS myTable1 THEN RAISE NOTICE 'WARNING: nella tabella Luogo esiste già almeno un record con valori identici sui campi "id_fonte" , "bunchCoordinate" , "bunchTempo" , "bunchToponimi" , "distretto_erariale"'; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ ELSEIF 0 < count FROM ( SELECT count (*) FROM luogo WHERE ( id_fonte=NEW.id_fonte ) ­­AND ­­( est_x=NEW.est_x AND nord_y=NEW.nord_y) ­­bunchCoordinate AND ( grado_affidabilita=NEW.grado_affidabilita) AND ( anno=NEW.anno AND mese=NEW.mese AND giorno=NEW.giorno AND tipo_anno=NEW.tipo_anno AND indizione=NEW.indizione ) ­­bunchTempo AND ( toponimo_ita=NEW.toponimo_ita AND toponimo_lat=NEW.toponimo_lat ) ­­bunchToponimi AND ( id_distretto_erariale=NEW.id_distretto_erariale ) ) AS myTable1 THEN RAISE NOTICE 'WARNING: nella tabella Luogo esiste già almeno un record con valori identici sui campi "id_fonte" , "grado_affidabilità" , "bunchTempo" , "bunchToponimi" , "distretto_erariale"'; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ ELSEIF 0 < count FROM ( SELECT count (*) FROM luogo WHERE ( id_fonte=NEW.id_fonte ) AND ( est_x=NEW.est_x AND nord_y=NEW.nord_y) ­­bunchCoordinate ­­AND ­­( grado_affidabilita=NEW.grado_affidabilita) AND ( anno=NEW.anno AND mese=NEW.mese AND giorno=NEW.giorno AND tipo_anno=NEW.tipo_anno AND indizione=NEW.indizione ) ­­bunchTempo AND ( toponimo_ita=NEW.toponimo_ita AND toponimo_lat=NEW.toponimo_lat ) ) AS myTable1 ­­bunchToponimi ­­AND ­­( id_distretto_erariale=NEW.id_distretto_erariale ) THEN RAISE NOTICE 'WARNING: nella tabella Luogo esiste già almeno un record con valori Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 54/109 CAPITOLO 3 - Implementazione dei controlli di consistenza identici sui campi "id_fonte" , "bunchCoordinate" , "bunchTempo" , "bunchToponimi"'; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ ELSEIF 0 < count FROM ( SELECT count (*) FROM luogo WHERE ­­( id_fonte=NEW.id_fonte ) ­­AND ( est_x=NEW.est_x AND nord_y=NEW.nord_y) ­­bunchCoordinate AND ( grado_affidabilita=NEW.grado_affidabilita) AND ( anno=NEW.anno AND mese=NEW.mese AND giorno=NEW.giorno AND tipo_anno=NEW.tipo_anno AND indizione=NEW.indizione ) ­­bunchTempo AND ( toponimo_ita=NEW.toponimo_ita AND toponimo_lat=NEW.toponimo_lat ) ­­bunchToponimi AND ( id_distretto_erariale=NEW.id_distretto_erariale ) ) AS myTable1 THEN RAISE NOTICE 'WARNING: nella tabella Luogo esiste già almeno un record con valori identici sui campi "bunchCoordinate" , "grado_affidabilità" , "bunchTempo" , "bunchToponimi" , "distretto_erariale"'; END IF; RETURN NEW; END; $integritaLuogo$ language plpgsql; ­­CREAZIONE DEL TRIGGER VERO E PROPRIO CREATE TRIGGER integritaLuogo BEFORE INSERT OR UPDATE ON luogo FOR EACH ROW EXECUTE PROCEDURE integritaLuogo( ); ­­ IL TRIGGER NON PASSA ARGOMENTI ALLA CORRISPONDENTE FUNZIONE­TRIGGER Tab. 11: Funzione­ trigger e trigger identificati per prevenire la ridondanza nella tabella Luogo ­ codice PL/pgSQL Infine, il controllo di consistenza è stato validato; l'esito positivo della validazione viene riportato in Tab. 12. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 55/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ primo tentativo di forzare il trigger: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0005' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alessano' , 'Alessano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1458 , 1 , 6 , 91 , 91 , '0101000020797F0000068195433AF327419A99999114DD5041' ); ­­RISULTATO: ­­ Query returned successfully: one row with OID 44629 inserted, 162 ms execution time. ­­ L'INSERIMENTO VIENE ESEGUITO POICHÉ IL PROGRAMMA NON SA COME TRATTARE I VALORI NULLI SUI CAMPI “MESE” E “GIORNO”. ­­ secondo tentativo di forzare il trigger, aggiungendo rispetto al primo caso dei VALORI INVENTATI AD HOC nei campi “MESE” e “GIORNO”: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , mese , giorno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0000' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alessano' , 'Alessano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1458 , 2 , 4 , 1 , 6 , 91 , 91 , '0101000020797F0000068195433AF327419A99999114DD5041' ); ­­RISULTATO: ­­ Query returned successfully: one row with OID 39264 inserted, 127 ms execution time. ­­ L'INSERIMENTO VIENE ESEGUITO. ­­ terzo tentativo di forzare il trigger, riproponendo su tutti i campi gli stessi identici valori del primo caso: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , mese , giorno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0003' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alessano' , 'Alessano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1458 , 2 , 4 , 1 , 6 , 91 , 91 , '0101000020797F0000068195433AF327419A99999114DD5041' ); ­­RISULTATO: ­­ ERRORE: Inserimento non consentito. Motivazione: nella tabella Luogo esiste già almeno un record con valori identici sui campi "id_fonte" , "bunchCoordinate" , "grado_affidabilità" , "bunchTempo" , "bunchToponimi" , "distretto_erariale" ­­ L'INSERIMENTO VIENE CORRETTAMENTE RIFIUTATO. ­­ quarto di forzare il trigger, modificando il campo “ANNO” rispetto al secondo tentativo: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , mese , giorno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0071' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alessano' , 'Alessano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1448 , 2 , 4 , 1 , 6 , 91 , 91 , '0101000020797F0000068195433AF327419A99999114DD5041' ); ­­RISULTATO: ­­ NOTIFICA: WARNING: nella tabella Luogo esiste già almeno un record con valori identici sui campi "id_fonte" , "bunchCoordinate" , "grado_affidabilità" , "bunchToponimi" , "distretto_erariale" Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 56/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ Query returned successfully: one row with OID 39264 inserted, 127 ms execution time. ­­ IL WARNING VIENE SOLLEVATO, MA L'INSERIMENTO VIENE EFFETTUATO. ­­ quinto tentativo di forzare il trigger, modificando il campo “TOPONIMO_ITA” rispetto al secondo tentativo: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , mese , giorno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0076' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alesssano' , 'Alessano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1458 , 2 , 4 , 1 , 6 , 91 , 91 , '0101000020797F0000068195433AF327419A99999114DD5041' ); ­­RISULTATO: ­­ NOTIFICA: WARNING: nella tabella Luogo esiste già almeno un record con valori identici sui campi "id_fonte" , "bunchCoordinate" , "grado_affidabilità" , "bunchTempo" , "distretto_erariale" ­­ Query returned successfully: one row with OID 39268 inserted, 109 ms execution time. ­­ L'INSERIMENTO VIENE EFFETTUATO, MA IL WARNING VIENE SOLLEVATO. ­­ sesto tentativo di forzare il trigger, modificando il campo “ID_FONTE” rispetto al secondo tentativo: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , mese , giorno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0003' , 10040 , 'F1010010248100210' , 21458 , 'Alexanum' , 'Alessano' , 'Alessano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1458 , 2 , 4 , 1 , 6 , 91 , 91 , '0101000020797F0000068195433AF327419A99999114DD5041' ); ­­RISULTATO: ­­ NOTIFICA: WARNING: nella tabella Luogo esiste già almeno un record con valori identici sui campi "bunchCoordinate" , "grado_affidabilità" , "bunchTempo" , "bunchToponimi" , "distretto_erariale" ­­ Query returned successfully: one row with OID 39272 inserted, 98 ms execution time. ­­ L'INSERIMENTO VIENE EFFETTUATO, MA IL WARNING VIENE SOLLEVATO. ­­ settimo tentativo di forzare il trigger, modificando i campi “GIORNO” e “TOPONIMO_LAT” rispetto al secondo tentativo: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , mese , giorno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0078' , 10040 , 'F1010010248104211' , 21458 , 'Alesanum' , 'Alessano' , 'Alessano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1458 , 2 , 5 , 1 , 6 , 91 , 91 , '0101000020797F0000068195433AF327419A99999114DD5041' ); ­­RISULTATO: ­­ Query returned successfully: one row with OID 39273 inserted, 109 ms execution time. ­­ L'INSERIMENTO VIENE EFFETTUATO E NESSUN WARNING VIENE SOLLEVATO, COM'ERA DA ASPETTARSI TRATTANDOSI DI COMBINAZIONE CHE NON DÀ LUOGO AD ALCUNA AZIONE. Tab. 12: Validazione del controllo di ridondanza sulla tabella Luogo ­ codice PL/pgSQL Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 57/109 CAPITOLO 3 - Implementazione dei controlli di consistenza 3.2.3 Verifica della lunghezza delle stringhe In vista della futura ristrutturazione della base di dati, che prevederà l'introduzione di campi testuali per l'inserimento di informazioni aggiuntive in alcune tabelle relazionali 50, è stato previsto un controllo sulla lunghezza delle stringhe. Una lunghezza eccessiva, infatti, potrebbe suggerire l'opportunità di ripartire l'informazione nelle strutture già presenti nella base di dati, favorendo in questo modo la completezza e la consistenza della base di dati. Per memorizzare la lunghezza massima della stringa –ossia il numero di caratteri oltre il quale attivare la notifica– è possibile utilizzare nuovamente la tabella relazionale ausiliaria variabili_numeriche_integer, creata in precedenza per implementare il controllo sulle date (v. paragrafo 3.2.1). L'operazione di popolamento della tabella con il nuovo parametro (il cui valore iniziale è stato fissato arbitrariamente), viene riportata in Tab. 13, unitamente alle funzioni ausiliare che in qualsiasi momento permettono di estrarre e modificare il parametro stesso. 50 Comunicazione personale. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 58/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ Popolamento della tabella variabili_numeriche_integer con il valore della Lunghezzaassimo della stringa superato il quale scatta il WARNING INSERT INTO variabili_numeriche_integer (nome_variabile , valore_variabile) VALUES ( 'Max_Str_Length' , 30 ); ­­ PER MODIFICARE IL VALORE DEL RECORD BISOGNA UTILIZZARE LA FUNZIONE cambiaLunghezzaMassimaStringa ­­ Creazione della funzione ausiliaria cambiaLunghezzaMassimaStringa CREATE OR REPLACE FUNCTION cambiaLunghezzaMassimaStringa(nuovaLunghezzaMax INTEGER) RETURNS VOID AS $$ BEGIN UPDATE variabili_numeriche_integer SET valore_variabile=nuovaLunghezzaMax WHERE nome_variabile='Max_Str_Length'; END; $$ LANGUAGE plpgsql; ­­ Creazione della funzione ausiliaria Estrai_Lunghezza_Massima_Stringa CREATE OR REPLACE FUNCTION Estrai_Lunghezza_Massima_Stringa ( OUT parametro_di_output INTEGER ) AS $$ DECLARE BEGIN SELECT variabili_numeriche_integer.valore_variabile INTO parametro_di_output FROM variabili_numeriche_integer WHERE variabili_numeriche_integer.nome_variabile = 'Max_Str_Length'; RETURN; END; $$ LANGUAGE plpgsql; Tab. 13: Creazione delle strutture ausiliarie per il controllo della lunghezza delle stringhe ­ codice PL/pgSQL Non essendo al momento presenti nel database tabelle con campi di tipo text, il trigger è stato implementato e testato su una tabella creata ad hoc (v. Tab. 14); l'eventuale futuro adattamento a reali esigenze applicative non dovrebbe costituire un problema. ­­ CREAZIONE TABELLA DI PROVA farlockTable, su cui sperimentale il controllo sulla lunghezza del campo: CREATE TABLE farlockTable ( campo_id SERIAL PRIMARY KEY, campoTesto TEXT ); Tab. 14: Creazione di una tabella fittizia per testare il controllo sulla lunghezza delle stringhe ­ codice PL/pgSQL Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 59/109 CAPITOLO 3 - Implementazione dei controlli di consistenza Il controllo sulla lunghezza delle stringhe si limita ad avvertire l'utente qualora la stringa superi la lunghezza prestabilita, suggerendogli al contempo di ripartire –se possibile– l'informazione testuale nelle tabelle relazionali disponibili. La traduzione in codice PL/pgSQL di quanto appena detto viene presentata in Tab. 15. ­­ CREAZIONE DELLA FUNZIONE­TRIGGER checkStrLength CREATE OR REPLACE FUNCTION checkStrLength() RETURNS TRIGGER AS $checkStrLength$ DECLARE ­­ Dichiarazione delle variabili max_lunghezza_stringa INTEGER := ( SELECT valore_variabile FROM variabili_numeriche_integer WHERE nome_variabile='Max_Str_Length' ); BEGIN ­­ Corpo della Funzione if ( char_length( NEW.campoTesto ) > max_lunghezza_stringa ) then raise notice 'Lunghezza della stringa «%» superiore a % caratteri: potrebbe essere opportuno ripartire l''informazione in altri campi' , NEW.campoTesto , max_lunghezza_stringa ; end if; RETURN NEW; end; $checkStrLength$ language plpgsql; ­­ CREAZIONE DEL TRIGGER checkStrLength VERO E PROPRIO CREATE TRIGGER checkStrLength BEFORE INSERT OR UPDATE ON farlockTable FOR EACH ROW EXECUTE PROCEDURE checkStrLength( ) ; Tab. 15: Funzione­ trigger e Trigger relativi al controllo sulla lunghezza delle stringhe ­ codice PL/pgSQL La validazione del codice, avvenuta con esito positivo, viene riportata in Tab. 16. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 60/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ primo tentativo di forzare il trigger: INSERT INTO farlockTable ( campoTesto ) VALUES ( 'Testo di prova.' ); ­­RISULTATO: ­­ Query returned successfully: 1 row affected, 55 ms execution time. ­­ NON VIENE SOLLEVATA ALCUNA NOTIFICA, POICHÉ LA LUNGHEZZA DELLA STRINGA RISULTA INFERIORE AL LIMITE MASSIMO CONSENTITO ­­ secondo tentativo di forzare il trigger: INSERT INTO farlockTable ( campoTesto ) VALUES ( 'Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova.' ); ­­RISULTATO: ­­ NOTIFICA: Lunghezza della stringa «Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova. Testo di prova.» superiore a 30 caratteri: potrebbe essere opportuno ripartire l'informazione in altri campi Query returned successfully: 1 row affected, 25 ms execution time. ­­ IL WARNING VIENE SOLLEVATO, MA L'INSERIMENTO VIENE COMUNQUE CONSENTITO. Tab. 16: Validazione del controllo sulla lunghezza delle stringhe ­ codice PL/pgSQL 3.2.4 Prevenzione di refusi tipografici nella tabella “ufficiale” Un ulteriore accorgimento in vista della futura ristrutturazione dello schema della base di dati prevede una modifica strutturale della tabella ufficiale (riportata integralmente nelle Tab. 2 e 17), in maniera tale da rendere più flessibile e allo stesso tempo più robusta la gestione delle cariche attribuite ad un ufficiale. La soluzione progettuale attuale prevede di utilizzare un campo di tipo boolean per ciascuna delle otto possibili cariche (baiulo, capitano, vicario, tesoriere_rif, tesoriere, castellano, esattore_affida, doganiere); la soluzione proposta prevede invece di sfruttare la natura object­relational di PostgreSQL per creare un tipo­di­dato “tipoCarica” di tipo enum, e sostituire gli otto campi booleani con un unico campo di tipo “array di tipoCarica”. Il confrontro fra le due soluzioni viene presentato in Tab. 17. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 61/109 CAPITOLO 3 - Implementazione dei controlli di consistenza SCHEMA ATTUALE MODIFICA PROPOSTA – CREAZIONE DEL TIPO­ DI­DATO “tipoCarica” di tipo enum: CREATE TYPE tipoCarica AS ENUM ('baiulo', 'capitano','vicario','tesoriere_rif','tesorie re','castellano','esattore_affida','doganiere '); CREATE TABLE ufficiale ( id_ufficiale integer NOT NULL, id_personaggio integer, id_fonte character varying(20), id_distretto_erariale integer, id_unita_fiscale integer, id_ufficio integer, anno integer, nome_funz_lat character varying(75), nome_funz_ita character varying(75), nome_da_fonte character varying(75), soci boolean, erario_generale boolean, erario_locale boolean, baiulo boolean , capitano boolean , vicario boolean , tesoriere_rif boolean , tesoriere boolean , castellano boolean , esattore_affida boolean , doganiere boolean , num_doganieri integer, CONSTRAINT ufficiale_pk PRIMARY KEY (id_ufficiale ), CONSTRAINT distretto_erariale_ufficiale_fk FOREIGN KEY (id_distretto_erariale) REFERENCES distretto_erariale (id_distretto_erariale) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT fonte_ufficiale_fk FOREIGN KEY (id_fonte) REFERENCES fonte (id_fonte) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT personaggio_ufficiale_fk FOREIGN KEY (id_personaggio) REFERENCES personaggio (id_personaggio) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT relationship20 FOREIGN KEY (id_ufficio) REFERENCES ufficio (id_ufficio) MATCH SIMPLE CREATE TABLE ufficialeMODIFICATA ( id_ufficiale integer NOT NULL, id_personaggio integer NOT NULL, id_fonte character varying(20) NOT NULL, id_distretto_erariale integer NOT NULL, id_unita_fiscale integer NOT NULL, id_ufficio integer NOT NULL, anno integer, nome_funz_lat character varying(75), nome_funz_ita character varying(75), nome_da_fonte character varying(75), soci boolean, erario_generale boolean, erario_locale boolean, caric a tipoCarica[ ], ­­ utilizzo del tipo user­defined tipoCarica in campo di tipo ARRAY conta_cariche integer DEFAULT 1, ­­ contatore di cariche del personaggio. Il valore di default pari a 1 è dovuto al fatto che è OBBLIGATORIO per un personaggio avere ALMENO UNA carica. num_doganieri integer, CONSTRAINT ufficialeMODIFICATA_pk PRIMARY KEY (id_ufficiale ), CONSTRAINT distretto_erariale_ufficialeMODIFICATA_fk FOREIGN KEY (id_distretto_erariale) REFERENCES distretto_erariale (id_distretto_erariale) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT fonte_ufficialeMODIFICATA_fk FOREIGN KEY (id_fonte) REFERENCES fonte (id_fonte) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT personaggio_ufficialeMODIFICATA_fk FOREIGN KEY (id_personaggio) REFERENCES personaggio (id_personaggio) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT relationship20 FOREIGN KEY (id_ufficio) Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 62/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT unita_fiscale_ufficiale_fk FOREIGN KEY (id_unita_fiscale) REFERENCES unita_fiscale (id_unita_fiscale) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION ) WITH ( OIDS=TRUE ); ALTER TABLE ufficiale OWNER TO postgres; REFERENCES ufficio (id_ufficio) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT unita_fiscale_ufficialeMODIFICATA_fk FOREIGN KEY (id_unita_fiscale) REFERENCES unita_fiscale (id_unita_fiscale) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION ) WITH ( OIDS=TRUE ); ALTER TABLE ufficialeMODIFICATA OWNER TO postgres; ­­ VALIDAZIONE: risposta dell'interprete all'inserimento del precedente codice: NOTIFICA: CREATE TABLE / PRIMARY KEY creerà un indice implicito "ufficialemodificata_pk" per la tabella "ufficialemodificata" Query returned successfully with no result in 194 ms. Tab. 17: Modifica proposta allo schema della tabella ufficiale ­ codice PL/pgSQL La modifica proposta consentirebbe, oltre ad una gestione più flessibile delle cariche, anche un'efficace tutela della consistenza: il fatto stesso che tipoCarica sia di tipo enum, infatti, è sufficiente a garantire che eventuali errori tipografici sul campo carica vengano sistematicamente identificati come tali, ed impediti. Si consideri che ciò non avverrebbe se tipoCarica fosse basato, ad esempio, su tipi di dato testuali come char o varchar. 3.3 Controlli geografici 3.3.1 Controllo Bounding Box In maniera strutturalmente analoga al controllo sulle date illustrato nel paragrafo 3.2.1, è possibile implementare un controllo sui campi est_x e nord_y delle tabelle relazionali luogo, luogo_attuale, unita_fiscale e ufficio: in questo caso l'inserimento di un record viene consentito soltanto a condizione che le coordinate (Est,Nord) appartengano ad un certo range Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 63/109 CAPITOLO 3 - Implementazione dei controlli di consistenza di ammissibilità; in caso contrario l'inserimento viene rifiutato, avvertendo l'utente del problema occorso. L'implementazione del controllo Bounding Box ha richiesto l'ampliamento dello schema logico con una tabella relazionale ausiliaria, chiamata variabili_numeriche_double, nella quale memorizzare in maniera persistente i valori massimo e minimo di entrambe le coordinate planimetriche. La tabella è stata popolata con valori scelti arbitrariamente e, nel tentativo di semplificare l'interazione con il sistema agli utenti non tecnici, sono state create otto funzioni ausiliarie per permettere operazioni di modifica e di recupero dei valori senza bisogno di ricorrere a query. Il codice PL/pgSQL relativo a queste operazioni viene riportato in Tab. 18. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 64/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ CREAZIONE TABELLA variabili_numeriche_double: CREATE TABLE variabili_numeriche_double ( codice_variabile SERIAL PRIMARY KEY, nome_variabile CHARACTER VARYING(45) UNIQUE, valore_variabile DOUBLE PRECISION ); ­­ POPOLAMENTO della TABELLA variabili_numeriche_double: INSERT INTO variabili_numeriche_double (nome_variabile , valore_variabile) VALUES ( 'CoordEstMin' , 0.0 ); INSERT INTO variabili_numeriche_double (nome_variabile , valore_variabile) VALUES ( 'CoordEstMax' , 1000000.0 ); INSERT INTO variabili_numeriche_double (nome_variabile , valore_variabile) VALUES ( 'CoordNordMin' , 4000000.0 ); INSERT INTO variabili_numeriche_double (nome_variabile , valore_variabile) VALUES ( 'CoordNordMax' , 5280000.0 ); ­­ PER CAMBIARE GLI ESTREMI SARÀ NECESSARIO ANDARE A MODIFICARE QUESTI DUE RECORD MEDIANTE LE FUNZIONI cambiaCoordEstMin , cambiaCoordEstMax , cambiaCoordNordMin , cambiaCoordNordMax CREATE OR REPLACE FUNCTION cambiaCoordEstMin(nuovoValoreEstMin DOUBLE PRECISION) RETURNS VOID AS $$ BEGIN UPDATE variabili_numeriche_double SET valore_variabile=nuovoValoreEstMin WHERE nome_variabile='CoordEstMin'; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION cambiaCoordEstMax(nuovoValoreEstMax DOUBLE PRECISION) RETURNS VOID AS $$ BEGIN UPDATE variabili_numeriche_double SET valore_variabile=nuovoValoreEstMax WHERE nome_variabile='CoordEstMax'; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION cambiaCoordNordMin(nuovoValoreNordMin DOUBLE PRECISION) RETURNS VOID AS $$ BEGIN UPDATE variabili_numeriche_double SET valore_variabile=nuovoValoreNordMin WHERE nome_variabile='CoordNordMin'; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION cambiaCoordNordMax(nuovoValoreNordMax DOUBLE PRECISION) RETURNS VOID AS $$ BEGIN UPDATE variabili_numeriche_double SET valore_variabile=nuovoValoreNordMax WHERE nome_variabile='CoordNordMax'; END; $$ LANGUAGE plpgsql; Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 65/109 CAPITOLO 3 - Implementazione dei controlli di consistenza CREATE OR REPLACE FUNCTION Estrai_Coord_Est_Min ( OUT parametro_di_output DOUBLE PRECISION ) AS $$ DECLARE BEGIN SELECT variabili_numeriche_double.valore_variabile INTO parametro_di_output FROM variabili_numeriche_double WHERE variabili_numeriche_double.nome_variabile = 'CoordEstMin'; RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION Estrai_Coord_Est_Max ( OUT parametro_di_output DOUBLE PRECISION ) AS $$ DECLARE BEGIN SELECT variabili_numeriche_double.valore_variabile INTO parametro_di_output FROM variabili_numeriche_double WHERE variabili_numeriche_double.nome_variabile = 'CoordEstMax'; RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION Estrai_Coord_Nord_Min ( OUT parametro_di_output DOUBLE PRECISION ) AS $$ DECLARE BEGIN SELECT variabili_numeriche_double.valore_variabile INTO parametro_di_output FROM variabili_numeriche_double WHERE variabili_numeriche_double.nome_variabile = 'CoordNordMin'; RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION Estrai_Coord_Nord_Max ( OUT parametro_di_output DOUBLE PRECISION ) AS $$ DECLARE BEGIN SELECT variabili_numeriche_double.valore_variabile INTO parametro_di_output FROM variabili_numeriche_double WHERE variabili_numeriche_double.nome_variabile = 'CoordNordMax'; RETURN; END; $$ LANGUAGE plpgsql; Tab. 18: Creazione delle strutture ausiliarie per il controllo Bounding Box delle coordinate ­ codice PL/pgSQL Definite le strutture ausiliare è stato possibile creare la funzione­ trigger ed i trigger veri e propri, riportati in Tab. 19. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 66/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ CREAZIONE DELLA FUNZIONE­TRIGGER UNIVERSALE ControllaBoundingBox() ­­ ATTENZIONE: LA FUNZIONE­TRIGGER È IN GRADO DI FUNZIONARE “UNIVERSALMENTE” (CIOÈ PER TUTTI I TRIGGER ControllaBoundingBox) SOLO SE IL RECORD CHE LE VIENE PASSATO PER IL CONTROLLO CONTIENE CAMPI DI NOME “est_x” e “nord_y” ­­ IN CASO CONTRARIO FALLISCE. CREATE OR REPLACE FUNCTION ControllaBoundingBox() RETURNS TRIGGER AS $ControllaBoundingBox$ DECLARE ­­ Dichiarazione delle variabili Est_min DOUBLE PRECISION; Est_max DOUBLE PRECISION; Nord_min DOUBLE PRECISION; Nord_max DOUBLE PRECISION; contatore INTEGER := 0; BEGIN ­­ Corpo della Funzione SELECT Estrai_Coord_Est_Min INTO Est_min FROM (SELECT Estrai_Coord_Est_Min()) AS tempTable1; SELECT Estrai_Coord_Est_Max INTO Est_max FROM (SELECT Estrai_Coord_Est_Max()) AS tempTable2; SELECT Estrai_Coord_Nord_Min INTO Nord_min FROM (SELECT Estrai_Coord_Nord_Min()) AS tempTable3; SELECT Estrai_Coord_Nord_Max INTO Nord_max FROM (SELECT Estrai_Coord_Nord_Max()) AS tempTable4; if (new.est_x < Est_min) then raise notice 'Inconsistenza dei valori numerici: coordinata Est (%) inferiore al valore minimo consentito (%)' , new.est_x , Est_min; contatore = contatore+1; end if; if (new.est_x > Est_max) then raise notice 'Inconsistenza dei valori numerici: coordinata Est (%) superiore al valore massimo consentito (%)' , new.est_x , Est_max; contatore = contatore+1; end if; if (new.nord_y < Nord_min) then raise notice 'Inconsistenza dei valori numerici: coordinata Nord (%) inferiore al valore minimo consentito (%)' , new.nord_y , Nord_min; contatore = contatore+1; end if; if (new.nord_y > Nord_max) then raise notice 'Inconsistenza dei valori numerici: coordinata Nord (%) superiore al valore massimo consentito (%)' , new.nord_y , Nord_max; contatore = contatore+1; end if; if (contatore > 0) then raise exception 'Inserimento rifiutato. Motivazione: un numero di coordinate pari a % risulta esterno al bounding box' , contatore ; end if; RETURN NEW; end; $ControllaBoundingBox$ language plpgsql; ­­ CREAZIONE DEL TRIGGER VERO E PROPRIO ­­ ATTENZIONE: SE VENGONO CAMBIATI I NOMI DEGLI ATTRIBUTI “est_x” e “nord_y” DELLA TABELLA DIVENTA IMPOSSIBILE UTILIZZARE LA FUNZIONE­TRIGGER UNIVERSALE ControllaBoundingBox() CREATE TRIGGER ControllaBoundingBoxLuogo Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 67/109 CAPITOLO 3 - Implementazione dei controlli di consistenza BEFORE INSERT OR UPDATE ON luogo FOR EACH ROW EXECUTE PROCEDURE ControllaBoundingBox( ) ; ­­ CREAZIONE DEL TRIGGER VERO E PROPRIO ­­ ATTENZIONE: SE VENGONO CAMBIATI I NOMI DEGLI ATTRIBUTI “est_x” e “nord_y” DELLA TABELLA DIVENTA IMPOSSIBILE UTILIZZARE LA FUNZIONE­TRIGGER UNIVERSALE ControllaBoundingBox() CREATE TRIGGER ControllaBoundingBoxLuogo_Attuale BEFORE INSERT OR UPDATE ON luogo_attuale FOR EACH ROW EXECUTE PROCEDURE ControllaBoundingBox( ) ; ­­ CREAZIONE DEL TRIGGER VERO E PROPRIO ­­ ATTENZIONE: SE VENGONO CAMBIATI I NOMI DEGLI ATTRIBUTI “est_x” e “nord_y” DELLA TABELLA DIVENTA IMPOSSIBILE UTILIZZARE LA FUNZIONE­TRIGGER UNIVERSALE ControllaBoundingBox() CREATE TRIGGER ControllaBoundingBoxUnita_Fiscale BEFORE INSERT OR UPDATE ON unita_fiscale FOR EACH ROW EXECUTE PROCEDURE ControllaBoundingBox( ) ; ­­ CREAZIONE DEL TRIGGER VERO E PROPRIO ­­ ATTENZIONE: SE VENGONO CAMBIATI I NOMI DEGLI ATTRIBUTI “est_x” e “nord_y” DELLA TABELLA DIVENTA IMPOSSIBILE UTILIZZARE LA FUNZIONE­TRIGGER UNIVERSALE ControllaBoundingBox() CREATE TRIGGER ControllaBoundingBoxUfficio BEFORE INSERT OR UPDATE ON ufficio FOR EACH ROW EXECUTE PROCEDURE ControllaBoundingBox( ) ; ­­ VERIFICHE: SELECT Estrai_Coord_Est_Min(); ­­RISULTATO: '0' SELECT Estrai_Coord_Est_Max(); ­­RISULTATO: '1000000' SELECT Estrai_Coord_Nord_Max(); ­­RISULTATO: '5280000' Tab. 19: Funzione­ trigger e trigger per il controllo Bounding Box delle coordinate ­ codice PL/pgSQL Infine, il controllo di consistenza è stato validato; l'esito positivo della validazione viene riportato in Tab. 20. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 68/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ primo tentativo di forzare il trigger: INSERT INTO luogo ( id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 11550 , 'F1010010248105110' , 21458 , 'Sflechum' , 'Secli''' , 'Seclì' , 'LE' , ­764624.739 , 4447043.323 , 3 , 1458 , 1 , 6 , 25 , 25 , '0101000020797F00003F355E7AA15527413108ACD4D0F65041' ); ­­RISULTATO: ­­ NOTIFICA: Inconsistenza dei valori numerici: coordinata Est (­764624.739) inferiore al valore minimo consentito (0) ­­ ERRORE: Inserimento rifiutato: un numero di coordinate pari a 1 risulta esterno al bounding box ­­ secondo tentativo di forzare il trigger: INSERT INTO luogo ( id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 11550 , 'F1010010248105110' , 21458 , 'Sflechum' , 'Secli''' , 'Seclì' , 'LE' , 999764624.739 , 5280000.323 , 3 , 1458 , 1 , 6 , 25 , 25 , '0101000020797F00003F355E7AA15527413108ACD4D0F65041' ); ­­RISULTATO: ­­ NOTIFICA: Inconsistenza dei valori numerici: coordinata Est (999764624.739) superiore al valore massimo consentito (1000000) ­­ NOTIFICA: Inconsistenza dei valori numerici: coordinata Nord (5280000.323) superiore al valore massimo consentito (5280000) ­­ ERRORE: Inserimento rifiutato. Motivazione: un numero di coordinate pari a 2 risulta esterno al bounding box ­­ terzo tentativo di forzare il trigger: INSERT INTO luogo ( id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 11550 , 'F1010010248105110' , 21458 , 'Sflechum' , 'Secli''' , 'Seclì' , 'LE' , 764624.739 , 3447043.323 , 3 , 1458 , 1 , 6 , 25 , 25 , '0101000020797F00003F355E7AA15527413108ACD4D0F65041' ); ­­RISULTATO: ­­ NOTIFICA: Inconsistenza dei valori numerici: coordinata Nord (3447043.323) inferiore al valore minimo consentito (4000000) ­­ ERRORE: Inserimento rifiutato. Motivazione: un numero di coordinate pari a 1 risulta esterno al bounding box ­­ quarto tentativo di forzare il trigger: INSERT INTO luogo ( id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 11550 , 'F1010010248105110' , 21458 , 'Sflechum' , 'Secli''' , 'Seclì' , 'LE' , 999764624.739 , 7775280000.323 , 3 , 1458 , 1 , 6 , 25 , 25 , '0101000020797F00003F355E7AA15527413108ACD4D0F65041' ); Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 69/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­RISULTATO: ­­ NOTIFICA: Inconsistenza dei valori numerici: coordinata Est (999764624.739) superiore al valore massimo consentito (1000000) ­­ NOTIFICA: Inconsistenza dei valori numerici: coordinata Nord (7775280000.323) superiore al valore massimo consentito (5280000) ­­ ERRORE: Inserimento rifiutato. Motivazione: un numero di coordinate pari a 2 risulta esterno al bounding box ­­ quinto tentativo di forzare il trigger, utilizzando valori numerici delle coordinate Est e Nord leggermente diversi da quelli reali: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti ) VALUES ( 'Farlock0062' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alessano' , 'Alessano' , 'LE' , 784797.136 , 4420690.272 , 3 , 1458 , 1 , 6 , 91 , 91 ); ­­RISULTATO: ­­ Query returned successfully: one row with OID 39258 inserted, 70 ms execution time. ­­ L'INSERIMENTO VIENE ESEGUITO. Tab. 20: Validazione del controllo di consistenza Bounding Box ­ codice PL/pgSQL Il controllo Bounding Box può risultare utile per effettuare una verifica grossolana della georeferenziazione; qualora si disponga della necessaria informazione geografica, tuttavia, diventa possibile implementare un controllo affine al Bounding Box, ma estremamente più raffinato rispetto ad esso: tale controllo viene illustrato nel paragrafo 3.3.2. 3.3.2 Controllo su toponimi e poligoni nella tabella Luogo Un controllo di consistenza geografico assai più significativo rispetto al Bounding Box51 è costituito dal point­ in­polygon. L'implementazione di tale controllo, qui proposta per la tabella luogo52, prevede di verificare che le coordinate (Est,Nord) del nuovo record da inserire risultino effettivamente interne ai poligoni dei territorî comunale e provinciale indicati nei campi comune_attuale e provincia del record stesso. La realizzazione del controllo point­ in­polygon così definito ha richiesto una serie di operazioni preliminari, tra cui: 51 Illustrato nel paragrafo 3.3.1 52 Il cui schema logico è illustrato in Tab. 4, a pagina 18. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 70/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ▶ reperimento presso il sito ufficiale Istat53 degli shapefile54 di province e comuni (i confini amministrativi, aggiornati al 1° gennaio 2011, vengono rilasciati da Istat nel sistema di riferimento ED_1950_UTM Zona 32); ▶ importazione dei due shapefile in QGIS: conversione del sistema di riferimento in WGS84/UTM Fuso33 zoneN, codice EPSG 32633, al fine di uniformarsi ai dati geografici presenti nel database; ▶ eliminazione delle colonne non necessarie; esportazione in due nuovi shapefile; importazione in PostgreSQL degli shapefile modificati, mediante il comando da bash: /usr/bin/shp2pgsql ­s 32633 ­W "latin1" /path/to/file/shapefile.shp public.NomeTabella | psql ­h localhost ­d postgres ­U postgres; Tab. 21: Comando da terminale per importare gli shapefile nel database Lo schema logico viene così ulteriormente55 ampliato con l'introduzione di due tabelle relazionali, istat_shapefile ed istat_shapefile_province, contenenti rispettivamente l'informazione geografica relativa ai territorî comunali e provinciali italiani. La struttura delle tabelle è riportata in Tab. 22. 53 H ttp://www.istat.it/it/archivio/24613 54 Formato sviluppato e regolato da ESRI, diventato ormai standard de facto per i dati vettoriali spaziali. 55 Ulteriormente rispetto alle estensioni dello schema logico già descritte nei paragrafi 3.2.1 e 3.3.1 . Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 71/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ Table: istat_shapefile ­­ DROP TABLE istat_shapefile; CREATE TABLE istat_shapefile ( gid serial NOT NULL, cod_region integer, cod_provin integer, pro_com integer, toponimo character varying(58), geom geometry, CONSTRAINT istat_shapefile_pkey PRIMARY KEY (gid ), CONSTRAINT enforce_dims_geom CHECK (st_ndims(geom) = 2), CONSTRAINT enforce_geotype_geom CHECK (geometrytype(geom) = 'MULTIPOLYGON'::text OR geom IS NULL), CONSTRAINT enforce_srid_geom CHECK (st_srid(geom) = 32633) ) WITH ( OIDS=FALSE ); ALTER TABLE istat_shapefile OWNER TO postgres; ­­ Table: istat_shapefile_province ­­ DROP TABLE istat_shapefile_province; CREATE TABLE istat_shapefile_province ( gid serial NOT NULL, cod_region integer, cod_provin integer, toponmprov character varying(50), ­­ toponimo della provincia automprov character varying(2), ­­ sigla automobilistica della provincia geom geometry, CONSTRAINT istat_shapefile_province_pkey PRIMARY KEY (gid ), CONSTRAINT enforce_dims_geom CHECK (st_ndims(geom) = 2), CONSTRAINT enforce_geotype_geom CHECK (geometrytype(geom) = 'MULTIPOLYGON'::text OR geom IS NULL), CONSTRAINT enforce_srid_geom CHECK (st_srid(geom) = 32633) ) WITH ( OIDS=FALSE ); ALTER TABLE istat_shapefile_province OWNER TO postgres; Tab. 22: Schema logico delle tabelle relazionali istat_shapefile ed istat_shapefile_province ­ codice PL/pgSQL Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 72/109 CAPITOLO 3 - Implementazione dei controlli di consistenza Svolte le operazioni preliminari è stato possibile passare al controllo di consistenza vero e proprio. La logica implementativa del controllo prevede che, all'inserimento di un record nella tabella luogo, vengano automaticamente verificate le seguenti condizioni: ▶ il toponimo comunale deve appartenere alla lista ufficiale Istat dei nomi dei comuni, contenuta nella tabella istat_shapefile; ▶ le coordinate (Est,Nord) del nuovo record devono essere coerenti con il codice dichiarato nel campo geom; ▶ le coordinate (Est,Nord) devono effettivamente appartenere: al territorio del comune dichiarato nel campo comune_attuale del record; al territorio della provincia dichiarata nel campo provincia del record. Qualora anche soltanto una condizione non risulti verificata, l'inserimento viene rifiutato, avendo cura di fornire all'utente informazioni circostanziate sul problema occorso. La parte di codice relativa al controllo su toponimi e poligoni nella tabella Luogo è riportata in Tab. 23. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 73/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ CREAZIONE DELLA FUNZIONE­TRIGGER controllaGeolocalizzazioneLuogo() CREATE OR REPLACE FUNCTION controllaGeolocalizzazioneLuogo() RETURNS TRIGGER AS $controllaGeolocalizzazioneLuogo$ DECLARE ­­ La funzione­trigger non prevede variabili BEGIN ­­ CONTROLLO SULLA PRESENZA DEL TOPONIMO (campo “comune_attuale”) ALL'INTERNO DEL DATABASE UFFICIALE ISTAT (AGGIORNATO ALL'ANNO 2011) if new.comune_attuale not in (select toponimo from istat_shapefile) then raise exception 'L_inserimento non può essere effettuato: il toponimo comunale inserito ("%") non risulta presente all''interno del database Istat' , new.comune_attuale ; end if; ­­ CONTROLLO SULLA COERENZA TRA I VALORI (est_x,nord_y) ED IL VALORE INSERITO NEL CAMPO Geom IF ( ( ST_SetSRID(ST_MakePoint(NEW.est_x, NEW.nord_y), 32633) <­> NEW.geom ) > 0 ) THEN RAISE EXCEPTION 'Inserimento non consentito. Motivazione: le coordinate (Est,Nord) (%, %) risultano non coerenti con il valore presente nel campo "Geom" (%). Ricontrollare coordinate o Geom.' , NEW.est_x , NEW.nord_y , NEW.geom ; END IF; ­­ PROVINCIA: CONTROLLO SUI CAMPI (Est,Nord) IF 0 < count FROM ( SELECT count (*) FROM istat_shapefile WHERE gid IN ( SELECT shape1.gid FROM istat_shapefile_province AS shape1 WHERE ( ST_CONTAINS( shape1.geom , ST_SetSRID(ST_MakePoint(NEW.est_x, NEW.nord_y), 32633) ) AND shape1.automprov<>NEW.provincia ) ) ) AS myTable1 THEN RAISE EXCEPTION 'Inserimento non consentito. Motivazione: le coordinate (Est,Nord) (%, %) risultano esterne alla provincia di %. Ricontrollare coordinate o provincia.' , NEW.est_x , NEW.nord_y , NEW.provincia ; END IF; ­­ PROVINCIA: CONTROLLO SUL CAMPO Geom IF 0 < count FROM ( SELECT count (*) FROM istat_shapefile WHERE gid IN ( SELECT shape1.gid FROM istat_shapefile_province AS shape1 WHERE ( ST_CONTAINS( shape1.geom , NEW.geom ) AND shape1.automprov<>NEW.provincia ) ) ) AS myTable1 THEN RAISE EXCEPTION 'Inserimento non consentito. Motivazione: il campo "geom" (%) fa riferimento a coordinate esterne alla provincia di %. Ricontrollare coordinate o provincia.' , NEW.geom , NEW.provincia ; END IF; ­­ COMUNE: CONTROLLO SUI CAMPI (Est,Nord) IF 0 < count FROM ( SELECT count (*) FROM istat_shapefile WHERE gid IN ( SELECT shape2.gid FROM istat_shapefile AS shape2 WHERE ( ST_CONTAINS( shape2.geom , ST_SetSRID(ST_MakePoint(NEW.est_x, NEW.nord_y), 32633) ) AND shape2.toponimo<>NEW.comune_attuale ) ) ) AS myTable1 THEN RAISE EXCEPTION 'Inserimento non consentito. Motivazione: le coordinate (Est,Nord) (%, %) risultano esterne al comune di %. Ricontrollare coordinate o comune.' , NEW.est_x , NEW.nord_y , NEW.comune_attuale ; END IF; Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 74/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ COMUNE: CONTROLLO SUL CAMPO Geom IF 0 < count FROM ( SELECT count (*) FROM istat_shapefile WHERE gid IN ( SELECT shape2.gid FROM istat_shapefile AS shape2 WHERE ( ST_CONTAINS( shape2.geom , NEW.geom ) AND shape2.toponimo<>NEW.comune_attuale ) ) ) AS myTable1 THEN RAISE EXCEPTION 'Inserimento non consentito. Motivazione: il campo "geom" (%) fa riferimento a coordinate esterne al comune di %. Ricontrollare coordinate o comune.' , NEW.geom , NEW.comune_attuale ; END IF; RETURN NEW; END; $controllaGeolocalizzazioneLuogo$ language plpgsql; ­­ CREAZIONE DEL TRIGGER VERO E PROPRIO CREATE TRIGGER controllaGeolocalizzazioneLuogo BEFORE INSERT OR UPDATE ON luogo FOR EACH ROW EXECUTE PROCEDURE controllaGeolocalizzazioneLuogo( ) ; Tab. 23: Funzione­ trigger e trigger del controllo su toponimi e poligoni ­ codice PL/pgSQL Infine, il controllo di consistenza è stato validato; l'esito positivo della validazione viene riportato in Tab. 24. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 75/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ primo tentativo di forzare il trigger: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0050' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alessano' , 'Alessano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1458 , 1 , 6 , 91 , 91 , '0101000020797F0000068195433AF327419A99999114DD5041' ); ­­RISULTATO: ­­ Query returned successfully: one row with OID 39139 inserted, 100 ms execution time. ­­ L'INSERIMENTO VIENE ESEGUITO, POICHÈ IL RECORD CONTIENE VALORI CORRETTI ­­ secondo tentativo di forzare il trigger. Rispetto al primo tentativo, si deforma appositamente il TOPONIMO COMUNALE: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0051' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alessano' , 'Alesssano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1458 , 1 , 6 , 91 , 91 , '0101000020797F0000068195433AF327419A99999114DD5041' ); ­­RISULTATO: ­­ ERRORE: L_inserimento non può essere effettuato: il toponimo comunale inserito ("Alesssano") non risulta presente all'interno del database Istat ­­ L'INSERIMENTO VIENE CORRETTAMENTE IMPEDITO ­­ terzo tentativo di forzare il trigger: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0052' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alessano' , 'Alessano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1458 , 1 , 6 , 91 , 91 , '0101000020797F0000068195433AF327419A99999114DD5041' ); ­­RISULTATO: ­­ Query returned successfully: one row with OID 39123 inserted, 100 ms execution time. ­­ LA QUERY VIENE ESEGUITA, POICHÈ IL RECORD CONTIENE VALORI CORRETTI ­­ quarto tentativo di forzare il trigger modificando rispetto al TERZO CASO il campo GEOM con i valori contenuti nei campi omologhi di un record con stessa provincia ma diverso comune, e mantenendo identici i valori numerici delle coordinate (Est,Nord): INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0053' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alessano' , 'Alessano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1458 , 1 , 6 , 91 , 91 , '0101000020797F000014AE4721426327413D0AD7BBBAE15041' ); ­­RISULTATO: ­­ ERRORE: Inserimento non consentito. Motivazione: le coordinate (Est,Nord) (784797.132,4420690.275) risultano non coerenti con il valore presente nel campo "Geom" (0101000020797F000014AE4721426327413D0AD7BBBAE15041). Ricontrollare coordinate o Geom. ­­ L'INSERIMENTO VIENE CORRETTAMENTE IMPEDITO Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 76/109 CAPITOLO 3 - Implementazione dei controlli di consistenza ­­ quinto tentativo di forzare il trigger, modificando rispetto al TERZO CASO le coordinate ed il campo GEOM con i valori contenuti nei campi omologhi di un record con stessa provincia, ma diverso comune: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0054' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alessano' , 'Alessano' , 'LE' , 766369.065 , 4425450.935 , 3 , 1458 , 1 , 6 , 91 , 91 , '0101000020797F000014AE4721426327413D0AD7BBBAE15041' ); ­­RISULTATO: ­­ ERRORE: Inserimento non consentito. Motivazione: le coordinate (Est,Nord) (766369.065,4425450.935) risultano esterne al comune di Alessano. Ricontrollare coordinate o comune. ­­ sesto tentativo di forzare il trigger, utilizzando uno dei record anomali presenti nel database identificati nel corso del controllo delle province: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , geom ) VALUES ( 'Farlock0055' , 10150 , 'F1010010248114611' , 'Vigiliee' , 'Bisceglie' , 'Bisceglie' , 'BA' , 625851.108 , 4566848.078 , 3 , 1460 , 1 , 8 , '0101000020797F0000A8C64B3776192341B6F3FD04D06B5141' ); ­­RISULTATO: ­­ ERRORE: Inserimento non consentito. Motivazione: le coordinate (Est,Nord) (625851.108,4566848.078) risultano esterne alla provincia di BA. Ricontrollare coordinate o provincia. ­­ settimo tentativo di forzare il trigger, utilizzando uno dei record anomali presenti nel database identificati nel corso del controllo delle province: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , geom ) VALUES ( 'Farlock0056' , 11600 , 'F1010010248119811' , 'Spinacziola' , 'Spinazzola' , 'Spinazzola' , 'BA' , 591638.24 , 4535887.662 , 3 , 1451 , 1 , 14 , '0101000020797F0000AE47E17A2C0E22413F355EEA934D5141' ); ­­RISULTATO: ­­ ERRORE: Inserimento non consentito. Motivazione: le coordinate (Est,Nord) (591638.24,4535887.662) risultano esterne alla provincia di BA. Ricontrollare coordinate o provincia. ­­ ottavo tentativo di forzare il trigger, modificando rispetto al TERZO CASO il campo GEOM: INSERT INTO luogo ( id_luogo , id_luogo_attuale , id_fonte , id_distretto_erariale , toponimo_lat , toponimo_ita , comune_attuale , provincia , est_x , nord_y , grado_affidabilita , anno , tipo_anno , indizione , fuochi_fiscali , fuochi_paganti , geom ) VALUES ( 'Farlock0059' , 10040 , 'F1010010248104211' , 21458 , 'Alexanum' , 'Alessano' , 'Alessano' , 'LE' , 784797.132 , 4420690.275 , 3 , 1458 , 1 , 6 , 91 , 91 , '0101000020797F0000AE47E17A2C0E22413F355EEA934D5141' ); ­­RISULTATO: ­­ ERRORE: Inserimento non consentito. Motivazione: le coordinate (Est,Nord) (784797.132,4420690.275) risultano non coerenti con il valore presente nel campo "Geom" (0101000020797F0000AE47E17A2C0E22413F355EEA934D5141). Ricontrollare coordinate o Geom. Tab. 24: Validazione del controllo su toponimi e poligoni ­ codice PL/pgSQL Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 77/109 CAPITOLO 3 - Implementazione dei controlli di consistenza Nel corso dell'implementazione del controllo su toponimi e poligoni è stato possibile sottoporre a verifica anche i dati già presenti nella tabella luogo; gli esiti di tali verifiche vengono riportati nel paragrafo 3.3.2.1 per la parte relativa ai comuni, e nel paragrafo 3.3.2.2 per la parte relativa alle province. 3.3.2.1 Verifica sui Comuni La prima operazione volta a verificare la consistenza dei dati già presenti nel database è consistita nell'estrarre l'id_luogo di ciascun record della tabella luogo le cui coordinate (Est,Nord) risultano interne al poligono comunale Istat con toponimo identico al campo comune_attuale del record, ovverosia nell'estrazione di tutti i punti correttamente localizzati rispetto al comune: SELECT luogo.id_luogo FROM luogo join istat_shapefile AS istat on luogo.comune_attuale=istat.toponimo WHERE ST_Contains( istat.geom , luogo.geom ) l'interrogazione restituisce un totale di 538 risultati, su un numero totale di record della tabella luogo pari a 590. Ciò significa che nella tabella luogo esistono 52 record che presentano delle anomalie. Mediante la seguente query la lista di tali record anomali viene estratta e memorizzata nel file Punti_anomali_tabella_Luogo.csv: Copy ( SELECT luogo.id_luogo FROM luogo WHERE luogo.id_luogo NOT IN ( SELECT luogo.id_luogo FROM luogo join istat_shapefile AS istat on luogo.comune_attuale=istat.toponimo WHERE ST_Contains( istat.geom , luogo.geom ) ) ) To '/path/to/file/Punti_anomali_tabella_Luogo.csv' With CSV; Mediante il seguente comando bash il risultato della query che estrare Id e Geom dei punti anomali viene esportato in formato shapefile56. 56 Si osservi come, nonostante la richiesta di estrarre anche i 6 record con campo Geom NULLO (da considerarsi anch'essi anomali), vengano esportati in formato shapefile soltanto 46 record: data la natura del formato Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 78/109 CAPITOLO 3 - Implementazione dei controlli di consistenza pgsql2shp ­f /path/to/file/Layer_punti_anomali.shp ­h localhost ­u postgres ­P password postgres "SELECT luogo.id_luogo AS Id_pt_anom , luogo.comune_attuale AS Toponimo , luogo.geom FROM luogo WHERE luogo.id_luogo NOT IN ( SELECT luogo.id_luogo FROM luogo join istat_shapefile AS istat on luogo.comune_attuale=istat.toponimo WHERE ST_Contains( istat.geom , luogo.geom ) ) OR ( luogo.geom IS NULL )" L'esportazione dei punti anomali in formato shapefile ne ha consentito l'importazione in QGIS, e quindi la visualizzazione (v. Figura 3.3). shapefile, tale comportamento è da considerarsi corretto. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 79/109 CAPITOLO 3 - Implementazione dei controlli di consistenza L'osservazione in maggior dettaglio (v. Figure 3.4, 3.5, 3.6, 3.7, 3.8) dei casi anomali mappabili suggerisce diverse possibili cause d'inconsistenza dei dati, approssimativamente riconducibili alle seguenti categorie: ▶ ▶ ▶ errori di natura tipografica: Secli' invece di Seclì Nardo' invece di Nardò toponimi incompleti/non aggiornati: Corigliano invece di Corigliano d'Otranto Carpignano invece di Carpignano Salentino Faggiano invece di Fasano errori verosimilmente legati all'accuratezza del posizionamento, soprattutto nelle aree di confine tra due o più comuni: ▶ Cellino San Marco invece di Campi Salentina errori dovuti a cause non immediatamente definibili: San Pietro in Lama invece di Santa Cesarea Terme Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 80/109 CAPITOLO 3 - Implementazione dei controlli di consistenza Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 81/109 CAPITOLO 3 - Implementazione dei controlli di consistenza Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 82/109 CAPITOLO 3 - Implementazione dei controlli di consistenza Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 83/109 CAPITOLO 3 - Implementazione dei controlli di consistenza Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 84/109 CAPITOLO 3 - Implementazione dei controlli di consistenza Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 85/109 CAPITOLO 3 - Implementazione dei controlli di consistenza 3.3.2.2 Verifica sulle Province Analogamente a quanto visto nel paragrafo 3.3.2.1 per i comuni, la prima operazione per la verifica di consistenza della georeferenziazione provinciale è consistita nell'estrazione di tutti i record presenti nella tabella luogo le cui coordinate (Est,Nord) risultano (correttamente) appartenenti al poligono regionale Istat dichiarato nel campo provincia57: ­­ Estrazione dei record CORRETTI per quanto riguarda la georeferenziazione provinciale SELECT luogo.id_luogo FROM luogo, istat_shapefile_province AS istat WHERE ST_Contains( istat.geom , luogo.geom ) AND ( luogo.provincia = istat.automprov ) L'interrogazione restituisce un totale di 578 risultati, su un numero totale di record della tabella luogo pari a 590. Ciò significa che nella tabella luogo esistono 12 record che presentano anomalie legate alla georeferenziazione provinciale. Di questi 12 record anomali, 6 risultano privi di georeferenziazione, come già visto nel paragrafo 3.3.2.1; i restanti 6 record anomali vengono estratti mediante la seguente query, la quale, oltre all'id_luogo, estrae anche la provincia dichiarata e la provincia reale, permettendo di approfondire l'analisi delle anomalie: SELECT DISTINCT luogo.id_luogo AS Id_luogo, luogo.provincia AS Provincia_dichiarata , istat.automprov AS Provincia_reale FROM luogo, istat_shapefile_province AS istat WHERE ( (luogo.geom IS NOT NULL) AND ( ST_Contains( istat.geom , luogo.geom ) AND ( luogo.provincia <> istat.automprov ) ) ) L'interrogazione restituisce il seguente risultato: "C44811145811";"BR";"LE" "I90711145111";"BA";"BT" "A88311146011";"BA";"BT" "C44811145911";"BR";"LE" "I90711145711";"BA";"BT" "D46311145811";"TA";"BR" 57 L'utilizzo dell'attributo automprov (sigla automobilistica della provincia) è dovuto al fatto che il campo provincia della tabella luogo contiene soltanto le 2 lettere iniziali del toponimo provinciale, mentre il campo toponmprov della tabella istat_shapefile_province contiene il nome intero della provincia. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 86/109 CAPITOLO 3 - Implementazione dei controlli di consistenza Il seguente comando bash permette di esportare in formato shapefile il risultato della query che estrae Id, Geom, ProvinciaReale, ProvinciaDichiarata dei punti anomali. Data la presenza di 6 record con campo Geom NULLO, vengono esportati in formato shapefile soltanto 6 record: pgsql2shp ­f /path/to/file/Layer_punti_anomali_Province.shp ­h localhost ­u postgres ­P password postgres "SELECT DISTINCT luogo.id_luogo AS Id_punto, luogo.provincia AS Provincia_dichiarata , istat.automprov AS Provincia_reale, luogo.geom FROM luogo, istat_shapefile_province AS istat WHERE ( (luogo.geom IS NOT NULL) AND ( ST_Contains( istat.geom , luogo.geom ) AND ( luogo.provincia <> istat.automprov ) ) )" L'esportazione dei punti anomali in formato shapefile consente di analizzare graficamente le inconsistenze mediante software GIS. L'osservazione dei casi anomali mappabili (v. Figura 3.9) suggerisce due probabili cause d'inconsistenza dei dati: ▶ ragioni burocratiche (istituzione di nuove province): ▶ Bari invece di Barletta­Andria­Trani errori probabilmente legati all'accuratezza del posizionamento: quando il punto si trova al confine tra due o più province, le sue coordinate (Est,Nord) possono risultare appartenenti ad una di esse, mentre il toponimo dichiarato ad un'altra: Taranto invece di Brindisi Brindisi invece di Lecce Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 87/109 CAPITOLO 3 - Implementazione dei controlli di consistenza Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 88/109 CAPITOLO 4 - Considerazioni finali CAPITOLO 4 ­ Considerazioni finali 4.1 Considerazioni sul lavoro svolto Il presente lavoro di Tesi, collocandosi nell'ambito del Progetto di Ricerca «Organizzazione del territorio, occupazione del suolo e percezione dello spazio nel Mezzogiorno medievale (secoli XIII – XV). Sistemi informativi per una nuova cartografia storica» (PRIN 2009), ha consentito di rafforzarne gli aspetti relativi alla consistenza dei dati mediante le seguenti operazioni: ▶ realizzazione di verifiche di consistenza sui dati storici presenti nel geodatabase del progetto «Geografie dell’Italia Medievale (XIII – XV sec.)»; ▶ progettazione ed implementazione di diverse tipologie di controlli avanzati di consistenza sul geodatabase stesso; ▶ predisposizione di alcuni accorgimenti tecnici potenzialmente utili in vista di eventuali future ristrutturazioni della base di dati. Le verifiche effettuate sui record della tabella Luogo hanno evidenziato numerose inconsistenze, alcune grossolane ed altre più sottili, molte delle quali sarebbero risultate identificabili ed emendabili già in fase di inserimento, applicando i controlli di consistenza sviluppati. In questo senso, pur nella consapevolezza che intercettare tutte le possibili forme di inconsistenza, data la complessa articolazione della base di dati, rappresenta un limite sostanzialmente non raggiungibile, è possibile affermare che i controlli tematici e geografici implementati apporteranno un'utilità tangibile al progetto, garantendo maggiore affidabilità all'informazione archiviata nel geodatabase. L'utilizzo dei trigger, in particolare, si è rivelato uno strumento potente e versatile nella realizzazione dei controlli, evidenziando la notevole capacità del software PostgreSQL di conciliare il mondo dei DBMS relazionali con le logiche di programmazione dei tradizionali linguaggi di alto livello. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 89/109 CAPITOLO 4 - Considerazioni finali 4.2 Sviluppi futuri Una significativa integrazione del lavoro svolto sarebbe rappresentata dall'implementazione di un sistema semi­automatico per correggere le inconsistenze rilevate, realizzabile mediante l'utilizzo combinato di funzioni PostGIS e funzioni operanti sulle stringhe disponibili in PostgreSQL. Tale operazione aumenterebbe notevolmente l'affidabilità dell'informazione attualmente presente nel database. Per quanto attiene ai controlli di consistenza, una possibile estensione potrebbe consistere nell'applicare controlli di ridondanza analoghi a quelli definiti sulla tabella luogo58 anche alle restanti tabelle relazionali, per poi passare dalle singole tabelle al database nel suo complesso. Come spiegato nel paragrafo 2.1.1, infatti, l'informazione contenuta nella base di dati risulta interconnessa, e ciò potrebbe costituire l'origine di ulteriori inconsistenze. Un'ulteriore linea di evoluzione, infine, potrebbe consistere nel rendere sempre più “attivo” il supporto all'inserimento dati da parte dell'utente: ad esempio, nel momento in cui i dati inseriti dovessero risultare inconsistenti, invece di limitarsi ad impedirne l'inserimento, il sistema potrebbe suggerire all'utente un'alternativa, o proporgli una modifica automatica. Abbinando ancora una volta l'ingente quantità di funzioni sulle stringhe nativamente disponibili in PostgreSQL –alcune delle quali estremamente complesse– e le funzioni PostGIS, si potrebbero implementare ricerche automatiche sui geodati in memoria, e, al posto di laconici messaggi di notifica tipo « Errore: il toponimo X non risulta presente nel database Istat», fornire notifiche più simili a «Errore: il toponimo X non risulta presente nel database Istat. Nell'area circostante però esiste la località Y, il cui toponimo risulta simile ad X. Si desidera sostituire Y nella primitiva di inserimento?». Un sistema, insomma, per certi versi non dissimile da quello del motore di ricerca Google, apparentemente capace di comprendere le richieste dell'utente anche in presenza di errori ortografici, sintattici o tipografici. Naturalmente lo sviluppo di questo genere di funzionalità, quand'anche tecnicamente 58 Descritti nel paragrafo 3.2.2 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 90/109 CAPITOLO 4 - Considerazioni finali realizzabile, richiederebbe una considerevole quantità di risorse, in termini di competenze, fondi, e ore­uomo. 4.3 Aspetti critici Un elemento di criticità del lavoro è costituito dagli elementi di arbitrarietà presenti in alcuni dei controlli implementati. La prevenzione della ridondanza nella tabella Luogo 59, ad esempio, operativamente ha richiesto di identificare le combinazioni “a rischio” (v. Figure 3.1 e 3.2) e di predisporre per ciascuna di esse una strategia di risposta; l'individuazione delle combinazioni a rischio e delle possibili risposte sarebbe tuttavia risultata più significativa se svolta in compartecipazione con le Unità di Ricerca degli Storici, maggiormente qualificate per analisi di questo tipo. In futuro, tuttavia, nulla esclude di poter sfruttare le strutture create per procedere in questo senso. Una criticità strutturale –e in quanto tale difficilmente emendabile– è invece legata all'aspetto burocratico dei controlli sulla georeferenziazione. Come già osservato nel paragrafo 3.3.2.2, infatti, i confini degli enti amministrativi possono variare nel tempo – ed in Italia tendono a farlo con frequenza singolarmente elevata. Per gestire il problema si potrebbe pensare di aggiornare o sostituire, ad ogni cambiamento dei confini, le tabelle relazionali corrispondenti agli shapefile poligonali di comuni e province. Unitamente a questa operazione, tuttavia, sarebbe indispensabile aggiornare anche tutti gli altri dati del database, per preservarne la consistenza. Come si capisce, si tratta di operazioni estremamente delicate, in quanto potenzialmente in grado di corrompere l'integrità dell'informazione conservata. Il problema, sfortunatamente, risulta di non facile soluzione. 59 Controllo implementato nel paragrafo 3.2.2, a pag. 47. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 91/109 BIBLIOGRAFIA BIBLIOGRAFIA Atzeni P., Ceri S., Paraboschi S. e Torlone R. (1999). Basi di dati. Modelli e linguaggi di programmazione, Milano, Mc Graw Hill. Atzeni P., Ceri S., Fraternali P., Paraboschi S. e Torlone R. (2003). Basi di dati. Architetture e linee di evoluzione. Milano, Mc Graw Hill. Burrough P. e McDonnell R. (1998). Principles of geographical information systems. Oxford University Press. Carrion, D. e Migliaccio, F. (2009). Il Principato di Taranto in un GIS: problemi e potenzialità. In Domini del principe di Taranto in età orsiniana (1399­1463) a cura di Somaini F. e Vetere B. Galatina (LE), Italy, Congedo Editore, pp. 37­60. Casagrande L., Cavallini P., Frigeri A., Furieri A., Marchesini I. e Neteler M. (2012). GIS Open Source. GRASS GIS, Quantum GIS e Spatialite. Palermo, Dario Flaccovio Editore. Chen P.P.­S. (1976). The Entity­Relationship Model: Toward a Unified View of Data. ACM on Database Systems, Special issue: papers from the international conference on very large data bases, Framingham, USA, Settembre 22–24, 1975, Vol. 1 n.1, pp. 9­36. Codd, E. F. (1970). A relational model of data for large shared data banks. Communications of Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 92/109 BIBLIOGRAFIA the ACM, New York, USA, Vol. 13, n.6, pp. 377­387. Migliaccio F. (2008). Sistemi informativi territoriali e cartografia. Milano, Maggioli Editore. Politecnica. Mogorovich P. e Mussio P. (1988). Automazione del Sistema Informativo territoriale. Elaborazione Automatica dei Dati Geografici. Milano, Masson, vol.2 pp.503­8. Monti C. (2011). La cartografia dall’antichità fino al XVIII secolo. Milano, Maggioli Editore. Politecnica. Pratesi F., «Archiviazione e ricerca di immagini per contenuto cromatico attraverso database PostgreSQL», Tesi di laurea discussa alla Facoltà di Ingegneria Informatica, Università degli Studi di Firenze, A.A. 2005/2006 Zambrano C. (2013), «Progettazione e realizzazione del sistema informativo territoriale “Geografie dell’Italia Medievale (XIII – XV Sec.)”» , Tesi di dottorato discussa alla Facoltà di Ingegneria per l'Ambiente e il Territorio, Dipartimento di Ingegneria Civile e Ambientale, Politecnico di Milano Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 93/109 SITOGRAFIA SITOGRAFIA Storicamente (Laboratorio di Storia) – Laura Berti Ceroni – Diffusione ed utilizzo dei Geographical Information System nelle discipline umanistiche: prima indagine http://www.storicamente.org/02_tecnostoria/strumenti/Berti_Ceroni_1.htm Ultimo accesso avvenuto in data 23 Ottobre 2013 Wikipedia, l'enciclopedia libera ­ Indizione http://it.wikipedia.org/wiki/Indizione Ultimo accesso avvenuto in data 14 Novembre 2013 Wikipedia, l'enciclopedia libera – Storia di SQL http://it.wikipedia.org/wiki/Sql#Storia Ultimo accesso avvenuto in data 14 Novembre 2013 Sito ufficiale PostgreSQL – Storia di PostgreSQL http://www.postgresql.org/about/history/ Ultimo accesso avvenuto in data 19 Ottobre 2013 Wikipedia, l'enciclopedia libera – PostGIS http://en.wikipedia.org/wiki/PostGIS Ultimo accesso avvenuto in data 14 Novembre 2013 Wikipedia, l'enciclopedia libera – Portabilità http://it.wikipedia.org/wiki/Portabilit%C3%A0 Ultimo accesso avvenuto in data 14 Novembre 2013 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 94/109 SITOGRAFIA Ente nazionale per la digitalizzazione della Pubblica Amministrazione ­ Criteri per valutazioni comparative ai sensi dell’art. 68 del CAD http://www.digitpa.gov.it/notizie/avviso-partecipazione-tavolo-lavoro-redazione-linee-guida-criteri-valutazioni -comparative-ai Ultimo accesso avvenuto in data 14 Novembre 2013 PostgreSQL Official Site – Documentazione PostgreSQL 8.4 http://www.postgresql.org/docs/8.4/static/index.html Ultimo accesso avvenuto in data 14 Novembre 2013 Scuola Linux (appunti di informatica libera a uso delle scuole professionali per il commercio a indirizzo informatico) ­ PotgreSQL http://scuola.linux.it/informatica_commercio_elettronico/a2ice13.html#title277 Ultimo accesso avvenuto in data 7 Novembre 2013 Stack Overflow ­ Question and answer site for professional and enthusiast programmers http://stackoverflow.com/questions/955167/return-setof-record-virtual-table-from-function/17247118#17247 118 Ultimo accesso avvenuto in data 7 Novembre 2013 Network Theory Ltd (Free software manuals) – Looping through query results http://www.network-theory.co.uk/docs/postgresql/vol2/LoopingThroughQueryResults.html Ultimo accesso avvenuto in data 7 Novembre 2013 PostgreSQLTutorial.com ­ PostgreSQL 'UPDATE' syntax http://www.postgresqltutorial.com/postgresql-update/ Ultimo accesso avvenuto in data 10 Novembre 2013 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 95/109 SITOGRAFIA PostGIS Official Site – Funzione ST_MakePoint() http://postgis.refractions.net/docs/ST_MakePoint.html Ultimo accesso avvenuto in data 10 Novembre 2013 Michael Paquier WebSite ­ Manipulating arrays in PostgreSQL http://michael.otacoo.com/postgresql-2/manipulating-arrays-in-postgresql/ Ultimo accesso avvenuto in data 10 Novembre 2013 Associazione culturale ITPUG (Italian PostgreSQL Users Group) ­ Documentazione di PostgreSQL 9.0 http://docs.itpug.org/9.0/ Ultimo accesso avvenuto in data 14 Novembre 2013 Wikipedia, l'enciclopedia libera ­ Object­relational mapping http://it.wikipedia.org/wiki/Object-relational_mapping Ultimo accesso avvenuto in data 14 Novembre 2013 YouTube – Minicorso PostgreSQL PL/pgSQL (di Federico Campoli) http://www.youtube.com/playlist?list=PL02754FB2F933441E Ultimo accesso avvenuto in data 5 Ottobre 2013 Associazione culturale ITPUG (Italian PostgreSQL Users Group) ­ Il sistema dei tipi di PostgreSQL http://docs.itpug.org/9.0/extend-type-system.html Ultimo accesso avvenuto in data 10 Novembre 2013 Wikipedia, l'enciclopedia libera – Formato proprietario http://en.wikipedia.org/wiki/Proprietary_format Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 96/109 SITOGRAFIA Ultimo accesso avvenuto in data 14 Novembre 2013 Wikipedia, l'enciclopedia libera – Vendor Lock­in http://en.wikipedia.org/wiki/Vendor_lock-in Ultimo accesso avvenuto in data 14 Novembre 2013 WebNews ­ Retrocompatibilità: una bomba ad orologeria http://www.webnews.it/news/leggi/6342/retrocompatibilita-una-bomba-ad-orologeria/ Ultimo accesso avvenuto in data 14 Novembre 2013 Wikipedia, l'enciclopedia libera – Total Cost of Ownership http://en.wikipedia.org/wiki/Total_cost_of_ownership Ultimo accesso avvenuto in data 14 Novembre 2013 Wikipedia, l'enciclopedia libera – Embrace, Extend and Extinguish http://en.wikipedia.org/wiki/Embrace,_extend_and_extinguish Ultimo accesso avvenuto in data 14 Novembre 2013 Rob Weir's blog ­ Update on ODF Spreadsheet Interoperability http://www.robweir.com/blog/2009/05/update-on-odf-spreadsheet-interoperability.html Ultimo accesso avvenuto in data 10 Novembre 2013 Rob Weir's blog ­ A follow­up on Excel 2007 SP2′s ODF support http://www.robweir.com/blog/2009/05/follow-up-on-excel-2007-sp2s-odf.html Ultimo accesso avvenuto in data 10 Novembre 2013 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 97/109 SITOGRAFIA CNN.com ­ Crypto expert: Microsoft products leave door open to NSA http://www.cnn.com/TECH/computing/9909/03/windows.nsa/ Ultimo accesso avvenuto in data 14 Novembre 2013 Wikipedia, l'enciclopedia libera – Backdoor http://en.wikipedia.org/wiki/Backdoor_%28computing%29 Ultimo accesso avvenuto in data 14 Novembre 2013 Wired ­ Did NSA Put a Secret Backdoor in New Encryption Standard? http://www.wired.com/politics/security/commentary/securitymatters/2007/11/securitymatters_1115 Ultimo accesso avvenuto in data 14 Novembre 2013 Washington Post ­ Windows Security Flaw Is 'Severe' http://www.washingtonpost.com/wp-dyn/content/article/2005/12/29/AR2005122901456.html Ultimo accesso avvenuto in data 14 Novembre 2013 Free Software Foundation ­ The Free Software Definition http://www.gnu.org/philosophy/free-sw.html Ultimo accesso avvenuto in data 14 Novembre 2013 Wikipedia, l'enciclopedia libera ­ Differenza tra software libero e open source http://it.wikipedia.org/wiki/Differenza_tra_software_libero_e_open_source Ultimo accesso avvenuto in data 14 Novembre 2013 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 98/109 INDICE DELLE TABELLE INDICE DELLE TABELLE Tab. 1: Tabella relazionale personaggio ­ codice SQL...............................................................16 Tab. 2: Tabella relazionale ufficiale ­ codice SQL......................................................................17 Tab. 3: Tabella relazionale imposte ­ codice SQL......................................................................17 Tab. 4: Tabella relazionale luogo ­ codice SQL..........................................................................18 Tab. 5: Tabella relazionale ufficio ­ codice SQL........................................................................19 Tab. 6: Forma semplificata della sintassi PL/pgSQL per la creazione di una funzione­trigger..34 Tab. 7: Sintassi PL/pgSQL per la creazione di un trigger..........................................................34 Tab. 8: Creazione delle strutture ausiliarie per il controllo delle date ­ codice PL/pgSQL........44 Tab. 9: Creazione della funzione­trigger e dei trigger per il controllo delle date ­ codice PL/pgSQL..................................................................................................................................46 Tab. 10: Validazione del controllo di consistenza sulla data ­ codice PL/pgSQL.......................47 Tab. 11: Funzione­trigger e trigger identificati per prevenire la ridondanza nella tabella Luogo ­ codice PL/pgSQL.....................................................................................................................55 Tab. 12: Validazione del controllo di ridondanza sulla tabella Luogo ­ codice PL/pgSQL........57 Tab. 13: Creazione delle strutture ausiliarie per il controllo della lunghezza delle stringhe ­ codice PL/pgSQL.......................................................................................................................59 Tab. 14: Creazione di una tabella fittizia per testare il controllo sulla lunghezza delle stringhe ­ codice PL/pgSQL.......................................................................................................................59 Tab. 15: Funzione­trigger e Trigger relativi al controllo sulla lunghezza delle stringhe ­ codice PL/pgSQL..................................................................................................................................60 Tab. 16: Validazione del controllo sulla lunghezza delle stringhe ­ codice PL/pgSQL..............61 Tab. 17: Modifica proposta allo schema della tabella ufficiale ­ codice PL/pgSQL...................63 Tab. 18: Creazione delle strutture ausiliarie per il controllo Bounding Box delle coordinate ­ codice PL/pgSQL.......................................................................................................................66 Tab. 19: Funzione­trigger e trigger per il controllo Bounding Box delle coordinate ­ codice PL/pgSQL..................................................................................................................................68 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 99/109 INDICE DELLE TABELLE Tab. 20: Validazione del controllo di consistenza Bounding Box ­ codice PL/pgSQL................70 Tab. 21: Comando da terminale per importare gli shapefile nel database................................71 Tab. 22: Schema logico delle tabelle relazionali istat_shapefile ed istat_shapefile_province ­ codice PL/pgSQL.......................................................................................................................72 Tab. 23: Funzione­trigger e trigger del controllo su toponimi e poligoni ­ codice PL/pgSQL. . .75 Tab. 24: Validazione del controllo su toponimi e poligoni ­ codice PL/pgSQL..........................77 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 100/109 INDICE DELLE FIGURE INDICE DELLE FIGURE Figura 1.1: Territori di raccolta dei dati......................................................................................9 Figura 1.2 ­ Struttura tabellare del nucleo originario di dati del progetto «Geografie dell’Italia Medievale (XIII – XV sec.)» (stralcio)........................................................................................12 Figura 1.3: Schema Concettuale – Entità georeferenziate (Zambrano, 2013)...........................15 Figura 1.4: Schema Concettuale – Entità prive di georeferenziazione (Zambrano, 2013)........15 Figura 1.5: Schema logico relazione del geodatabase. In verde le tabelle ponte, in grassetto le chiavi primarie delle tabelle relazionali (Zambrano, 2013)......................................................21 Figura 2.1: Successione temporale dei rilasci di PostgreSQL (fonte: Wikipedia)......................28 Figura 3.1: Identificazione delle combinazioni di confronti sui supercampi potenzialmente in grado di generare ridondanza, e corrispondenti azioni (pt 1/2)...............................................50 Figura 3.2: Identificazione delle combinazioni di confronti sui supercampi potenzialmente in grado di generare ridondanza, e corrispondenti azioni (pt 2/2)...............................................51 Figura 3.3: Analisi grafica delle anomalie sulla georeferenziazione comunale.........................79 Figura 3.4: Analisi grafica delle anomalie sulla georeferenziazione comunale ­ Dettaglio 1.....81 Figura 3.5: Analisi grafica delle anomalie sulla georeferenziazione comunale ­ Dettaglio 2.....82 Figura 3.6: Analisi grafica delle anomalie sulla georeferenziazione comunale ­ Dettaglio 3.....83 Figura 3.7: Analisi grafica delle anomalie sulla georeferenziazione comunale ­ Dettaglio 4.....84 Figura 3.8: Analisi grafica delle anomalie sulla georeferenziazione comunale ­ Dettaglio 5.....85 Figura 3.9: Analisi grafica delle anomalie sulla georeferenziazione provinciale.......................88 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 101/109 SOFTWARE UTILIZZATI SOFTWARE UTILIZZATI Sistemi operativi: ▶ Linux Ubuntu 12.04.3 “Precise Pangolin” + GnomeShell 3.4 ▶ Linux Ubuntu 13.10 “Saucy Salamander” + GnomeShell 3.8 DBMS: PostgreSQL 8.4.18 + pgAdminIII 1.14.0 + Estensione PostGIS 2.0.3 GIS: ▶ QGIS 1.8.0 “Lisboa” ▶ QGIS 2.0.1 “Dufour” Editor di testo: ▶ gEdit 3.8.3 ▶ LibreOffice Writer 4.1.3 + Estensione Cooder Tool grafico per confronto e unione di file di testo: Meld 1.8.1 + Nautilus­compare Foglio di calcolo: LibreOffice Calc 4.1.3 Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 102/109 APPENDICE A – Descrizione esaustiva dei campi della struttura tabellare APPENDICE A – Descrizione esaustiva dei campi della struttura tabellare Viene qui riportato l'elenco completo dei campi dell'originaria struttura tabellare di archiviazione dei dati estratti dal Quaternus Declaracionum, tratto da (Zambrano, 2013): ▶ NOME TOPONIMO ITALIANO: Nome attuale del toponimo ove si localizza l’insediamento medievale. ▶ NOME TOPONIMO LATINO: Nome latino del toponimo, riportato nella forma grafica con cui viene indicato nel documento in esame. ▶ NOME CITTA’ ATTUALE: Nome della città a cui appartiene il toponimo (nei casi in cui si tratti di siti a continuità di vita, tale nome viene a coincidere con il nome del toponimo italiano). ▶ PROVINCIA: Provincia di appartenenza della città, indicata con la sigla, espressa con due lettere maiuscole. ▶ APPARTIENE A: Nei casi in cui il centro dipenda fiscalmente da un altro centro si indica il toponimo di appartenenza COORDINATE X: Coordinate geografiche piane, espresse da codice numerico di sei cifre (esempio: 768.580). Tali coordinate sono funzionali alla georeferenziazione dei centri presi in esame. ▶ COORDINATE X: Coordinate geografiche piane, espresse da codice numerico di sei cifre (esempio: 768.580). Tali coordinate sono funzionali alla georeferenziazione dei centri presi in esame. ▶ COORDINATE Y: Coordinate geografiche piane, espresse da codice numerico di sette cifre (esempio: 4.458.413). Tali coordinate sono funzionali alla georeferenziazione dei centri presi in esame. ▶ COEFFICIENTE DI PRECISIONE: Coefficiente attribuito alle coordinate, relativo al grado Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 103/109 APPENDICE A – Descrizione esaustiva dei campi della struttura tabellare di precisione raggiunto nella georeferenziazione. ▶ Toponimi con scarsissime notizie: Scarso grado di precisione; Toponimi incerti: Basso grado di precisione; Città: Medio grado di precisione; Piccoli agglomerati abitativi: Alto grado di precisione; Edifici isolati: Massimo grado di precisione. ID FONTE: Codice alfanumerico identificativo della fonte in esame. Di solito tale sigla è composta dall’indicazione di archivio, segnatura e numero del documento. (esempio: ASN DS II Reg. 249 ovvero Archivio di Stato di Napoli, Diversi Sommaria, II numerazione, Registro 249). In alcuni casi tale sigla è seguita da una virgola e dall’indicazione delle carte in cui si trova l’informazione registrata nel record. ▶ ▶ TIPOLOGIA FONTE: Indica la tipologia della fonte esaminata: Registro erariale Libro di fuochi ANNO: Codice numerico recante l’indicazione dell’anno a cui fa riferimento la fonte. Nel caso di anno indizionale si indica l’anno solare su cui si estende maggiormente l’anno indizionale. ▶ ▶ CODICE: Codice numerico binario (0/1) indicante la tipologia del computo annuale: 0: Anno Solare (1 Gennaio – 31 Dicembre); 1: Anno Indizionale (1 settembre – 31 agosto anno solare successivo). MESE: Ove presente, viene riportato il mese relativo alla registrazione dei dati elencati nel record. ▶ GIORNO: Codice numerico indicante, ove presente, il giorno relativo alla registrazione dei dati presenti nel record. ▶ INDIZIONE: Codice numerico compreso tra 1 e 15 indicante il numero di Indizione; tale codice esplicita l’anno specifico all’interno del periodo Indizionale di durata quindicennale. ▶ Numero dei FUOCHI FISCALI: Codice numerico indicante il numero dei fuochi imponibile, vale a dire, il numero di fuochi che effettivamente versava al principe l’imposta diretta. Ai Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 104/109 APPENDICE A – Descrizione esaustiva dei campi della struttura tabellare fuochi censiti attraverso le numerazioni venivano sottratti i fuochi esenti (nobili ed ecclesiastici). Ciascuna comunità poteva ottenere dal principe di essere tassata per un minor numero di fuochi. ▶ FUOCHI de corpore: Codice numerico indicante il numero dei fuochi imponibile, vale a dire, il numero di fuochi che effettivamente versava al principe l’imposta diretta. Ai fuochi censiti attraverso le numerazioni venivano sottratti i fuochi esenti (nobili ed ecclesiastici). Ciascuna comunità poteva ottenere al principe di essere tassata per un minor numero di fuochi. ▶ TASSA FOCATICO: Codice numerico indicante l’importo complessivo, espressa in grana, dell’imposta sui fuochi versata dal centro al principe. Il focatico corrisponde all’imposta diretta introdotta da Alfonso d’Aragona con la riforma fiscale del 1443. Tale sistema era fondato sull’imposizione di 1 ducato d’oro, pari a 5 tarì e 10 grana, per ogni fuoco. ▶ COLLETTA: Codice numerico indicante l’entità complessiva, espressa in grana, dell’imposta diretta versata dal centro al principe. La colletta era la forma di prelievo fiscale utilizzata nel periodo angioino, dapprima richiesta come imposta straordinaria, con Carlo I assunse un carattere fisso e annuale. Fu sostituita dal focatico, in seguito alla riforma fiscale attuata da Alfonso d’Aragona, ma all’interno del Principato di Taranto, le comunità potevano essere sottoposte all’una o all’altra forma di prelievo fiscale. ▶ THOMOLI SALE: Codice numerico indicante la quantità complessiva di tomoli di sale acquistata da ciascun centro. ▶ TASSA MILIZIA: Codice numerico indicante l’entità complessiva, espressa in grana, della tassa per le milizie versata dal centro al principe. ▶ DONATIVO: Codice numerico indicante l’entità complessiva, espressa in grana, della tassa “Pro dono consueto”versata dal centro al principe. ▶ TAVERNA: Codice numerico indicante l’entità complessiva, espressa in grana, della tassa “pro iure tabernae”, ovvero il diritto di gestire taverne. ▶ DISTRETTO ERARIALE: Codice numerico (1/2/3/4) indicante l’Area Fiscale di Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 105/109 APPENDICE A – Descrizione esaustiva dei campi della struttura tabellare appartenenza. Terra d’Otranto risulta divisa in tre distretti: ▶ 1. Da Taranto a Lecce: sede dell’erario del distretto: TARANTO; 2. Da Lecce a Leuca: sede dell’erario del distretto: LECCE; 3. Distretto di Soleto: sede dell’erario del distretto: SOLETO 4. Distretto di Bari: sede dell’erario del distretto: BARI NOME LATINO DELL’ERARIO DEL DISTRETTO: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi in latino, riportati nella forma grafica emersa dal documento. ▶ NOME ITALIANO DELL’ERARIO DEL DISTRETTO: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi nella trasposizione italiana del nome riportato nella fonte. ▶ NOME LATINO DELL’ERARIO LOCALE: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi in latino, riportati nella forma grafica emersa dal documento. ▶ NOME ITALIANO DELL’ERARIO LOCALE: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi nella trasposizione italiana del nome riportato nella fonte. ▶ NUMERO BAIULI: Codice numerico indicante il numero dei baiuli che reggono la BAGLIVA nell’anno di riferimento della fonte. ▶ SEDE CAPITANIALE: Codice numerico binario (0/1) indicante l’Assenza/Presenza di sede capitanale: 0: NO – Sede capitaneale assente; 1: SI – Sede capitaneale presente. ▶ ELENCO LOCALITA’ DEL CAPITANATO: Elenco località facenti parte della stessa giurisdizione capitaneale. ▶ NOME LATINO DEL CAPITANO: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi in latino, riportati nella forma grafica emersa dal documento. ▶ NOME ITALIANO DEL CAPITANO: Codice alfabetico indicante Cognome e provenienza Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 106/109 APPENDICE A – Descrizione esaustiva dei campi della struttura tabellare seguito da virgola e nome, espressi nella trasposizione italiana del nome riportato nella fonte. ▶ CENTRO DI VICARIE: Codice numerico binario (0/1) indicante l’Assenza/Presenza di centro vicariale. 0:NO – Sede Vicariale assente; 1: SI – Sede Vicariale presente. ▶ NOME LATINO DEL VICARIO: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi in latino, riportati nella forma grafica emersa dal documento. ▶ NOME ITALIANO DEL VICARIO: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi nella trasposizione italiana del nome riportato nella fonte. ▶ SEDE DI TESORERIA: Codice numerico binario (0/1) indicante l’Assenza/Presenza di sede di Tesoreria. 0: NO – Sede di Tesoreria assente; 1: SI – Sede di Tesoreria presente. ▶ TESORIERE DI RIFERIMENTO: Nel caso in cui nel centro in esame non sia presente la Tesoreria, si indica la sede del Tesoriere di riferimento. ▶ NOME LATINO DEL TESORIERE GENERALE: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi in latino, riportati nella forma grafica emersa dal documento. ▶ NOME ITALIANO DEL TESORIERE GENERALE: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi nella trasposizione italiana del nome riportato nella fonte. ▶ NOME LATINO DEL TESORIERE LOCALE: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi in latino, riportati nella forma grafica emersa dal documento. ▶ NOME ITALIANO DEL TESORIERE LOCALE: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi nella trasposizione italiana del nome riportato nella fonte. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 107/109 APPENDICE A – Descrizione esaustiva dei campi della struttura tabellare ▶ SEDE DI CASTELLANIA: Codice numerico binario (0/1) indicante l’Assenza/Presenza di sede di Castellania. 0: NO – Sede di Castellania assente; 1: SI – Sede di Castellania presente. ▶ NOME LATINO DELCASTELLANO: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi in latino, riportati nella forma grafica emersa dal documento. ▶ NOME ITALIANO DEL CASTELLANO: Codice alfabetico indicante Cognome e provenienza seguito da virgola e nome, espressi nella trasposizione italiana del nome riportato nella fonte. ▶ SEDE DI DOGANA: Codice numerico binario (0/1) indicante l’Assenza/Presenza di sede di Dogana. 0: NO – Sede Dogananale assente; 1: SI – Sede Dogananale presente. ▶ NUMERO DOGANIERI: Codice numerico indicante il numero dei doganieri operanti nel centro nell’anno di riferimento della fonte. AV. ▶ SEDE DI FONDACO: Codice numerico binario (0/1) indicante l’Assenza/Presenza di sede di Fondaco. 0: NO – Sede di Fondaco assente; 1: SI – Sede di Fondaco presente. ▶ BAGLIVA: Codice numerico indicante l’entità complessiva, espressa in grana, dei proventi ricavati dalla Bagliva nell’anno di riferimento del documento in questione. ▶ PLATEA: Codice numerico indicante l’entità complessiva, espressa in grana, dello “ius plateae” versata al principe per il diritto sul commercio. ▶ AFFIDA – PROVENTI PARZIALI: Codice numerico indicante l’entità complessiva, espressa in grana, della tassa “Pro Iure Affidae”versata dal centro in esame a quello avente tale diritto, in quanto fornitore di pascolo. [...] ▶ LOCALITA’ – A CHI PAGANO: Nome della località, seguita da trattino e nome del funzionario a cui il centro in esame versa l’imposta. (sono indicati sia la località che il Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 108/109 APPENDICE A – Descrizione esaustiva dei campi della struttura tabellare soggetto al quale si paga) ▶ CENTRO DI AFFIDA: Codice numerico binario (0/1) indicante l’Assenza/Presenza di sede Centro di Affida. 0: NO – Centro di Affida assente; 1: SI – Centro di Affida presente. ▶ AFFIDA TOTALE: Codice numerico indicante l’entità complessiva, espressa in grana, della tassa “Pro Affida” incamerata dal centro avente tale diritto. Progettazione e implementazione di controlli di consistenza su un GeoDatabase di dati storici Pag 109/109