UNIVERSIT� ADEGLISTUDIDIMODENA
Facolt�adiIngegneria
CorsodiLaureainIngegneriaInformatica
Progettoerealizzazionediun
pre-processoreODL/C++
Relatore
TesidiLaureadi
Chiar.moProf.SoniaBergamaschi
IvanoBianchi
AnnoAccademico1996-97
Parolechiave:
Pre-Processore
BasidiDatiadOggetti
ODMG-93
C++
RegolediIntegrit�a
Aimieigenitori
RINGRAZIAMENTI
Desideroringraziareilmiorelatore,Prof.ssaSoniaBergamaschi,perla
suagrandedisponibilit�a.
RingrazioinoltrelaDott.ssaAlessandraGarutiperl'aiutoneiproblemi
tecnici.
Indice
1
Introduzione
1
2
LoStandardODMG-93
3
2.1
Introduzione............................
3
2.1.1
PrincipidiProgettazionedelLinguaggio
........
4
2.1.2
LegamecolLinguaggio..................
5
2.1.3
MappaggiodelModelloadOggettiODMGsulC++
.
6
2.1.4
UtilizzodegliAspettidelLinguaggioC++
.......10
2.2
C++ODL.............................10
2.2.1
DichiarazionidiAttributi
................11
2.2.2
DichiarazionidiCamminiAttraversoleRelazioni...23
2.2.3
DichiarazionidiRelazioniUnidirezionali........24
2.2.4
DichiarazionidiOperazioni
...............25
2.3
C++OML
............................25
2.3.1
Creazione,Cancellazione,Modi�caeRiferimentiad
Oggetti
..........................25
2.3.2
Propriet�a
.........................30
2.3.3
Operazioni.........................44
2.3.4
ClassePersistentObject.................45
2.3.5
ClasseRef.........................46
2.3.6
ClassiCollezione
.....................49
2.3.7
Transazioni........................61
2.3.8
OperazionisullaBasediDati..............63
2.4
C++OQL.............................65
2.4.1
MetodidiInterrogazionenellaClasseCollection....65
2.4.2
FunzioneOQL
......................66
2.5
Esempio..............................68
2.5.1
De�nizionedelloSchema.................69
2.5.2
ImplementazionedelloSchema..............70
2.5.3
UnaApplicazione.....................73
2.6
FutureEstensionidelLegameC++ODL/OML
........76
ii
INDICE
2.6.1
ODL............................79
2.6.2
OML............................81
2.6.3
ProblemidiMigrazione..................86
3
L'ambienteODB-ToolsPreesistente
89
3.1
L'architetturadiODB-Tools...................89
3.1.1
Schemieregolediintegrit�a
...............90
3.2
IllinguaggioOCDL........................92
3.2.1
Sintassi
..........................93
3.3
Validatoredischemi
.......................94
4
ArchitetturaFunzionaledelPre-ProcessoreODLRule/C++
97
4.1
EstensioniRispettoalC++
...................97
4.2
TipiDatiintrodotti........................99
4.3
ODLRule
..............................100
4.4
ArchitetturaFunzionaledelPre-ProcessoreODLRule/C++
..100
4.4.1
Esecuzionedelpre-processoreODLRule/C++dallali-
neadicomando......................102
4.4.2
FilesdiOutput......................103
5
IlPre-processoreODLRule/C++
105
5.1
IlTraduttore
...........................105
5.1.1
Strutturadelprogramma.................105
5.1.2
LaSintassiODLRule/C++
................106
5.1.3
LestruttureDati.....................107
5.2
DescrizionedelleFunzioni....................112
5.3
TraduzionedelleregolediIntegrit�a
...............121
5.3.1
Lastrutturadati.....................121
5.3.2
Funzionidigestionedelleregolediintegrit�a
......124
5.3.3
AlgoritmodiTrasformazionedelleRegolediIntegrit�a.124
6
NoteConclusive
139
6.1
SviluppiFuturi..........................139
A
Lex&
Yacc
141
B
Principiodicovarianzaecontrovarianzadimetodi
145
B.1
Principiodicovarianzaecontrovarianza.............145
Capitolo1
Introduzione
ScopodellaTesi
L'ideadibase�equelladidotareilprogettistadibasi
didatiadoggettidiunambientesoftwarechegliconsentadicreareuno
schemadibasididatiadoggettieloaiutinelcontrollodicorrettezzaedi
consistenzaditaleschema.
L'ambientesoftwaredovr�apermettediutilizzaresialepotenzialit�aespressi-
vedelC++(chefondeallenotecaratteristichedelC,lapossibilit�adiuna
programmazioneorientataaglioggetti)chelepotenzialit�adellinguaggiodi
altolivelloODL(LinguaggiodiDescrizionedischemidibasididatinel-
l'ambitodelloStandardODMG-93
1
perbasididatiadoggetti).Inoltre,per
esprimereinmanieradichiarativavincolidiintegrit�asuschemidibasidi
dati,ilprogettistapotr�autilizzareunaversioneestesadiODL(ODLRule)
chepermettedide�nireregole\ifthen"perognunadelleclassidescritte.
L'ausilioalcontrollodicorrettezzaediconsistenzadiunoschemadibasi
didativerr�arealizzatoutilizzandoilcomponenteOCDLDesignerdiODB-
Tools
2
basatosutecnichediintelligenzaarti�cialeesviluppatopressoilDi-
partimentodiScienzedell'Ingegneria.
Elementofondamentaleperlosviluppodiunambientesoftwareconqueste
�nalit�a�edotarsisiunpre-processoreODLRule/C++ingradodiacquisireun
sorgenteincludenteistruzionineiduelinguaggi.Nellapresentetesi�estato
quindiprogettatoerealizzatounpre-processoreODLRule/C++ispiratodal-
l'approccioStandardODMG-93.Talestandardde�nisceappuntoiprincipi
dicollegamentodiODL/OMLdirettoversoilC++ede�nisceunlinguaggio
standardODBMSperODL/OML.
1Siveda[Cat94]
2Siveda[Gar95]
2
Introduzione
Lapresentetesitrattasoltantoilprogettodischemidibasididati,quindi
nonvieneapprofonditalaparterelativaaOML(LinguaggiodiManipolazio-
nedegliOggetti),senonperattingereadichiarazionidiparticolariclassidi
oggettifondamentaliivide�niteeperl'utilizzodifunzioniemetodiperla
gestionedellebasididatinell'ambitodelleregolediintegrit�a.
NelCapitolo2vieneriportatounampiostralciodellostandardODMG-93
relativoallegametraC++
eODL/OML,alqualelapresentetesisiispi-
ra.NelCapitolo3sio�reunavisioneriassuntivadell'ambienteODB-Tools
preesistenteacuiilpre-processoreODLRule/C++sivaadaggiungere.Nel
Capitolo4vienepresentatoilprogettodelpre-processoreODLRule/C++a
grandilinee.NelCapitolo5sientraneiparticolaridellarealizzazionedel
pre-processoreODLRule/C++analizzandoognicomponenteeponendopar-
ticolareattenzioneallatrattazionedelleregolediintegrit�a.
Capitolo2
LoStandardODMG-93
2.1
Introduzione
Questocapitolode�nisceillegametraC++eODL/OMLespressonellostan-
dard
1.
ODL�el'acronimodiObjectDe�nitionLanguage(LinguaggiodiDe�nizione
degliOggetti).IllegamedelC++conODL�eespressocomeunalibreriadi
classiedunaestensionedellagrammaticaC++perlade�nizionestandard
delleclassi.Lalibreriadiclassifornisceclassiefunzioniperimplementare
iconcettide�nitidalmodelloadoggettidiODMG.L'estensioneconsistein
unasolaparolachiaveaggiuntivaedinunasintassiampliatacheaggiunge
unsupportodichiarativoperlerelazioninelledichiarazionidiclassiinC++.
OML�einvecel'acronimodiObjectManipulationLanguage(Linguaggiodi
ManipolazionedegliOggetti).Questo�eillinguaggioutilizzatoperrecupe-
rareoggettidallabasedidatiemodi�carli.LasintassielasemanticaC++
OMLsonoquelleC++standardnelcontestodellalibreriastandarddiclassi.
ODLeOMLspeci�canosoltantolecaratteristichelogichedeglioggettiedelle
operazioniutilizzatepermanipolarli.Nonsioccupanodellaallocazione�sica
deglioggetti.Nonindirizzanoclusterenongestisconolocazionidimemoria
associateconlarappresentazione�sicadellaallocazionedeglioggetti;non
accedononeppureastrutturecomeindiciutilizzatiperaccelerareilrecupero
deglioggetti.Nelmondoidealequestecosedovrebberoesseretrasparential
programmatore.Nelmondorealeinvecenonlosono.Uninsiemeaddizionale
dicostruttichiamatiphysicalpragma�ede�nitoperpermetterealprogram-
matorediinserirealcunicontrollidirettisuquestecose,oalmenoperrenderlo
1Siveda[Cat94]
4
LoStandardODMG-93
capacediprocurarsi\aiuti"perilsottosistemadigestionedelleallocazioni
fornitocomepartedell'esecuzionedell'ODBMS.Lephysicalpragmaesisto-
nosiaall'internodiODLchediOML.Essesonoaggiunteallede�nizioni
ditipidioggettiinODL,espressecomeoperazioniOML,omostratecome
argomentiopzionaliperoperazionide�niteinOML.Siccomequestepragma
nonsonoinnessuncasounlinguaggioas�estante,masonoinveceuninsieme
dicostruttiaggiuntiadODL/OMLperindirizzarel'implementazionedelle
locazioni,essevengonoinclusecomesottosezionirilevantidiquestocapitolo.
Ilcapitolo�eorganizzatonelmodoseguente.Lasezione2.2discutel'ODL.
Lasezione2.3discutel'OML.Lasezione2.4discutel'OQL-ilsottoinsieme
distintodiOMLchesupportailrecuperoassociativo.Ilrecuperoassociativo
�eilrecuperobasatosuivaloridellepropriet�adeglioggettianzich�esuiloro
IDosuiloronomi.Lasezione2.5fornisceunprogrammadiesempio.La
sezione2.6de�nisceunlegameC++
ODL/OMLcheabbiamostimatodi
o�rireinfuturoquandosar�acomuneutilizzarlo.
2.1.1
PrincipidiProgettazionedelLinguaggio
IlegamiperODL/OMLde�nitinelcapitolo2diquestatesi,perlapro-
grammazioneinunospeci�colinguaggio,sonobasatisudiunprincipiodi
base:ilprogrammatoreusaunsololinguaggio,nonduelinguaggisepara-
ticoncon�niarbitraritraloro.Questoprincipiopossiedequattrocorollari
chesonoevidentinellaprogettazionedellegameC++de�nitonelcorpodi
questocapitolo:
1.C'�eunsolosistemauni�catoditipitraillinguaggiodiprogrammazione
edlabasedidati;leistanzeindividualidiquestitipicomunipossono
esserepersistentiotransienti;
2.Illegamediprogrammazionetraunospeci�colinguaggio(nelnostro
casoilC++)eODL/OMLrispettalasintassielasemanticadellin-
guaggiodiprogrammazionedibaseincuiessovieneinserito;
3.Illegame�estrutturatocomeunpiccoloinsiemediaggiunteallinguaggio
diprogrammazionedibase;questonondeveintrodurrecostruttidi
unospeci�cosottolinguaggiocheduplicanofunzionalit�agi�apresenti
nellinguaggiodibase;
4.LeespressioniinOMLsicompongonoliberamenteconleespressioni
nellinguaggiodiprogrammazionebaseeviceversa.
LegamecolLinguaggio
5
2.1.2
LegamecolLinguaggio
L'approccioperillegametraC++edillinguaggiodell'ODBMSdescrittoin
questostandard�ebasatosudiunpuntatore\Ref-based".
InunapproccioRef-based,illegameC++
mappailModelloadOggetti
nelC++
introducendouninsiemediclassichepossonoavereistanzesia
persistentichetransienti.Questeclassisonoreferenziateinformalmentecome
"classicapacidipersistenza"all'internodelpresentecapitolo.Questeclassi
sonodistintedallenormaliclasside�niteattraversoillinguaggioC++,che
sonotuttetransienti:infattinonsopravvivonoall'esecuzionedelprocessonel
qualesonocreate.Dove�enecessariodistingueretraquesteduecategoriedi
classi,leprimesonochiamate"classicapacidipersistenza";alleultimeci
siriferiscecome"classitransienti".PerogniclasseTcapacedipersistenza,
unaclasseausiliariaRef<T>vienede�nita.Leistanzedelleclassicapacidi
persistenzasonoallorareferenziateusandoriferimentiparametrizzati,e.g.,
(1)Ref<Professor>profP;
(2)Ref<Department>deptRef;
(3)profP->grant_tenure();
(4)deptRef=profP->dept;
L'istruzione
(1)
dichiara
l'oggetto
profP
come
un'istanza
del
tipo
Ref<Professor>.
L'struzione(2)dichiaradeptRefcomeun'istanzadel
tipoRef<Department>.L'istruzione(3)invocal'operazionegranttenure
de�nitanellaclasseProfessor,nellaistanzadellaclasseprofP.L'operazione
(4)assegnailvaloredell'attributodeptdelprofessoreprofPallavariabile
deptRef.
Leistanzedelleclassicapacidipersistenzapossonoconteneremembriditipi
C++,classide�nitedall'utenteopuntatoriadatitransienti.Leapplicazio-
nipossonoriferirsiatalimembriusandopuntatoriC++
(*)oriferimenti
(&)soltantodurantel'esecuzionediunatransazione.Quando�einattouna
transazione,ipuntatoriinterniadoggetticollegatiadallocazionipermanenti
sarannosettatialvalore0dall'operazioneTransaction::commit.
Inquestocapitolouseremoiterminiseguentiperdescriverelesituazioninell
qualilostandardvieneformalmenteconsideratoinde�nitoopermetteadun
implementatorediprenderedecisionisuspeci�cheimplementazioninelri-
spettodellostandardstesso.
Iterminisono:
6
LoStandardODMG-93
Inde�nito:ilcomportamentononvienespeci�catodallostandard.Leim-
plementazionihannocompletalibert�a(possonofaretuttooniente),ed
ilcomportamentononhanecessit�adiesseredocumentatodall'imple-
mentatoreodalvenditore.
De�nitosull'Implementazione:ilcomportamento�especi�catodaogni
implementatore/venditore.All'implementatore/venditore�epermes-
soprenderedecisionisuspeci�cheimplementazioniriguardantiilfun-
zionamento.Comunque,ilfunzionamentodeveesserebende�nitoe
completamentedocumentatoepubblicatocomepartedellostandard
relativoallaimplementazionedelvenditore.
La�gura2.1mostralagerarchiadilinguaggiinquestione,attaversounpre-
processore,lacompilazioneedipassidilinkchegeneranounaapplicazione
eseguibile.
2.1.3
MappaggiodelModelloadOggettiODMG
sul
C++
SebbeneilC++forniscaunmodellodidatimoltopotenteevicinoaquello
presentatonelcapitolo2,valelapenacercaredispiegarepi�uprecisamente
comeiconcettiintrodottinelcapitolo2venganomappatiinconcretonei
costruttiC++.
OggettieLetterali
UntipodioggettoODMGvienemappatoinunaclasseC++.Aseconda
dicomeunaclasseC++vieneistanziata,ilrisultatopu�oessereunoggetto
ODMGoppureunletteraleODMG.UnoggettoC++chesiamembrointerno
diunaclassevienetrattatocomeunletteraleODMG.Questo�espiegatodal
fattocheunbloccodimemoriavieneinseritonell'oggettoinclusoedappar-
tieneinteramenteadesso.Peresempio,nonsipu�ocopiarel'oggettoincluso
senzafareunacopiadell'oggettomembroallostessotempo.Inquestosenso
l'oggettomembrononpu�oessereconsideratocomeseavesseunaidentit�a,
infattiessosicomportacomeunletteraleimmutabile.
Strutture
LanozionedistrutturadelModelloadOggettivienemappataneicostrutti
C++distructeclassinterniinunaclasse.
MappaggiodelModelloadOggettiODMG
sulC++
7
Ese
guib
ili
Sorg
ente
C+
+
Inte
staz
ione
]
Ese
cuzi
one
Cod
ice
Lin
ker
Bas
e di D
ati
Dic
hiar
azio
ni
C+
+ O
DL
Prep
roce
ssor
e
OD
L
File
di
[e S
orge
nte]
Inte
staz
ione
Gen
erat
i
Ute
nte
[ed
con
OM
L
Com
pila
tore
C+
+ Ogg
etto
OD
BM
S
Met
adat
i
OD
BM
S
Ese
cuzi
one
OD
BM
S
App
licaz
ioni
Figura2.1:GerarchiadiLinguaggio
8
LoStandardODMG-93
Implementazione
IlC++possiedeimplicitamentelanozionedisuddivisionedellade�nizionedi
unaclasseindueparti:lasuainterfaccia(partepubblica)elasuaimplemen-
tazione(membriprivatieprotettiede�nizionedellefunzioni).Comunque,
inC++�epossibilespeci�caresoltantounaimplementazioneperunadata
classe.
ClassiCollezione
IlmodelloadoggettiODMGcomprendedeigeneratoriditipicollezione,tipi
collezioneedistanzecollezione.Igeneratoriditipicollezionesonorappre-
sentaticomeclassitemplateinC++.Itipicollezionesonorappresentati
comeclassicollezioneeleistanzecollezionesonorappresentatecomeistanze
diquesteclassicollezione.Illustriamoquestetrecategorie:
template<classT>classSet:publicCollection<T>{...};
classShip{...};
Set<Ref<Ship>>Cunard_Line;
Set<T>
�eunaclassetemplatecollezione.Set<Ref<Ship>>
�eunaclasse
collezione,eCunardLine�eunaparticolarecollezione,unaistanzadellaclasse
Set<Ref<Ship>>.
Lagerarchiasottotipo/supertipoditipicollezionede�nitanelmodelloODMG
�edirettamentetrasportatanelC++.IltipoCollection<T>
�eunaclasse
astrattainC++connessunaistanzadiretta.Risultaistanziabilesoltanto
attraversolesueclassiderivate.Lasoladi�erenzatreleclassicollezionenel
legameC++elelorocontropartinellostandardsonoleseguenti:
�
LeoperazioniconunnomenelModelloadOggettisonomappatein
funzionimembroinC++.
�
Peralcuneoperazioni,illegameC++includesialefunzioniconnome
cheleoperazionisovrapposte,e.g,Set::unionwithhaanchelaforma
operator+=.L'istruziones1.unionwith(s2)es1+=s2sonofunzional-
menteequivalenti.
�
Leoperazionichenellostandardrestituivanounvalorebooleanosono
modellatecomefunzionimembrocherestituisconounintnellegame
C++.QuestovienefattopervenireincontroallaconvenzioneCche
uninterodivalorezerosigni�cafalsoedognialtrovaloresigni�cavero.
�
Leoperazionidicreateedeletede�nitenellostandardsonostaterim-
piazzatecoicostruttoriedistruttoriC++.
MappaggiodelModelloadOggettiODMG
sulC++
9
Array
IlC++fornisceunasintassipercreareedaccedereadunasequenzaindicizza-
biledioggetti.Questa�estatasceltapermappareparzialmentelacollezione
ArraydiODMG.Percomplementarla,vienefornitaunaclasseVarrayche
implementaunarrayilcuiestremosuperiorepu�ovariareneltempo.
Relazioni
LerelazioninonsonodirettamentesupportatedalC++.Comunque,esseso-
nosupportateinODMGgenerandoautomaticamentedeimetodiC++che
attraversanolerelazionistesse.
Larelazioneins�estessavieneimplementatacomeunriferimento(rela-
zioneuno-a-uno)ocomeunacollezione(relazioneuno-a-molti)all'interno
dell'oggetto.
Estensioni
LeestensioninonsonosupportatedirettamentedalC++.Ilprogrammatore
�eresponsabiledellade�nizionediunacollezioneedellascritturadeimetodi
perilsuomantenimento.
Chiavi
Ladichiarazionidichiavinon�esupportatadalC++.
Nomi
NellegamecolC++
unoggettopu�oacquisiresolounnome,mentrenel
modelloODMGpi�udiunnomepu�oriferirsiallostessooggetto.Untentativo
diassociarepi�udiunnomeallostessooggettocausaunerrore.
AmministrazionedellaBasediDati
Alcuneoperazioniriguardantil'amministrazionediunabasedidatisono
omesseintenzionalmentedallegamecolC++.Peresempioillegamecol
C++nonfornisceunmezzopercreareunabasedidatin�eperde�nireun
indicesuunacollezione.
10
LoStandardODMG-93
2.1.4
UtilizzodegliAspettidelLinguaggioC++
Pre�sso
Inomiglobalinell'interfacciaODMGavrannoilpre�ssoodb.L'intenzione
�edievitarelecollisioniconaltrinominellospaziodeinomi.
ManipolazionedelleEccezioni
Sipiani�cadiusarelamanipolazionedelleeccezioniC++
inquantoessa
risultaunmezzogeneralmentedisponibilenellamaggiorpartedegliambienti
C++.Perilmomento,quandounacondizionedieccezionevieneincontrata,
unaroutinedierroresar�arichiamata.Entrambequestesoluzionisaranno
identi�catecomeoriginedierrori.
Identi�catoredelPre-processore
Unidenti�catoredelpre-processore,
ODMG93
,�ede�nitopercompila-
zionisottocondizioni.
2.2
C++
ODL
Questasezionede�nisceilLinguaggiodiDe�nizionedegliOggettidelC++.
ilC++ODLfornisceunadescrizionedelloschemadellabasedidaticome
uninsiemediclassidioggetti-comprendenteiloroattributi,relazionied
operazioni-inunostilesintatticocheconsistedellaporzionedichiarativadi
unprogrammaC++.Leistanzediquesteclassipossonoesseremanipolate
attraversoilC++OML.
DiseguitosihaunesempiodidichiarazionedeltipoProfessor.
Sino-
til'introduzionedellanuovaparolachiaveinversenelladichiarazionedi
relazioni.
classProfessor:publicPersistent_Object{
public:
//proprieta':
int
age;
int
id_number;
String
office_number;
String
name;
Ref<Department>
dept
inverseprofessors;
DichiarazionidiAttributi
11
Set<Ref<Student>>
advises
inverseStudent::advisor;
//operazioni:
void
grand_tenure();
void
assign_course(Course&);
private:
...
};
questasintassiperladichiarazionediunaclasseperC++ODL�eidentica
alladichiarazionediunaclasseinC++trannecheessaincludeladichiarazio-
nediattributiecamminiattraversorelazioni.Ladichiarazionediattributi
mappasudiuninsiemeristrettodidichiarazionidiattributidiunaclassein
C++.Ledichiarazionidicamminiattraversorelazionisonosintatticamente
distintidagliattributidiunaclassedallapresenzadellaclausolainverse.
Gliattributistaticidelleclassinonsonocontenutiall'internodiogniistanza
masonoclassistaticamenteallocate.Questiattributistaticinonsonoallo-
catinellabasedidati,masonosupportatiperleclassicapacidipersistenza.
Isupertipisonospeci�catiutilizzandolasintassistandardC++all'interno
dell'intestazionedellaclasse,e.g.,classProfessor:publicPerson.Sebbene
questaspeci�cautilizziattributiemetodipubbliciperfacilit�aebrevit�a,i
corrispondentiattributiemetodiprivatioprotettisonosupportati.
2.2.1
DichiarazionidiAttributi
Ledichiarazionidiattributisonosintatticamenteidentichealledichiarazioni
deimembridatoinC++.Siccomenozionidiattributicomeoggettinonsono
ancorade�niteedincluseinquestostandard,gliattributiedimembridato
nonsonoenonpossonoesseredistinti.Inquestostandard,unattributonon
pu�oaverepropriet�a(e.g,unit�adimisura)enonc'�emododispecializzare
leoperazionigetvalueesetvaluede�nitesultipo(e.g.,perscatenareun
eventoquandounvalore�ecambiato).
LasintassielasemanticaC++standardperlade�nizionedelleclassisono
supportate.Comunqueleimplementazioninonnecessitanodisupportarei
seguentitipidatoall'internodelleclassipersistenti:
�
unioni
�
campidibit(bit�elds)
12
LoStandardODMG-93
�
riferimenti(&)
comemembri.Unioniecampidibitpongonodeiproblemiquandosisup-
portanoambientieterogenei.Lesemantichedeiriferimentisonotalicheessi
sonoinizializzatisoltantoallalorocreazione:tuttelesusseguentioperazioni
sonodiretteall'oggettoreferenziato.Iriferimentiall'internodioggettipersi-
stentinonpossoesserere-inizializzatiquandosonoportatidallabasedidati
inmemoriael'indirizzocheessicontengonodaquandosonostatiinizializ-
zatipotrebbe,ingenerale,esserenonvalido.Tuttiipuntatoriall'interno
diunoggettopersistentesonotrattaticomepuntatoriadatitransienti.Un
insiemediclassispeciali�ede�nitoall'internodellespeci�chediODMGper
contenereriferimentiaglioggettipersistenti.Inaggiuntaatuttiitipididato
primitivi,eccettuatiquelliaccennatisopra,lestruttureeleclassidioggetti
possonoessereattributidiunaclasse.Cisonoparecchitipistrutturatidi
letteralichesonofornite.Questiincludono:
�
String
�
Interval
�
Date
�
Time
�
Timestamp
esempi:
classStudent:publicPersistent_Object{
public:
String
name;
Date
birth_date;
Phone_Number
dorm_phone;
struct{
int
PO_box;
String
university;
String
city;
String
state;
String
zip_code;
}university_address;
List<String>
favorite_friend;
};
DichiarazionidiAttributi
13
L'attributonameprendeunaStringcomesuovalore.L'attributodormphone
prendeuntipoPhoneNumber,de�nitodall'utente,comesuovalore.L'at-
tributouniversityaddressprendeunastruttura.L'attributofavoritefriends
prendeunaListdiStringcomesuovalore.
Lesezioniseguenticontengonoledescrizionideitipiletteraliforniti.
String
Laclasseseguentede�nisceuntipodatoletteraledausarsicomeattributo
stringa.Restaintesochequestaclasse�eusatasoltantoperallocarestringhe
nellabasedidati,quindinon�ecertamenteunaclassegenericadistringhe
contuttelefunzionalit�adiunaclassedistringhenormalmenteutilizzataper
stringhetransientiinunaapplicazione.
Inizializzazione,assegnamento,copiaeconversionedaeallestringhedica-
ratteridelC++sonosupportate.Glioperatoridicomparazionesonode�niti
suStringpercompararequestaconun'altraStringounastringadicaratteri
delC++.Sipu�oancheaccedereadunelementonellaStringtramiteun
indice,inoltre�epossibiledeterminarelalunghezzadellaString.
De�nizione:
classString{
public:
String();
String(constString&);
String(constchar*);
~String();
String&
operator=(constString&);
String&
operator=(constchar*);
operatorconstchar*()const;
char&
operator[](unsignedlongindex);
unsignedlong
length()const;
friendint
operator==(constString&sL,
constString&sR);
friendint
operator==(constString&sL,
constchar*pR);
friendint
operator==(constchar*pL,
constString&sR);
14
LoStandardODMG-93
friendint
operator!=(constString&sL,
constString&sR);
friendint
operator!=(constString&sL,
constchar*pR);
friendint
operator!=(constchar*pL,
constString&sR);
friendint
operator<(constString&sL,
constString&sR);
friendint
operator<(constString&sL,
constchar*pR);
friendint
operator<(constchar*pL,
constString&sR);
friendint
operator<=(constString&sL,
constString&sR);
friendint
operator<=(constString&sL,
constchar*pR);
friendint
operator<=(constchar*pL,
constString&sR);
friendint
operator>(constString&sL,
constString&sR);
friendint
operator>(constString&sL,
constchar*pR);
friendint
operator>(constchar*pL,
constString&sR);
friendint
operator>=(constString&sL,
constString&sR);
friendint
operator>=(constString&sL,
constchar*pR);
friendint
operator>=(constchar*pL,
constString&sR);
};
Interval
LaclasseInterval�eutilizzataperrappresentareunintervalloditempo.Vie-
neancheusatapere�ettuareoperazioniaritmetichesulleclassiDate,Time
eTimestamp.Ungiorno�eilpi�uampiocomponenteditempocontenutoin
unInterval.Questaclassecorrispondeall'intervalloday-timecome�ede�nito
nellostandardSQL.
DichiarazionidiAttributi
15
Inizializzazione,assegnamento,aritmeticaefunzionidicomparazionesono
de�nitenellaclasse,comeanchelefunzionimembroperaccedereallecom-
ponentiditempodelsuovalorecorrente.
De�nizione:
classInterval{
public:
Interval(intday=0,inthour=0,intmin=0,
floatsec=0.0);
Interval(constInterval&);
Interval&operator=(constInterval&);
int
day()const;
int
hour()const;
int
minute()const;
float
second()const;
int
is_zero()const;
Interval&operator+=(constInterval&);
Interval&operator-=(constInterval&);
Interval&operator*=(int);
Interval&operator/=(int);
Interval
operator-()const;
friendIntervaloperator+(constInterval&L,
constInterval&R);
friendIntervaloperator-(constInterval&L,
constInterval&R);
friendIntervaloperator*(constInterval&L,intR);
friendIntervaloperator*(intL,constInterval&R);
friendIntervaloperator/(constInterval&L,intR);
friendint
operator==(constInterval&L,
constInterval&R);
friendint
operator!=(constInterval&L,
constInterval&R);
friendint
operator<(constInterval&L,
constInterval&R);
friendint
operator<=(constInterval&L,
constInterval&R);
friendint
operator>(constInterval&L,
constInterval&R);
friendint
operator>=(constInterval&L,
16
LoStandardODMG-93
constInterval&R);
};
Date
LaclasseDatecontieneunarappresentazionediunadatacompostadaanno,
meseegiorno.Pu�oessereinizializzataedusataanchenellarappresentazione
giulianadiunadata.Fornisceinoltreenumerazioniperdenotaregiornidella
settimanaedimesi.
Inizializzazione,assegnamento,aritmeticaefunzionidicomparazionesono
fornite.Leimplementazionipossonoaverefunzioniaggiuntivedisponibili
persupportareconversionedaedaltipousatodalsistemaoperativoper
rappresentareunadata.Sonofornitefunzioniperaccedereallecomponenti
diunadata.Cisonoanchefunzioniperdeterminareilnumerodelgiorno
inunmese,ecc.Lafunzionestaticacurrentrestituisceladatacorrente.Le
funzioninextepreviousavanzanoladataalprossimogiornodellasettimana
speci�cato.
De�nizione:
classDate{
public:
enumWeekday{
Sunday=0,
Monday=1,
Tuesday=2,
Wednesday=3,Thursday=4,
Friday=5,
Saturnday=6
};
enumMonth{
January=1,February=2,March=3,April=4,
May=5,June=6,July=7,August=8,September=9,
October=10,November=11,December=12
};
Date();
Date(unsignedshortyear,
unsignedshortjulian_day);
Date(unsignedshortyear,
unsignedshortmonth=1,
unsignedshortday=1);
DichiarazionidiAttributi
17
Date(constDate&);
Date(constTimestamp&);
Date&
operator=(constDate&);
Date&
operator=(constTimestamp&);
unsignedshort
year()const;
unsignedshort
month()const;
unsignedshort
day()const;
unsignedshort
day_of_year()const;
Weekday
day_of_week()const;
int
is_leap_year()const;
staticint
is_leap_year(unsignedshortyear);
staticDate
current();
Date&
next(Weekday);
Date&
previous(Weekday);
Date&
operator+=(constInterval&);
Date&
operator+=(intndays);
Date&
operator++();
Date
operator++(int);
Date&
operator-=(constInterval&);
Date&
operator-=(intndays);
Date&
operator--();
Date
operator--(int);
friendDate
operator+(constDate&L,
constInterval&R);
friendDate
operator+(constInterval&L,
constDate&R);
friendDate
operator-(constDate&L,
constInterval&R);
friendint
operator==(constDate&L,
constDate&R);
friendint
operator!=(constDate&L,
constDate&R);
friendint
operator<(constDate&L,
constDate&R);
friendint
operator<=(constDate&L,
constDate&R);
friendint
operator>(constDate&L,
constDate&R);
friendint
operator>=(constDate&L,
constDate&R);
int
is_between(constDate&,
18
LoStandardODMG-93
constDate&)const;
friendint
overlaps(constDate&psL,
constDate&peL,
constDate&psR,
constDate&peR);
friendint
overlaps(constTimestamp&psL,
constTimestamp&peL,
constDate&psR,
constDate&peR);
friendint
overlaps(constDate&psL,
constDate&peL,
constTimestamp&psR,
constTimestamp&peR);
staticint
days_in_year(unsignedshortyear);
int
days_in_year()const;
staticint
days_in_month(unsignedshortyr,
unsignedshortmonth);
int
days_in_month()const;
staticint
is_valid_date(unsignedshortyear,
unsignedshortmonth,
unsignedshortday);
int
is_valid()const;
};
Lefunzionioverlapsprendonodueperiodi(inizioe�ne),ogniperiododeno-
tatodauntempoinizialeedauno�nale,edeterminanoseidueperiodidi
temposisovrappongono.Lafunzioneisbetweendeterminaseilvaloredella
Date�einternoadunadatoperiodo.
Time
LaclasseTimevieneusataperdenotareun'orariospeci�co,che�einternamen-
teallocatocomeOraMediadiGreenwich(GreenwichMeanTime=GMT).
Inizializzazione,assegnamento,aritmeticaedoperatoridicomparazionesono
de�niti.Cisonoinoltrefunzioniperaccedereadognunodeicomponentidi
unvalorediorario.Leimplementazionipossonoaverefunzioniaggiuntive
disponibiliasupportareconversionidaealtipousatodalsistemaoperativo
perrappresentareiltempo.
DichiarazionidiAttributi
19
L'enumerazioneTimeZone�eresadisponibileperdenotareunaspeci�cazona
temporale.Lezonetemporalisononumerateinaccordocolnumerodiore
chedeveessereaggiuntoosottrattodall'orariolocaleperottenerel'oradi
Greenwich(InghilterraGMT).Cos��ilvalorediGMT�e0.UnaTimeZone
chiamataGMT6indicaun'orariodi6oreavantirispettoaGMTecos��6de-
veesseresottrattodaessoperottenereGMT.Alcontrario,GMT8signi�ca
chel'orario�e8oreindietrorispettoaGMT(leggereilsottotrattocomeun
meno).Unazonatemporaledidefaultvienemantenutaed�einizialmente
settatalavaloredellazonatemporalelocale.Risultapossibilecambiarela
zonatemporaledidefaultcomepureresettarlaalvalorelocale.
De�nizione:
classTime{
public:
enumTime_Zone{
GMT
=0,GMT12=12,GMT_12=-12,
GMT1
=1,GMT_1=-1,GMT2
=2,GMT_2=-2,
GMT3
=3,GMT_3=-3,GMT4
=4,GMT_4=-4,
GMT5
=5,GMT_5=-5,GMT6
=6,GMT_6=-6,
GMT7
=7,GMT_7=-7,GMT8
=8,GMT_8=-8,
GMT9
=9,GMT_9=-9,GMT10=10,GMT_10=-10,
GMT11=11,GMT_11=-11,
USeastern=-5,UScentral=-6,USmountain=-7,
USpacific=-8
};
staticvoid
set_default_Time_Zone(Time_Zone);
staticvoid
set_default_Time_Zone_to_local();
Time(unsignedshorthour,
unsignedshortminute,
floatsec);
Time(unsignedshorthour,
unsignedshortminute,
floatsec,shorttzhour,
shorttzminute);
Time(constTime&);
Time(constTimestamp&);
Time&
operator=(constTime&);
Time&
operator=(constTimestamp&);
20
LoStandardODMG-93
unsignedshort
hour()const;
unsignedshort
minute()const;
float
second()const;
short
tz_hour()const;
short
tz_minute()const;
staticTime
current();
Time&
operator+=(constInterval&);
Time&
operator-=(constInterval&);
friendTime
operator+(constTime&L,
constInterval&R);
friendTime
operator+(constInterval&L,
constTime&R);
friendInterval
operator-(constTime&L,
constTime&R);
friendTime
operator-(constTime&L,
constInterval&R);
friendint
operator==(constTime&L,
constTime&R);
friendint
operator!=(constTime&L,
constTime&R);
friendint
operator<(constTime&L,
constTime&R);
friendint
operator<=(constTime&L,
constTime&R);
friendint
operator>(constTime&L,
constTime&R);
friendint
operator>=(constTime&L,
constTime&R);
friendint
overlaps(constTime&psL,
constTime&peL,
constTime&psR,
constTime&peR);
friendint
overlaps(constTimestamp&psL,
constTimestamp&peL,
constTime&psR,
constTime&peR);
friendint
overlaps(constTime&psL,
constTime&peL,
constTimestamp&psR,
constTimestamp&peR);
DichiarazionidiAttributi
21
};
LefunzioniOverlapsprendonodueperiodi,ognunodenotatodaunorarioini-
zialeedauno�nale,edeterminanosedueperiodiditemposisovrappongono.
Timestamp
UnTimestampconsistedidataeorario.
De�nizione:
classTimestamp{
public:
Timestamp(unsignedshortyear,
unsignedshortmonty=1,
unsignedshortday=1,
unsignedshorthour=0,
unsignedshortminute=0,
floatsec=0.0);
Timestamp(constDate&);
Timestamp(constDate&,constTime&);
Timestamp(constTime&);
Timestamp&
operator=(constTimestamp&);
Timestamp&
operator=(constDate&);
Date&
date();
constTime&
time()const;
unsignedshort
year()const;
unsignedshort
month()const;
unsignedshort
day()const;
unsignedshort
hour()const;
unsignedshort
minute()const;
float
second()const;
short
tz_hour()const;
short
tz_minute()const;
staticTimestamp
current();
Timestamp&
operator+=(constInterval&);
Timestamp&
operator-=(constInterval&);
friendTimestamp
operator+(constTimestamp&L,
constInterval&R);
22
LoStandardODMG-93
friendTimestamp
operator+(constInterval&L,
constTimestamp&R);
friendTimestamp
operator-(constTimestamp&L,
constInterval&R);
friendint
operator==(constTimestamp&L,
constTimestamp&R);
friendint
operator!=(constTimestamp&L,
constTimestamp&R);
friendint
operator<(constTimestamp&L,
constTimestamp&R);
friendint
operator<=(constTimestamp&L,
constTimestamp&R);
friendint
operator>(constTimestamp&L,
constTimestamp&R);
friendint
operator>=(constTimestamp&L,
constTimestamp&R);
friendint
overlaps(constTimestamp&psL,
constTimestamp&peL,
constTimestamp&psR,
constTimestamp&peR);
friendint
overlaps(constTimestamp&psL,
constTimestamp&peL,
constDate&psR,
constDate&peR);
friendint
overlaps(constDate&psL,
constDate&peL,
constTimestamp&psR,
constTimestamp&peR);
friendint
overlaps(constTimestamp&psL,
constTimestamp&peL,
constTime&psR,
constTime&peR);
friendint
overlaps(constTime&psL,
constTime&peL,
constTimestamp&psR,
constTimestamp&peR);
};
DichiarazionidiCamminiAttraversoleRelazioni
23
2.2.2
DichiarazionidiCamminiAttraversoleRelazio-
ni
Lerelazioninonhannodellede�nizioniseparatesintatticamente.Comun-
queicamminitrasversalisonode�nitiall'internodeicorpidellede�nizioni
diognunodeiduetipidioggettichehannounruolonellarelazione.Per
esempio,sec'�eunarelazioneAdvisesuno-a-moltitraProfessoreStudent,
allorailcamminotrasversaleAdvises�ede�nitoall'internodellade�nizione
deltipodell'oggettoProfessoredilcamminotrasversaleAdvisor�ede�nito
all'internodellade�nizionedeltipodell'oggettoStudent.
Ladichiarazionediuncamminoattraversolerelazioni�esimilealladichia-
razionediunattributo,maconleseguentidi�erenze.Ilcodominiodiuna
relazionehauncamminoattraversolarelazione.Unadicharazionedicam-
minotrasversaleassomigliaadunadichiarazionediattributo,ma�eseguita
dallaparolachiaveinverseedalnomedelcamminoattraversolarelazione
nellaclasseall'altrocapodellarelazione.Ladichiarazionedell'attributode-
veesseredeltipoRef<T>,Set<Ref<T>>,orList<Ref<T>>
peralcune
classipersistentiT.Ilcamminodiattraversamentodellerelazionidesignato
dopolaparolachiaveinversedeveesseredichiaratonellaclasseT.Ilper-
corsotrasversaleadognicapodellarelazionedeveriferirsi,nellasuaclausola
inversa,alcorrispondentemembrodell'altraclassecoinvoltanellarelazione.
Ilnomedelcamminotrasversaleinversopu�oessereunnomecompleto.Lo
studiodellarelazionenegliesempiseguentirender�aquestoconcettochiaro.
Esempi:
classDepartment:publicPersistent_Object{
public:
Set<Ref<Professor>>professorsinverseProfessor::dept;
};
classProfessor:publicPersistent_Object{
public:
Ref<Department>
dept
inverseDepartment::professors;
Set<Ref<Student>>advisesinverse
Student::advisor;
};
classStudent:publicPersistent_Object{
public:
24
LoStandardODMG-93
Ref<Professor>
advisor
inverseProfessor:advisees;
Set<Ref<Course>>
classes
inverseCourse::students_enrolled;
};
classCourse:publicPersistent_Object{
public:
Set<Ref<Student>>students_enrolledinverseStudent::classes;
};
L'integrit�areferenzialedellerelazionibidirezionali�emantenutaautomati-
camentedallODBMS.Seunarelazioneesistetradueoggettiedunodegli
oggettivienecancellato,larelazionenonvienepi�uconsideratacomeesistente
edilcamminotrasversalesar�aalteratoperrimuoverelarelazione.
2.2.3
DichiarazionidiRelazioniUnidirezionali
PeradeguarsiadunapraticacomunenellaprogrammazioneC++,unaforma
degeneratadirelazionevienepermessa:quellachespeci�cauncamminoa
sensounico.Inquestocaso,laclausolainversevieneomessa.Siosserviche
lasintassiperladichiarazionedirelazioniunidirezionali�eattualmenteindi-
stinguibiledallasintassiC++utilizzataperdichiararemembriditipoRefo
qualunquesottoclassediCollectionchereferenziadunoggettopersistente.
Nelcasospeci�codirelazioniunidirezionali,�el'applicazioneadessererespon-
sabiledelmantenimentoconsistentedellarelazionequandol'oggetto(oggetti)
alla�nedelcammino�ecancellato(sonocancellati).Nessunmantenimento
diintegrit�areferenzialevienefattoperlerelazioniunidimensionali.
Taledichiarazionedirelazioneunidirezionalevienepermessasiaall'interno
diunaclassecheall'internodiunattributodiunastruttura.
Esempi:
structResponsible{
String
dept;
Ref<Employee>
e;
Date
due_date;
};
classOrder{
DichiarazionidiOperazioni
25
public:
Set<Ref<Client>>
who;
String
what;
Responsible
contact;
};
2.2.4
DichiarazionidiOperazioni
LedichiarazionidioperazioniinC++sonosintatticamenteidentichealledi-
chiarazionideimetodidiunaclasse.Adesempio,siguardigranttenure
eassigncoursede�nitiperlaclasseProfessornellasezione2.2.
2.3
C++
OML
QuestasezionedescriveillegameC++perl'OML.Unprincipioguidanel
progettodelC++ODL�echelasintassiusatapercreare,cancellare,identi-
�care,leggere/assegnareivaloridipropriet�aedinvocareoperazionisudiun
oggettopersistentedovrebberoessere,perquantopossibile,senzadi�erenze
rispettoaquellausataperglioggettidivitapi�ubreve.Unasingolaespres-
sionepu�oliberamentemischiareriferimentiadoggettipersistentietransienti.
L'obiettivoalungotermine�echenientepossaesserefattoconoggettipersi-
stentichenonpossaesserefattoancheconoggettitransienti;inrealt�aquesto
standardtrattaglioggettipersistentietransientiinmanieraunpocodi�e-
rente.Leinterrogazionielaconsistenzadelletransazionivengonoapplicate
soltantoaglioggettipersistenti.
2.3.1
Creazione,Cancellazione,Modi�caeRiferimenti
adOggetti
Glioggettipossonoesserecreati,cancellatiemodi�cati.Glioggettisono
creatiinC++
OMLusandol'operatorenew,che�eride�nitoperaccetta-
reargomentiaggiuntivichespeci�canoiltempodivitadell'oggetto.Una
pragmaopzionalediallocazionepermettealprogrammatoredispeci�carein
chemodoglioggettiappenaallocatidebbanoesseredispostinelrispettoagli
altrioggetti.
26
LoStandardODMG-93
LavariabilestaticaDatabase::transientmemory,dellaclasseDatabase,�ede-
�nitaperconsentirealibreriechecreinooggettidiessereusateindei�erente-
mentepercrearesiaoggettitransientichepersistenti.Questavariabilepu�o
essereusatacomevaloretragliargomentinell'operatorenew
dellabasedi
datipercreareoggetticontempodivitatransiente.
staticconstDatabase*constDatabase::transient_memory;
LeformeinODMGdell'operatoreC++newsono:
(1)void*operatornew(size_tsize,constchar*typename=0);
(2)void*operatornew(size_tsize,
constRef<Persistent_Object&clustering,
constchar*typename=0);
(3)void*operatornew(size_tsize,constDatabase*database,
constchar*typename=0);
Questioperatoripossiedonoilcampod'azionedeiPersistentObjectperle
cuiimplementazionivieneintrodottalaclassePersistentObject.(1)vie-
neusatapercreareoggettitransientiderivatidaiPersistentObject.(2)e
(3)creanooggettipersistenti.In(2)l'utentespeci�cachel'oggettoappena
creatodovrebbeesserepiazzato\vicino"alcilindroesistentepergliogget-
ti.L'esattainterpretazionedi\vicino"�ede�nitadall'implementazione.Una
possibileinterpretazionepotrebbeessere\nellastessapaginasepossibile".
In(3)l'utentespeci�cachel'oggettoappenacreatodovrebbeessereposto
nellabasedidatispeci�cata,manessunaallocazionevienespeci�cata.
L'argomentosize,cheapparecomeprimoargomentoinogniriga,rappre-
sentaladimansionedellarappresentazionedell'oggetto.Vienedeterminata
dalcompilatorecomeunafunzionedellaclassedellaqualeilnuovooggetto
�eunaistanza,enonpassatocomeunargomentoesplicitodalprogrammatore.
L'argomentoopzionaletipenameserveperspeci�careunnomeperunogget-
toevieneusatoinalcuneimplementazioni.
Leimplementazionidevonofornirealminimoquestetreformeepossono
renderedisponibilidellevarianti,conparametriaggiuntivi.Ogniparametro
aggiuntivodeveavereunvaloredidefault.Questopermetteadapplicazio-
nichenonusanoiparametriaggiuntividiessereportabili.Tipiciusidei
parametriaggiuntividovrebberoessererichiestediallocazioneinmemoria
Creazione,Cancellazione,Modi�caeRiferimentiadOggetti
27
distribuitaodipassaggiodiunaStringperilnomedellaclasse.
Esempi: D
atabase*yourDB,*myDB;
//siassumechevengano
//inizializzatiinmodocorretto
(1)
Ref<Schedule>temp_sched1=newSchedule;
(2)
Ref<Professor>prof2=new(yourDB,"Professor")Professor;
(3)
Ref<Student>student1=new(myDB)Student;
(4)
Ref<Student>student2=new(student1)Student;
(5)
Ref<Student>temp_student=
new(Database::transient_memory)Student;
L'istruzione(1)creal'oggettotransientetempsched1.Leistruzioni(2)-(4)
creanooggettipersistenti.L'istruzione(2)creaunanuovaistanzadellaclasse
ProfessornellabasedidatiyourDB.L'istruzione(2)illustraancheilpassag-
giodelnomediunaclassecomevaloredelterzoparametroopzionale.Forme
particolaridiquestoparametropossonoessererichiestedaalcuneimplemen-
tazioni.L'istruzione(3)creaunanuovaistanzadellaclasseStudentnella
basedidatimyDB.L'istruzione(4)falastessacosa,maspeci�cacheilnuo-
vooggettostudent2dovrebbeesserepostovicinoastudent1.L'istruzione
(5)creal'oggettotransientetempstudent.
CancellazionediOggetti
Glioggetti,appenacreati,possonoesserecan-
cellatiinC++OMLusandoilmetodoRef::deleteobject.Lacancellazione
diunoggetto�epermanente,sottomessaallatransazionecoinvolta.L'oggetto
vienerimossodallamemoriae,seerapersistente,dallabasedidati.L'istan-
zaRefesisteancorainmemoriamailsuovalorediriferimento�einde�nito.
UntentativodiaccedereaquestooggettodaqualunqueistanzaReffallisce
egeneraunerrore.
Esempi:
Ref<anyType>obj_ref;
...//sisettaobj_refinmodochereferenzi
//unoggettopersistente
obj_ref.delete_object();
IlC++richiedechel'operandodideletesiaunpuntatore,cos��lacancella-
zionediunoggettoreferenziatodaunRefrichiedecheunafunzionemembro
28
LoStandardODMG-93
tipodeleteobjectsiade�nita.L'invocazionedideletesudiunRefrisulta
essereunerroredicompilazione,infattiRefnon�eunpuntatore.
Modi�cadiOggetti
Lostatodiunoggettovienemodi�catocambiando
lesuepropriet�aoinvocandooperatorisudiesso.Lamodi�cadioggetti
persistentivieneresavisibiledaglialtriutentidellabasedidatiquandovie-
neeseguitaunaoperazionedicommitsudiunatransazionecontenentela
modi�ca.
Glioggettipersistentichesonostatidistruttiomodi�catidevonocomuni-
care,durantel'esecuzionedelprocessoODBMS,ilfattocheillorostato�e
cambiato.L'ODBMSmodi�cher�alabasedidaticonquestinuovidatiquan-
dolatransazioneverr�ae�ettivamenteeseguita.Ilcambiamentodioggetti,
de�nitanellasezione2.3.4,vieneusatonelmodoseguente:
obj_ref->mark_modified();
Lachiamataallafunzionemarkmodi�ed�einclusaneimetodidelcostrut-
toreedistruttoreperleclassicapacidipersistenza,i.e.,perlaclassePersi-
stentObject.Losviluppatoredovrebbeincluderelachiamatainognialtro
metodochemodi�caoggettipersistenti.
Perconvenienza,ilprogrammatorepu�oometterelechiamateamarkmodi�ed
suglioggettilecuiclassisianostatecompilateusandounappositopara-
metrodiunpre-processoreC++
OML;ilsistemaindividuer�aautomati-
camentequandoglioggettisonomodi�cati.Nelcasodidefault,lechia-
mateamarkmodi�edsonorichiesteperch�einalcuneimplementazionisa-
rebbemegliochefosseilprogrammatorestessoarichiamareesplicitamente
markmodi�ed.Comunque,ognivoltacheunoggettopersistentevienemo-
di�catodaunmetodofornitoesplicitamentedalleclassiODMG,lachiamata
amarkmodi�ednon�enecessariainquantoquestovienefattoautomatica-
mente.
RiferimentiadOggetti
Glioggetti,sianoessipersistentioppureno,pos-
sonoreferenziarealtrioggettiattraversoriferimentiadoggetti.InC++OML
iriferimentiadoggettisonoistanzedellaclassetemplateRef<T>(vedisezio-
ne2.3.5).Tuttigliaccessiadoggettipersistentisonofattiattraversometodi
Creazione,Cancellazione,Modi�caeRiferimentiadOggetti
29
de�nitinelleclassiRef,PersistentObjecteDatabase.L'operatoredidere-
ferenziazione->vieneusatoperaccedereaimembridell'oggettopersistente
\puntato"daundatoriferimentoadoggetto.Inchemodounriferimentoad
oggettovieneconvertitoinunpuntatoreC++all'oggetto�eunade�nizione
dell'implementazione.
Unaoperazionedidereferenziazionesuunriferimentoadoggettogarantisce
semprechel'oggettoreferenziatovienerestituitooppurevienegeneratoun
errore.Ilcomportamentodiunriferimento�eilseguente.Seunriferimen-
toadoggettosiriferisceadunoggettopersistentecheesistemanon�ein
memoriaquandounadereferenziazionevienefatta,vieneautomaticamente
prelevatodadisco,mappatoinmemoriaerestituitoassiemealrisultatodella
dereferenziazione.Sel'oggettoreferenziatononesiste,unerrorerelativovie-
negenerato.Iriferimentiadoggettitransientifunzionanoesattamenteallo
stessomodo(oalmenoinsuper�cie).
Ogniriferimentoadoggettipu�oesseresettatoadunriferimentonulloocan-
cellatoperindicareunriferimentochenonsiriferisceanessunoggetto.
Leregoleperquandounoggettodurantelasuavitapossariferireadun
altrodiunaltrotempodivitasonounadirettaestensionedelleregoleC++
perlesuedueformedioggettitransienti-processieprocedurelimitrofe.
Unoggettopu�osempreriferirsiadunaltrooggettoditempovitamaggiore.
Unoggettopu�oriferirsiadunoggettoditempodivitaminoresolomentre
l'oggettoditempodivitapi�ubreveesiste.
Unoggettopersistentevieneprelevatodadiscoallasuaattivazione.Risulta
responsabilit�adell'applicazioneinizializzareivaloridiognipuntatoreadog-
gettochepuntiadoggettitransienti.Infatti,quandounoggettopersistente
vienecoinvolto,l'ODBMSsettaituttisuoiRefinterniadoggettitransienti
edipuntatoriinternialvalore0.
NomidiOggetti
Un'applicazioneperbasididatigeneralmenteinizier�a
processandotramitel'accessounoopi�uoggetticriticieproceder�adaessi.
Questioggettisonoinuncertosensooggetti\radice",cheguidanoallarete
diinterconnessionedeglialtrioggetti.Lapossibilit�adinominareoggettie
recuperarlipi�utarditramiteilnomerendefacilitatelecapacit�adiinizia-
lizzazione.Ladenominazionedioggetti�eancheconvenienteinmoltealtre
situazioni.
30
LoStandardODMG-93
C'�eunsoloscopedname,inunabasedidati;cos��tuttiinomiinunapartico-
larebasedidatisonounici.Unnomenon�eesplicitamentede�nitocomeun
attributodiunoggetto.Leoperazionipermanipolareinomisonode�nite
nellaclasseDatabasenellasezione2.3.8.
2.3.2
Propriet�a
Attributi
IlC++OMLutilizzalostandardC++peraccedereagliattri-
buti.Peresempio,assumendocheprofsiastatoinizializzatoperreferenziare
unprofessoreenoivogliamomodi�careilsuoid\_number:
prof->id_number=next_id;
cout<<prof->id_number;
Lamodi�cadiunvalorediunattributovieneconsideratacomeunamodi�-
cadell'interaistanzaoggetto.Occorrechiamaremarkmodi�edperl'oggetto
primadicompierelatransazione.
IllegamecolC++permettealleclassipersistentidiincludereclassiC++ed
altreclassipersistenti.Tuttavia,glioggettiinterninonsonoconsiderati"og-
gettiindipendenti"enonpossiedonoun'identit�adioggettopersonale.Agli
utentinonvienepermessodimanipolareunRefadunoggettointerno.Esat-
tamentecomeunattributo,lamodi�cadiunoggettointernovieneconside-
ratacomelamodi�cadell'interaistanzaoggettocontenitoreemarkmodi�ed
perl'oggettocontenitoredeveesserechiamataprimadicompierelatransa-
zione.
Relazioni
L'ODLspeci�caqualirelazioniesistonotraclassidioggetti.
Creazione,attraversamentoecancellazionedirelazionifraistanzesonode�-
niteinC++OML.Icamminitrasversalia-unoea-moltisonosupportatida
OML.L'integrit�adellerelazionivienemantenutadall'ODBMS.
Idiagrammiseguentimostrerannogra�camenteglie�ettidell'aggiunta,mo-
di�caecancellazionedirelazionifraleclassi.Adognidiagrammaviene
datounnomecheri ettelacardinalit�ael'e�ettosullarelazione.Ilnome
comincer�acon1-1,1-m
om-m
perdenotarelacardinalit�aeterminer�acon
Propriet�a 31
a
rarb
b
Figura 2.2: 1-1N: Nessuna relazione
N(Nessuna relazione), A(Aggiunta di una relazione) o M(Modi�ca di una
relazione). Quando una relazione viene cancellata, si torner�a nello stato che
non possiede relazioni (N).
Sebbene i cammini di attraversamento delle relazioni siano disegnati all'in-
terno di un'istanza di una classe, questo non signi�ca che l'implementazione
inserisca �sicamente il cammino di attraversamento della relazione come un
membro all'interno della classe. Una linea continua viene disegnata per indi-
care una operazione esplicita eseguita dal programma e una linea tratteggiata
mostra l'e�etto collaterale eseguito automaticamente dall' ODBMS per man-
tenere l'integrit�a referenziale.
Assumiamo che la seguente relazione 1-1 esista tra le classi A e B:
class A {
Ref<B> rb inverse B::ra;
};class B {
Ref<A> ra inverse A::rb;
};
Si noti che la classe A e la classe B potrebbero essere la stessa classe. In
ognuno dei diagrammi mostrati, ci sar�a un'istanza di A chiamata a oppure
aa ed un'istanza di B chiamata b o bb. Nello scenario 1-1N di �gura 2.2, non
ci sono relazioni tra a e b.
Quindi aggiungiamo una relazione tra a e b attraverso
a.rb=&b;
32 Lo Standard ODMG-93
ra
a
rb
b
Figura 2.3: 1-1A: Aggiunta di una relazione
il risultato �e quello mostarato in �gura 2.3.
La freccia continua indica l'operazione speci�cata dal programma e quel-
la tratteggiata mostra che operazione viene svolta automaticamente dal-
l'ODBMS.
Prendiamo ora in considerazione il diagramma precedente (�gura 2.3) e sup-
poniamo che rappresenti lo stato corrente della relazione tra a e b. Se il
programma esegue l'istruzione
a.rb.clear();
il risultato sarebbe l'assenza di relazioni come mostrato in �gura 2.2.
Riprendiamo nuovamente in considerazione la relazione mostrata in �gu-
ra 2.3. Se noi adesso eseguiamo
a.rb=&bb;
otteniamo il risultato mostrato in �gura 2.4.
Si noti che b.ra non referenzia pi�u a e bb.ra viene settato automaticamente
come riferimento ad a.
Il cammino attraverso la relazione rb si comporta come se fosse un attributo
della classe A il cui tipo potrebbe essere la classe seguente che de�nisce le
operazioni disponibili su rb. Le operazioni che hanno e�etto sulla relazione
possiedono un commento che indica quale dei precedenti scenari 1-1 si avreb-
be come risultato dopo che l'operazione fosse stata eseguita.
Propriet�a 33
bb
ra
rb
a
ra
b
Figura 2.4: 1-1M: Modi�ca di una Relazione
class A_to_B {
public:
A_to_B() // N
A_to_B(const A_to_B &f); // A, se
//r non e nullo
A_to_B(const Ref<B> &f); // A, se
//r non e nullo
A_to_B(B *r); // A, se
//r non e nullo
~A_to_B() // N
// Attraversamenti della relazione
Ref<B> get() const;
operator Ref<B>() const;
operator Ref_Any<B>() const;
B * operator->() const;
B & operator*() const;
// Instaurazione della relazione
A_to_B & set(const A_to_B &); // A or M
A_to_B & set(const Ref<B> &); // A or M
A_to_B & set(B *); // A or M
34 Lo Standard ODMG-93
A_to_B & operator=(const A_to_B &); // A or M
A_to_B & operator=(const Ref<B> &); // A or M
A_to_B & operator=(B *); // A or M
A_to_B & set(const A_to_B &); // A or M
// Cancellazione della relazione
void clear(); //N
int is_null() const;
void delete_object() //N
friend int operator==(const A_to_B &, const A_to_B &);
friend int operator==(const A_to_B &, const Ref<B> &);
friend int operator==(const Ref<B> &, const A_to_B &);
friend int operator==(const A_to_B &, const Ref_Any &);
friend int operator==(const Ref_Any &, const A_to_B &);
friend int operator==(const A_to_B &, const B *);
friend int operator==(const B *, const A_to_B &);
friend int operator!=(const A_to_B &, const A_to_B &);
friend int operator!=(const A_to_B &, const Ref<B> &);
friend int operator!=(const Ref<B> &, const A_to_B &);
friend int operator!=(const A_to_B &, const Ref_Any &);
friend int operator!=(const Ref_Any &, const A_to_B &);
friend int operator!=(const A_to_B &, const B *);
friend int operator!=(const B *, const A_to_B &);
};
Ogni qualvolta l'operando di inizializzazione o assegnamento rappresenta un
riferimento nullo, il risultato sar�a una assenza di relazioni come in 1-1N. Nel
caso dell'assegnamento, se ci fosse una relazione, verrebbe rimossa. Se la
relazione �e attualmente nulla (is null restituirebbe vero), un assegnamento
potrebbe aggiungere una relazione, a meno che anche l'operando di assegna-
mento fosse nullo.
Se esiste gi�a una relazione con un oggetto, il fare un assegnamento modi�ca
la relazione come in 1-1M. Se l'operando di assegnamento �e nullo, la relazione
esistente viene rimossa.
Quando un oggetto coinvolto in una relazione viene cancellato, tutte le rela-
Propriet�a 35
sb
a b
ra
Figura 2.5: 1-mN: Nessuna relazione
zioni in cui l'oggetto era coinvolto saranno rimosse.
Ci sono altre due cardinalit�a da considerare: uno-a-molti e molti-a-molti.
Dopo aver dato una descrizione gra�ca degli e�etti delle operazioni su di
una relazione di entrambe queste cardinalit�a, sar�a speci�cata l'interfaccia
del cammino di attraversamento della relazione, sia esso disordinato oppure
posizionale.
Consideriamo una relazione disordinata di insieme uno-a-molti tra le classi
A e B:
class A {
Set<Ref<B>> sb inverse B::ra;
};class B {
Ref<A> ra inverse A::sb;
};
Supponiamo di avere le seguenti istanze a e b senza relazioni (�gura 2.5)
a.sb possiede tre elementi, ma essi si riferiscono ad istanze di B diverse da b.
Ora supponiamo di aggiungere la relazione tra a e b eseguendo l'istruzione
36 Lo Standard ODMG-93
sb
a b
ra
Figura 2.6: 1-mA: Aggiunta di una relazione
a.sb.insert_element(&b);
Il risultato �e quello di �gura 2.6:
Il cammino trasversale b.ra viene settato automaticamente per riferenziare
a. Se invece noi eseguiamo l'istruzione
b.ra=&a;
un elemento verr�a automaticamente aggiunto ad a.sb per riferirsi a b. Ma �e
necessario eseguire nel programma soltanto una delle due operazioni, l'ODBMS
automaticamente genera il cammino trasversale inverso.
Data la situazione mostrata in �gura 2.6, se noi eseguiamo
a.sb.remove_element(&b) oppure b.ra.clear();
il risultato sarebbe che la relazione tra a e b verrebbe rimossa e lo stato di a
e b sarebbe nuovamente quello indicato in �gura 2.5.
Propriet�a 37
aa
a
sb
sb
ra
b
Figura 2.7: 1-mM: Modi�ca di una relazione
Adesso assumiamo di avere una relazione tra a e b come mostrato in �gu-
ra 2.6. Se eseguiamo la seguente istruzione:
b.ra=&aa;
il risultato viene evidenziato in �gura 2.7
Dopo che l'istruzione �e stata eseguita, b.ra si riferisce ad aa e come e�etto
collaterale, l'elemento interno ad a.sb che referenziava b �e stato rimosso men-
tre un elemento �e stato aggiunto ad aa.sb in modo che si riferisca a b.
La terza cardinalit�a di una relazione da considerare �e molti-a-molti. Suppo-
niamo di avere la seguente relazione tra A e B.
class A {
Set<Ref<B>> sb inverse B::sa;
};class B {
Set<Ref<A>> sa inverse A::sb;
38 Lo Standard ODMG-93
sa
a b
sb
Figura 2.8: m-mN: Nessuna relazione
};
Inizialmente, non ci sono relazioni tra le istanze a e b, bench�e a e b abbiano
relazioni con altre istanze (�gura 2.8).
La seguente istruzione aggiunge una relazione tra a e b.
a.sb.insert_element(&b);
Il risultato �e quello di �gura 2.9:
In aggiunta al fatto che un elemento che referenzi b �e stato aggiunto ad a.sb,
c'�e un elemento che referenzia a inserito automaticamente in b.sa.
Eseguendo ancora
a.sb.remove_element(&b) oppure b.sb.remove_element(&a)
risulta che la relazione tra a e b �e stata rimossa e si �e ritornati alla situazione
m-mN.
Propriet�a 39
sa
a b
sb
Figura 2.9: m-mA: Aggiunta di una relazione
Per ultimo consideriamo la modi�ca ad una relazione molti-a-molti. Assu-
miamo lo stato precedente mostrato in m-mA, ed assumiamo anche che sb
rappresenti una relazione posizionale. La seguente istruzione modi�ca una
relazione esistente tra a e b, facendo in modo che a venga posto in relazione
con bb.
a.sb.replace_element_at(&bb,3);
Il risultato viene mostrato in �gura 2.10:
Il risultato di questa operazione �e che l'elemento in b.sa che referenziava a �e
stato rimosso ed un elemento che referenzia a �e stato aggiunto a bb.sa.
Lo stesso concetto \generatore" applicato per cammini trasversali a-molti
viene anche applicato per cammini trasversali a-uno. Nella sintassi C++
ODL, un cammino trasversale a-molti assomiglia ad un'istanza di una sem-
plice classe collezione (dove ogni classe collezione �e attualmente una classe
template). Tuttavia, per implementare la semantica delle relazioni, il cam-
mino trasversale deve essere convertito in un attributo C++ OML che �e
un'istanza di una classe che \capisce" il tipo di cammino trasversale che �e
stato dichiarato.
40 Lo Standard ODMG-93
b
sb
a
sa
sa
bb
Figura 2.10: m-mM: Modi�ca di una relazione
Propriet�a
41
Conrelazioniuno-a-moltiemolti-a-molti,l'insiemedelleoperazionipermesse
�ebasatosulfattochelarelazionesiauninsiemedisordinatooposizionale.
Dataunarelazionea-moltitraAeBcomein
classA{
Set<Ref<B>>sb
inverseB::ra;
};
sbsicomportacomesefosseunattributodellaclasseAdeltipodellaclasse
seguenteAtoBschede�nisceleoperazionidisponibilisusb.Ogniopera-
zionechealteralarelazionehauncommentocheindicaqualescenariosi
avrebbecomerisultatodell'operazione.
classA_to_Bs{
public:
A_to_Bs();
//N
A_to_Bs(constA_to_Bs&s);
//A,
//Nses\`enullo
A_to_Bs(constSet<Ref<B>>&s);
//A,
//Nses\`enullo
~A_to_Bs();
//N
Set<Ref<B>>
get()const;
A_to_Bs&
set(constA_to_Bs&);
//M,
//Asenessunantecedente
A_to_Bs&
set(constSet<Ref<B>>&);
//M,
//Asenessunantecedente
A_to_Bs&
operator=(constA_to_Bs&);
//M,
//Asenessunantecedente
A_to_Bs&
operator=(constSet<Ref<B>>&);
//M,
//Asenessunantecedente
Iterator<Ref<B>>
create_iterator()const;
unsignedlong
cardinality()const;
int
is_empty()const;
int
contains_element(constRef<B>&)const;
void
insert_element(constRef<B>&);
//A
42
LoStandardODMG-93
void
remove_element(constRef<B>&);
//N
void
remove_all();
//Npertutti
};
LeinizializzazioniegliassegnamentichehannounargomentodeltipoAtoBs
oppureSet<Ref<B>>sonomoltopi�ucoinvolterispettoaisemplicidiagram-
miprecedentiperch�ecoinvolgonol'esecuzionedellecorrispondentioperazioni
perognielementodell'insiemerispettoalfarloperunsoloelemento.Lafun-
zioneremoveallrimuoveognimembrodellarelazione,togliendoancheogni
riferimentoall'indietroperognunodeimembrireferenziati.Seglioperato-
ridiassegnamentohannounargomentocherappresentauninsiemevuoto,
l'assegnamentoavr�alostessoe�ettodellafunzioneremoveall.
Questespeci�chesupportanoilconcettodiiteratoretramiteunagenerica
classetemplatechiamataIterator,manoncisonocertamenteragioniper
cuiunasottotemplatespecializzatadiquestaclassenonpossaesserede�ni-
ta.L'iteratorevieneutilizzatoperattraversaretuttiimembridellarelazione.
LaclasseListrappresentaunacollezioneposizionale,mentrelaclasseSet�e
semplicementeunacollezionedisordinata.Assumendounarelazionea-molti
posizionaletraunaclasseAedunaclasseB:
classA{
List<Ref<B>>sb
inverseB::ra;
};
sbsicomportacomesefosseunattributodellaclasseAdeltipodellaclasse
seguenteAtoBpchede�nisceleoperazionidisponibilisusb.
classA_to_Bp{
public:
A_to_Bp();
//N
A_to_Bp(constA_to_Bp&s);
//A,
//Nses\`enullo
A_to_Bp(constList<Ref<B>>&s);
//A,
//Nses\`enullo
~A_to_Bp();
//N
List<Ref<B>>
get()const;
Propriet�a
43
A_to_Bp&
set(constA_to_Bp&);
//M,
//Asenessunantecedente
A_to_Bp&
set(constList<Ref<B>>&);
//M,
//Asenessunantecedente
A_to_Bp&
operator=(constA_to_Bp&);
//M,
//Asenessunantecedente
A_to_Bp&
operator=(constList<Ref<B>>&);//M,
//Asenessunantecedente
Iterator<Ref<B>>
create_iterator()const;
//Testdiesistenza
int
is_empty()const;
unsignedlong
cardinality()const;
int
contains_element(constRef<B>&)const;
int
find_element(constRef<B>&,
unsignedlong&pos)const;
//Recuperodirelazioni
Ref<B>
retrieve_element_at(
unsignedlongpos)const;
Ref<B>
operator[](intposition)const;
Ref<B>
retrieve_first_element()const;
Ref<B>
retrieve_last_element()const;
//Instaurazionedirelazioni
void
insert_element(constRef<B>&);
//A
void
insert_element_first(constRef<B>&);
//A
void
insert_element_last(constRef<B>&);
//A
void
insert_element_after(constRef<B>&,
//A
unsignedlongpos);
void
insert_element_before(constRef<B>&,
//A
unsignedlongpos);
void
replace_element_before(unsigendlongpos,//M
constRef<B>&);
//Rimozionedirelazioni
void
remove_element(constRef<B>&);
//N
void
remove_first_element();
//N
void
remove_last_element();
//N
void
remove_element_at(unsignedlongpos);
//N
void
remove_all();
//N
44
LoStandardODMG-93
};
Naturalmenteleclassipossonoanchede�niredeimetodispeci�cidelvendi-
tore.Ma,pi�uimportante,essidevonogestireogniintegrit�areferenzialeche
siarichiestaedognicaratteristicadiunarelazionespeci�cadelvenditoreche
siadichiaratenelC++ODL.Unaimplementazioneconformepu�oscegliere
diusareunasolaclasse\base"pertuttiitipidirelazioneopu�ode�nireclassi
direlazionispecializzate.
Esempi:
Ref<Professor>p;
Ref<Student>Sam;
Ref<Department>english_dept;
//Inizailizzazionedeiriferimentidip,Sameenglish_dept
p->dept=english_dept;
//creazionediunarelazione1:1
p->dept.clear();
//cancellalarelazione
p->advisees.insert_element(Sam);//aggiungeSam
//all'insiemedeglistudenti
//consigliatidap;halostesso
//effettodi'Sam->advisor=p'
p->advisees.remove_element(Sam);//rimuoveSamdell'insieme
//deglistudenti
//consigliatidaped
//inoltrecancella
//Sam->advisor
2.3.3
Operazioni
Leoperazionisonode�niteinOMLcomeingeneraleinC++.Leoperazioni
suoggettitransientiepersistentisicomportanointeramentecomede�nito
nelcontestooperazionalede�nitonellostandardC++.Questoincludeleso-
vrapposizioni,l'invio,lastrutturadichiamatael'invocazionedellefunzioni,
lastrutturadichiamatael'invocazionedeimetodi,ilpassaggiodiparametri
elarisoluzione,lagestionedeglierrori,eleregoledicompilazione.
ClassePersistentObject
45
2.3.4
ClassePersistentObject
LaclassePersistentObjectvieneintrodottaede�nitacomesegue:
De�nizione:
classPersistent_Object{
public:
Persistent_Object();
Persistent_Object(constPersistent_Object&);
~Persistent_Object();
void
mark_modified();//marcal'oggetto
//comemodificato
void*
operatornew(size_tsize,
constchar*typename=0);
void*
operatornew(size_tsize,
Ref<Persistent_Object>cluster,
constchar*typename=0);
void*
operatornew(size_tsize,Database*database,
constchar*typename=0);
virtualvoid
odb_activate();
virtualvoid
odb_deactivate();
};
Questaclassevieneintrodottaperpermettereachide�nisceitipidispe-
ci�carequandounaclasse,de�nitaallostessomododiquelletransienti,�e
ingradodirimanerepersistente.UnaclasseAchesiapersistentedovrebbe
ereditaredallaclassePersistentObject:
classMy_Class:public:Persistent_Object{...};
Alcuneimplementazioni,ancheseaccettanolasuperclassePersistentObject
comeindicazionedipersistenzapotenziale,nonnecessitanodell'introduzione
�sicadiunaclassePersistentObject.Tutteleimplementazioniaccettano
chiamateamarkmodi�edancheselaclassePersistentObjectnonesiste.
Perpermettereadun'applicazionediinizializzarepartitransientidiunog-
gettopersistente,lafunzioneobjactivatepu�oessereride�nitainogniclasse
46
LoStandardODMG-93
persistente.Questafunzione�echiamataautomaticamentequandounogget-
tovienemessoinmemoria.Alcontrario,quandounoggettovienerimosso
dallamemoria,lafunzioneodbdeactivatevienechiamataautomaticamen-
te.Risultaresponsabilit�adell'applicazioneride�nirequestefunzioniinuna
classecapacedipersistenzaquandolacontabilit�a�estatafattaperlaparte
transientediunoggettopersistente.
2.3.5
ClasseRef
Glioggettipossonoriferirsiadaltrioggettiattraversounpuntatoreoppure
tramiteunriferimentochiamatoRef.UnRef<T>�eunriferimentoaduna
istanzaditipoT.C'�eancheunaclasseRefAnyde�nitaperfornireungene-
ricoriferimentoadognitipo.
UnRef�eunaclassetemplatede�nitacomesegue:
De�nizione:
template<classT>classRef{
public:
Ref();
Ref(T*fromPtr);
Ref(constRef<T>&);
Ref(constRef_Any&);
~Ref();
operatorRef_Any()const;
Ref<T>&
operator=(T*);
Ref<T>&
operator=(constRef<T>&);
Ref<T>&
operator=(constRef_Any&);
void
clear();
T*
operator->()const;//dereferenziail
//riferimento
T&
operator*()const;
T*
ptr()const;
int
is_null()const;
void
delete_object();//cancellal'oggetto
//referenziatodallamemoria
//edallabasedidati
ClasseRef
47
//questiRefepuntatoripossonoriferirsi
//aglistessioggetti?
friendint
operator==(constRef<T>&refL,
constRef<T>&refR);
friendint
operator==(constRef<T>&refL,
constT*ptrR);
friendint
operator==(constT*ptrL,
constRef<T>&refR);
friendint
operator==(constRef<T>&refL,
constRef_Any&anyR);
friendint
operator==(constRef_Any&anyL,
constRef<T>&refR);
friendint
operator!=(constRef<T>&refL,
constRef<T>&refR);
friendint
operator!=(constRef<T>&refL,
constT*ptrR);
friendint
operator!=(constT*ptrL,
constRef<T>&refR);
friendint
operator!=(constRef<T>&refL,
constRef_Any&anyR);
friendint
operator!=(constRef_Any&anyL,
constRef<T>&refR);
};
Iriferimenti,inmoltiaspetti,sicomportanocomepuntatoriC++,maforni-
sconounmeccanismoaggiuntivochegarantiscel'integrit�aneiriferimentiad
oggettipersistenti.AncheselasintassiperdichiarareunRef�edi�erenteda
quellaperdichiarareunpuntatore,l'utilizzo�e,nellamaggiorpartedeicasi,
lostessochesefosserosovrapposti;e.g.,iRefadunaclassepossonoessere
dereferenziaticonl'operatore*,assegnaticonl'operatore=,ecc.UnRefad
unaclassepu�oessereassegnatoadunRefdiunasuperclasse.IRefpossono
esserespecializzatiperfornirecomportamentireferenzialispeci�ci.
Ilpuntatoreoilriferimentorestituitodall'operatore->odall'operatore*�e
validosolamente�nch�eRefnonvienecancellato,latransazionepi�uesterna
termina,oppure�nch�el'oggettoacuipuntavienecancellato.Ilpuntatore
restituitodaptrrestavalido�nch�elatransazionepi�uesternahatermineo
�nch�el'oggettoacuipuntavienecancellato.IlvalorediunRefdopol'ese-
48
LoStandardODMG-93
cuzionediunatransazione(siaessaandataomenoabuona�ne)�einde�nito.
UnaclasseRefAny�ede�ntapersupportareunriferimentoadognitipo.
Ilsuoobiettivoprincipale�edimanipolareriferimentigenericiepermettere
laconversionediRefinuntipogerarchico.UnoggettoRefAnypu�oesse-
reusatocomeunintermediariotraqualunqueduetipiRef<X>eRef<Y>
doveXeYsonotipidi�erenti.UnRef<T>
pu�osempreessereconverti-
toinunRefAny;c'�eunafunzionechesvolgelaconversioneneltemplate
Ref<T>.OgniclasseRef<T>
possiedeuncostruttoreedunoperatoredi
assegnamentocheprendeunriferimentoadunRefAny.L'oggettoreferen-
ziatodall'argomentoRefAnydeveessereditipoTounasottoclassediT,
altrimentivienesegnalatounerrore.
LaclasseRefAny�ede�nitacomesegue:
De�nizione:
classRef_Any{
public:
Ref_Any();
Ref_Any(constRef_Any&);
Ref_Any(Persistent_Object*);
~Ref_Any();
Ref_Any&
operator=(constRef_Any&);
Ref_Any&
operator=(Persistent_Object*);
void
clear();
int
is_null();
void
delete_object();
friendint
operator==(constRef_Any&,
constRef_Any&);
friendint
operator==(constRef_Any&,
constPersistent_Object*);
friendint
operator==(constPersistent_Object*,
constRef_Any&);
friendint
operator!=(constRef_Any&,
constRef_Any&);
friendint
operator!=(constRef_Any&,
constPersistent_Object*);
friendint
operator!=(constPersistent_Object*,
ClassiCollezione
49
constRef_Any&);
};
Leoperazionide�nitesuRef<T>nonsonodipendentidaunospeci�cotipo
TchesiastatofornitonellaclasseRefAny.
2.3.6
ClassiCollezione
Itemplatecollezionesonofornitipersupportarelarappresentazionediuna
collezioneicuielementisonodiuntipoarbitratio.Unaimplementazione
devesupportarealmenoiseguentisottotipidiCollection:
�
Set
�
Bag
�
List
�
Varray
Lede�nizionidiclassidelC++perognunodiquestitipisonode�nitinelle
sottosezioniseguenti.Gliiteratorisonode�nitiununasottosezione�nale.
LaseguentediscussioneutilizzalaclasseSetperspiegarelecollezioni,mala
descrizionepu�oessereapplicataatutteleclassiderivatedaCollection.
DattounoggettodeltipoT,ladichiarazione
Set<T>s;
de�nisceunacollezioneSeticuielementisonodeltipoT.Sequestoset
vieneassegnatoadun'altrosetdellostessotipo,entrambiglioggettiSeted
ognielementodelsetvengonocopiati.Glielementisonocopiatiusandola
semanticadicopiade�nitaperiltipoT.Unaconvenzionecomunesar�aquella
diaverecollezionichecontengonoRefadoggettipersistenti.Adesempio,
Set<Ref<Professor>>faculty;
50
LoStandardODMG-93
LaclasseRefhaunasemanticadicopiapocoprofonda.PerunSet<T>,se
T�editipoRef<C>
perunaclassepersistenteC,sologlioggettiRefsono
copiati,nonglioggettiCcheglioggettiRefreferenziano.
Questo�evalidoinognicampo;inparticolare,ses�edichiaratocomeattributo
all'internodiunaclasse,l'interosetsar�ainseritoall'internocomeun'istanza
dellaclasseSet.Quandounoggettodiquestaclasseinclusa�ecopiatoin
un'altrooggettodellastessaclasse,ilsetinternovienevoltacopiatoseguendo
lasemanticadicopiade�nitasopra.Questodeveesseredi�erenziatodalla
dichiarazione
Ref<Set<T>>ref_set;
chede�nisceunriferimentoadunSet.Quandounriferimento�ede�nitocome
unapropriet�adiunaclasse,questosigni�cacheilset�eunoggettoindipenden-
techegiacefuoridaun'istanzadellaclasse.Parecchioggettipossonoavere
incomunelostessoset,anchesecopiandounoggettononsicopier�aancheil
set,masoltantoilriferimentoadesso.Questoverr�aillustratoinFigura2.11.
Glielementidiunacollezionepossonoesserediognitipo.
OgnitipoT
chediventaunelementodiunadatacollezionedevesupportareleseguenti
operazioni:
classT{
public:
T();
T(constT&);
~T();
T&
operator=(constT&);
friendint
operator==(constT&,constT&);
};
Questo�el'insiemecompletodellefunzionirichiesteperde�nirelesemantiche
dicopiaperundatotipo.Peritipicherichiedonounordine,deveanche
esserefornitalaseguenteoperazione
friendint
operator<(constT&,constT&);
Classi Collezione 51
Si noti che il compilatore C++ generer�a automaticamente un costruttore di
copia ed un operatore di assegnamento se il progettista della classe non ne
dichiara uno. Si noti anche che la classe Ref<T> fornisce queste operazioni,
eccetto che per operator<.
Le collezioni di letterali, inclusi letterali atomici e strutturati, sono de-
�nite come parte dello standard. Queste includono primitive ed i tipi
Set<literal type> de�niti dall'utente sono de�niti con lo stesso comporta-
mento; e.g., Set<int>, Set<Struct time t>.
Il diagramma mostrato in �gura 2.11 illustra vari tipi coinvolgenti Set, Ref,
tipi letterali L (int per esempio) e classi persistenti T. L'oggetto Set �e rap-
presentato da un rettangolo che referenzia ad un insieme di elementi del tipo
speci�cato. Una freccia continua �e usata per denotare il contenimento del-
l'insieme di elementi all'interno dell'oggetto Set. I Ref hanno delle frecce
tratteggiate che puntano agli oggetti referenziati del tipo T.
Classe Collection La classe Collection �e una classe astratta in C++ e
non pu�o avere istanze. Deriva da Persistent Object, permette istanze di
classi concrete derivate da essa. Come per il caso a�rontato nella sezio-
ne 2.3.4 sui Persistent Object, non tutte le implementazioni richiedono che
la classe Persistent Object venga introdotta per supportare la persistenza;
queste implementazioni non deriveranno necessariamente Collection da Per-
sistent Object.
De�nizione:
template <class T> class Collection:
public Persistent_Object {
public:
Collection();
Collection(const Collection<T> &);
~Collection();
Collection<T> & operator=(const Collection<T> &);
friend int operator==(const Collection<T> &cL,
const Collection<T> &cR);
friend int operator!=(const Collection<T> &cL,
const Collection<T> &cR);
unsigned long cardinality();
52 Lo Standard ODMG-93
T
Ref<T>
R T
Set<Ref<T>>
S
R
R
R
T
T
T
Set<T>
S
T
T
T
Set<Literal>
S
L
L
L
Ref<Set<Ref<T>>>
R S R
R
R
T
T
Figura 2.11: Collezioni e Riferimenti
ClassiCollezione
53
int
is_empty()const;
int
is_ordered()const;
int
allows_duplicates()const;
int
contains_element(
constT&element)const;
void
insert_element(constT&elem);
void
remove_element(constT&elem);
void
remove_all();
constT&
retrieve_element_at(
constIterator<T>&iter)const;
void
remove_element_at(
constIterator<T>&iter);
void
replace_element_at(constT&,
constIterator<T>&);
Iterator<T>
create_iterator()const;
constT&
select_element(
constchar*OQL_predicate)const;
Iterator<T>
select(constchar*OQL_predicate)const;
int
query(Collection<T>&,
constchar*OQL_predicate)const;
int
exist_element(
constchar*OQL_predicate)const;
};
ClasseSet
UnSet<T>�eunacollezionenonordinatadielementiditipo
Tsenzaduplicati.
De�nizione:
template<classT>classSet:publicCollection<T>{
public:
Set();
Set(constSet<T>&);
~Set();
Set<T>&
operator=(constSet<T>&);
Set<T>&
union_of(constSet<T>&sL,constSet<T>&sR);
Set<T>&
union_with(constSet<T>&s2);
Set<T>&
operator+=(constSet<T>&s2);//union_with
Set<T>
create_union(constSet<T>&s)const;
54
LoStandardODMG-93
friendSet<T>operator+(constSet<T>&s1,
constSet<T>&s2);
Set<T>&
intersection_of(constSet<T>&sL,
constSet<T>&sR);
Set<T>&
intersection_with(constSet<T>&s2);
Set<T>&
operator*=(constSet<T>&s2);
//intersection_with
Set<T>
create_intersection(constSet<T>&s)const;
friendSet<T>operator*(constSet<T>&s1,
constSet<T>&s2);
Set<T>&
difference_of(constSet<T>&sL,
constSet<T>&sR);
Set<T>&
difference_with(constSet<T>&s2);
Set<T>&
operator-=(constSet<T>&s2);
//difference_with
Set<T>
create_difference(constSet<T>&s)const;
friendSet<T>operator-(constSet<T>&s1,
constSet<T>&s2);
int
is_subset_of(constSet<T>&s2)const;
int
is_proper_subset_of(
constSet<T>&s2)const;
int
is_superset_of(constSet<T>&s2)const;
int
is_proper_superset_of(
constSet<T>&s2)const;
};
Sinotichetutteleoperazionide�niteneltipoCollectionsonoereditatedal
tipoSet,e.g.,insertelement,removeelement,selectelement,eselect.
Esempi:
�
creazione:
Databasedb
//apriamolabasedidati
Ref<Professor>Guttag
//settiamoquesto
//adunprofessore
Ref<Set<Ref<Professor>>>my_profs=new8&db)
Set<Ref<Professor>>;
�
inserimento:
ClassiCollezione
55
my_profs->insert_element(Guttag);
�
rimozione:
my_profs->remove_element(Guttag);
�
cancellazione:
my_profs->delete_object();
Perognunadelleoperazionisugliinsiemi(unione,intersezioneedi�erenza)ci
sonotremodidiottenerel'insiemerisultante.Questesarannospiegateutiliz-
zandol'operazionediunione.Ognunadellefunzioniunionehadueoperandi
insiemeecompielalorounione.Essevarianonelmodoincuiglioperandi
insiemesonopassatierispettoalmodoincuiilrisultatovienerestituito,per
supportareidi�erentistilidiinterfaccia.Lafunzioneunionof�eunafunzione
membrochehadueargomentichesonoriferimentiaSet<T>.Essaesegue
l'unionediquestidueinsiemieponeilrisultatonell'oggettoSetconcuila
funzione�estatachiamata,rimuovendoilcontenutooriginariodell'insieme.
Lafunzioneunionwith�eanch'essaunmembroeponeilsuorisultatonel-
l'oggettoconcui�estatachiamata.Ladi�erenza�echeunionwithutilizzail
contenutodell'insiemecorrentecomeunodeidueoperandichedevonoessere
uniti,equindi�erichiestoilpassaggiodiunsoloparametro.Siaunionofche
unionwithrestituisconounriferimentoall'oggettoconcuisonostateinvo-
cate.Lafunzioneunionwithhaunacorrispondentefunzioneoperator+=
de�nita.Dall'altraparte,createunioncreaerestituisceunanuovaistanza
Setpervalorechecontienel'unione,lasciandoinalteratiidueinsiemiorigi-
nali.Anchequestafunzionepossiedelacorrispondentefunzioneoperator+
de�nita.
ClasseBag
UnaBag<T>�eunacollezionedisordinatadielementiditipo
Tchepermettevaloriduplicati.
De�nizione:
template<classT>classBag:publicCollection<T>{
public:
Bag();
Bag(constBag<T>&);
56
LoStandardODMG-93
~Bag();
Bag<T>&
operator=(constBag<T>&);
Bag<T>&
union_of(constBag<T>&bL,
constBag<T>&bR);
Bag<T>&
union_with(constBag<T>&b2);
Bag<T>&
operator+=(constBag<T>&b2);//union_with
Bag<T>
create_union(constBag<T>&b)const;
friendBag<T>operator+(constBag<T>&b1,
constBag<T>&b2);
Bag<T>&
intersection_of(constBag<T>&bL,
constBag<T>&bR);
Bag<T>&
intersection_with(constBag<T>&b2);
Bag<T>&
operator*=(constBag<T>&b2);
//intersection_with
Bag<T>
create_intersection(constBag<T>&b)const;
friendBag<T>operator*(constBag<T>&b1,
constBag<T>&b2);
Bag<T>&
difference_of(constBag<T>&bL,
constBag<T>&bR);
Bag<T>&
difference_with(constBag<T>&b2);
Bag<T>&
operator-=(constBag<T>&b2);
//difference_with
Bag<T>
create_difference(constBag<T>&b)const;
friendBag<T>operator-(constBag<T>&b1,
constBag<T>&b2);
};
Leoperazionidiunione,intersezioneedi�erenzasonodescrittenellasezione
precedenterelativaallaclasseSet.
ClasseList
UnaList<T>
�eunacollezioneordinatadielementiditipo
Tepermettevaloriduplicati.Ilvaloreinizialedell'indicediunalista�e0,
seguendolaconvenzionediCeC++.
De�nizione:
template<classT>classList:publicCollection<T>{
public:
ClassiCollezione
57
List();
List(constList<T>&);
~List();
List<T>&
operator=(constList<T>&);
constT&
retrieve_first_element()const;
constT&
retrieve_last_element()const;
void
remove_first_element();
void
remove_last_element();
constT&
operator[](unsignedlongposition)const;
int
find_element(constT&element,
unsignedlong&position)const;
constT&
retrieve_element_at(
unsignedlongposition)const;
void
remove_element_at(unsignedlongposition);
void
replace_element_at(constT&element,
unsignedlongposition);
void
insert_element_first(constT&element);
void
insert_element_last(constT&element);
void
insert_element_after(constT&element,
unsignedlongposition);
void
insert_element_before(constT&element,
unsignedlongposition);
List<T>
concat(constList<T>&listR)const;
friendList<T>
operator+(constList<T>&listL,
constList<T>&listR);
List<T>&
append(constList<T>&listR);
List<T>&
operator+=(constList<T>&listR);
};
Lafunzioneinsertelement(ereditatadaCollection<T>)inserisceunnuovo
elementoalla�nedellalista.
ClasseArray
IltipoArrayde�nitonellostandard�eimplementatodal-
l'arraycostruitointernamenteallinguaggioC++.Questo�eunarrayaduna
dimensioneedilunghezza�ssata.
ClasseVarray
UnVarray<T>�eunarrayadunadimensionedilunghez-
zavariabilecontenenteelementideltipoT.Ilvaloreinizialedell'indicedel
58
LoStandardODMG-93
Varray�e0,seguendolaconvenzionediCeC++.
De�nizione:
template<classT>classVarray:publicCollection<T>{
public:
Varray();
Varray(unsignedlonglength);
Varray(constVarray<T>&);
~Varray();
Varray<T>&
operator=(constVarray<T>&);
unsignedlong
upper_bound()const;
void
resize(unsignedlonglength);
constT&
operator[](unsignedlongindex)const;
int
find_element(constT&element,
unsignedlong&index)const;
constT&
retrieve_element_at(
unsignedlongindex)const;
constT&
remove_element_at(unsignedlongindex);
constT&
replace_element_at(constT&element,
unsignedlongindex);
};
Lafunzioneinsertelement(ereditatadaCollection<T>)inserisceunnuovo
elementoincrementandolalunghezzadelVarraydiunoeponendoilnuovo
elementoinquestanuovaposizionedelVarray.
Esempi:
Varray<double>
vector(100);
vector.replace_element_at(3.14159,97);
vector.resize(2000);
ClasseIterator
UnaclassetemplateIterator<T>
de�nisceilgenerico
comportamentoperl'iterazione.Tuttigliiteratoriusanounprotocollocon-
sistenteperrestituiresequenzialmenteognielementodallacollezionesulla
qualel'iterazione�ede�nita.Unaclassetemplate�estatausataperdarcidegli
ClassiCollezione
59
iteratoriditiposicuro,i.e.,iteratorichegarantisconolarestituzionediun'i-
stanzadeltipodell'elementodellacollezionesullaqualel'iteratore�ede�nto.
Normalmente,uniteratore�einizializzatotramiteilmetodocreateiteratorsu
unaclassecollezione.LaclassetemplateIterator<T>�ede�nitacomesegue:
template<classT>classIterator{
public:
Iterator(constCollection<T>&);
Iterator(constIterator<T>&);
~Iterator();
Iterator<T>&
operator=(constIterator<T>&);
void
reset();
int
not_done()const;
void
advance();
void
operator++();
void
operator++(int);
constT&
get_element()const;
int
next(T&objRef);
};
Quandouniteratorevienecostruito,essoprendeunriferimentoadunacol-
lezione(un'istanzadiunaclasseconcretaderivatadaCollection)oppure
un'altroiteratore.
L'assegnamentodell'iteratore�ecomunquesupportato.
Unafunzionedireset�efornitaperre-inizializzarel'iteratoreall'iniziodell'i-
terazioneperlastessacollezione.
Lafunzionenotdonepermettedideterminaresevisonoancoraelementidel-
lacollezionedavisitarenellaiterazione.Essarestituisce1secisonoancora
elementie0sel'iterazione�ecompleta.Lafunzioneadvancemuovel'itera-
toreavanti�noalprossimoelementodellacollezione.Sel'iterazionenon�e
ancoracominciata,essasettal'iteratorealprimoelementodell'insieme.Le
formepre�ssaepost�ssadell'operatore++diincrementosonosovrapposte
perfornireunaoperazioneequivalentediavanzamento.
Lafunzionegetelementrestituisceunriferimentocostanteall'elementocor-
rente.All'iniziodell'iterazione,essarestituisceilprimoelemento;altrimenti,
durantel'iterazione,essarestituiscel'elementocorrente.Senonc'�el'elemento
correntevienesollevatounerrore.Nonc'�el'elementocorrentesel'iterazione
�estatacompletata(notdonerestituisce0)oppureselacollezionenonpos-
60
LoStandardODMG-93
siedeelementi.
Lafunzionenextfornisceilmezzopercontrollarela�nedell'iterazione,fa-
cendoavanzarel'iteratoreerestituendol'elementocorrente,secen'�euno.Si
comportanelmodoseguente:
template<classT>intiterator<T>::next(T&objRef)
{if(!not_done())return0;//noncisonoaltrielementi,
//restituiscefalso
advance();
//seall'inizio,siposiziona
//alprimoelemento,
//altrimentialprossimo
objRef=get_element();
//assegnaalparametrodi
//uscital'elemento
return1;
//restituiscevero,
//sihaunelementosuccessivo
}Sinotichelafunzionenexteseguel'assegnamentodiunoggetto,mentre
usandodellafunzionegetelementsiotterrebbeunsempliceriferimentoco-
stanteall'elemento.L'ultimapotrebbeesserepreferibileinsituazioniincui
iltipodielementohaunasemanticadicopiaprofondael'applicazionenon
habisognoononvuolepagareiltempodiesecuzionedellacopiadell'oggetto.
Questeoperazionipermettonoduetipidistiliiterativi,utilizzabilipercicli
whileofor.
Esempi:
DataunaclasseStudent,edunasuaistanzaesistentestudents:
(1)Iterator<Ref<Student>>iter=strudents.create_iterator();
Ref<Student>s;
(2)while(iter.next(s)){
...
}
oinmodoequivalenteconunciclofor:
Transazioni
61
(3)for(Iterator<Ref<Student>>iter=strudents;
iter.not_done();iter++){
(4)
Ref<Student>s=iter.get_element();
...
}
L'istruzione(1)de�nisceuniteratoreiterchesimuovesullacollezionestu-
dents.L'istruzione(2)iteraattraversoquestacollezione,restituendounRef
adunoStudentadognisuccessivachiamatadinext,legandoci�oalciclodella
variabiles.Ilcorpodell'istruzionewhile�ealloraeseguitaunavoltaperogni
studentenellacollezionestudents.Leciclo(3)l'iteratorevieneinizializza-
to,l'iterazionevienecontrollatapervedereserisultacompletael'iteratore
vieneavanzato.All'internodelciclofor,lafunzionegetelementpu�oessere
chiamataperottenereunriferimentoall'elementocorrente.
2.3.7
Transazioni
Lasemanticadelletransazioni�ede�nitanelmodelloadoggettiespostonello
standard.
Letransazionipossonoesserefatteiniziare,sipossonocompletare,abortire
econtrollare.Letransazionipossonoancheessereinnestate.Risultaim-
portanteosservarecheaccesso,creazione,modi�caecancellazionedioggetti
persistentidevonoesserefattimedianteunatransazione.
LetransazionisonoimplementateinC++comeoggettidellaclasseTransac-
tion.LaclasseTransactionde�nisceleoperazioniperiniziare,completare,
abortireecontrollareletransazioni.Questeoperazionisono:
classTransaction{
public:
Transaction();
~Transaction();
void
begin();
void
commit();
void
abort();
void
checkpoint();
62
LoStandardODMG-93
};
Letransazionidevonoessereesplicitamentecreateediniziate;essenonven-
gonoiniziateautomaticamenteconlabasedidatiaperta,dopolacreazione
diunoggettoTransaction,nemmenoseseguitadaun'operazionedicommit
oabort.
Lafunzionebegininiziaunatransazione.Chiamandobeginmoltevoltesullo
stessooggettotransazione,senzal'interventodicommitoabort,sigenera
unerroresullasecondaesullesusseguentichiamate.
Chiamandocommitsicoinvolgonotuttiglioggettipersistentimodi�catiap-
partenentiallabasedidati(compresiquellicreatiocancellati)all'interno
dellatransazione.L'operazionedicommitsettaiRef,siaperglioggettiper-
sistentiaglioggettitransientia0edipuntatoriinterniadoggettipersistenti,
siachepuntinoadoggettipersistenti,siachepuntinoadoggettitransienti,
vengonoalorovoltasettatia0.Inalternativa,leimplementazionipossono
sceglieredimantenerelavalidit�adeipuntatoritraoggettipersistentiattra-
versoicon�nidellatransazione.L'operazionedicommitnoncancellagli
oggettidellatransazione.
Chiamandocheckpointsisalvanosumemeoriapersistenteglioggettimodi-
�catiall'internodellatransazionedaquando�estatofattol'ultimocontrollo
sullabasedidati.TuttiiRefedipuntatorirestanoinvariati.
Chiamandoabort,siabortisconoicambiamentiaglioggetti,inoltrenonvie-
necancellatol'oggettotransazione.
Ildistruttoreabortiscelatransazioneserisultaattiva.
Nellostandardcorrente,glioggettitransientinonsonosoggettiallaseman-
ticadelletransazioni.L'impegnodiunatransazionenonrimuoveglioggetti
transientidallamemoria.L'abortodiunatransazionenonripristinalostato
deglioggettitransientimodi�cati.
Glioggettitransazionenonhannounavitalunga(oltreicon�nidelprocesso)
enonpossonoesseresalvatinellabasedidati.Questosigni�cacheglioggetti
transazionepossonononesserepersistentiechelanozionedi\transazione
lunga"non�ede�nitainquestaspeci�ca.
OperazionisullaBasediDati
63
Letransazionipossonoessereinnestate.Ilcommitdellatransazionepi�uin-
terna�esoltantorelativoallatransazionepi�uesterna;icambiamentifattiin
quellainternavengonocoinvoltisoltantoseancheletransazioniesternerag-
giungonoilcommit.Seunatransazioneinternaharaggiuntoilcommitsu
unabortodiunatransazioneesterna,icambiamentifattinellatransazione
internasonoabortitialorovolta.
Riassumendo,leregolechesiapplicanoallamodi�cadiunoggetto(necessa-
riamenteduranteunatransazione)sono:
1.Icambiamentifattisuglioggettipersistentiall'internodiunatransa-
zionepossonoessere\disfatti"abortendolatransazione.
2.GlioggettitransientisonooggettiC++standard.
3.Glioggettipersistenticreatinell'ambitodiunatransazionesonoma-
nipolaticoerentementeaicon�nidellatransazione:salvatinellabase
didatierimossidallamemoria(alcommitdellatransazione)oppure
cancellati(comerisultatodell'abortodiunatransazione).
2.3.8
OperazionisullaBasediDati
C'�euntipoDatabaseprede�nito.Essosupportaiseguentimetodi:
classDatabase{
public:
enumaccess_status{not_open,read_write,
read_only,exclusive};
void
open(constchar*database_name,
access_statusstatus=read_write);
void
close();
void
set_object_name(constRef_Any&theObject,
constchar*theName);
constchar*
get_object_name(constRef_Any&)const;
void
rename_object(constchar*oldName,
constchar*newName);
Ref_Any
lookup_object(constchar*name)const;
};
L'oggettobasedidati,comeunoggettotransazione,�etransiente.Lebasidi
datinonpossonoesserecreatedaprogrammausandoilC++OMLde�nito
64
LoStandardODMG-93
daquestostandard.Lebasididatidevonoessereaperteprimadicominciare
qualunquetransazionecheusilabasedidatistessa,echiusedopola�nedi
questetransazioni.
Peraprireunbasedidati,siusaDatabase::open,cheprendeilnomedella
basedidaticomesuoargomento.Questoinizializzal'istanzadell'oggetto
Database.
database->open("myDB");
Ilmetodoopenlocalizzalabasedidatinominataedesegueleappropriate
connessioniallabasedidati.Occorreaprirelabasedidatiprimadipoter
accedereaisuoioggetti.Eventualiestensionialmetodoopenpermetteranno
adalcuniODBMSdiimplementarenomidibasididatididefaulte/oaprire
unabasedidatididefaultquandounasessionediunabasedidati�ecomin-
ciata.AlcuniODBMSpossonosupportarel'aperturalogicaallostessomodo
diquella�sica.AlcuniODBMSpossonosupportarelaloroconnessionea
basididatimultipleallostessoistante.
PerchiudereunabasedidatisiusaDatabase::close:
database->close();
Dopochesi�echiusaunabasedidati,ognitentativodiaccedereaglioggetti
checontienegenerer�aunerrore.Ilcomportamentoalterminedelprogram-
ma,selebasididatinonsonochiuseoletransazioninonhannoraggiunto
ilcommitosonostateabortite,risultainde�nito.
Imetodinamepermettonolamanipolazionedeinomideglioggetti.Unog-
gettopu�oacquisiresoltantounnome.Ilmetodosetobjectnameassegna
unnomestringadicaratteriall'oggettoreferenziato.Selastringafornita
comeargomentonomenonrisultaunicaall'internodellabasedidati,viene
generatounerrore.Sel'oggettopossiedegi�aunnome,vieneribattezzatocol
nuovonome.Ilmetodorenameobjectcambiailnomediunoggetto.Seil
nuovonome�egi�autilizzato,vienesollevatounerroreevienelasciatoilvec-
chionome.Unoggettonominatopu�oavereilsuonomerimossoponendoa
0ilpuntatorealvaloredelnuovonome.Quandounoggettonominatoviene
cancellato,lasuavocevieneautomaticamenterimossadall'elencodeinomi.
AdunoggettosiaccedetramitenomeutilizzandolafunzionemembroDa-
tabase::lookupobject.
Esempio:
2.4C++
OQL
65
Ref<Professor>prof=myDatabase->lookup_object("Newton");
Seun'istanzachiamata\Newton"esiste,essavienereferenziataedunRefAny
vienerestituitodalookupobject.IlvalorerestituitoRefAnyvieneusatoper
inizializzareprof.Seinvecel'oggettochiamato"Newton"non�eun'istanza
diProfessorounasottoclassediProfessor,vienegeneratounerroredurante
questainizializzazione.
2.4
C++
OQL
NellostandardvienedescrittoagrandilineeilLinguaggiodiInterrogazione
adOggetti.InquestasezionelasemanticaOQLvienemappatanellinguag-
gioC++.Visonoingeneraledueopzioniperlegareunsottoliguaggiodi
interrogazioneadunlinguaggiodiprogrammazione:accoppiamentolascoo
accoppiamentostretto.Nell'approccioadaccoppiamentolasco,funzioniin-
terrogazionesonointrodotteperprenderestringhecontenentiinterrogazioni
comeloroargomenti.Questefunzionianalizzanoevalutanol'interrogazio-
nedurantel'esecuzionedelprogramma,restituendoilrisultatoattraversoil
parametrodioutputresult.Nell'approccioadaccoppiamentostrettoilsot-
tolinguaggiodiinterrogazionevieneintegratodirettamentenellinguaggiodi
programmazioneespandendolade�nizionedeivalorinonterminali<term>
ed<expression>comede�nitinellaBNFdellinguaggiodiprogrammazione.
L'approccioadaccoppiamentostrettopermetteinterrogazionichepossono
essereottimizzatedurantelacompilazione;nell'approccioadaccoppiamento
lascoessevengonoingeneraleottimizzatedurantel'esecuzione.Illegame
C++perOQLsupportaduevariantiperl'accoppiamentolasco:
�
unmetododiinterrogazione�ede�nitonellaclassegenericaCollection
�
unafunzioneoqlliberaaldifuoridiogniclasse.
Leduevariantisonode�nitenellesottosezioniseguenti.
2.4.1
MetodidiInterrogazionenellaClasseCollection
LaclasseCollectionpossiedeunmetodointerrogazionelacuidichiarazione
�e:intquery(Collection<T>&result,
constchar*predicate)const;
66
LoStandardODMG-93
Questafunzione�ltralacollezioneusandoilpredicatoedassegnandoilrisul-
tatoalprimoparametro.Restituisceuncodicediversodazero,sel'interro-
gazionenon�estatabenformulata.Ilpredicato�edatocomeunastringacon
lasintassidellaclausolawherediOQL.Lavariabileprede�nitathisviene
usataall'internodelpredicatoperdenotarel'elementocorrentedellacolle-
zionecheviene�ltrata.
Esempio:
DatalaclasseStudent,doveStudents�eunacollezionedioggettidellaclasse
Student,siricavil'insiemedeglistrudenticheseguonoicorsidimatematica:
Set<Ref<Student>>mathematicians;
//estensionedimatematici
Students->query(mathematicians,
"existsinthis.takes:\
s.section_of.name=\"math\"");
LafunzioneCollection::selectelementprendeunpredicatoOQLcomear-
gomentoerestituiscel'elementochesoddisfal'interrogazione.Senonc'�e
unsoloelementodarestituirevienegeneratounerrore.LafunzioneCollec-
tion::selectpassaunpredicatoOQLerestituisceuniteratoreperattraversare
lacollezionedielementichesoddisfanol'interrogazione.LafunzioneCollec-
tion::existelementvienepassatacomeunpredicatoOQLerestituisceun
valorenonnullosec'�ealmenounelementonellacollezionechesoddisfal'in-
terrogazione.Sel'argomentopredicatodiunqualunquediquestefunzioni
membro�emalposto,vienegeneratounerrore.
2.4.2
FunzioneOQL
Lafunzioneoqlpermettealprogrammatorediottenerel'accessoatuttele
funzionalit�aOQLdaunprogrammaC++.Essa�eunafunzioneisolata,cio�e
nonrisultapartedinessunade�nizionediclasse.Prendecomeparametriun
riferimentoadunavariabileincuiporreilrisultato,unaproposizioneOQL
edunalistavariabilediespressioniC++icuivalorisonooperandidiingresso
perl'interrogazione.All'internodell'interrogazionequestioperandivengono
identi�catidallasintassidatasotto.Lafunzionerestituisceunavalorenon
nullosel'interrogazionenonrisultabenposta.
Ledichiarazionisovrappostediquestafunzionesono:
�
Un'interrogazionecherestituisceunoggetto.
FunzioneOQL
67
template<classT>intoql(Ref<T>&result,
constchar*query,...);
�
Un'interrogazionecherestituisceunacollezione.
template<classT>intoql(Collection<T>&result,
constchar*query,...);
�
Un'interrogazionecherestituisceunvaloreatomico.
intoql(int&,constchar*query,...);
intoql(char&,constchar*query,...);
intoql(double&,constchar*query,...);
�
Un'interrogazionecherestituisceunastringa.Inquestocaso,ilrisulta-
to�eallocatodinamicamentetramiteOQL.Ilprogramma�eresponsabile
delladeallocazionedellastringa.
intoql(char*&,constchar*query,...);
Diseguitoaiprimidueparametri,oqlaccettaqualunquenumerodiparametri
opzionali.Ognunodiessipu�oessereunaespressioneC++.Laproposizione
diinterrogazionesiriferisceall'i-esimoparametrodiquestalistatramitela
notazionedilegameconquestasintassi:
$<range><type>
<range>�euninterocheforniscelaposizionedelparametro(partendoda1).
<type>�euncaratterechede�nisceiltipodellaespressioneC++:
�
iindicaunintero(int)
�
cindicauncarattere(char)
�
rindicaunreale(double)
�
sindicaunastringa(char*)
�
kindicaunacollezione(oggettodiunasottoclassediCollection<T>)
�
oindicaunoggetto(oggettoreferenziatodaunaclasseosottoclasse
Ref<T>)
68
LoStandardODMG-93
�
iindicaunintero(int)
Ilcontrollodeltipodeiparametridiinputinaccordocollorousonell'inter-
rogazionevienefattodurantel'esecuzione.Similmenteiltipodelrisultato
dell'interrogazionevienecontrollatoperaccordarsicoltipodelprimopara-
metro.Ogniviolazioneditipogeneraunerrore.
Sel'interrogazionerestituisceunoggettomutabileditipoT,lafunzionere-
stituisceunRef<T>.Sel'interrogazionerestituisceunletteralestrutturato,
ilvalorediquesto�eassegnatoalvaloredell'oggettoocollezionedenotato
dallavariabilerisultato,assicurandounaccordodeitipi.
Esempio:
Traglistrudentidimatematica(ottenutiprimanellasezione2.4.2nellavaria-
bilemathematicians)c'�echi�eunassistenteall'insegnamentoecheguadagna
pi�udix,trovarel'insiemedeiprofessoridaessiassistiti.Sisupponecheesista
unaestensionepergliassistentiall'insegnamentochevienechiamata\TA".
Set<Ref<Student>>mathematicians;
//ottenutocome
//inprecedenza
Set<Ref<Professor>>assisted_profs;
doublex=...
oql(assisted_prof,"selectt.assist.taught_by\
fromtinTAwheret.salary>$1r\
andtin$2k",
x,mathematicians);
2.5
Esempio
Questasezionefornisceunesempiocompletodiunapiccolaapplicazione
C++.Questaapplicazionegestiscerecorddipersone.UnaistanzadiPerson
pu�oessereintroddottanellabasedidati.Quindialcunieventispecialiposso-
noessereregistrati:ilsuomatrimono,lanascitadei�gli,ilsuotrasferimento
adunnuovoindirizzo.
L'applicazionecomprendeduetransazioni:laprimapopolalabasedidati,
mentrelasecondalaconsultaelaaggiorna.
Laprossimasezionede�nisceloschemadellabasedidaticomeclassiC++
De�nizionedelloSchema
69
ODL.IlprogrammaC++vienedatonellasezionesusseguente.
2.5.1
De�nizionedelloSchema
Perlaspiegazionedellasemanticadiquestoesempio,sivedalostandard.Di
seguitovi�elasintassiC++ODL:
//DefinizionedelloschemainC++ODL
classCity;
//dichiarazionesuccessiva
structAddress{
int
number;
String
street;
Ref<City>
city;
Address();
Address(int,constchar*,constRef<City>&);
};
classPerson:publicPersisten_Object{
public:
//Attributi(tuttipubblici,inquestoesempio)
String
name;
Address
address;
//Relazioni
Ref<Person>
spouse
inversespouse;
List<Ref<Person>>
childreninverseparents;
List<Ref<Person>>
parents
inversechildren;
//Operazioni
Person(constchar*pname);
void
birth(constRef<Person>&child);
//unfiglionasce
void
marriage(constRef<Person>&with);
//unosposo/a
Ref<Set<Ref>person>>>ancestors()const;
//restituiscegli
//antenatidiPerson
void
move(constAddress&);
70
LoStandardODMG-93
//trasferisce
//l'indirizzo
//Estensioni
staticRef<Set<Ref<Person>>>people;//riferimentoalla
//classeestensione:
//questavariabile
//statica(transiente)
//vieneinizializzata
//quandoinizia
//latransazione(si
//vedal'applicazione)
staticconstchar*const
extent_name;
};
classCity:publicPersistent_Object{
public:
//Attributi
int
city_code;
String
name;
Ref<Set<Ref<Person>>>
population;
//gentecheviveinqui
//Operazioni
City(int,constchar*);
//Estensioni
staticRef<Set<Ref<City>>>
cities;//riferimentoalla
//classeestensione
staticconstchar*const
extent_name;
};
2.5.2
ImplementazionedelloSchema
De�niamoadessoilcodicedelleoperazionidichiaratenelloschema.Questo
vienescrittoinC++.SiassumecheunpreprocessoreC++
ODLabbia
generatoun�lechiamato"schema.hxx"echecontengalede�nizionistandard
C++equivalentialleclassiC++ODL.
//ImplementazionedelleClassiinC++
#include"schema.hxx"
ImplementazionedelloSchema
71
//StrutturaAddress
Address::Address(intpnumber,constchar*pstreet,
constRef<City>&pcity)
:number(pnumber);
street(pstreet);
city(pcity);
{}
Address::Address()
:number(0);
street(0);
city(0);
{}
//ClassePerson
constchar*constPerson::extent_name="people";
Person::Person(constchar*pname)
:name(pname)
{people->insert_element(this);//mettequesta
//Personnella
//estensione
} voidPerson::birth(constRef<Persono>&child)
{
//aggiungeunnuovo
//figlioallalista
//deifigli
children.insert_element_last(child);
if(spouse!=0)
spouse->children.insert_element_last(child);
} voidPerson::marriage(constRef<Persono>&with)
{
//Inizializzala
//relazionespouse
spouse=with;
//with->spouseviene
72
LoStandardODMG-93
//automaticamente
//settatoa
//questaPerson
} Ref<Set<Ref<Person>>>Person::ancestors()
{
//construiscel'insieme
//degliantenatidiquestaPerson
Ref<Set<Ref<Person>>>the_ancestors=
newSet<Ref<Person>>;
inti;
for(i=0;i<2;i++)
if(parents[i]!=0){
//antenati=genitoriuniti
//agliantenatideigenitori
the_ancerstos->insert_element(parents[i]);
Ref<Set<Ref<Persono>>>grand_parents=
parents[i]->ancestors();
the_ancestors->union_with(*grand_parents);
grand_parents.delete_object();
}returnthe_ancestors;
} voidPerson::move(constAddress&new_address)
{
//aggiornal'attributoindirizzodiPersona
If(address_city!=0)
address_city->population->remove_element(this);
new_address.city->population->insert_element(this);
address=new_address;
mark_modified();
//DANONDIMENTICARE!
//Sinoticherisulta
//necessariosolonel
//casoincuivenga
//modificatol'attributo
//diun'oggetto.Quando
//simodificaunarelazione,
//l'oggettovienemarcato
//modificatoautomaticamente
}
UnaApplicazione
73
\\ClasseCity
constchar*constCity::extent_name="cities";
City::City(intcode,constchar*cname)
:city_code(code),
name(cname);
{cities->insert_element(this);
}2.5.3
UnaApplicazione
Adessoabbiamol'interoschemabende�nitoedimplementato.Siamoingra-
dodipopolarelabasedidatiemanipolarla.Nellaseguenteapplicazione,
latransazioneLoadcostruiscealcunioggettieliinseriscenellabasedidati.
LatransazioneConsultlilegge,stampaalcunirapportisudiessi,elimar-
caaggiornati.Ognitransazione�eimplementataall'internodiunafunzione
C++.
Labasedidati�eapertadalprogrammaprincipale,chepoiinizialetransa-
zioni.
#include<iostream.h>
#include"schema.hxx"
staticDatabasedbobj;
staticDatabase*database=&dbobj;
voidLoad()
{
//Transazionechepopolalabasedidati
Transactionload;
load.begin();
//CreazioneleestensioniPersoneeCitta`elinomina.
Person::people=new(database)Set<Ref<Person>>;
City::cities=new(database)Set<Ref<City>>;
database-set_object_name(Person::people,
Person::extent_name);
74
LoStandardODMG-93
database-set_object_name(City::cities,
City::extent_name);
//Costruzione
di3oggetti
//persistentidellaclassePerson.
Ref<Person>God,Adam,Eve;
God=new(database)Person("God");
Adam=new(database)Person("Adam");
Eve=new(database)Person("Eve");
//CostruzionediunastrutturaAddress,Paradise,
//come(7AppleStreetGarden)
//esettaggiodegliattributiaddressdiAdameEve.
AddressPeradise(7,"Apple",new(database)City(0,"Garden");
Adam->move(Paradise);
Eve->move(Paradise);
//Definizionedellerelazionifamigliari.
God->birth(Adam);
Adam->marriage(Eve);
Adam->birth(new(database)Person("Cain"));
Adam->birth(new(database)Person("Abel"));
load.commit();
//impegnalatransizoine,prendendogli
//oggettidalladasedidati.
} staticvoidprint_persons(constCollection<Ref<Person>>&s)
{
//Funzionediservizioper
//stampareunacollezionediPerson
Ref<Person>P;
Iterator<Ref<Person>>it=s.create_iterator();
while(it.next(p)){
cout<<""---"<<p->name<<"livesin";
if(p->address.city!=0)
cout<<p->address.city->name;
UnaApplicazione
75
else
cout<<"Unknown";
cout<<endl;
}} v
oidConsult()
{
//Transazionecheconsultaeaggiornalabasedidati
Transactionconsult;
List<Ref<Person>>list;
consult.begin();
//Iriferimentiaglioggettioallecollezionidevono
//esserericalcolatidopounimpegno
Person::people=database->
lookup_object(Person::extent_name);
City::cities=database->
lookup_object(City::extent_name);
//Adessoinizialatransazione;
cout<<"Allthepeople...:"<<endl;
print_persons(*Person::people);
cout<<"Allthepeoplesortedbyname...:"<<endl;
oql(list,"sortpinpeoplebyp.name");
print_persons(list);
cout<<"Peoplehaving2children\
andlivinginParadise...:"<<endl;
oql(list,"selectpfrompinpeople\
where
p.address.city!=niland\
p.address.city.name=\"Garden\"\
andcount(p.children)=2");
print_persons(list);
//AdameEvetraslocano
AddressEarth(13,"Macadam",
new(database)City(1,"St-Croix"));
76
LoStandardODMG-93
Ref<Person>Adam;
oql(Adam,"element(selectpfrompinpeople\
wherep.name=\"Adam\")");
Adam.move(Earth);
Adam->spouse->move(Earth);
cout<<"Cain'sancestors...:"<<endl;
Ref<Person>Cain=Adam->children.retrieve_element_at(0);
print_persons(*(Cain->ancestors()));
consult.commit();
} main()
{database->open("family");
Load();
Consult();
database->close();
}2.6
Future
Estensioni
del
Legame
C++
ODL/OML
Questasezionede�nisceillegameC++ODL/OMLcheilgruppodistandar-
dizzazioneODMG-93o�rir�ainfuturo.Cisiaspettacheanchelatecnologia
C++evolvapersupportareilgradoditrasparenzadescrittainquestasezione
ocheunpre-processoreC++possaessereintrodottoperpermetterequesta
trasparenza.
Semplicemente,illegamefuturo�eunapi�ucompletarealizzazionedelprinci-
piochenondovrebbeesservidi�erenzanelmodoincuiunprogrammatore
C++
trattaglioggettipersistentietransienti.Allostessotempo,questo
richiedeunapi�ucomplessaimplementazione.Inassenzadeicambiamentidi-
scussinellasezione2.6.2,illegamefuturorichiedeunpre-processorecapace
dimaneggiarel'interolinguaggioC++,eallostessomodovisiaunaintegra-
zioneattentaconimaggioridebuggeredambientidiprogrammazioneper
ilC++.Riconoscendoledi�colt�apratichediconseguiredelleimplementa-
zionirobustediquestolegameinprodotticorrentementeinusonel1993,i
membridelgruppodiODMGhannosceltodiporrel'obiettivodellegame,
2.6FutureEstensionidelLegameC++
ODL/OML
77
spiegatodallasezione2.2allasezione2.5,comeunostandardbasatosulle
lineeperlaportabilit�adiapplicazionidiintersistemioggi,piuttostocheil
legamespiegatoinquestasezione2.6.Illegamefuturovienede�nitoinque-
stostandardcomunque,perprevenireunproblemacheilgruppoODMG-93
-assiemeavenditoriconclientidibasecoinvolticonottodi�erentilegami,
alcuniabbastanzasimili,altriveramentediversi-hariscontrato,inaccordo
collegamecorrente.De�nendoilfuturolegameadesso,precedendodi�erenti
implementazionifornitedadi�erentivenditori,tentiamodievitarel'allarga-
mentodiquestoproblema.
Lemaggioridi�erenzetralostandardcorrenteedillegamefuturosonoin
duearee:comemaneggiareiriferimentiadoggetti,ecomeillinguaggiodelle
interrogazioni�eintegratoall'internodellinguaggiodiprogrammazione.
Ponendol'attenzionesullaprimadiqueste,illegamecorrenteintroduceuna
nuovaformapeririferimenti(Ref<T>)perclassipersistentieperleistan-
zetransienti.Questeclassisonoindicatecome\classicapacidipersistenza"
dallaSezione2.2allaSezione2.5perdistinguerledalle\classiC++".Risulta
chiarocheilprincipiochelapersistenzasiaortogonalealtipo�elimitato,nel
legameattuale,perquesteclassicapacidipersistenza.Unasintassidi�erente
vieneusataperriferirsiadistanzedelleclassicapacidipersistenzarispetto
aquellausataperriferirsiallealtreclassiC++.
Illegamefuturo,alcontrario,permetter�aadognitipo,siaunaclasseC++
cheuntipode�nitodall'utente,diavereistanzesiapersistentichetransienti
epermetter�aalprogrammatorediusarelostessopuntatoreelasintassi
referenzialeC++che�esemprestatausata,perreferirsiadistanzepersistenti
nellostessomododiquelletransienti,e.g.,
Professor*p;
p->office_number="4818";
inaggiuntaa
Ref<Professor>p;
p->office_number="4818";
Lasecondaareanellaqualeillegamefuturodi�eriscedallegamecorrente�e
nelsottolinguaggiodelleinterrogazioni.Illegamefuturoconsentir�aancora
78
LoStandardODMG-93
maggiorcompletaintegrazionecolC++,maancoraaspesediunapi�uso�-
sticataimplementazionedapartedelvenditoreODBMS.Nellegamecorrente
unprogrammatoreinvocaunafunzionediinterrogazioneepassailtestodel-
l'interrogazionecomeunastringaaquestafunzione(sivedalaSezione2.4).
Illegamedellevariabilidellinguaggiodiprogrammazioneconlevariabiliin-
terneallastringadiinterrogazionevienefattocomesesifossenellafunzione
printf:$1vieneinseritonellastringadiinterrogazioneesiriferiscealvalo-
redell'argomentopassatodopolastringadiinterrogazione.Illegamedegli
argomentiallevariabilidell'interrogazione�eperposizione,e.g,$2siriferisce
alvaloredelsecondoargomento;egliargomentisonoopzionali,cos��queste
interrogazionisenzadiessioconpochidiessinonnecessitanodegliargo-
menti�ttizi.Staalprogrammatorevederecheitipidegliargomentipassati
combacinoconquellichecisiaspettadallevariabilidell'interrogazione.Il
risultatodell'interrogazionevienerestituitocomeuninsiemeoppureattraver-
souniteratore.Ancora,illinguaggiopermetteafunzioniarbitrariede�nite
dalprogrammadiessereinvocateall'internodelcorpodell'interrogazione,e
questorichiedeuninterpreteOQLabbastanzaso�sticatoche,durantel'ese-
cuzione,localizzi,leghiedeseguaimetodicheimplementanoquestefunzioni.
Cisiaspettaper�ochemoltisistemipossanorestringerequestecapacit�a.
Illegamefuturo,alcontrario,nonrichieder�achel'interrogazionevengapas-
sataadunafunzionecomeunastringa;inveceestender�alade�nizionedi
espressioninellagrammaticadellinguaggiodiprogrammazionedibaseper
supportarel'identi�cazionedioggettitramiteladescrizionecomesefossero
nomidivariabili.Questedescrizionisononellaformadipredicatide�niti
sugliattributidioggetti,sullelororelazioniconaltrioggetti,esuirisultati
dioperazioniapplicateaglioggettistessi.Questosigni�cacheleespressioni
C++
possonoessereusateliberamenteall'internodelsottolinguaggiodel-
leinterrogazioni,eleespressionidellinguaggiodelleinterrogazionipossono
essereinclusecomesottoespressioniall'internodinormaliespressioniC++.
Nonvi�elanecessit�adiunostiledistampaperiprocessidilegamedegliar-
gomenti,eleespressionidiinterrogazionepossonoessereottimizzatedurante
lacompilazionedelprogramma,invececheinesecuzione.
SinoticheilfuturolegamecolC++�esoltantounasempli�cazionedellin-
guaggiodilegameperlafunzionalit�acorrentede�nitoinODMG-93.L'ac-
crescimentodellostandardperincluderemaggiorifunzionalit�aavanzate(ese
necessario,sintassipersupportarle)sar�ailsoggettodiunafuturarevisione
dellostandardODMG.
IlcorpodiquestaSezione2.6discuteledi�erenzetraillegamecolC++
ODL
79
correnteequellofuturo.Unsommariodelledi�erenze�eilseguente:
�
Tuttiitipidiprimitivecostruiteinternamenteeitipide�nitidal
programmatore,possonoavereistanzepersistenti.Non�enecessario
designareuninsiemespecialediclassicapacidipersistenza.
�
IpuntatoriC++standardeiriferimentipossonoessereutilizzatiper
referenziareoggetti;non�enecessariointrodurreunnuovotipodirife-
rimento.
�
Lasintassipercreareecancellareglioggetti�epienamenteconcordecol
C++:(1)l'allocazioneautomaticadeglioggettivienesupportataper
glioggettipersistentiallostessomododellerichiestediallocazionedel
programma(new),e(2)l'operatorestandardC++
deletepu�oessere
usatoperoggettipersistentietransienti,unaformaseparataperoggetti
persistentireferenziaticonlasintassiRef<T>non�erichiesta.
�
Leinterrogazionipossonoessereintegrateinmodopi�unaturalenel
linguaggiodiprogrammazione.
Leprimetredi�erenzeinquestalistasonodiscussenellaSezione2.6.1(ODL).
LeultimeduesonodiscussenellaSezione2.6.2(OML).Peraiutareadistin-
guereicomponentiODLeOMLdellegamefuturodallelorocontropartidel
legamecorrente,cisiriferisceadessicomeODL/futureeOML/futurenel
corpodiquestasezione.
2.6.1
ODL
Lasoladi�erenzatraledichiarazionidiclassiesteseinC++accettatedal
pre-processoreC++perillegamecorrenteedilpre-processoreODL/OML
perillegamefuturo�enell'usodellasintassistandardC++peripuntatori
(*)invecediavereiltiporiferimentoRef<T>introdottonellegamecorrente.
Lade�nizionediclasseseguentemostralaversioneODL/futuredellade�ni-
zionediunaclasse.
classProfessor{
public:
//proprieta':
int
age;
80
LoStandardODMG-93
char*
name;
Department*
dept
inverseDepartment::professors;
Set<Student*>adviseesinverseStudent::advisor;
//operazioni:
void
grant_tenure();
void
assign_course(Course*);
private:
...
};
Ledichiarazionidiattributosonolestesseneiduelegami.
Ledichiarazionidirelazionedi�erisconosoltantoperl'usodeipuntatori
standardC++invececheperlasintassiRef<T>,e.g,
classProfessor{
public:
Department*
dept
inverseDepartment::professors;
Set<Student*>adviseesinverseStudent::advisor;
...
};
invecedi
classProfessor{
public:
Ref<Department>
dept
inverseDepartment::professors;
Set<Ref<Student>>adviseesinverseStudent::advisor;
...
};
Ladichiarazionedelleoperazionidi�eriscesoltantonelfattocheillegame
futuroutilizzailpuntatoreadoggettostandardC++(*)elasintassi(&)
peririferimentiadoggetto.Non�enecessariousarelaformaRef<T>
per
referenziarea\oggettidellabasedidati".
OML
81
2.6.2
OML
L'OML/futurenon�eprincipalmenteuninsiemedinuoveespressionioistru-
zioni(eccettuatalanuovaformapeririferimenti)aggiuntoalC++.Esso
lasciainvariateleformesintatticheesistentimaneespandeleinterpretazio-
ni.Invecediintrodurreunsottolinguaggioseparatodicuiservirsicoidati
persistenti,ilC++OMLespandel'interpretazionedelleformedellasintassi
esistenteinmodochepossanoessereapplicateuniformementeaidatipersi-
stentietransienti.IllinguaggiodiprogrammazioneC++possiedegi�aoggetti
conduetempidivita:quellichevivonoperiltempodivitadellaprocedura
nellaqualesonostaticreatie(2)quellicherimangonoinvitapertuttala
duratadelprocesso.Questedi�erenzeneltempodivitasonoimplicitein
duedi�erentiformesintatticheusatepercreareglioggetti:unformadichia-
rativaperquellichevivonoperladuratadiunaproceduraedunachiamata
esplicitaadunafunzione(new)perquellechesopravvivonoallaprocedura.
Unvoltacheglioggetticonquestiduetempidivitasonostaticreati,lasin-
tassiusatapermanipolarli�elastessa.IllegameODBMSde�nitoattraverso
C++OMLsemplicementeaggiungeunterzotempodivitaperglioggetti-
persistenti.Unoggettopersistente�etalechesopravvivealprocessocheloha
creato.Essoviveperiltempodivitadellabasedidatiincuivieneriposto.
Unavoltacheunoggettopersistente�estatocreato,illegameOML/future
permettedireferenziarloemanipolarlousandolastessasintassicheilC++
utilizzaperglioggettichevivonomeno.
IllegameOML/futurecoinvolgesoltanto:
1.Estensioniversol'altocompatibiliconlasintassiC++perlacrazione
deglioggetti.Leestensionipermettonoalprogrammatoredispeci�care
unterzotempodivita(persistente)inaggiuntaaiduegi�asupportati
dallinguaggiodiprogrammazione.
2.Estensioniversol'altocompatibiliconlasintassiC++perleespressioni
concuiriferirsiaglioggetti.Leestensionipermettonolaselezionedegli
oggettibasatasulledescrizionidiquestioggettiesullerelazioniacui
essipartecipanoinvecechesoltantoattraversoinomidellevariabilia
cuiessisonostatiassegnati.
Illegamecontinuaadusareledueclassiautocostruitede�nitedallegame
corrente:
1.Uninsiemediclassicollezioneautocostruitepersupportarelacapacit�a
diinterrogazione
82
LoStandardODMG-93
2.Uninsiemediclassitransazioneebasididatichesupportanolacon-
correnzacontrollata,l'integrit�aelegaranziedirecuperodelDBMS
L'insiemedifunzionimembroesportatedaquesteclassi�einvocatoutilizzan-
dolasintassiC++standard.Lesoleestensioniallasintassisonolegatealla
creazionedeglioggettipersistentiedalleespressionidiinterrogazione.
Idettaglidiquesteestensioniallasintassielelorodi�erenzeconleloroequi-
valentinellegameOMLcorrentesonospiegatenellesottosezioniseguenti.
Creazione,CancellazioneeRiferimentiadOggetti
IlC++supportadelleimplicitecreazionidioggettinell'ambitodiunadi-
chiarazione,comepurequelleesplicite,creazioniecancellazionidioggetti
controllatedalprogrammatoreusandoglioperatorinewedelete.Illegame
OMLcorrentesupportasoltantoledichiarazioniesplicitedioggettipersi-
stenti.Illegamefuturosupportacreazioniimpliciteedesplicitedioggetti
persistenti.
CreazionediOggetti
Lacreazionedioggettipersistentivienefattasovrapponendol'operatorenew
a�nch�eaccettiunargomentoaggiuntivochepermettelacreazionedioggetti
persistenticomepurediquellitransienti.Sonosupportatedueformesin-
tatticheperl'operatore.Lasecondaformaincludeunastoragepragmache
permettealprogrammatoredispeci�careinchemodoglioggettiappena
allocatidebbanoessereposizionatirispettoaglialtrioggetti.Perpermette-
realibreriedicreareoggettichepossanoessereusatiuniformementecome
oggettidiunqualunquetempodivita,unavariabilemembrostaticaData-
base::transientmemoryvienede�nitaepu�oessereusatacomevaloreperun
argomentodellabasedidati.Un'invocazionedell'operazionenewconquesto
valorediargomentorisulter�acomeunanormaleallocazionedell'oggettofuori
dalloheaptransientedelC++.
Sintassi:
class_name*pointer_name=
new(database*[,class_descriptor*])
class_name[[array_element]]
[new_initializer]
new(database*,object*
OML
83
[,class_descriptor*])class_name
[[array_element_count]][new_initializer]
Esempi:
Student*s1=new(university_database)Student:
Student*s1=new(university_database,s2)Student:
Student*s1=new(transient_memory)Student:
CancellazionediOggetti
IllegameOML/futuremantieneilmodelloC++perlacancellazioneesplici-
tadeglioggetti.Lasoladi�erenzatralacancellazionedioggettinellegame
OML/currentequellanellegameOML/future�elasintassidellacancellazione
esplicita.IlC++de�nisceunoperatoredeletechevieneusatoperglioggetti
allocatifuoridelloheap.Questafunzionerichiedeunvoid*comesuoargo-
mentoequindinonpu�oessereusatanellegamecorrente.Infattiillegame
correntede�nisceunafunzionedeleteobjectseparata,perlacancellazionedi
oggettipersistenti.SiccomeillegameOML/futurousaipuntatoristandard
C++perreferenziareoggettipersistenticomeperquellitransienti,nonvi
�enecessit�adiunafunzionedeleteobjectaggiuntivanellegamefuturo.Il
legameOML/futurutilizzasemplicementel'operatoredeletedellostandard
C++pertuttiglioggetticreatiesplicitamente,senzabadareallorotempo
divita.
RiferimentiadOggetti
Nell'OML/futureglioggettireferenzierannoaltrioggettiusandoipuntatori
standardC++
(*)oppureiriferimentistandardC++
(&).Questeforme
possonoessereusateperreferenziaresiaoggettitransientichepersistenti.I
puntatoripossonoesseresettatiadunvalorenulloperindicarecheessinon
referenzianoalcunoggetto.Talevalorenullo�ede�nito0comeinC++.
Questosigni�cachelasintassiC++standardpu�oessereusataperricavaree
settareilvalorediattributi,percreare,cancellareedattraversarerelazioni,
eperinvocareoperazioni;e.g.,
Esempidiassegnamentodiunavaloreadunattributo:
p.age=32;
84
LoStandardODMG-93
x=p.age;
Laprimaistruzioneassegnailvalore32all'attributoagedip.Laseconda
istruzioneassegnailvaloredell'attributoagedipallavariabilex.
Esempidicreazione,cancellazioneedattraversamentodirelazioni:
Datelede�nizioni:
Department*english_dept;
Student*
Sam;
Professor*p;
econsiderandolaclasseProfessorcomemostratonellasezione2.2,
p->dept=english_dept;
p->dept=0;
p->advisees.insert_element(Sam);
p->advisees.remove_element(Sam);
Sam->advisor=p;
Laprimadiquesteistruzionicreaunarelazioneuno-a-unotrailprofessore
denotatodapedildipartimentodiinglese.Lasecondaistruzionecancella
larelazione.LaterzaistruzioneaggiungeSam
nell'insiemedeglistudenti
consigliatidap.LaquartaistruzioneeliminaSamdall'insiemedeglistudenti
consigliatidap.L'ultimaistruzionehalostessorisultatodellaterza-nomi-
nalmentepercreareunanuovarelazionetralostudenteSamedilprofessore
p.Lasoladi�erenza�echeessausaun'istruzionecherisultaappropriatae
vantaggiosadalpuntodivistadichiunqueguardiallabasedidatidalpunto
divistadellostudente.
Esempiodiinvocazionedioperazione:
s.register_for(c);
OML
85
Interrogazioni
Laformabasilareperunainterrogazioneintegrata�e:
collectionobject=collection[predicate]
L'espressionesullatodestrodiquestaistruzioneselezionadallacollezione
queglielementichesoddisfanoilpredicato.
Ipredicatipossonoesserede�nitisuattributi,relazionioppureoperazioni.
Ipredicatipossonoincludereunsolotermineoppuredellecongiunzioniboo-
leaneditermini,e.g.,
Professorx;
Set<Professor*>ee_professors;
x=professors[name=="Guttag"];
ee_professors=professors{dept==electrical_engineering};
Leparentesiquadre,peresempioinprofessors[name=="Guttag"],sono
usateperindicarechelasottoespressionedell'interrogazionedovrebbe
restituireun
solo
valore.
Leparentesigra�e,peresempio
in
pro-
fessorsfdept==electricalengineeringg,
sono
usate
per
indicare
che
la
sottespressionedell'interrogazionedovrebberestituireuninsiemedioggetti.
Leinterrogazionipossonoancheattraversareunarelazionetraoggetti,e.g.,
Set<Student*>guttags_students;
guttags_students=students{takeCourse
[taught_byProfessor[name=="Guttag"]]
};
Questainterrogazionerestituisceuninsiemedistrudentichepartecipanoal
corsotenutodalprofessorechesichiamaGuttag.
Lasintassidelpredicatousatanegliesempidiquestasezionerappresentano
unarestrizionedellasintassiOQLcompleta.Altrerestrizionisonopossibili,
comeilsupportodell'interasintassi.
86
LoStandardODMG-93
Questa�eun'areadellegamefuturoincuiciaspettiamosiapermessoalmer-
catodiaiutarciafareunasceltaduranteiltempocheillegameOML/future
diventer�alaparteprincipaledelC++.Ladomandabasilare�eseunasintassi
simileaSQLoqualcosadiancorapi�uvicinoall'inglesestrutturatomostrato
negliesempidiquestasottosezionevincer�a.
Leinterrogazioninonsonolimitateaglioggettipersistenti;essefunzionano
beneancheconoggettitransienti.
TrasazionieOperazionisullaBasediDati
LetransazionielebasididatinellegameOMLfuturo,sonomodellateco-
meleclassicostruiteinternamentecomeperquellocorrente.Lasintassiper
referenziareunaistanzadiquestitipicostruitiinternamente�eanch'essala
stessaperentrambiilegami,datochen�eletransazioni,n�eglioggetti"cana-
le"usatiperrappresentarelaconnessionetraunprocessoedunabasedidati
sonooggettipersistenti.NellaversionecorrentedelModelloadOggetti,gli
oggettitransientiequellicanalesonotransientiequindireferenziatiusando
deipuntatoriC++inentrambiilegami.
L'operazionedicommitsettaipuntatoriadoggettipersistentieadoggettidi
vitapi�ubrevealvalore0.Ognipuntatoretraoggettistabilitoall'internodi
unatransazione,daoggettitransientiadaltripersistenti,oviceversa,rimane
validodopol'esecuzionedell'operazionecheckpoint.
2.6.3
ProblemidiMigrazione
Cisonoduecammininellegamefuturo:(1)evolvelade�nizionedioperatore
sovrappostoall'internodellade�nizionedellinguaggioC++;(2)introduce
unpre-processorechepossamanipolareicorpideimetodiC++allostesso
mododelledichiarazionidiclasse.
Ipassidipre-processing,compilazioneelinkrichiestiperunaimplementa-
zionedipre-processorediunlegamefuturocolC++
sonomostratiinFi-
gura2.12.Ildiagramma�estatostrutturatoinmodotalechepossaessere
direttamenteconfrontatoconl'analoga�guraperillegamecorrente,Figu-
ra2.1.Lasoladi�erenza�echeilpre-processoreperillegamecorrentesi
occupasoltantodelladichiarazionedelleclassiC++.Ilpre-processoredel
legamefuturosioccupaalcorpodeimetodicheimplementanolefunzioni
ProblemidiMigrazione
87
membrode�nitesulleclassi.Ovvero,nellinguaggiodelledue�gure,illega-
mecorrenterichiedeun\pre-processoreODL",illegamefuturorichiedeun
\pre-processoreODL/OML".
Laragione�echeilpre-processoreperilfuturolegamedeveoccuparsideicorpi
deimetodiecheleistruzioniinquestimetodireferenzinooggettipersisten-
tiallostessomododeglioperatoripuntatoreusatiperreferenziareoggetti
transientisemprepresentiinmemoriavirtuale.Questiriferimentidevono
esseresostituiticonchiamatedifunzionisudiuntiporiferimentochepossa
determinaresel'oggettoreferenziato�egi�ainmemoriavirtualeuppureno.Se
l'oggetto�etransiente,larispostasar�asempresi.Sel'oggetto�epersistente,
larispostapu�oesseresioppureno.Selarisposta�eno,alloradeveessere
chiamataunaoperazionecheportil'oggettoinmemoriavirtualeprimadi
completareladereferenziazione.Lasecondaragionepercuisirendeneces-
sarioilpre-processore�eilpermetterelastrettaintegrazionedellinguaggio
delleinterrogazionicollinguaggiodiprogrammazionedibase.
Ungrandesottoinsiemediquestolegame-tuttoeccettol'integrazionedel-
leespressionidiinterrogazioneconleespressioniC++
-pu�oesserefatto
con(1)unpre-processoresoloODL(comecontemplatonellegamecorrente)
pi�ualcunegeneralizzazionidisovrapposizionedioperatoripersupportare
glioperatorifreccia("->")epunto(".")nellade�nizionedelC++,oppu-
re(2)un'architetturadiimplementazioneODBMSchepermettailnormale
codicedidereferenziazionegeneratodalcompilatoreC++perlavorareallo
stessomodoconoggettopersistentietransienti.Alcunivenditoripossono
supportaresistemineiqualilacreazione,lacancellazioneedilriferimento
adoggetti,letturaesettaggiodeivaloridegliattributi,attraversamentodel-
lerelazioni,el'invocazionedelleoperazioniusanolasintassistandardC++
perlavoraresuglioggettitransienti,maillorolinguaggiodiinterrogazione
internochiamalafunzioneoqlpassandol'interrogazionecomeunastringa.
Visonoduecamminiperspostareleapplicazioniscrittenellegamecorrente
versoillegamefuturo:(1)nonfarecambiamenti,infattileimplementazioni
chesupportanoillegamefuturocontinuanoasupportareillegamecorrente,
oppure(2)usaretoolcheautomaticamentetraducanoilcodicesorgenteal
legamesusseguente.
88
LoStandardODMG-93
OD
BM
S
Ese
cuzi
one
Cod
ice
Lin
ker
Bas
e di D
ati
Com
pila
tore
C+
+ Ogg
etto
OD
BM
S
Met
adat
i
OD
BM
S
Sorg
ente
C+
+ C
++
Tes
tata
File
di
con
OD
L/O
ML
inte
rno
Prog
ram
ma
C+
+ S
orge
nte
Pre-
Proc
esso
re O
DL
/OM
L
App
licaz
ioni
Ese
guib
ili
Ese
cuzi
one
Figura2.12:PassidiunPre-Processorefuturo
Capitolo 3
L'ambiente ODB-Tools
Preesistente
Riporto nel seguito una breve descrizione dell'ambiente ODB-Tools preesi-
stente dal quale il pre-processore ODLRule/C++ trae spunti e col quale
coopera.
D'ora in avanti, salvo diverso avviso, ogni riferimento a ODLRule, deve inten-
dersi come un riferimento a ODL esteso alla de�nitione di regole di integrit�a
succintamente descritto in questo capitolo.
3.1 L'architettura di ODB-Tools
Il progetto ODB-Tools ha come obiettivo lo sviluppo di strumenti per la pro-
gettazione assistita di basi di dati ad oggetti e l'ottimizzazione semantica di
interrogazioni. Si basa su algoritmi che derivano da tecniche dell'intelligenza
arti�ciale.
Il risultato della ricerca svolta nell'ambito di questo progetto �e un prototipo
che realizza l'ottimizzazione di schemi e l'ottimizzazione semantica delle in-
terrogazioni.
In questa sezione si intende presentare in modo schematico ODB-Tools ed i
suoi componenti maggiormente collegati al lavoro svolto in questa tesi1.
In �gura 3.1 sono rappresentati i vari moduli che compongono tale prototipo.
1Per una trattazione pi�u approfondita si veda [Cor97]
90 L'ambiente ODB-Tools Preesistente
ODL ODL_TRASL OCDL-designer
OCDL-optimizer
Text file
ottimizzato
schemain OCDL
Text file
ottimizzato
schemain OCDL
OCDL
ODBQOText file
Query
OCDL
Queryin OQL
ottimizzata
OQL
OQL
File V
F
File
VF
SC Visual(Applet Java)
Figura 3.1: Componenti ODB-Tools
3.1.1 Schemi e regole di integrit�a
I vincoli di integrit�a sono asserzioni che devono essere vere durante tutta la
vita di una base di dati ed hanno lo scopo di imporre la consistenza di una
base di dati. I seguenti vincoli di integrit�a sono gi�a esprimibili nello schema
e vengono imposti agli oggetti tramite la nozione di istanza legale:
� vincoli di dominio: per ogni attributo �e speci�cato l'insieme dei valori
ammissibili
� vincoli di integrit�a referenziale: devono esistere tutti gli oggetti in
qualche modo referenziati
� vincoli di ereditariet�a: un oggetto che appartiene ad una certa classe
C deve appartenere anche a tutte le superclassi di C.
Per poter inserire nel modello regole di integrit�a �e stata necessaria una sua
estensione.
Schemieregolediintegrit�a
91
Leregolediintegrit�ahannolaforma:
nomeregola:tipo
a
!
tipo
c
edilseguentesigni�cato:perognivalorevditipotipo
a
alloravdev'essere
ancheditipotipo
c,inaltritermini,ognivaloredell'interpretazioneditipo
a
dev'esserecontenutonell'interpretazioneditipo
c.Itipitipo
a
etipo
c
vengono
dettirispettivamenteantecedenteeconseguentedellaregola.
Riportodiseguitolasintassidelleregolediintegrit�adiODLRule
accettate
dalpre-processoreODLRule/C++:
<
RuleDcl>
::=
rule
<
Identi�er>
<
RuleAntecedente>
then
<
RuleConseguente>
<
RuleAntecedente>
::=
<
Forall>
<
Identi�er>
in
<
Identi�er>
:
<
RuleBodylist>
<
RuleConseguente>
::=
<
RuleBodyList>
<
RuleBodyList>
::=
(
<
RuleBodyList>
)
j
<
RuleBody>
j
<
RuleBodylist>
and
<
RuleBody>
j
<
RuleBodylist>
and
(
<
RuleBodyList>
)
<
RuleBody>
::=
<
DottedName>
<
RuleConstOp>
<
LiteralValue>
j
<
DottedName>
<
RuleConstOp>
<
RuleCast>
<
LiteralValue>
j
<
DottedName>
in
<
TypeSpec>
j
<
ForAll>
<
Identi�er>
in
<
DottedName>
:
<
RuleBodylist>
j
exists
<
Identi�er>
in
<
DottedName>
:
<
RuleBodylist>
j
<
DottedName>
=
<
TypeSpec>
<
OpDclRule>
<
RuleConstOp>
::=
=
j>
=
j<
=
j<
j>
<
RuleCast>
::=
(
<
TypeSpec>
)
<
DottedName>
::=
<
Identi�er>
j
<
Identi�er>
.<
DottedName>
<
ForAll>
::=
foralljforall
92
L'ambienteODB-ToolsPreesistente
<
OpDclRule>
::=
<
Identi�er>
(
<
OptParameterListRule>
)
<
OptParameterListRule>
::=
[<ParameterListRule>
]
<
ParameterListRule>
::=
<
DottedName>
j
<
DottedName>
,
<
ParameterListRule>
Osservazionisullasintassi
Lasintassiappenapresentatasidiscostaleg-
germentedallasintassiODL-estesapresentatain[Ric98]perquellocheri-
guardaleoperazioni.
Risultacomunquepossibilefarelaseguenteconsiderazione:
�
Leoperazionidichiaratenelcorpodellerulepossonoapparteneresola-
menteadunsottoinsiemedelleoperazioni.Essesonoconsideratedelle
funzionimatematiche.Questosigni�cachesonovincolatearispettare
leseguentiregole:
{devonorestituireunrisultato
{ogniparametro,sespeci�cato,siconsiderapassatopervalorein
quantononpu�oenondeveesseremodi�cato.
3.2
IllinguaggioOCDL
InquestasezionevieneriportatoqualchecennoallinguaggioOCDLinquan-
topartedell'outputdelpre-processoreODLRule/C++sar�autilizzatocome
inputperODLTrasl
2
chetraduceunsorgenteODLRule
informatoOCDL.
OCDL(ObjectandCostraintDe�nitionLanguage)estensionediODL(del
progettoODB-Tools)conregole,�eillinguaggioattraversoilquale�epossibile
descrivereunoschemadidati.OCDL�esupportatodaOCDL-Designerche
validaedottimizzaschemidibasididati.
2Siveda[Ric98]
Sintassi
93
3.2.1
Sintassi
Ladescrizionediunoschemaconsisteinunasequenzadide�nizioniditipi,
classieregole.Perdistinguereivaricostrutti�estatointrodottounpre�sso
chespeci�cailtipodelterminechesistade�nendo.Talepre�ssopu�oessere:
prim:classeprimitiva;
virt:classevirtuale;
type:tipovalore;
btype:tipobase;
Lade�nizionedicostruttohalaseguentesintassi:
prefissoNometipo=descrizionedeltipo
doveladescrizionedeltipopu�oesseredescrittadallaseguentegramma-
tica(indicoconSladescrizionediuntipo)):
S
!
B
tipoatomico
N
nometipo
fSg
tipoinsieme
<S>
tiposequenza
^S
tipooggetto
[a1
:S1;:::;ak
:Sk]tipotupla
S1&S2
intersezione;indicaereditarieta
0
Regolediintegrit�a
Comesi�evisto,unaregoladiintegrit�ahalaforma
nomeregola:tipo
a
!
tipo
c
Itipitipo
a
etipo
c
vengonodescritticonduede�nizioniseparate,essipossono
esseresoloclassivirtualietipi-valore.
Introduciamocos��quattronuovetipologiechedescrivonoleregolediinte-
grit�a:
antev:antecedentediunaregoladitipoclassevirtuale.
antet:antecedentediunaregoladitipovalore.
consv:conseguentediunaregoladitipoclassevirtuale.
const:conseguentediunaregoladitipovalore.
94
L'ambienteODB-ToolsPreesistente
Ilvalidatoreinterpretaitipichedescrivonounaregolacomeclassivirtuali
quandolatipologia�eantevoconsvmentreliinterpretacometipi-valore
quandolatipologia�eantetoconst.
Permantenerelarelazionetraantecedenteeconseguentediunastessaregola
occorredareunparticolarenomealtipo.Ilnomedellaparteantecedente�e
datodalnomedellaregolaseguitodaunaa.Ilnomedellaparteconseguente
�edatodalnomedellaregolaseguitodaunac.
3.3
Validatoredischemi
Ilprogrammachesvolgel'operazionedivalidazioneeottimizzazionediuno
schema�estatochiamatoOCDL-designer.Taleprogrammaacquisisceschemi
dibasididatiadoggetticomplessiespressinellinguaggioOCDL,operala
trasformazioneinformacanonicaal�nedicontrollarelaconsistenzadello
schemaecalcolalerelazioniisaeventualmenteimplicitenelledescrizioni.
Ilprogrammaprendeiningressoun�leditestonomefile.sccontenentelo
schemainiziale,durantelefasisuccessivecomunicaavideoeventualimes-
saggidierrorieincoerenzerilevate,sel'esecuzionehaterminecorrettamen-
teirisultatidell'elaborazionevengonoscrittiindue�le:nomefile.fce
nomefile.sb.Ilprimocontieneirisultatidellatrasformazionecanonica,il
secondolerelazionidisussunzioneelerelazioniisaminimalicomputate.La
fasediacquisizioneconsistenellaletturadel�lecontenenteloschemaela
creazionedellerelativestrutturedinamicherappresentantilede�nizionidei
tipi(classi).Durantequestafasenonvienerealizzatouncontrollosintattico
esemanticosistematico,masoloalcunicontrollidicomodoperrilevareeven-
tualierrorinellascritturadel�lediinput.Siassumeinfatticheloschema
presoininputsiacorrettodalpuntodivistasintatticoesemantico,eprivo
diciclirispettoallerelazioniisaeallede�nizionideitipivalori(schemaben
formato).
Unavoltaacquisitoloschemahainiziolafasedigenerazionedelloschema
canonico.Durantetalefase,ilprogrammaindividuaitipi(classi)incoerenti,
quelli,cio�e,lacuidescrizione�einconsistentequindiconestensionevuota.
Unavoltadeterminatalaformacanonicasipassaall'esecuzionedell'algo-
ritmodisussunzionechepermettediricalcolaretuttelerelazioniisa.Il
programmarilevaanchelerelazioniimplicitenelladescrizioneoriginalediti-
pieclassiedeterminaitipieleclassiequivalenti.Inoltrecalcolalerelazioni
disussunzioneesistentitraparteantecedenteeconseguentediregole.
3.3Validatoredischemi
95
Perulterioriinformazionisulvalidatorevederelatesi[Gar95].
96
L'ambienteODB-ToolsPreesistente
Capitolo 4
Architettura Funzionale del
Pre-Processore ODLRule/C++
Nello schema di �gura 4.1, viene presentato lo schema generale dell'archi-
tettura del pre-processore ODLRule/C++ il quale riceve in input un �le
sorgente scritto secondo una opportuna sintassi ODLRule/C++ che consen-
te anche l'utilizzo di dichiarazioni tipiche dell'ODL pur mantenendosi il pi�u
possibile vicina alla sintassi di un sorgente C++ standard.
4.1 Estensioni Rispetto al C++
Brevemente vengono riportate tutte le estensioni previste dal pre-processore
ODLRule/C++ che non rientrano nel C++ standard.
Tipi Dati supportati: oltre a tutti quelli resi disponibili dal C++ si hanno
i seguenti tipi resi disponibili sotto forma di classi di oggetti:
� Range
� Persistent Object
� Collection
� Set
� Bag
� List
� Array
� Varray
98 Architettura Funzionale del Pre-Processore ODLRule/C++
Esegue un parsing del file sorgente,compie un eventuale controllo dicovarianza e/o controvarianza se
- un file ODLRule
richiesto espressamente (utilizzaper questo il programma ODL_TRASLche compie tali controlli su dueclassi-interfacce).Genera due file: - un file C++
File C++
Compilatore C++
ODL_TRASL
File ODLRule
Sorgente ODLRule/C++
Pre-processore ODLRule/C++
Figura 4.1: Schema generale del pre-processore ODLRule/C++ e del suo
ambiente
4.2TipiDatiintrodotti
99
Dichiarazionidellechiavidiunaclasse,sianoesseprimarieoppureno.
Dichiarazionidelleestensionidelleclassi.
Dichiarazionidellerelazionidiunaclasse,necessariamentetuttebi-
narie.
DichiarazionidelleRule,relativeallevarieclassidioggetti.
4.2
TipiDatiintrodotti
Diseguitovienepresentataunabrevemaesaurientespiegazionerelativaai
nuovitipidatisupportatidalpre-processoreODLRule/C++
1.
Range:intervallo.Sitrattadiuntipodatocheconsenteallevariabilidi
assumereunvalorecompresotraquelliespressidagliestremidelrange.
Attualmenteirangesonorelativiavaloriinteriereali.Persemplicit�a
irangenonsonode�niticomeunaclasse,bens��comeunnuovotipodi
dato.
PersistentObject:serveperde�nireleinterfaccedelleclassichepopolano
labasedidati,lecuiistanzesivuolerimanganomemorizzateinmodo
persistentenellabasedidatistessa.
Collection:�eunaclasseastrattainC++enonpu�oavereistanze.Deriva
daPersistentObjectepermetteaclassiconcretechealorovolta
derivanodaessadipossedereoggettipersistenti.LaclasseCollection
contemplaalcunesemplicioperazioniqualil'inizializzazione,l'intro-
duzioneelarimozionedioggetti,ilcalcolodellacardinalit�aedaltro
ancora.
Set:�eunacollezionenonordinatadielementichenonpermetteduplicati.
DerivadallaclasseCollectionepossiedeasuavoltaoperazionitipiche
degliinsiemiqualil'unione,l'intersezione,ladi�erenza,ilcontrollodi
uguaglianza.
Bag:risultadeltuttosimileallaclasseSet,senonch�eammetteelementi
duplicatialpropriointerno.
1Perunapprofondimentosirimandaallesezioni2.3.4,2.3.5e2.3.6
100
ArchitetturaFunzionaledelPre-ProcessoreODLRule/C++
List:�eunacollezioneordinatadielementienonpermetteduplicati.An-
ch'essaderivadallaclasseCollectionequindineereditadatiemetodi.
Ilprimovaloredell'indicediunaList�ezeroperseguirelaconvenzione
delCedelC++.
Array:vienefornitaunaclasseArray,derivatadallaclasseCollectionche
permettedide�nireoggettiditipoarrayadunasoladimensioneedi
lunghezzaassegnata(pu�ocontenerealpi�uuncertonumeropre�ssato
dielementi)edinoltreilsuoindiceiniziadalvalorezeroinaccordocon
laconvenzioneCeC++.
Varray:�eunArraydilunghezzavariabile,maadi�erenzadiquestopossie-
dealcunimetodiaggiuntivirispettoallaclasseCollectiondacuideriva
anch'esso.Talimetodipermettonodialterareilnumerodielementidel
Varrayquandoquesto�egi�astatocreato.
4.3
ODLRule
RiferendosiadODLRule,siintendeparlaredellinguaggioODLstandardal
quale�estataaggiuntalasintassirelativaalleregolediintegrit�a.
Schematicamentesipu�oquindiscrivere:
ODL-Rule=ODL+RegolediIntegrit�a
Si�eassuntacomesintassiditaliregolequellade�nitanell'ambitodell'am-
bienteODB-ToolscomeestensionedellinguaggioODL
2.Questascelta�estata
fattaperevitarediintrodurreunanuovasintassiequivalenteaquellagi�aesi-
stente.
4.4
ArchitetturaFunzionaledelPre-Processore
ODLRule/C++
Passiamooraadunavisionepi�uparticolareggiatadelpre-processoreODLRule/C
edelsuorealefunzionamento.Occorrepremettereche,ondeconsentirela
massimaportabilit�apossibile,si�epreferitoutilizzareilCcomelinguaggiodi
programmazione.
Comesivededalla�gura4.2loschemadelpre-processoreODLRule/C++
2Sivedalasezione3.1.1
4.4ArchitetturaFunzionaledelPre-ProcessoreODLRule/C++101
OCDL-Designer
Controllo suCovarianza eControvarianza
Errori
ODB_Types
Analisi Sintattica
Lex&Yacc
Traduttore
Nomefile.cpp Nomefile.odl
ODL_TRASL
Sorgente ODLRule/C++
Figura
4.2:
Schema
a
blocchidell'architettura
del
pre-processore
ODLRule/C++
risultafortementeintegratoall'ambientechelocirconda.Icomponenticol
bordotratteggiatofannoparteditaleambiente,mentrequelliabordocon-
tinuosonomodulidelpre-processoreODLRule/C++.I�le,sianoessidi
input,dioutputodilibreria,hannoilbordocontinuocongliangoliarroton-
dati.
L'analisisintattica�ebasatasull'utilizzodiLEX&YACC
3.Inparticolareoc-
correleggereecapireilsorgentechevieneaccettatoiningressoinmododa
poterlopoitradurre.Serichiestodall'utentetramiteappositiparametripas-
satidallalineadicomando,�epossibilerichiedereilcontrollodicovarianza
e/ocontrovarianzasuimetodidellevarieclasside�nitenelsorgente.Attual-
mentequestocontrollonon�edisponibileeperunapprofondimentointal
3Sivedal'AppendiceA
102
ArchitetturaFunzionaledelPre-ProcessoreODLRule/C++
sensosivedal'appendiceB.
Nelcasosianoriscontratierroridisintassiodiqualunquealtrogenere,ne
vienedatanotiziaall'utenteel'esecuzionedelprogrammahatermine.Vi-
ceversa,setutto�eandatobene,ilprogrammapassaallapartesuccessiva
ovverolatraduzioneveraepropria.LatraduzioneinlinguaggioC++,viene
e�ettuatagrazieun�ledilibreriachede�niscetuttiitipidatieleclas-
siintrodotte(ODBTypes);il�leC++
risultantenonavr�aquindierrori
dicompilazionedovutiallatraduzione,masipotrebberoaverealtritipidi
erroriinquantonessuncontrolloe�ettivovienee�ettuatosullacorrettezza
deidatiintrodotti,i.e.,dichiarazionedidueclassidiverseconlostessonome.
Lerelazionieledichiarazionidichiavivengonoeliminatenel�leC++cos��
ottenuto.Perquantoriguardaleregolediintegrit�aessepossonoesseretra-
sformateinfunzioniesterneoinmetodi(operazioni)internialleclassiacui
leregolesiriferiscono.
LatraduzioneinODLRule,equindilaproduzionedel�leODLRule,risul-
taabbastanzasempliceinquantolasintassiaccettatadalpre-processore
ODLRule/C++simantienemoltovicinaallasintassiODLRule,purconsen-
tentendovarieestensioniversoillinguaggioC++.Ingenere�esu�ciente
sostituireoaggiungereparticolariparolechiave.
4.4.1
Esecuzionedelpre-processoreODLRule/C++dal-
lalineadicomando
L'utilizzodelpre-processoreODLRule/C++deveseguirelaseguentesintassi
dadigitareallalineadicomando:
odlcppprepnome�le[-v][-t]
dove:
odlcppprep�eilnomedell'eseguibile;
nome�leidenti�cail�lesorgentescrittoinlinguaggioODLRule/C++.Nes-
sunaestensionedeveesserespeci�catainquantovieneconsiderataper
defaultl'estensione\.cpo".Questoparametro�enecessarioelasua
mancanzacausal'arrestoimmediatodelprogramma;
-vparametroopzionalecherichiedeilcontrollodellacovarianza;
FilesdiOutput
103
-tparametroopzionalecherichiedeilcontrollodellacontrovarianza;
4.4.2
FilesdiOutput
Ilprodottodelpre-processoreODLRule/C++
,ammessochenonsisiano
veri�catierrori,risultaconsistere,comegi�adettoindue�leicuinomisono
ugualiaquellospeci�catocomeparametro,mentrenevarial'estensione:.cpp
peril�leC++e.odlperil�leODLRule.
104
ArchitetturaFunzionaledelPre-ProcessoreODLRule/C++
Capitolo5
IlPre-processore
ODLRule/C++
5.1
IlTraduttore
5.1.1
Strutturadelprogramma
LasintassidiODLestesaversoillinguaggioC++�estatadi�usainforma-
tolex&yacc
1,talescelta�einaccordoconlapoliticadell'ODMGdirendere
ODL,equindituttiisuoiderivati,facilidaimplementare.
AllasintassiLex&Yaccsonostateaggiunte:
1.LeactionsdellaparteYacc.Nelleactionsvengonomemorizzatitutti
iconcettilettidal
pre-processoreODLRule/C++
,vengonoinoltre
eseguitialcunicontrollisemantici.
2.RoutinedistampainformatoODLRule
eC++.Questeultimecom-
prendonoleroutineditraduzioneveraepropriaeleroutineditrasfor-
mazionedelleregolediintegrit�ainmetodiefunzioniC++.
Ilprogramma�ecompostodaiseguentimoduli
�
moduloprincipale(preprocm.c):
Sihal'inizializzazionedellevariabiliglobali,echiamainsequenza:il
parser,laroutineditraduzioneinODLRule,laroutineditraduzionein
C++.
�
parserdellasintassiODLRule/C++:
� Ecompostodalmodulolex(preproc.l)edalmoduloyacc(preproc.y).
1sivedaappendiceA
106
IlPre-processoreODLRule/C++
SvolgeilcontrollosintatticodellasintassiODLRule/C++
grazieal-
leroutinegenerateconLex&Yacc.Durantetalecontrolloriempiele
strutturedatiinmemoria.
�
routineditraduzioneinODLRule:
DallestrutturedatiallocatedalparserestraelaformaODLRule.
�
routineditraduzioneinC++:
DallestrutturedatiallocatedalparserestraelaformaC++oltread
eseguire�sicamentelatrasformazionedelleregolediintegrit�adalla
sintassiODLRule
ametodiefunzioniC++.
Diseguitosarannodescrittesololepartiprincipalidelprogrammaedinpar-
ticolarmodolatrattazionedelleregolediintegrit�aal�nedellalorotrasfor-
mazione.Pereventualichiarimentisullastrutturaoriginaledeltraduttore
sivedalaTesidilaureadiS.Riccio[Ric98]allaqualelapresentetesisi�e
ispirata.
5.1.2
LaSintassiODLRule/C++
LasintassiODLRule/C++�efortementelegataaquellaODLRule,maneau-
mentala essibilit�aconcedendoalprogettistadibasididatiadoggettinuove
potenzialit�a.Talesintassi�estataispiratadallostandardODMGriportato
nelcapitolo2conalcunemodi�cheresenecessarie,amioavviso,perlachia-
rezzaespressivadellastesuradiunsorgente.
Diseguitoriportosoltantoledi�erenzerispettoatalestandard.
DichiarazionidiFileInclusi
Sebbenelostandardnonnefacciaparola,�ediusocomunedichiarareinclusio-
nidi�leinunsorgenteC++.Atalescopoilpre-processoreODLRule/C++
consentetalidichiarazionieleriportanel�leC++
dioutput,mentrele
ignorasemplicementedurantelacostruzionedel�leODLRule.
DichiarazionidiClassidiOggetti
Onderenderepi�uchiaraladichiarazionediunaclasse,sonostateaggiunte
duenuoveparolechiave:relationshipeoperationdaporrerispettivamen-
tedavantiadognidichiarazionedirelazioneedioperazione(peroperazione
siintendaci�ochecitalostandardovverometododiunaclasseofunzione
esterna).
LestruttureDati
107
Risultaancheprevistalapossibilit�adidichiararechiavirelativealleclassi.
Discostandosidallostandardpertenersiilpi�uvicinopossibileadODL,
lasintassiperladichiarazionediunaclasseprevedeladichiarazionedella
estensionedellaclassestessanelmodoseguente.
<
ClassDcl>
::=
<
class>
<
Identi�er>
[<InheritanceSpec>
]
[<KeySpec>
]<
ExtentSpec>
f[<ClassBody>
]g;
<
ExtentSpec>
::=
<
extent>
<
Identi�er>
DichiarazionediRegolediIntegrit�a
Lostandardnonlemenzionaneppure,quindihodecisodimantenerela
sintassiODLRule
2
perladichiarazioneditaliregoleondenoncostringereil
progettistadibasididatiadimparareunanuovasintassideltuttoequivalente
adunagi�aesistente.
5.1.3
LestruttureDati
Riportodiseguitoalcunedellestrutturedatinellequalivienememorizzato
loschemadiunsorgenteODLRule/C++.
Rappresentazionediunadichiarazioneinclude
Vediamocomesono
memorizzateleinformazionirelativealledichiarazioniinclude.
structs_include_list
{chartype;
/*'q'->""
'b'-><>*/
char*nomefile;
structs_include_list*next;
}*Include_list;
Leinformazionivengonomemorizzatesottoformadilistadinomidi�lee
tipodiinclusione.
2Perunapprofondimentodettagliatosivedano[Cor97]e[Ric98]
108
IlPre-processoreODLRule/C++
Rappresentazionediunaclass
Vediamocomesonomemorizzatele
informazionidiunaclass.
structs_class_type
{chartype;
/*'f'->forward
'b'->body
*/
char*name;
char*extent_name;
structs_iner_list*iner;
char*key;
structs_prop_list*prop;
}*Class_type;
Ilcampoinerpuntaallalistadeinomidelleclassidacuiderivalaclassein
questione.
Ilcampoproppuntaallalistadellepropriet�adellaclassemedesima:attri-
buti,relazioniedoperazioni.
Rappresentazionedellepropriet�a
Vediamoinchemodosonomemo-
rizzateleinformazionirelativeallepropriet�adiunaclasse.
structs_prop_list
{structs_prop_type*p;
structs_prop_list*next;
}*Prop_list;
structs_prop_type
{chartype;
/*'c'->costante
't'->tipo
'a'->attributo
'r'->relazione
'o'->operazione
*/
unions_prop
{
LestruttureDati
109
char*c;
structs_type_type*t;
char*a;
structs_rel_type*r;
structs_op_type*o;
}prop;
}*Prop_type;
Percomodit�asi�epreferitotenereseparatelalistadellepropriet�adallasin-
golapropriet�a.Icampidell'unioneprophannoilseguentesigni�cato:
�
c:lapropriet�a�eunacostanteevienememorizzatainunastringadi
caratterichecontieneancheiltipoedilvalore.
�
t:lapropriet�a�eunadichiarazioneditipointernaallaclasseinquestio-
ne.
�
a:lapropriet�a�eunacostanteolistadicostantievienememorizzata
inunastringadicaratterichecontieneancheiltipo.
�
r:lapropriet�a�eunadichiarazionedirelazione.
�
o:lapropriet�a�eunadichiarazionedioperazione(metodo).
Rappresentazionedelleregolediintegrit�a
Perlarappresentazione
delleregolediintegrit�a,accettandoilpre-processoreODLRule/C++lasin-
tassiODLRule,houtilizzatolestrutturerelativealtraduttoreODLTrasl
3
conalcuneleggerevarianti:
structs_rule_body_list
/*------------------------------*/
/*gestionerules
*/
{chartype;
/*flagchepuo'valere:
*
'c'
dichiarazionedicostante
*
'i'
dichiarazioneditipo
*
'f'
laregolae'unforalloun'exist
*/
charfg_ok;
3Siveda[Ric98]
110
IlPre-processoreODLRule/C++
/*variabiledicomodopersaperese
*unadatacondizione
*e'gia'stataconsiderata
*puo'valere:
*
''
condizioneNONancoraconsiderata
*
'*'
condizionegia'considerata
*/
charfg_ok1;
/*variabiledicomodo
*usataSOLOperlabody_listdelprimolivello
*dellaparteconseguentediunarule
*servepersapereseunadatacondizione
*e'gia'stataconsiderata
*infattinelcasoparticolaredelprimolivello
*diunacondizioneconseguente
*sihannoduetipidicondzioni
*
1.quellechecoinvolgonoXcomeiteratore
*
es:
X.int_value=10
*
questedevonoessereracchiusetra[]
*
2.quellechecoinvolgonoXinquantoindica
*
ilmembrodell'estensione
*
es:
XinTManager
*
questedevonoesseremesseinand
*
coniltipoclasse
*
es:
Manager&TManager...
*puo'valere:
*
''
condizioneNONancoraconsiderata
*
questoe'ilvaloredidefault
*
'*'
condizionegia'considerata
*/
char*dottedname;/*nomevariabileinteressata*/
union
{struct
{/*dottednamee'lavariabiledamettere
*inrelazioneconlacostante
*/
char*operator;
char*cast;
/*NULLsemancailcast*/
char*value;
}c;
struct
LestruttureDati
111
{/*dottednamee'lavariabilesucuiimporre
*iltipo
*
Nelcasodifunzioni,'type'rappresentail
*tipodiritorno
*/
char*type;
/*identif.tipo
*/
/*listadeiparametridellafunzione
*seNULLnonsifausodeifunzioni
*/
structs_op_type*param_list;
}i;
struct
{/*dottednamee'lalistasucuiiterare*/
charfg_forall;
/*
puovalere:
*
'f'
forall
*
'e'
exist
*
significacheil
*
tipoe'un'exist
*questoflage'stato
*introdottoinquantoi
*tipiEXISTeFORALL
*hannomoltissimecose
*incomune
*/
char*iterator;
/*nomeiteratore*/
structs_rule_body_list*body;
}f;
}r;
structs_rule_body_list*next;
}*Rule_body_list;
L'unicadi�erenzarispettoallastrutturaoriginalestanell'attributoparamlist
cheinquestocasorisultaessereunpuntatorealtiposoptypeinveceche
altiposoperationparam.Ilnuovotipopossiedelaseguentestruttura:
structs_op_type
{char*returnvalue;
char*name;
112
IlPre-processoreODLRule/C++
structs_param_list*param;
}*Op_type;
structs_param_list
{char*tipo;
char*param;
structs_param_list*next;
}*Param_list;
Talemodi�ca�estatafattainquantolastrutturasoperationparamrisulta
ridondantepergliscopipre�ssati.Ilsigni�catodell'attributorimanecomun-
queinvariato.
Perquelcheconcernelastrutturasruletype,sonostatee�ettuatealcune
sempli�cazioni:
structs_rule_type
{char
*name;
/*nomedellarule*/
structs_rule_body_list*ante;
structs_rule_body_list*cons;
/*listaglobaleditutteleregole*/
structs_rule_type
*next;
}*Rule_type;
Rispettoall'originalesonostatieliminatigliattirbutiocdlanteeocdlcons
inquantoinutilinell'applicazionesviluppatanellapresentetesi.
5.2
DescrizionedelleFunzioni
UtilizzandoilparsergeneratodaLex&Yacc�epossibileriempirelestrutture
datiinmemoriaconleinformazionirelativealloschemapresentatoininput.
Diseguitosipresentanolefunzionicheleggonoquestestrutturedatiper
eseguirelatraduzioneelamanipolazionediquestidationdepoirestituirein
outputil�leinformatoODLRule
equelloinformatoC++.
Facciopresentechenessuncontrollodicoerenzavienee�ettuatodalpre-
processoreODLRule/C++inquantoridondante.Talicontrollivengonoese-
guitidaOCDLDesigneredalcompilatoreC++aiqualii�ledioutputsono
destinati.Vieneinvecegarantitacorrettezzasintatticaegrammaticaledi
5.2DescrizionedelleFunzioni
113
entrambi�leprodotti.
Diseguitovengonoriportateleprincipalifunzionicherealizzanol'algoritmo
ditraduzione.
Sonoduelefunzionifondamentali:unasioccupadellatraduzionedelsor-
genteinODLRule;l'altraproducel'equivalenteC++econverteleregoledi
integrit�ainoperazioni.
FunzioneperlaTraduzioneinODLRule
Lafunzioneprincipaleditraduzione�etraduciodled�econtenutanelmo-
dulopreodl.cassiemeatuttelefunzioniminorispecializzate.Essaesegue
unaletturasequenzialedellastrutturadide�nizionipresenteinmemoriado-
poche�estatoe�ettuatoilparsing.Asecondadeltipodide�nizioneviene
richiamataunaspeci�casottofunzionespecializzataatrattareilgeneredi
datoinquestione.
�
Costanti:vienesemplicementeriportataladichiarazioneODLRule/C++.
�
Classi:vienerichiamatalafunzioneprintclassodl.
�
RegolediIntegrit�a:vienerichiamatalafunzioneprintruleodl.
�
TipiDato:vienerichiamatalafunzioneprinttypeodl.
�
Operazioni:vienerichiamatalafunzioneprintopodl.
LasintassiODLRule/C++risultavolutamentesimileallasintassiODLRule
dimodocheleoperazioniditraduzionerisultinosempli�cate.
Sonodacitarecomunquealcunenotevolidi�erenze:
�
ListadiEreditariet�a:lasintassiODLRule/C++
prevedecheinta-
lelistavisialaspeci�cadeltipodiereditariet�a(public,private
oprotected).Durantelatraduzione,taletipodiereditariet�aviene
omesso.
�
ListediAttributi:nellasintassiODLRule/C++vieneconsentitauna
dichiarazionediattributitipicadelC++,secondolasintassi:
<
AttrDcl>
::=
<
TypeSpec>
<
Identi�erList>
<
Identi�erList>
::=
<
Identi�er>
j
<
Identi�er>
,<
Identi�erList>
114
IlPre-processoreODLRule/C++
Diconseguenza,al�nedipotertradurrecorrettamentelavolont�adi-
chiarativadelprogettista,�estatonecessariotradurreildatodiquesto
tiponellasintassiODLRule:
<
AttrDcl>
::=
<
attribute>
<
TypeSpec>
<
Identi�er>
ripetendotaledichiarazionetantevoltequantodovuto.
�
TipiDato:ilC++
(edancheODLRule/C++)imponedidichiara-
revariabilistrutturaanteponendoalnomedeltipolaparolachia-
vestructmentrequestovieneconsideratounerrorenellasintassi
ODLRule.
Lafunzioneprintfattrodlelesottofunzioniadessa
collegate,eliminanotaleparolachiave.
�
ListediParametri:lasintassiODLRule/C++consenteilpassaggioad
unafunzionediparametripervaloreeperriferimentorifacendosialla
sintassitipicadelC++equindiutilizzandol'operatore&postod'in-
nanzialnomediunparametroperindicarecheessodeveesserepassato
perriferimentoenonpervalore.
Lafunzioneprintopodlcompieappuntotalecontrolloedinserisce
laparolachiaveinsenonsiriscontralapresenzadi&,incasocontra-
riovieneintrodottalaparolachiaveinoutinaccordoconlasintassi
ODLRule
4.
Un'osservazionerisultaevidente:
utilizzandoilpre-processoreODLRule/C++nonsar�amaipossibiledi-
chiarareparametridisolauscitaperunafunzionecomeinveceprevisto
daODLRule.Ilsoloparametrodisolauscitarisultaessereilvaloredi
ritornodellafunzionestessa.
Un'ultimaosservazione:avendoaccettatolasintassiODLRule
perladichiara-
zionedelleregolediintegrit�a,essavieneriportataquasiimmutatainuscita.
Inrealt�ailsigni�catodellaregolarestacomunqueinalterato,maacausa
dellamemorizzazionedellasuastruttura,aventualicondizioniposteinand
tralorovengonoriportatenel�ledioutputinordineinvertito.
4Siveda[Ric98]
5.2DescrizionedelleFunzioni
115
Esempio
Diseguitoriportounesempioditraduzione,daunsorgente
ODLRule/C++
adun�leinsintassiODLRule
corretta,compiutadalpre-
processoreODLRule/C++.
#include<stream.h>
structIndirizzo{
stringvia,numero,citta;
};
classPersona
keyscodfis
extentPersone
{stringnome,cognome,codfis;
structIndirizzoindirizzo;
relationshipPersonasposato_coninversePersona::sposato_con;
};
classManager:publicPersona
extentManagers
{range{20000,140000}salario;
range{1,13}livello;
set<Persona>collaboratori;
range{0,200000}premi;
intanno_assunzione;
relationshipset<Azienda>lavora_perinverseAzienda::dipendente;
operationrange{0,200000}premio(intanno_assunzione,intcontratti);
};
classTopManager:publicManager
extentTopManagers
{range{10,13}livello;
};
classAzienda
keyspartita_iva
extentAziende
116
IlPre-processoreODLRule/C++
{stringnome,partita_iva;
structIndirizzoindirizzo;
relationshipset<Manager>dipendenteinverseManager::lavora_per;
};
Lacuitraduzionerisultaessere:
structIndirizzo{
string
via,numero,citta;
};
interfacePersona
{ attributestring
nome;
attributestring
cognome;
attributestring
codfis;
attributeIndirizzoindirizzo;
relationshipPersonasposato_coninversePersona::sposato_con;
};
interfaceManager:Persona
{ attributerange{20000,140000}salario;
attributerange{1,13}livello;
attributeset<Persona>collaboratori;
attributerange{0,200000}premi;
attributeint
anno_assunzione;
relationshipset<Azienda>lavora_perinverseAzienda::dipendente;
range{0,200000}premio(inint
anno_assunzione,inint
contratti);
};
interfaceTopManager:Manager
{ attributerange{10,13}livello;
};
interfaceAzienda
{ attributestring
nome;
attributestring
partita_iva;
attributeIndirizzoindirizzo;
relationshipset<Manager>dipendenteinverseManager::lavora_per;
};
5.2DescrizionedelleFunzioni
117
FunzioneperlaTraduzioneinlinguaggioC++
Occorrefareundiscorsopreliminare.
IlC++standardnonconsenteladichiarazionidioggettiditipocollezione
qualiset,bag,list,ecc.Lostandardpresentatonelcapitolo2introduce
per�olede�nizioniditalistruttureproprioperunlegameconC++.� Estato
quindinecessariocreareun�ledilibreriaC++
contenentetalide�nizioni
oltrealconcettodirangecheODLRule/C++accetta.
Lafunzioneprincipaleditraduzione�etraducicpped�econtenutanelmo-
duloprecpp.cassiemeatuttelefunzioniminorispecializzate.Perpri-
macosaessainseriscenel�ledioutputunainclusionedel�ledilibreria
\cpolib.cpp",quindiaggiungeaventualiinclusioniaccessoriede�nitedal
progettistadibasididatinel�lesorgente.
Conseguentementevienefattaunaprimascansionesequenzialedeidatipre-
sentiinmemoriaondecrearenuovestrutturedidatidiservizioutilizzate
nellatraduzioneenellagestionedelleregolediintegrit�a.
Notiinomiditutteleclassi,vienescrittosul�ledioutputunaintestazione
speciale,richiestadalcompilatoreC++
dellaGNU,cheneconsentir�apoi
lacompilazione.Taleintestazioneconsistenellade�nizione,perogniclasse
dichiarata,dispecialitipirelativialleclassicollezione.
Lafunzioneeseguequindiunasecondaletturasequenzialedellastruttura
dide�nizionipresenteinmemoriadopoche�estatoe�ettuatoilparsing.A
secondadeltipodide�nizionevienerichiamataunaspeci�casottofunzione
specializzataatrattareilgeneredidatoinquestionesimilmenteaquanto
avvieneperlatraduzioneinODLRule.
�
Costanti:vienesemplicementeriportataladichiarazioneODLRule/C++.
�
Classi:vienerichiamatalafunzioneprintclasscpp.
�
RegolediIntegrit�a:vienerichiamatalafunzioneprintrulecpp.
�
TipiDato:vienerichiamatalafunzioneprinttypecpp.
�
Operazioni:vienerichiamatalafunzioneprintopcpp.
Ancheinquestocasosonodacitarealcunenotevolidi�erenzetrailsorgente
ODLRule/C++edil�leC++dioutput:
118
IlPre-processoreODLRule/C++
�
DichiarazionidiRelazionifraleClassi:talidichiarazioninonvengono
riportatenel�ledioutputinquantononsonogestibilidirettamente
tramiteillinguaggioC++.
�
ClassieCollezionidiClassi:comegi�adetto,ilC++nonsupportala
gestionediclassicollezione.Inaccordoconlostandardeconleesigenze
compilativedelC++,vengonofattealcunesostituzioni.Quandoun
nomediunaclassevieneutilizzatoperde�nireunattributo,atale
nomevienesostituitounriferimentoataleclasse.Inmodoanalogosi
operaconlecollezionidiclassi.
Esempio:
classPerson
{ };
classManager:Person
{Personmother;
Set<Person>children;
};
vienetradottoin:
classPerson
{ };
classManager:Person
{RerPersonmother;
RefSetRefPersonchildren;
};
�
Regolediintegrit�a:vengonotrasformateinfunzioniemetodiinterni
alleclassiperlequalivengonospeci�cate.Aidettagliditaletrasfor-
mazioneverr�adedicatolaprossimasezione.
5.2DescrizionedelleFunzioni
119
Esempio
Diseguitoriportounesempioditraduzione,daunsorgente
ODLRule/C++adun�leinlinguaggioC++,compiutadalpre-processore
ODLRule/C++.IlsorgenteODLRule/C++�elostessodell'esempiorelativo
allatraduzioneinODLRule.
#include"cpolib.cpp"
#include<stream.h>
classPersona;
typedefRef<Persona>RefPersona;
typedefSet<RefPersona>SetRefPersona;
typedefRef<SetRefPersona>RefSetRefPersona;
typedefBag<RefPersona>BagRefPersona;
typedefRef<BagRefPersona>RefBagRefPersona;
typedefList<RefPersona>ListRefPersona;
typedefRef<ListRefPersona>RefListRefPersona;
typedefArray<RefPersona>ArrayRefPersona;
typedefRef<ArrayRefPersona>RefArrayRefPersona;
typedefVarray<RefPersona>VarrayRefPersona;
typedefRef<VarrayRefPersona>RefVarrayRefPersona;
classManager;
typedefRef<Manager>RefManager;
typedefSet<RefManager>SetRefManager;
typedefRef<SetRefManager>RefSetRefManager;
typedefBag<RefManager>BagRefManager;
typedefRef<BagRefManager>RefBagRefManager;
typedefList<RefManager>ListRefManager;
typedefRef<ListRefManager>RefListRefManager;
typedefArray<RefManager>ArrayRefManager;
typedefRef<ArrayRefManager>RefArrayRefManager;
typedefVarray<RefManager>VarrayRefManager;
typedefRef<VarrayRefManager>RefVarrayRefManager;
classTopManager;
typedefRef<TopManager>RefTopManager;
typedefSet<RefTopManager>SetRefTopManager;
typedefRef<SetRefTopManager>RefSetRefTopManager;
typedefBag<RefTopManager>BagRefTopManager;
typedefRef<BagRefTopManager>RefBagRefTopManager;
typedefList<RefTopManager>ListRefTopManager;
typedefRef<ListRefTopManager>RefListRefTopManager;
typedefArray<RefTopManager>ArrayRefTopManager;
typedefRef<ArrayRefTopManager>RefArrayRefTopManager;
typedefVarray<RefTopManager>VarrayRefTopManager;
120
IlPre-processoreODLRule/C++
typedefRef<VarrayRefTopManager>RefVarrayRefTopManager;
classAzienda;
typedefRef<Azienda>RefAzienda;
typedefSet<RefAzienda>SetRefAzienda;
typedefRef<SetRefAzienda>RefSetRefAzienda;
typedefBag<RefAzienda>BagRefAzienda;
typedefRef<BagRefAzienda>RefBagRefAzienda;
typedefList<RefAzienda>ListRefAzienda;
typedefRef<ListRefAzienda>RefListRefAzienda;
typedefArray<RefAzienda>ArrayRefAzienda;
typedefRef<ArrayRefAzienda>RefArrayRefAzienda;
typedefVarray<RefAzienda>VarrayRefAzienda;
typedefRef<VarrayRefAzienda>RefVarrayRefAzienda;
structIndirizzo{
string
via,numero,citta;
};
classPersona
{ public:
string
nome,cognome,codfis;
structIndirizzoindirizzo;
staticconstchar*const
extent_name;
};
staticRefSetRefPersonaPersone;
classManager:publicPersona
{ public:
IRange
salario;
IRange
livello;
RefSetRefPersonacollaboratori;
IRange
premi;
int
anno_assunzione;
IRange
premio(int
anno_assunzione,int
contratti);
staticconstchar*const
extent_name;
};
staticRefSetRefManagerManagers;
classTopManager:publicManager
{ public:
IRange
livello;
staticconstchar*const
extent_name;
};
staticRefSetRefTopManagerTopManagers;
5.3TraduzionedelleregolediIntegrit�a
121
classAzienda
{ public:
string
nome,partita_iva;
structIndirizzoindirizzo;
staticconstchar*const
extent_name;
};
staticRefSetRefAziendaAziende;
Occorreosservarecheil�ledioutputinlinguaggioC++noncontieneicor-
pidellefunzioniedeimetodi,edinoltrenoncontienelafunzione\main"e
quindinon�edirettamentecompilabile.Risultanecessariocreareun�leC++
entroilqualeincludereilprodottodellatraduzione.
5.3
TraduzionedelleregolediIntegrit�a
ConriferimentoallasintassiODLRule/C++
presentatanellasezione3.1.1,
vienequimostratol'algoritmoditraduzionediregolediintegrit�ainunasin-
tassiODLRule
edinunafunzioneC++standard.
5.3.1
Lastrutturadati
Diseguitovienepresentataneldettagliolastrutturanellaqualesonomemo-
rizzatiidatiriguardantiunaregoladiintegrit�a.
structs_rule_type
{
char
*name;
/*nomedellarule*/
structs_rule_body_list*ante;
structs_rule_body_list*cons;
/*listaglobaleditutteleregole*/
structs_rule_type
*next;
} Lastructsruletypeservepermemorizzarelevarieregolediintegrit�a.
Tutteleregolediintegrit�adichiarateinunoschemasonouniteinunalista.
Comesivede,unarule�edescrittadaunaparteantecedenteedunacon-
seguente.Leduecondizioniantecedenteeconseguentesonodescrittecome
listedicondizioni.
122
IlPre-processoreODLRule/C++
Diseguito�eriportatalastrutturadatichepermettedimemorizzareuna
listadicondizioni.Sipu�onotarecheunrecordditalelista�eingradodi
descrivereunoqualunquedeicostruttibasechecompongonounacondizione
diunaregoladiintegrit�a.
structs_rule_body_list
{
chartype;
charfg_ok;
/*variabiledicomodopersapereseunadatacondizione
*e'gia'stataconsiderata
*puo'valere:
*
''
condizioneNONancoraconsiderata
*
'*'
condizionegia'considerata
*/
charfg_ok1;
/*variabiledicomodo
*usataSOLOperlabody_listdelprimolivello
*dellaparteconseguentediunarule
*servepersapereseunadatacondizione
*e'gia'stataconsiderata
*infattinelcasoparticolaredelprimolivello
*diunacondizioneconseguente
*sihannoduetipidicondzioni
*
1.quellechecoinvolgonoXcomeiteratore
*
es:
X.int_value=10
*
questedevonoessereracchiusetrapar.quadre
*
2.quellechecoinvolgonoXinquantoindica
*
ilmembrodell'estensione
*
es:
XinTManager
*
questedevonoesseremesseinandconiltipoclasse
*
es:
Manager&TManager...
*pu\`ovalere:
*
''
condizioneNONancoraconsiderata
*
questo\`eilvaloredidefault
*
'*'
condizionegi\`aconsiderata
*/
char*dottedname;
/*nomevariabileinteressata*/
union
{
struct
{
/*inquestocaso
*dottednamee'lavariabiledamettere
*inrelazioneconlacostante
Lastrutturadati
123
*/
char*operator;
char*cast;
/*NULLsemancailcast*/
char*value;
}c;
struct
{
/*inquestocaso
*dottednamee'lavariabilesucuiimporre
*iltipo
*/
char*type;
/*identif.tipo
*/
/*puntatoreallaoperazione*/
structs_op_type*param_list;
}i;
struct
{
/*inquestocaso
*dottedname\`elalistasucuiiterare
*/
charfg_forall;
/*
puovalere:
*
'f'
forall
*
'e'
exists
*
significacheil
*
tipo\`eun'exists
*questoflag\`estato
*introdottoinquantoi
*tipiEXISTSeFORALL
*hannoquasilastessatraduzione
*incomune
*/
char*iterator;
/*nomeiteratore*/
structs_rule_body_list*body;
}f;
}r;
structs_rule_body_list*next;
} Descrizionedellastruttura:
�
typeindicailtipodiparametro,ilqualepuo'valere:
{'c'dichiarazionedicostante
{'f'laregola�eunforalloun'exists
{'i'dichiarazioneditipo
Inquestocasoparticolare,puo'essereinseritanellacondizioneuna
124
IlPre-processoreODLRule/C++
dichiarazionedioperazione.Infattinellastrutturai�epresenteun
campo,denominatoparam
list,chepuntaallalistadeiparametri
diunaoperazione(soptype).
5.3.2
Funzionidigestionedelleregolediintegrit�a
Diseguitosonopresentatelefunzionicherealizzanol'algoritmoditrattazione
delleregolediintegrit�a.
�
printruleodl
Lafunzioneprintruleodle�ettuasemplicementelatrascrizionedel-
laruleinlinguaggioODLRule
senzae�ettuarealcuntipodicontrollo
(ognicontrollovienelasciatoaltoolOCDLDesignercheaccettainin-
gressoil�legeneratodalpre-processoreODLRule/C++).
Questafunzionescandiscesemplicementelastrutturadatiinmemoria
ondericostruirelaregoladichiarata.
Sipu�oosservarecheincasodicondizionimultiplepostesugliattributi
diunoggetto,acausadellaparticolarestrutturadatiutilizzata,esse
vengonoriportateinuscitainordineinverso.Questononponeproble-
mieccessiviperquelcheriguardailsigni�catodellaregoladiintegrit�a
inquantolevariecondizionisonopostein\and"logicotraloro.
�
printrulecpp
Lafunzioneprintrulecpptrasformaunaregoladiintegrit�ainuna
funzioneC++conlostessonome,cherestituisceunvalore\vero"se
lecondizioniimpostesonorispettate,unvalore\falso"incasocon-
trario.Talevalorevienecontenutoinunavariabilechiamata\ ag",
inizialmentepostaa1(\vero"),chefornir�apoiilvaloredarestituire.
Alladescrizioneneldettagliodell'algoritmoespletatodaquestafunzio-
nevienededicatalaprossimasezionedelcapitolo.
5.3.3
AlgoritmodiTrasformazionedelleRegolediIn-
tegrit�a
OccorreosservarechepermotividicoerenzaconlasintassiODLRule/C++,
si�edecisoditrasformareunaregoladiintegrit�ainunafunzioneesternaalle
classianzich�einunmetodorelativoallaclasseinteressata.Nullavietaper�o
die�ettuarelasceltaopposta.Inquestasezioneverrannoanchebrevemente
descrittelemodi�cheall'algoritmonecessarieperlagenerazionedimetodi
AlgoritmodiTrasformazionedelleRegolediIntegrit�a
125
anzich�efunzioni.
Ondechiarirealmegliol'algoritmoditrasformazione,riportodiseguitoal-
cuniesempispiegandopassopassocomel'algoritmointerpretaidatieagisce
diconseguenza.
Comescrivereunaregoladiintegrit�a:vediamoalcuneregolesemplicima
particolarmenteesplicative:
ruler1forallXinWorkers:
(X.salary>10000000
)
then X
inAgiatePerson;
Sipu�oleggerecos��:\perognielemento,cheindicoconX,dell'estensione
dellaclasseWorkers,sel'attributosalarydiXhavaloremaggioredi10
milioni,alloral'elementoXdevefarparteanchedellaclasseAgiatePerson
".
ruler1forallXinPerson:
(XinAgiatePerson)
then X
.taxes="High".
\perognielemento,cheindicoconX,dell'estensionedellaclassePerson,se
l'oggettoXappartieneancheall'estensionedellaclasseAgiatePersonallora
l'attributotaxesdiXdeveavervalore\high"".
Dotnotation(nomiconpunti)
All'internodiunacondizionegliattributieglioggettisonoidenti�catime-
dianteunanotazioneanomiconpunti(dottedname).
Conquestanotazione�epossibileidenti�caregliattributidioggettispeci�-
candoilpercorsocheportaall'attributo.
Adesempio,datalaseguentedichiarazione:
interfaceClass1()
{ attributestring
c1a1;
attributerange{1,15}
c1a2;
};
interfaceClass2()
126
IlPre-processoreODLRule/C++
{ attributereal
c2a1;
attributeClass1
c2a2;
};
interfaceClass3()
{ attributelong
c3a1;
attributeClass2
c3a2;
};
DatounoggettoXditipoClass3sihache:
X.c3a1:�editipolong,fariferimentodirettamenteall'attributode�nitonel-
laclasseClass3.
X.c3a2:�eunoggettodellaclasseClass2.
X.c3a2.c2a1:�editiporeal,fariferimentoall'attributode�nitonellaclasse
Class2,questo�epossibileinquantol'attributoc3a2�eunoggettodellaclasse
Class2.
X.c3a2.c2a2.c1a1:�editipostring,efariferimentoall'attributode�nito
nellaclasseClass1.
Nellerulesonopossibilioperazionidiconfrontotravalori,infattisesiscrive
X.c3a1=15oppureX.c3a2.c2a2.c1a1="pippo"siintendeconfrontare
ilvaloredell'attributoindicatoattraversoildottednameconilvaloredella
costante.
Ataleproposito,siccomeinC++cisiriferisceaglioggettidelleclassidichia-
ratetramitepuntatoriditipo\Ref"(sivedaatalepropositoilcapitolo2),
�estatonecessariocreareunaappositafunzionedta()(acronimodi\dotto
arrow",ovvero\dalpuntoallafreccia")chesostituisceognipuntopresente
inunparametroconunafreccia(operatoreC\->"chereferenziauntipo
datotramiteunpuntatore).
Esempio:
X.c3a2.c2a2.c1a
diventa:
X->c3a2->c2a2->c1a1
Costruttidellerule
Icostruttichepossonoapparireinunalistadicondizionisono:
AlgoritmodiTrasformazionedelleRegolediIntegrit�a
127
-condizionidiappartenenzaadunaclasse
identificatore_di_oggettoinnome_classe
esprimelacondizionediappartenenzadiunoggettoall'estensionediuna
classe.
Esempi:
XinAgiatePerson
oveXindividuaunoggetto,lacondizione�everaseXfapartedell'estensione
diAgiatePerson
LafunzioneditraduzionerisaleallaestensionedellaclasseAgiatePersonche
supponiamosichiamiAgiatePeople(semprede�nita)equindisemplicemente
sostituiscetalecostruttocon
AgiatePeople->contains_element(X)
OSS:ilmetodo\containselement"appartieneallaclasse\Collection"
de�nitanellostandard(sivedalaSezione2.3.6).
Allostessomodo:
X1.is_section_ofinCourse
oveX1individuaunoggetto,lacondizione�everi�cataseX1fapartedi
Course.
SupponendoCoursesestensionediCourselafunzionesostituiscetalecondi-
zionecon:
Course->contains_element(X1->is_section_of)
-condizionesultipodiunattributo
identificatorediattributoinnometipo
Esempio:
128
IlPre-processoreODLRule/C++
X.ageinrange{18,25}
oveXindividuaunoggettoconattributoageditiporange,interooreale.
Lacondizione�everi�cataseX.agehaunvalorecompresotra18e25inclusi.
Lafunzionericonosceiltiporangeelosostituisceconunadoppiacondizione
insintassiC++:
X->age>=18&&x->age<=25
-condizionisulvalorediunattributo
identificatorediattributooperatorecostante
Lacostantepu�oessereunletteraleoppureunaconstpurch�edellostessotipo
dell'attributo.
Esempi:
X.tass="High"
X.age>18
X.salary>lo_limitandX.salary<hi_limit
Analogamentealcasoriguardanteitipi,lafunzioneditrasformazionesosti-
tuiscetalicondizioniconleequivalentiC++.
Siosservicheilsegnodiuguaglianza\="vienesostituitoconilcorrispon-
denteoperatoreC++\=="elacongiunzione\and"conl'equivalente\&&".
X->tass=="High"
X->age>18
X->salary>lo_limit&&X->salary<hi_limit
Un'altraosservazionerisultanecessaria.IlconfrontotraduestringheinC++
vieneeseguitoattraversolafunzionedilibreria\strcmp",manellostandard
vienedichiarataunaclasse\String"checontemplafraisuoimetodi,l'ope-
ratore\=="sovrappostoequindivienepermessoilcontrollodiuguaglianza
soprariportato.
-condizionisucollezioniedestensioni
AlgoritmodiTrasformazionedelleRegolediIntegrit�a
129
foralliteratoreincollezione:
listadicondizioni
esprimeunacondizione(and)sututtiglioggettidiunacollezione.
Lacondizioneforall�everaquandotuttiglielementidellacollezionesod-
disfanoatuttelecondizionidellalistadicondizioni.
Importante:tuttiidottednamedellalistadicondizioniassociataalforall,
cio�elevariabilicheappaionotraleparentesitondedelforall,devonoiniziare
conilnomedell'iteratoredelforall.L'iteratoredev'esserequellodell'ultimo
forall,ovverodelforalldilivelloinferiore.Nonsonopermessiconfronticon
variabilidiforalldilivellisuperiori.
Esempio:
forallX1inX.teaches:
(X1.is_section_ofinCourseand
X1.is_section_of.number=1)
X.teachesdev'essereuntipocollezione,lacondizionediforall�everaquan-
dotuttiglioggettiinX.teacheshanno
X1.is_section_ofinCoursee
X1.is_section_of.number=1
Nonsonopermessescritturedeltipo
forallX1inX.teaches:
(X1.is_section_of.number=
X.annual_salary)
oppure
forallX1inX.teaches:
(X1.is_section_ofinCourseandX.annual_salary=4000)
Inquestocaso,lafunzioneditrasformazionecostruisceunciclo\while"che
permettelaiterazioneall'internodellaclassecollezionespeci�cata.Viene
fattoancorausodeimetodide�nitiperleclassicollezionedellostandard.
Lafunzioneesegueunanuovaiterazionedelleclassidichiarateondericavare
iltipodicollezionedell'attributodiX.Aquestopuntovienedichiaratauna
variabileX1deltiporicavatoeduniteratore(appartenenteallaclassetem-
plateIterator)de�nitasullacollezioneX.teaches.
Perquantoriguardalecondizioni,essevengonotrattaterichiamandouna
funzionededicata.
130
IlPre-processoreODLRule/C++
RefProfessorX1;
Iterator<RefProfessor>it=X->teaches->create_iterator();
while(it.next(X1))
{if(!CONDIZIONE)return0;/*valorefalso*/
};
Vienerestituitounvalorefalsoseancheunasoladelleinstanzecontenutein
X.teachesnonrispettalacondizione.
Casoparticolare:ilforallconcuiiniziaunaregolaantecedenteesprime
uncondizionesuisingolioggettidell'estensionediunainterface.Inquesto
casol'iteratoreindividuadeglioggetti.Ilcostruttoforallcambiadisi-
gni�cato,non�eunacondizionediandtralecondizionideisingolioggetti
dell'estensionemaindicadivalutarelalistadicondizionidelforallperogni
singolooggetto.Seilsingolooggettoveri�calecondizionialloralaregola
imponechesianoveri�cateanchelecondizionidellacondizioneconseguente.
existsiteratoreincollezione:
listadicondizioni
similealforallesprimeunacondizione(or)sututtiglioggettidiunacol-
lezione.
Lacondizioneexists�everaesistealmenounelementodellacollezioneche
soddisfaatuttelecondizionidellalistadicondizioni.
Esempio:
existsX1inX.teaches:
(X1.is_section_ofinCourseand
X1.is_section_of.number=1)
X.teachesdev'essereuntipocollezione,lacondizionediexists�everaquan-
doalmenounoggettoinX.teachesha
X1.is_section_ofinCourse
e X1.is_section_of.number=1
Anchequestocaso,lafunzioneditrasformazionecostruisceunciclo\while"
chepermettelaiterazioneall'internodellaclassecollezionespeci�cata.Vie-
neancorafattoancorausodeimetodide�nitiperleclassicollezionedello
AlgoritmodiTrasformazionedelleRegolediIntegrit�a
131
standard.Lafunzioneesegueunanuovaiterazionedelleclassidichiarate
ondericavareiltipodicollezionedell'attributodiX.Aquestopuntoviene
dichiarataunavariabileX1deltiporicavatoeduniteratore(appartenente
allaclassetemplateIterator)de�nitasullacollezioneX.teaches.
Perquantoriguardalecondizioni,essevengonotrattaterichiamandouna
funzionededicata.
RefProfessorX1;
Iterator<RefProfessor>it=X->teaches->create_iterator();
while(it.next(X1))
{if(CONDIZIONE)return1;/*valorevero*/
};
Vienerestituitounvaloreverosealmenounadelleinstanzecontenutein
X.teachesrispettalacondizione.
Esempiocompleto
#include<stream.h>
structIndirizzo{
stringvia,numero,citta;
};
classPersona
keyscodfis
extentPersone
{stringnome,cognome,codfis;
structIndirizzoindirizzo;
relationshipPersonasposato_coninversePersona::sposato_con;
};
classManager:publicPersona
extentManagers
{range{20000,140000}salario;
range{1,13}livello;
132
IlPre-processoreODLRule/C++
set<Persona>collaboratori;
range{0,200000}premi;
intanno_assunzione;
relationshipset<Azienda>lavora_perinverseAzienda::dipendente;
operationrange{0,200000}premio(intanno_assunzione,intcontratti);
};
classTopManager:publicManager
extentTopManagers
{range{10,13}livello;
};
classAzienda
keyspartita_iva
extentAziende
{stringnome,partita_iva;
structIndirizzoindirizzo;
relationshipset<Manager>dipendenteinverseManager::lavora_per;
};
rulem1forallXinManager:
(XinTopManager)
then
(X.salario>=100000);
rulem2forallXinManager:
(X.salarioinrange{40000,80000})
then
existsX1inX.collaboratori:
(X1.nome="Mario"andX1.cognome="Rossi");
rulem3forallXinManager:
(X.cognome="Neri")
then
X.premi=range{0,200000}premio(X.anno_assunzione,30);
LaversioneODLRule
risultante�e:
AlgoritmodiTrasformazionedelleRegolediIntegrit�a
133
structIndirizzo{
string
via,numero,citta;
};
interfacePersona
{ attributestring
nome;
attributestring
cognome;
attributestring
codfis;
attributeIndirizzoindirizzo;
relationshipPersonasposato_coninversePersona::sposato_con;
};
interfaceManager:Persona
{ attributerange{20000,140000}salario;
attributerange{1,13}livello;
attributeset<Persona>collaboratori;
attributerange{0,200000}premi;
attributeint
anno_assunzione;
relationshipset<Azienda>lavora_perinverseAzienda::dipendente;
range{0,200000}premio(inint
anno_assunzione,inint
contratti);
};
interfaceTopManager:Manager
{ attributerange{10,13}livello;
};
interfaceAzienda
{ attributestring
nome;
attributestring
partita_iva;
attributeIndirizzoindirizzo;
relationshipset<Manager>dipendenteinverseManager::lavora_per;
};
rulem1forallXinManager:
XinTopManager
then(X.salario>=100000);
rulem2forallXinManager:
X.salarioinrange{40000,80000}
thenexistsX1inX.collaboratori:
(X1.cognome="Rossi"and
X1.nome="Mario");
rulem3forallXinManager:
(X.cognome="Neri")
thenX.premi=range{0,200000}premio(X.anno_assunzione,30);
134
IlPre-processoreODLRule/C++
LaversioneC++risultante�e:
#include"cpolib.cpp"
#include<stream.h>
classPersona;
typedefRef<Persona>RefPersona;
typedefSet<RefPersona>SetRefPersona;
typedefRef<SetRefPersona>RefSetRefPersona;
typedefBag<RefPersona>BagRefPersona;
typedefRef<BagRefPersona>RefBagRefPersona;
typedefList<RefPersona>ListRefPersona;
typedefRef<ListRefPersona>RefListRefPersona;
typedefArray<RefPersona>ArrayRefPersona;
typedefRef<ArrayRefPersona>RefArrayRefPersona;
typedefVarray<RefPersona>VarrayRefPersona;
typedefRef<VarrayRefPersona>RefVarrayRefPersona;
classManager;
typedefRef<Manager>RefManager;
typedefSet<RefManager>SetRefManager;
typedefRef<SetRefManager>RefSetRefManager;
typedefBag<RefManager>BagRefManager;
typedefRef<BagRefManager>RefBagRefManager;
typedefList<RefManager>ListRefManager;
typedefRef<ListRefManager>RefListRefManager;
typedefArray<RefManager>ArrayRefManager;
typedefRef<ArrayRefManager>RefArrayRefManager;
typedefVarray<RefManager>VarrayRefManager;
typedefRef<VarrayRefManager>RefVarrayRefManager;
classTopManager;
typedefRef<TopManager>RefTopManager;
typedefSet<RefTopManager>SetRefTopManager;
typedefRef<SetRefTopManager>RefSetRefTopManager;
typedefBag<RefTopManager>BagRefTopManager;
typedefRef<BagRefTopManager>RefBagRefTopManager;
typedefList<RefTopManager>ListRefTopManager;
typedefRef<ListRefTopManager>RefListRefTopManager;
typedefArray<RefTopManager>ArrayRefTopManager;
typedefRef<ArrayRefTopManager>RefArrayRefTopManager;
typedefVarray<RefTopManager>VarrayRefTopManager;
typedefRef<VarrayRefTopManager>RefVarrayRefTopManager;
classAzienda;
typedefRef<Azienda>RefAzienda;
typedefSet<RefAzienda>SetRefAzienda;
typedefRef<SetRefAzienda>RefSetRefAzienda;
AlgoritmodiTrasformazionedelleRegolediIntegrit�a
135
typedefBag<RefAzienda>BagRefAzienda;
typedefRef<BagRefAzienda>RefBagRefAzienda;
typedefList<RefAzienda>ListRefAzienda;
typedefRef<ListRefAzienda>RefListRefAzienda;
typedefArray<RefAzienda>ArrayRefAzienda;
typedefRef<ArrayRefAzienda>RefArrayRefAzienda;
typedefVarray<RefAzienda>VarrayRefAzienda;
typedefRef<VarrayRefAzienda>RefVarrayRefAzienda;
structIndirizzo{
string
via,numero,citta;
};
classPersona
{ public:
string
nome,cognome,codfis;
structIndirizzoindirizzo;
staticconstchar*const
extent_name;
};
staticRefSetRefPersonaPersone;
classManager:publicPersona
{ public:
IRange
salario;
IRange
livello;
RefSetRefPersonacollaboratori;
IRange
premi;
int
anno_assunzione;
IRange
premio(int
anno_assunzione,int
contratti);
staticconstchar*const
extent_name;
};
staticRefSetRefManagerManagers;
classTopManager:publicManager
{ public:
IRange
livello;
staticconstchar*const
extent_name;
};
staticRefSetRefTopManagerTopManagers;
classAzienda
{ public:
string
nome,partita_iva;
structIndirizzoindirizzo;
136
IlPre-processoreODLRule/C++
staticconstchar*const
extent_name;
};
staticRefSetRefAziendaAziende;
intm1()
{ intflag=1;
RefManagerX;
Iterator<RefManager>it=Managers->create_iterator();
while(it.next(X))
{ if(TopManagers->contains_element((RefTopManager)X))
{ if(!((X->salario>=100000)))flag=0;
};
};
returnflag;
};
intm2()
{ intflag=1;
RefManagerX;
Iterator<RefManager>it=Managers->create_iterator();
while(it.next(X))
{ if(X->salario>=40000&&X->salario<=80000)
{ RefPersonaX1;
Iterator<RefPersona>it=X->collaboratori->create_iterator();
while(it.next(X1))
{ if(((X1->cognome=="Rossi"&&
X1->nome=="Mario")))returntrue;
};
};
};
returnflag;
AlgoritmodiTrasformazionedelleRegolediIntegrit�a
137
};
intm3()
{ intflag=1;
RefManagerX;
Iterator<RefManager>it=Managers->create_iterator();
while(it.next(X))
{ if((X->cognome=="Neri"))
{ if(!(X->premi==
X->premio(X->anno_assunzione,30)))flag=0;
};
};
returnflag;
};
CennisullaTrasformazionediRegolediIntegrit�ainMetodi
Tenendopresentel'esempioappenapresentato,eriferendosiadesempioal-
lafunzionem2(),sipu�oosservarecheilbloccodiistruzioniinternoalciclo
whilepi�uesterno,siriferisceall'istanzaXdellaclasseManager.Taliistru-
zionipotrebberoquindiformareilcorpodiunmetododellaclasseManager
conpochevarianti,qualilasostituzionediogniriferimentoall'oggettoXcon
l'operatorethisdelC++.
A�nch�elaregolavengaapplicataatutteleistanzediunaclasse,occorre
comunquechetalemetodovengainvocatoperognunadiesseequindisi
avrebbecomunquelapresenzadiunafunzioneesternachee�ettuataleope-
razione.
138
IlPre-processoreODLRule/C++
Capitolo6
NoteConclusive
Lapresentetesiharealizzatounambientesoftware,ispiratoall'approccio
standardODMG-93,periprogettistidibasididati.Taleambientesfrutta
unnuovolinguaggiodiprogrammazioneibrido,progettatoesviluppatonel-
l'ambitodellatesistessa.Talelinguaggiorisultapossederesialepotenzialit�a
dellinguaggiodialtolivelloODLchelepotenzialit�aespressivedellinguaggio
C++.
Taleambientesoftwareconsente:
�
lascritturadiun�lesorgentechesegualasintassiODLRule/C++;
�
lagenerazionedidue�ledioutput,unoinlinguaggioC++,l'altroin
linguaggioODLRule,sintatticamentecorretti;
�
latrattazionedelleregolediintegrit�a,espresseinsintassiODLRule,
direttamentedaunambienteC++,e�ettuandolatrasformazionedi
taliregoleinfunzioniometodiinlinguaggioC++.
Inoltre�eprevistalapredisposizionealcontrollodicovarianzaecontrovarian-
zasuimetodidelleclassidioggettidichiarate.
6.1
SviluppiFuturi
Ilprodottorealizzatoinquestatesipu�oedovrebbeesseremiglioratoper
forniremaggioriaiutialprogettistadibasididati.
Alcunisviluppipotrebberoriguardare:
140
NoteConclusive
�
l'interfacciautente:attualmentetaleinterfaccia�epressoch�enulla,li-
mitandosiallarigadicomando;
�
l'estensioneulterioredellinguaggioODLRule/C++:illinguaggiori-
conosciutodalpre-processoreODLRule/C++
haalcunilimitidovuti
all'ambientechelocircondaeallostandardseguito.Sarebbeutilepro-
iettarsiversounlegamefuturotraODLRule
eC++
comeauspicato
dallostandardstesso.
AppendiceA
Lex&
Yacc
LexeYaccsonodueutilitymoltousateperlarealizzazionedianalizzatori
sintattici.Diseguito�eriportataunabrevedescrizionedeidueprogrammi.
Inrealt�ainquestatesisonostatiutilizzatialtridueprogrammi ex&bison,
diversimacompatibiliconLex&Yacc.
FlexeBisonsonoduestrumentisoftwarechefacilitanolascritturadipro-
grammiinlinguaggioCperl'analisiel'interpretazionedisequenzedicarat-
terichecostituisconoundatotestosorgente.
Entrambiquestistrumenti,partendodaopportuni�ledispeci�ca,generano
direttamenteilcodiceinlinguaggioC,chepu�oquindiesseretrattatoallo
stessomododeglialtrimodulisorgentidiunprogramma.
Flex
Flexleggeun�ledispeci�cachecontienedelleespressioniregolariperilrico-
noscimentodeitoken(componentielementaridiunlinguaggio)egenerauna
funzione,chiamatayylex(),chee�ettual'analisilessicaledeltestosorgente.
Lafunzionegenerataestraeicaratteriinsequenzadalfussodiinput.Ogni
voltacheungruppodicaratterisoddisfaunadelleespressioniregolarivie-
nericonosciutountokene,diconseguenza,vieneinvocataunadeterminata
azione,de�nitaopportunamentedalprogrammatore.
Tipicamentel'azionenonfaaltrocherenderedisponibileiltokenidenti�cato
alriconoscitoresintattico.Perspiegaremeglioilmeccanismodifunziona-
mentoricorriamoadunesempio:l'individuazione,neltestosorgente,diun
numerointero
142
Lex&
Yacc
[0-9]+
{sscanf(yytext,"%d",&yylval);
return(INTEGER);
}
l'espressioneregolare[0-9]+rappresentaunasequenzadiunaopi�ucifre
compresenell'intervallo{0-9}.Lapartecompresatraparentesi{...}spe-
ci�cainvece,inlinguaggioC,l'azionechedeveessereeseguita.
InquestocasovienerestituitoalparseriltokenINTEGERpoich�e�estatorico-
nosciutounnumerointero.
Bison
Bison�eunprogrammaingradodigenerareunparserinlinguaggioCpar-
tendodaun�ledispeci�cachede�nisceuninsiemediregolegrammaticali.
InparticolareBisongeneraunafunzione,chiamatayyparse(),cheinter-
pretaunasequenzaditokenericonoscelasintasside�nitanel�lediinput.
Lasequenzaditokenpu�oesseregeneratadaunqualunqueanalizzatoreles-
sicale;disolitoper�oBisonvieneutilizzatocongiuntamenteaFlex.
Ilvantaggioprincipalechederivadall'utilizzodiBison�elapossibilit�adi
ottenereunveroeproprioparsersemplicementede�nendo,inunapposito
�le,lasintassidariconoscere.
Ci�oavvieneutilizzandounanotazionemoltosimileallaBakus-NaurForm
(BNF).
Occorreper�onotarecheiparsergeneratiinquestomodosonoingradodi
riconosceresoltantouncertosottoinsiemedigrammatiche,dettenonconte-
stuali.Aprimavistaci�opotrebbesembrareunalimitazione;inrealt�aquesto
tipodigrammatica�eingeneresu�ciente
1
perde�nirelasintassidiunlin-
guaggiodiprogrammazione.
Perillustraremeglioilfunzionamentodiquestosoftwareutilizziamounesem-
piodiunpossibileinputperBison:
var_declaration:
VARvar_list':'type_name';';
variable_list:
variable_name|
variable_list','variable_name;
variable_name:
STRING;
type_name:
INTEGER|FLOAT|BOOLEAN;
1unatrattazionepi�udettagliataeformale�edatain[ASU86,FRJL88]
143
Ogniregolaconsistediunnome,osimbolononterminale,seguitodauna
de�nizione,chepresentaasuavoltaunoopi�usimboliterminaliononter-
minali(ovveronomidialtreregole).
Isimboliterminali,rappresentatinell'esempioincaratteremaiuscolo,sonoi
tokenottenutidalriconoscitorelessicale.Ilriconoscimentodellagrammatica
avvieneconunprocedimentoditipobottom-up
2,includendoogniregolache
vienericonosciutainregolepi�ugenerali,�noaraggiungereunparticolare
simboloterminalecheincludetuttiglialtri.
Aquestopuntoiltestosorgente�estatocompletamentericonosciutoel'ana-
lisisintattica�eterminata.
Inrealt�aunparserdevesvolgereanchealtricompiti,comel'analisiseman-
ticaelagenerazionedelcodice.PerquestomotivoBisonconsentealpro-
grammatoredide�nireunsegmentodicodice,dettoazione,perogniregola
grammaticale.
Ognivoltacheunaregolavienericonosciutailparserinvocal'azionecorri-
spondente,permettendo,adesempio,diinserireinomidellevariabilinella
symboltabledurantel'analisidellasezionedichiarativadiunlinguaggio:
var_declaration:
VARvar_list':'type_name';'
{
Push($2);
} ;
Nell'esempioillustratoPush()�eunafunzioneinlinguaggioCchesioccupa
diinserireunalistadivariabilinellasymboltable.
Ilcodicechesioccupadellatraduzioneveraepropriapu�oalloraessereinte-
gratonelparserattraversoilmeccanismodelleazionisemantiche.
Ulterioriinformazionisipossonoreperireinrete(GNU
GENERALPU-
BLICLICENSE)ladocumentazionedi ex&bison.Illibrodiriferimento
perLex&Yacc�eLex&Yacc[MB91].
2descrittoampiamentein[MB91]
144
Lex&
Yacc
AppendiceB
Principiodicovarianzae
controvarianzadimetodi
Ilpre-processoreODLRule/C++
illustratoinquestatesi,o�relapossibi-
lit�adie�ettuareuncontrollodicovarianzae/ocontrovarianzasuimetodi
delleclassidichiarateinODLRule/C++esuimetodiaggiuntividovutialla
traduzionedelleregolediintegrit�a,avvalendosidell'ausiliodiunmodulodi
ODL-Designer.Talemodulo,almomentodellapresentazionedellatesi,non
risultaancoradisponibile,mal'architetturafunzionaledelpre-processore
ODLRule/C++neprevedecomunquelapresenza(seppurfacoltativa)equin-
diguardaalfuturoquandounacooperazionesar�aresapossibile.
B.1
Principiodicovarianzaecontrovarianza
Inletteraturasonopresentatidueapproccicontrastantipercontrollarela
consistenzadelleinterfacciedeimetodi:
1.Unprimoapproccioapplicaaiparametridelleoperazioniilmedesi-
moprincipioapplicatoagliattributidelleclassi,ossiailprincipiodi
covarianza.
2.Unsecondoapproccioapplicaaiparametridelleoperazioniilprincipio
oppostoaquelloapplicatoagliattributidelleclassi,ossiailprincipio
dicontrovarianza.
Diseguitovieneriportatalade�nizionedisottotiposecondolateoriadeitipi
didati(E.BertinoeL.D.Martino[EM92];BruceandWegner1986[BW86];
Cardelli1984[Car84];Albanoetal.1985[ACO85]).
146
Principiodicovarianzaecontrovarianzadimetodi
De�nizione1(sottotipo)Untipote'sottotipodeltipot0(t�
t0)se:
(1)leproprieta'dit0
sonounsottoinsiemediquelledit
(2)perognioperazionem
0 t
dit0esistelacorrispondenteoperazionemt
dit
taleche:
(a)mt
em
0 t
hannolostessonome
(b)mt
em
0 t
hannolostessonumerodiargomenti
(c)l'argomentoidim
0 t
e'unsottotipodell'argomentoidimt
(regoladi
controvarianza)
(d)mt
em
0 t
restituisconounvaloreoentrambinonhannoalcunparametro
diritorno(e)semt
em
0 t
restituisconounvaloreallorailtipodelrisultatodi
mte'unsottotipodeltipodelrisultatodim
0 t
(regoladicovarianza)
Inbaseatalede�nizione�evalidoilprincipiodisostituibilita',secondoil
qualeunaistanzadiunsottotipopuo'esseresostituitadaunsupertipoin
ognicontestonelqualequest'ultimopuo'esserelegalmenteusato.
Altrigruppidiricerca,comegliautorichehannosviluppatoilsistemaO2
[BDK96],hannoadottatolaregoladicovarianzaanchesuisingoliparametri
delleoperazioni:inquestomodoper�osipossonoprodurredeglierroriinfase
dirun-timeafrontediunacorrettezzasintattica.
InBruceandWegner1986[BW86]siriportaunadimostrazionerigorosadi
quantoa�ermatosopra,sottolineandosoprattuttoladi�erenzaesistentetra
itipidegliattributieitipideiparametriformalidelleoperazioni.
Percapirequestaa�ermazionesiproponeunsempliceesempio:
Suppongodimodellarel'aspettogeometricodeipuntidelpianocartesiano.
Ipuntisonodeglioggettide�nitidaduecoordinate(x,y),epossonoessere
positivioppurenegativi.
Ipuntipositivisonocontenutiinteramentenelprimoquadrantedelpiano
cartesiano,mentrequellinegativinelterzoquadrante.
Introducounaoperazionedenominata\disegna"conleduecoordinatecome
parametridiinput.
interfacePunto
(extentPunti)
{attributerange{-1000,1000}x;
attributerange{-1000,1000}y;
voiddisegna(inrange{-1000,1000}px,inrange{-1000,1000}py);
B.1Principiodicovarianzaecontrovarianza
147
};
interfacePunto_positivo:Punto
(extentPunti_positivi)
{attributerange{0,1000}x;
attributerange{0,1000}y;
voiddisegna(inrange{0,1000}px,inrange{0,1000}py);
};
Inquestoesempiohoapplicatolaregoladicovarianzaanchesuiduepara-
metridell'operazione(metododiO2).Supponiamodiinvocarel'operazione
disegna(-10,-10)suungenericooggettodellaclasse\Punto",sequestoog-
gettoe'ancheistanzadi\Puntopositivo"alloraverra'eseguital'operazione
nellaclassepiu'specializzata,causandounerroredirun-time.
Daunpuntodivistapraticoquestoesempioescludeilprincipiodicovarianza
egiusti�casoloinparteilprincipiodicontrovarianzaapplicatoaiparametri
dellefunzioni.Perevitareerroriinfasediesecuzionedelleoperazioni,e'
su�cientedichiarareiltipodeiparametridellesottoclassiugualeaquello
dellesuperclassi.Infattinell'esempioriportatodiseguitononvie'alcun
motivoperampliareilrangef0,1000g
deiparametridell'operazionePun-
topositivo::disegna.
interfacePunto
(extentPunti)
{attributerange{-1000,1000}x;
attributerange{-1000,1000}y;
voiddisegna(inrange{-1000,1000}px,inrange{-1000,1000}py);
};
interfacePunto_positivo:Punto
(extentPunti_positivi)
{attributerange{0,1000}x;
attributerange{0,1000}y;
voiddisegna(inrange{-1000,1000}px,inrange{-1000,1000}py);
};
Inconclusioneilprincipiodicontrovarianzae'statoadottatopermotividi
essibilita',infattirisultapiuttostovincolanteimporre,nellasignaturedelle
operazioni,l'usodeglistessitipidichiaratinellesuperclassi.
148
Principiodicovarianzaecontrovarianzadimetodi
Bibliogra�a
[ACO85]A.Albano,L.Cardelli,andR.Orsini.Galileo:astronglytyped,
interactiveconceptuallanguage.ACM
TransactionsonDatabase
Systems,10(2):230{260,1985.
[ASU86]
AlfredV.Aho,RaviSethi,andJe�reyD.Ullman.Compilers.
Principles,TechniquesandTools.AddisonWesley,1986.
[BDK96]F.Bancilhon,C.Delobel,andP.Kanellakis.buildinganObject-
OrientedDatabaseSystem,thestoryofO2.MorganKaufmann
Publishers,Inc.,1996.
[BW86]
KimB.BruceandP.Wegner.Analgebraicmodelofsubtypesin
object-orientedlanguages.InSIGPLANNotices,pages163{172,
1986.
[Car84]
L.Cardelli.Asemanticsofmultipleinheritance.InSemanticsof
DataTypes-LectureNotesinComputerScienceN.173,pages
51{67.Springer-Verlag,1984.
[Cat94]
R.G.G.Cattell.
TheObjectDatabaseStandard:
ODMG-93,
Release1.1.MorganKaufmannPublishers,Inc.,1994.
[Cor97]
AlbertoCorni.Odb-dsqounserverwww
perlavalidazionedi
schemididatiadoggettiel'ottimizzazionediinterrogazionicon-
formeallostandardodmg-93.TesidiLaurea,Facolt�adiScienze
dell'Ingegneria,dell'Universit�adiModena,Modena,1997.
[EM92]
BertinoEandL.D.Martino.SistemidiBasidiDati0rientateagli
Oggetti.Addison�WesleyMasson,Milano-Italia,1992.
[FRJL88]CharlesN.FischerandJr.RichardJ.LeBlanc.
Craftinga
Compiler.TheBenjamin/CummingPublishingCompany,Inc.,
1988.
150
BIBLIOGRAFIA
[Gar95]
AlessandraGaruti.Ocdl-designer:uncomponentesoftwareperil
controllodiconsistenzadischemidibasididatiadoggetticon
vincolidiintegrita'.TesidiLaurea,Facolta'discienzematemati-
che�sicheenaturali,corsodilaureadiscienzedelleinformazioni,
dell'universita'diBologna,1995.
[MB91]
T.MasonandD.Brown.Lex&Yacc.O'Reilly&AssociatesInc.,
1991.
[Ric98]
StefanoRiccio.Elet-designer:unostrumentointelligenteorientato
aglioggettiperlaprogettazionediimpiantielettriciindustriali.
TesidiLaurea,Facolt�adiScienzedell'Ingegneria,dell'Universit�a
diModena,Modena,1998.