1 Diederick de Vries qbe4or Automatisch genereren van dynamische Query-By-Example-forms voor Object-Relationele databases afstudeerscriptie informatie...
qbe4or Automatisch genereren van dynamische Query-By-Example-forms voor Object-Relationele databases
afstudeerscriptie informatiekunde begeleiders: dr. H. Klein en drs. H.W.A.E. Kuipers
Groningen, 2003-2004
Inhoudsopgave
Inhoudsopgave
Voorwoord........................................................................................................................................................ iii 1. Inleiding......................................................................................................................................................... 5 1.1 Inleiding................................................................................................................................................... 5 1.2 Probleemstelling.......................................................................................................................................5 1.3 Hoofdvraag.............................................................................................................................................. 6 1.4 Doelstelling.............................................................................................................................................. 7 1.5 Samenvatting............................................................................................................................................9 1.6 Verder onderzoek.....................................................................................................................................9 2. Vergelijkbare systemen...............................................................................................................................11 2.1 Het belang van een gebruiksvriendelijke zoekinterface......................................................................... 11 2.2 Het uitgebreide zoekveld....................................................................................................................... 12 2.3 Query-By-Templates..............................................................................................................................12 2.4 Vijfde-generatietalen..............................................................................................................................13 3. Query-by-Example......................................................................................................................................15 3.1 Het systeem............................................................................................................................................ 15 3.2 Voor- en nadelen....................................................................................................................................16 3.3 Recente closed-source toepassingen...................................................................................................... 17 3.4 Conclusie................................................................................................................................................19 4. Het object-relationele model...................................................................................................................... 21 4.1 OR versus traditioneel-relationeel..........................................................................................................21 4.2 Situation-based OR................................................................................................................................ 21 4.3 Complexiteit...........................................................................................................................................23 4.4 Active-flags en start- en eind-data..........................................................................................................23 4.5 Termen................................................................................................................................................... 24 4.6 Conclusie................................................................................................................................................25 5. De database..................................................................................................................................................27 5.1 Het model...............................................................................................................................................27 5.2 Relaties...................................................................................................................................................28 5.3 Conclusie................................................................................................................................................29 6. Het bevragen van een ORDB in SQL....................................................................................................... 31 6.1 Een tabel opvragen.................................................................................................................................31 6.2 De objecten van een type en zijn subtypen............................................................................................ 31 6.3 Toegepaste attributen van een bekend object en zijn supertypen...........................................................33 6.4 Niet-geldende data................................................................................................................................. 34 6.5 Nut en bruikbaarheid van MySQL-variabelen bij OR........................................................................... 36 6.6 Het opbouwen van de tabel....................................................................................................................37 6.7 Associaties van een bekend object ........................................................................................................ 39 i
qbe4or 6.8 Conclusie................................................................................................................................................41 7. qbe4or...........................................................................................................................................................43 7.1 Het systeem............................................................................................................................................ 43 7.2 Het algoritme voor de interface............................................................................................................. 46 7.3 De navigatieboom.................................................................................................................................. 47 7.4 De QBE-tabel.........................................................................................................................................47 7.5 De filters.................................................................................................................................................48 7.6 Conclusie................................................................................................................................................49 8. Conclusies.................................................................................................................................................... 51 8.1 Algemene conclusies..............................................................................................................................51 8.2 Problemen en oplossingen..................................................................................................................... 51 8.3 Gehaalde en niet-gehaalde doelstellingen.............................................................................................. 52 9. Bibliografie.................................................................................................................................................. 53 10. Bijlagen...................................................................................................................................................... 55 10.1 SQL: de DDL-statements van het datamodel.......................................................................................55 10.2 PHP: genereren van een HTML-tabel met objecten, hun attributen en QBE-invoervelden.................57 10.3 PHP: de navigatieboom....................................................................................................................... 62 10.4 PHP: Functiebibliotheek voor de navigatieboom................................................................................ 62 10.5 PHP: functies voor hierarchie uit de functiebibliotheek voor MySQL-gebruik...................................64 10.6 PHP: functies voor het tonen van de tabel........................................................................................... 64
ii
qbe4or
Voorwoord
Bij een van de eerste afspraken die ik met mijn afstudeerbegeleider had, vroeg hij mij waarom ik wilde afstuderen. Het toeval wilde dat ik daar daadwerkelijk over had nagedacht. Alfa-informatica is niet de eerste studie die ik geprobeerd heb. Sociale geografie, hoofdvak viool aan het conservatorium en geschiedenis gingen eraan vooraf. De studie is wel de eerste die ik heb afgemaakt, en dat vervult mij uiteraard met een zekere mate van voldoening. Maar onzeker als ik lange tijd was over of ik dit keer wel de juiste keuze had gemaakt, heb ik halvewege de studie al een stage gedaan, en niet, zoals te doen gebruikelijk, pas na afloop. Die stage overtuigde mij ervan dat ik softwareontwikkeling leuk vond en dat ik dus zou moeten afstuderen. Nu ik deze afstudeerscriptie af heb, besef ik dat het een van de laatste zal zijn die aan de Rijksuniversiteit Groningen geproduceerd zullen worden. Vanaf dit jaar heten ze namelijk in toenemende mate master-thesis. Voor die term had ik ook kunnen kiezen, maar dat deed ik niet. Als beloning voor die behoudendheid krijg ik twee titels, zowel de Nederlandse als de Europese. En dat is ook wat mijn afstudeerbegeleider bedoelde met zijn vraag. Want tegelijk met de overgang naar dit Europese titulatuursysteem kwam ook de mogelijkheid om na slechts drie jaar de studie af te breken en toch met een titel, die van bachelor, de arbeidsmarkt op te gaan. Bedanken wil ik in de eerste plaats mijn al genoemde begeleider, drs. Edwin Kuipers, voor zijn raad en zijn geduld voor mij, in wat voor hem drukke tijden moeten zijn geweest. Ook Dr. Henny Klein, mijn tweede lezer, die mij vooral in de onderzoeksfase hielp bij het zoekwerk en die, zoals ik af en toe aan de log van mijn webserver kon zien, de pieken en dalen van mijn vorderingen gadesloeg. Ook Dr. Alessandro Allodi, mijn stagebegeider, wil ik bedanken omdat hij mij geleerd heeft wat OR is. Ook moet ik mijn vriendin Klazina Botke bedanken, onder andere voor de door haar ontwikkelde alfa-informatica-implementatie van het kunstgeschiedenis-annotatiesysteem.
iii
1. Inleiding
1. Inleiding
1.1 Inleiding In het najaar van 2001 deed ik een stage bij de Nederlandse Aardolie Maatschappij (N.A.M.) te Assen, onder leiding van voormalig alfa-informatica stafmedewerker dr. Allesandro Allodi. Onderwerp van deze stage was het object-relationele datamodel (ORDB). Dit zeer krachtige model werd binnen de N.A.M. naar mijn mening onvoldoende uitgebuit. Door de complexiteit van het model is er een grote mate van deskundigheid nodig om queries te formuleren. Deze deskundigheid was bij de meeste gebruikers van de database niet aanwezig. Dit resulteerde bij de N.A.M. in een gebruik van de database die beperkt bleef tot een aantal vooraf door Allodi zelf geformuleerde queries, in een web-gebaseerde interface. Een systeem dat de gebruikers in staat stelde zelf queries te formuleren bestond niet. Om een database volledig te benutten is het echter nodig om deze mogelijkheid wel te bieden.
1.2 Probleemstelling Databases worden bevraagd met behulp van formele talen, meestal Structured Query Language (SQL). Het aanleren van deze, of andere formele talen, is voor gebruikers van een database niet mogelijk, aangezien zij daar de tijd en de expertise voor missen. Het is daarom voor normaal gebruik van elke database noodzakelijk een systeem te ontwikkelen waarin een gebruiker om informatie kan vragen zonder daarbij kennis te hoeven hebben van formele vraagtalen. Het object-reationele datamodel is bovendien dermate complex, dat het bevragen van een database die volgens dat model is opgezet, een bovengemiddeld gedegen kennis van SQL vereist. Beide feiten samen maken een gebruikersvriendelijke interface noodzakelijk voor het werken met een ORDB, voor iedereen behalve degene die zeer goed bekend is met het datamodel. Het is dus noodzakelijk een interface te ontwikkelen waarin de gebruiker zonder gebruik van een formele taal, en zonder te maken te hebben met de stuctuur van het datamodel, queries kan formuleren. Dit kan met behulp van een formulier. De in een dergelijk systeem opgestelde query moet vervolgens door dat systeem worden omgezet in een SQL-query, waarmee de database bevraagd wordt. De hierdoor verkregen resultaten moeten daarna aan de gebruiker worden getoond, opnieuw zonder dat hij daarbij te maken krijgt met de structuur van het datamodel. Er zijn verschillende interfacetypen die hiervoor in aanmerking kunnen komen. 1. Het uitgebreide enkele zoekveld, zoals bekend van geavanceerde zoekmachines als Google, Altavista en Yahoo. Het geven van een zoekopdracht gebeurt hier door het simpleweg invullen van een enkele zoekterm of een booleaanse expressie. Deze expressie wordt vergeleken met de in de database aanwezige gegevens, en treffers worden na afloop getoond. Deze methode is zeer ruw, aangezien op geen manier kan worden aangegeven wat de betekenis is van de expressie in de gezochte documenten. Het resultaat is bekend bij elke intensieve internetgebruiker: veel treffers waartussen weinig bruikbaars zit. 2. Query By Example (QBE) is een querytechniek die al bestaat sinds de jaren '70. Hierbij krijgt de gebruiker een formulier te zien waarin een blanco record wordt getoond. Hij kan hierin conditities aangeven waarin de gezochte records dienen te voldoen. Dit is eenvoudiger in het gebruik dan SQL. “QBE refers to a method of forming queries in which the database program displays a blank record with a space for each field. You can then enter conditions for each field that you want to be included in the query (...). 5
qbe4or QBE systems are considered easier to learn than formal query languages.”1 The philosphy of QBE is to require the user to know very little in order to get started and to minimize the number of concepts that he subsequently has to learn in order to understand and use the whole language.2 3. Vijfde-generatietalen zoals Microsoft English Query3 en Esperanr4 maken, op verschillende manieren, gebruik van natuurlijke taal als Engels om de gebruiker queries te laten formuleren. Een ingevoerde volzin wordt vertaald naar SQL om de gezochte gegevens uit de database te halen. Echter: “de praktische toepasbaarheid van natuurlijke taal-interfaces vereist dat niet alleen zinnen worden geaccepteerd die voldoen aan alle regels van het systeem. Een gebruiker (...) zal vroeger of later uitingen produceren die bij de ontwikkeling van het systeem niet voorzien zijn.”5 4. Query by Templates (QBT) in een type QBE dat de daadwerkelijke layout van in de database aanwezige documenten neemt, waarin op bepaalde plaatsen zoekcriteria kunnen worden ingevuld, bijvoorbeeld op de plaats waar de auteur, titel of ondertitel staan. Alle aan de criteria beantwoordende documenten zullen tot de treffers behoren.6 Voorwaarde hiervoor is dat de database gevuld is met tekstdocumenten die dezelfde layout hebben. Query-formulieren hebben ook een nadeel: “for each and every query a separate fill-out form needs to be made.”7 Dit nadeel is te omzeilen door het opbouwen van het formulier door het systeem te laten doen. De vraag welke van de genoemde interfacemethoden het meest geschikt is voor het oplossen van het gestelde probleem is een onderzoek op zich, waarop ik mij niet wil richten. Voor mijn onderzoek gebruik ik QBE omdat dit zoals gezegd robuust en gebruikersvriendelijk is, en niet te specifiek in de eisen aan de gezochte gegevens, zoals QBT. Wel zal ik in hoofdstuk twee verder ingaan op de hier behandelde systemen om te kijken wat daaruit van nut kan zijn voor qbe4or.
1.3 Hoofdvraag Het bovenstaande leidt mij tot de hoofdvraag van mijn onderzoek: Is het mogelijk om een zoekinterface te ontwikkelen die gegevens uit een object-relationele database weet te halen, volgens het Query-By-Example (QBE) interface-model? Hieruit moeten de volgende termen worden gedefinieerd: 1. zoekinterface: een aan een gebruiker gepresenteerd scherm waarin hij een zoekopdracht kan specificeren die hem een door een onderliggend database-systeem opgebouwd antwoord zal opleveren. 2. object-relationele database (ORDB): een systeem waarin gegevens opgeslagen liggen, gestructureerd volgens een principe waarbij de object-georiënteerde databaseprincipes worden gerealiseerd binnen een relationele engine. 3. Query-By-Example (QBE): een zoekinterface-model dat de gebruiker aan de hand van een database een voorbeeld-query aanbiedt waaruit hij zijn eigen query kan samenstellen.
1.3.1 Deelvragen Om de hoofdvraag te kunnen beantwoorden moeten onderstaande vragen worden beantwoordt: 1 2 3 4 5 6
7
6
Webopedia, lemma query-by-example Zloof, `Query-by-Example: a data base language', 324 Microsoft TechNet, Developing with English Query. Speedware – Esperant: Enterprise-wide, multi-database Query and Reporting keeps your business on target Bouma, Computationele Taalkunde en Taaltechnologie, 10 Sengupta en Dillon: `Query By Templates: A Generalized Approach for Visual Query Formulation for Text Dominated Databases' Gree, de, Generating Web Query Interfaces Based on Conceptual Schemas, 58
1. Inleiding 1. Aan welke eisen moet een dergelijk systeem minimaal voldoen? 2. Bestaat er al een systeem dat aan de genoemde specificaties voldoet en kan dit worden hergebruikt? 3. Welke problemen zijn anderen tegengekomen bij het ontwikkelen van een dergelijk systeem ?
1.4 Doelstelling Om de hoofdvraag te beantwoorden dient te worden vastgesteld onder welke omstandigheden geconcludeerd kan worden dat deze mogelijkheid bestaat. Het systeem moet een QBE-interface presenteren aan de gebruiker, waarmee deze zijn query kan formuleren. Vervolgens moet deze query worden vertaald naar SQL en worden doorgegeven aan de SQL-engine. De aldus verkregen gegevens moeten in de vorm van een tabel aan de gebruiker worden gepresenteerd. De volgende punten zijn minimale functionaliteit: 1. zoeken naar in de database aanwezige gegevens; 2. negeren ongeldige data: in een ORDB is data al dan niet geldig, hetzij doordat een record is gemarkeerd als ongeldig in een specifiek veld, hetzij doordat de tijd waarin de data geldig is, aangegeven in twee datumvelden, is verlopen. Voor meer informatie hierover verwijs is u naar hoofdstuk twee; 3. overerving: in een ORDB is het mogelijk een domein te specificeren waarin de daarin aanwezige objecten elkaars eigenschappen overnemen8. Dit heet overerving. Voor meer informatie hierover verwijs ik u naar hoofdstuk twee. Wanneer het systeem deze eigenschappen heeft kan de hoofdvraag bevestigend worden beantwoord. Bij de ontwikkeling verwacht ik twee technische moeilijkheden tegen te komen: 1. het automatische onderzoek naar de zogenaamde metadata, de gegevens in de database die slechts de structuur beschrijven waarmee de daadwerkelijke gegevens zijn vastgelegd, volgens welke de QBEinterface moet worden opgesteld; 2. de vertaling: de object-georiënteerde aard van de database maakt dat SQL-queries veel complexer zijn dan bij een traditionele relationele database. Om een voorbeeld te geven: bij een traditioneel-relationele database hoeft er, om de schrijver van een boek op te zoeken, alleen te worden gezocht naar het boek, op basis van bijvoorbeeld de titel, of een andere bekende eigenschap. Daarna is ook de schrijver bekend. Bij een object-georiënteerde database zal moeten worden vastgesteld dat er twee objecttypen zijn, namelijk `boek' en `schrijver', waarvan de instanties, `dit specifieke boek' en `deze specifieke schrijver', een relatie met elkaar hebben. Deze heet bijvoorbeeld `is geschreven door' voor de ene richting en `heeft geschreven' voor de andere richting. Ook heeft het objecttype `boek' eigenschappen: het boek zal moeten worden geïdentificeerd via de eigenschap `titel'.
1.4.1 `Nice-to-haves' Het zou wenselijk zijn daaraan de volgende zaken toe te voegen: 1. zoeken naar meta-gegevens; 2. naar keuze doorzoeken inactieve data; 3. caching; 4. door de gebruiker aanpasbare interface. Deze punten zijn echter van minder belang voor het afstudeeronderzoek zelf. Bij de N.A.M. werden de verschillende informatiesystemen via webpagina's op het lokale intranet aan de verschillende afdelingen en hun medewerkers aangeboden. Deze manier heeft daar aangetoond goed te werken. Daarom ligt het voor de hand om de interface als webpagina te ontwikkelen. Op die manier kan het 8
Fussell, Foundations of Relatuinal Mapping, 13
7
qbe4or eenvoudig via HTTP door iedereen worden geraadpleegd. Om het systeem te kunnen testen zal er een ORDB nodig zijn. Als engine daarvoor wil ik MySQL gebruiken, een goed presterende, wijd verbreide open-source database9. De nieuwste stabiele versie is 4.1.1-alpha. Die versie zal ik gebruiken. De taal ik gebruik om het systeem te maken is PHP. Deze embedded scripttaal bezit genoeg functionaliteit op het gebied van de communicatie met MySQL om het systeem in te kunnen ontwikkelen10. Momenteel bevindt versie 5 zich nog in het bèta-stadium11, dus ik gebruik versie 4. Deze maakt gebruik van de Zend engine versie 1, waarin object-georiënteerd programmeren nog niet volledig ondersteund wordt12. qbe4or zal ik dus volledig functioneel programmeren. Voor het beantwoorden van de hoofdvraag heeft dit geen concequenties. Zoals aangegeven draait het onderzoek voornamelijk om de vraag in hoeverre het mogelijk is een dergelijk systeem te bouwen. Aangezien het systeem daarom niet meer dan een prototype van een reëel systeem hoeft te worden is het niet wenselijk om de database te vullen met relevante data als documenten of andere media. Dit is voor het onderzoek niet relevant en maakt de zaak nodeloos ingewikkeld. Ik wil daarom de testdatabase populeren met de hemellichamen uit ons zonnestelsel. Dit is een complex geheel van sterren, planeten, zonnen, asteroïden, kometen, nevels en kunstmatige structuren met vele onderlinge relaties en gemeenschappelijke eigenschappen, wat het ideaal maakt om in een ORDB te beschrijven. Een voorbeeld van wat het uiteindelijke systeem zou moeten opleveren is het volgende. Meestal weet degene die de zoekopdracht geeft een bepaalde eigenschap van datgene waar hij naar zoekt. Bij een boek is dat bijvoorbeeld een titel of een auteur. In een ORDB kunnen beide zowel objecten zijn als attributen. In een traditioneel systeem bestaat dat onderscheid niet. De gebruiker zal een menu zien waaruit hij een schrijver kan kiezen en een waarmee hij uit boektitels kan kiezen. Maakt hij gebruik van het eerste, dan zal hij een lijst krijgen van alles wat bij die schrijver hoort, oftewel alle boeken, in het tweede geval alles wat bij die boektitel hoort, oftewel wie eraan geschreven hebben, hoeveel het kost, enzovoort. In het geval van het zonnestelsel zoekt de gebruiker bijvoorbeeld naar alle rotsplaneten, of alle met een atmosfeer waarin argon voorkomt. Het systeem moet dezelfde menu's aanbieden, en dezelfde resultaten geven. Met een menu moet gekozen kunnen worden uit de beschikbare objecten, met een ander uit de gebruikte attributen. Uit hoe meer menu's een keuze wordt gemaakt, hoe groter de precisie van de zoekopdracht wordt. Een zoekopdracht waarbij eigenschappen zijn opgegeven, moet een lijst opleveren waarbij deze eigenschappen overeenkomen met de opgegeven waarden, of die in de database nu als objecten, als attributen, of als associaties zijn gedefinieerd.
1.5 Samenvatting Het gegeven dat databases moeten worden bevraagd met behulp van formele talen, gecombineerd met de grote ingewikkeldheid van het object-relationele datamodel, maakt dat een gebruikersvriendelijke zoekinterface noodzakelijk is voor een optimaal gebruik van ORDBs. In deze scriptie wil ik onderzoeken of het mogelijk is een QBE-interface te ontwikkelen voor dat type database. Deze interface moet de gebruiker een formulier presenteren dat is opgebouwd aan de hand van de aanwezige database en de mogelijkheid geven een query te formuleren, zonder dat hij kennis heeft van formele vraagtalen of het gebruikte datamodel.
1.6 Verder onderzoek Wanneer de eerder in dit hoofdstuk gedefinieerde hoofdvraag positief kan worden beantwoord, kan het onderzoek nog worden voorgezet. De voor dit onderzoek gebruikte testdatabase is vrij klein en relatief weinig 9
10 11 12
8
Een uitgebreide vergelijking van de prestaties van deze versie met andere databases is te vinden op http://www.mysql.com/information/benchmarks.html. Converse en Park, PHP Bible. 2nd edition, 14. Het laatste nieuws over ontwikkelingen op dit gebied is te vinden op http://www.php.net. Voor een genuanceerde discussie over het gebruik van object-georiënteerde programmeertechnieken in scripttalen in het algemeen en PHP 4 in het bijzonder verwijs ik u graag naar Converse en Park, `PHP Bible. 2nd edition', resp. pagina 526 en 529.
1. Inleiding complex. Zo onbreken mogelijkheden tot het specificeren van attributen van attributen en associaties tussen attributen. In theorie kunnen dit soort verbanden tot in het oneindige worden doorgezet. Het is de moeite waard om te kijken in hoeverre qbe4or valt aan te passen voor nog complexere databases. Te verwachten valt echter dat een daaruit voortvloeiende uitbreiding van de QBE-fucntionaliteit ten koste zal gaan van het eenvoud en het comfort van de zoekinterface. De twee niet gehaalde punten in paragraaf 1.4.1 zijn de door de gebruiker aanpasbare interface en het naar keuze kunnen zoeken op inactieve gegevens. Dit zijn eenvoudige en voor het onderzoek irrelevante zaken waarvoor verder onderzoek niet nodig is.
9
2. Vergelijkbare systemen
2. Vergelijkbare systemen
2.1 Het belang van een gebruiksvriendelijke zoekinterface Sinds het verschijnen van het oorspronkelijke artikel over QBE door M.M. Zloof in het IBM Systems Journal in 1977 zijn er talloze zoekinterfaces ontwikkeld in wetenschappelijke en commerciële projecten. `Along with the explosive growth of the Internet, ad hoc query and reporting tools are perhaps the most significant new development in computing of this decade [de jaren '90]. (...) Unfortunately, most of the development effort (...) has been devoted to giving us better report writers, embedded graphics and fancier graphing options. (...) For example, we still lack a reasonable method of creating complex data filters (SQL “WHERE” clauses) in most of the popular tools.'13 `In corporate settings, the more information users have to sort through, the longer it takes to find the specific documents they need and the more productivity drops. In the e-commerce environment, if customers cannot find the products they want to buy with their first couple of queries, they will jump from site to site until they come across one where they can.'14 `Ease of use and user-friendliness often determine whether the database is used. A program will not be used if it is intimidating, is too difficult, or requires too much effort. (...) An effective user interface should not require extensive training to be used easily.'15 Het is van groot belang dat met behulpt van een een zoekinterface eenvoudig en snel de gewenste resultaten verkregen kunnen worden, of het nu gaat om een publiekelijk toegankelijke database met een web-interface, of een database die in een bedrijfsomgeving geraadpleegd wordt. In beide gevallen betekent het slecht presteren van de interface het verlies van geld, ongeacht de kwaliteit of inhoud van de onderliggende database. Men wil niet alleen zaken kunnen vinden, men wil dat bovendien snel en eenvoudig kunnen doen. `However, this ease of use may require a loss of power and flexibility.'16 Om het bedieningsgemak van een interface eenvoudig te houden moeten de opdrachten die de gebruiker kan geven beperkt in aantal en complexiteit zijn. Het risico dat men hierbij loopt is dat dit ten koste gaat van de functionaliteit van het het systeem. Aangezien alle bekende publiek toegankelijke algemene zoeksites op het Internet in eerste instantie niet meer aanbieden dan een enkel invoerveld voor enkele zoektermen, zullen de meeste mensen gewend zijn aan dit type zoeken. Deze interfaces leveren niets anders op dan vaak grote lijsten met resutaten. Het blijkt mogelijk de verhouding tussen recall en precision te verbeteren met behulp van methoden als syntactic phrase indexing17, vectorruimtemodellen18 of andere statistische methoden19. Echter: `Most simple search engines trade of precision (...) for recall (...). This is because it is much easier to return exhaustive lists of documents than it is to effectively rank results in terms of relevancy. Faced with this, users often abandon simple searches altogether.'20 13 14 15 16 17 18 19 20
Dorsey, `Ad Hoc Query Tools: Do They Really Support Ad Hoc Querying?' Verity Search: The Advantages of Advanced Informattion Retrieval, 3 `Technical Architecture Framework for Information Management (TAFIM)' `Technical Architecture Framework for Information Management (TAFIM)' Pohlman en Kraaij, `The Effect of Syntactic Phrase Indexing on Retrieval Performance for Dutch Texts', 5 Joachims, `Text Categorization with Support Vector Machines: Learning with Many Relevant Features', 11 Hull, `Using Statistical Testing in the Evaluation of Retrieval Experiments', 325 Verity Search, 3.
11
qbe4or
2.2 Het uitgebreide zoekveld De meest eenvoudige zoekinterface is een enkel veld waarin de gebruiker een term kan invullen die vervolgens wordt vergeleken met de in de database aanwezige gegevens. Komt deze ergens voor dan kan het betreffende object worden vermeld in de resultaatset. Een stap geavanceerder is het mogelijk om deze zoekterm te specificeren met booleaanse of reguliere expressies. Hiermee wordt het mogelijk om in plaats van enkele woorden vaste series of variaties daarvan als zoekterm te gebruiken, andere strings uit te sluiten en naar combinaties ervan te laten zoeken. Op deze manier ontstaat er een veel genuanceerder en krachtiger query waarmee het aantal nuttige treffers kan worden vergroot ten opzichte van het totale aantal treffers. Dit gegeven staat bekend als de recall/precision-verhouding.21. QBE maakt eveneens gebruik van eenvoudige booleaanse expressies voor het evalueren van gegevens22. De verschillende velden waaruit deze interface bestaat accepteren als invoer elk apart een dergelijke expressie. Ook voor qbe4or heeft dit zeker nut. De kracht van een filter kan hierdoor sterk vergroot worden.
2.3 Query-By-Templates In het voor databases met alleen tekstdocumenten ontwikkelde Query-by-Templates (QBT) wordt de daadwerkelijke lay-out van de in de database aanwezige documenten genomen als model voor de zoekschermen, de zogenaamde template. Daardoor kan een gebruiker die op titels zoekt zijn zoektermen op de plaats kwijt waar in een echt document de titel zou staan, de zogenaamde regions, of regio's in het Nederlands. Dit heeft gebleken zeer intuitief te werken. Het concept is echter alleen bruikbaar voor tekstdatabases23. In ieder geval zal het type en aantal attributen van elk object in de database gelijk moeten zijn. Aangezien, zoals in hoofdstuk vier duidelijk zal worden, dit bij OO- en ORDBs niet het geval is komen deze voor een interfacetype als QBT niet in aanmerking, Toch zit er in QBT een voor qbe4or bruikbaar idee. Zoals in hoofdstuk zeven zal blijken moet er in qbe4or een manier aan de gebruiker worden geboden om zich vrijelijk te kunnen bewegen tussen diverse queryinterfaceschermen, die ontstaan vanwege de grote aantallen mogelijke attributen van alle objecttypen samen. QBT kampt met een vergelijkbaar probleem en heeft daar een voor qbe4or bruikbare oplossing voor. QBT bestaat in drie vormen24: 1. Flat templates: waarin QBT werkt zoals hierboven beschreven. Alle regio's worden weergegeven in een eenvoudige twee-dimensionale template die exact de layout vaneen typisch document uit de database weergeeft. 2. Nested templates: waarin de regio's zijn opgedeeld in subregio's. Een strofe uit een gedicht bijvoorbeeld kan zo als geheel worden behandeld, waarbij de gebruiker kan zoeken op het voorkomen van zijn zoekterm in de gehele strofe, of per regel apart. In het laatste geval kan hij zoeken naar deze zoekterm in bijvoorbeeld specifiek een bepaalde regel, of naar combinaties van zoektermen in verschillende specifiek aangegeven regels. 3. Structured templates: waarin de gebruiker als het ware kan inzoomen op een regio om deze in meerdere subregio's te verdelen, of uitzoomen om het aantal subregio's weer te verkleinen. Als een document opdeelbaar blijkt in teveel regio's en subregio's, is het vaak niet langer wenselijk om die alle tegelijk weer te geven. De gebruiker krijgt een boomstructuur te zien waarmee hij tussen verschillende niveaus van detaillering van het queryscherm kan navigeren.
21 22 23
24
12
Su, `The relevance of recall and precision in user evaluation' Zloof, `Query-by-Example', 331 Sengupta en Dillon, `Query By Templates: A Generalized Approach for Visual Query Formulation for Text Dominated Databases ', 1 Sengupta en Dillon, `Query By Templates', 5
2. Vergelijkbare systemen
Afbeelding 1. Een QBT queryscherm met navigatieboom
Een dergelijke boom is voor qbe4or eveneens goed in te zetten. Hierdoor kan de gebruiker tussen de diverse objecttypen25 navigeren waarbij het aantal de attributen zal verkleinen naarmate er meer op een object wordt ingezoomd.
2.4 Vijfde-generatietalen Microsoft English Query en Esperant zijn voorbeelden van commerieel ontwikkelde querytalen van wat bij Microsoft zelf de vijfde generatie wordt genoemd26. Deze talen staan zeer dicht bij de gebruiker, in de zin dat zij de queries in natuurlijk Engels laten stellen. Het is daarna aan het systeem om op basis daarvan een SQLquery te formuleren. Op deze manier proberen zij een extreem hoge gebruiksriendelijkheid te creëeren. Microsoft English Query , een onderdeel van SQL Server 7.0, laat de gebruiker zijn zin helemaal zelf formuleren in een daarvoor bestemd invoerveld. `A lot of people are excited about the English Query capability of SQL Server 7.0. The promise is great, but I'm a bit of a skeptic when it comes to querying. It takes a power user to make queries, because the user needs some understanding of the underlying data structures.'27 Daarmee lijkt het gebruik van de interface beperkt tot de beheerders van een database, mensen van wie verwacht kan worden dat ze SQL machtig zijn en een dergelijke interface niet nodig hebben. English Query gaat evenwel zelfs nog een stap verder, door de interface te voorzien van een spraakherkenningsmechanisme.28 Momenteel kan daarbij slechts een beperkt domein aan woorden en zinsconstructies gebruikt worden. Dat betekent dat de gebruiker vooraf moet weten welke dat zijn. Mijns inziens gaat daarmee al een deel van de beoogde gebruiksvriendelijkheid verloren, aangezien hiervoor toch weer een leerproces of handleiding nodig is. Echter: `This type of grammar could be an interim step between context-free and dictation grammar-based applications.'29 Esperant van Software AG werkt anders. `It doesn't try to accept natural language as input. Instead, it uses a “point and click” interface (...). The difference is that ESPERANT shows the query in English as it is created using a more or less traditional method.'30 Op deze manier slaagt het systeem er bovendien in de gebruiker te verhinderen incorrecte queries te formuleren. `Once a field is selected, only fields that make logical sense are displayed for further result.'31`Esperant (...) is best known for its ability to prevent users from building SQL 25 26 27 28 29 30 31
Voor een uitleg over OR-terminologie verwijs ik u graag naar hoofdstuk vier. Microsoft TechNet, Developing with English Query Campbell, `SQL Server 7.0 -- The Developer's Product' Hess, `Using Speech Recognition with Microsoft English Query' Hess, `Using Speech Recognition with Microsoft English Query' Dorsey, `Ad Hoc Query Tools: Do They Really Support Ad Hoc Querying?' Dorsey, `Ad Hoc Query Tools'
13
qbe4or queries that return incorrect or invalid results, even though the SQL syntax may not generate an error.'32 `Few query tools let end users construct complex queries with the ease found in Software AG's Esperant. (...) However, Esperant will be a stronger tool if future versions catch up with the analytical prowess found in other products (...).'33 Het is in natuurlijke taal goed mogelijk om QBE-filters te formuleren, de technische problemen die daarbij komen kijken daargelaten. In plaats van een constructie als `= 4' zou men in het Engels `is 4' kunnen gebruiken. Bij complexere filters, die de equivalent van booleaanse expressies met AND, OR of XOR zouden moeten vormen, eventueel met nesting, worden volzinnen echter snel te lang om op een duidelijke manier in een invoerveld te kunnen worden weergegeven dat niet breder is dan een enkele kolom uit de voorbeeldtabel die de interface vormt. Het gebruik van natuurlijke taal als invoermethode is daarvoor geen oplossing, aangezien in QBE de filters in de resultaattabel eveneens moeten worden weergegeven.
32 33
14
Frank, `Esperant 3.0.' Frank, `Esperant 3.0.'
3. Query-by-Example
3. Query-by-Example
3.1 Het systeem QBE is `a high level data base management language that provides the user with a convienient and unified interrface to query, update, define, and control a data base.'34 Het probleem zoals geformuleerd in hoofdstuk een is beperkt tot het bevragen van de database. De complexiteit van ORDBs maakt dat deze in de praktijk alleen door, of met tussenkomst van, deskundigen beheerd en bevraagd worden. Dat was althans mijn ervaring bij de N.A.M. Dit onderzoek en het daaruit voortkomende systeem is daarom beperkt tot het querygedeelte van de functionaliteit van QBE, aangezien dat een oplossing voor het gestelde probleem is. `Two basic concepts are fundamental to Query-By-Example. Programming is done within two-dimensional skeleton tables. This is accomplished by filling in the appropriate table spaces with an example of the solution.'35 Onderstaande afbeelding toont een dergelijke voorbeeldtabel. Onder de kolomnaamvelden kan in elke kolom een voorbeeld van de gezochte gegevens worden ingevoerd. Deze voorbeelden werken als filters voor de te retourneren gegevens, doordat al deze gegevens daarmee overeen moeten komen.
Afbeelding 2. Voorbeeldtabel
`When the user performs an operation against the data base, he fills in an example of a solution to that operation in skeleton tables that can be associated with actual tables in the data base.'36 De hier genoemde voorbeeldtabellen hebben dezelfde kolommen en kolomtitels als de daadwerkelijke tabellen in de database, en wanneer de gebruiker zijn query in deze voorbeeldtabel formuleert, `he perceives that behind this query skeleton there is a real table (...) that contains the actual data. In other words, (...) he mimics the operation of scanning tables manually.'37 Het tweede principe luidt dat er onderscheid wordt gemaakt tussen constante en voorbeeld-elementen. Een voorbeeldelement is een door de gebruiker ingevoerd element dat als filter dient. `The P stands for print, which indicates the desired output. ROD, which is an example element (variable) – is 34 35 36 37
qbe4or underlined, and represents an example of a possible anwer.'38Variabele elementen zijn variabelen die in combinatie met commando's gebruikt worden. Deze elementen zijn voor qbe4or niet van belang, voornamelijk omdat het commando altijd P voor `print' zou zijn. Voor de QBE-commando's die het sorteren van de tabellen regelen zijn tegenwoordig betere oplossingen, zoals een klik op de kolomtitel om de tabel op die kolom oplopend te sorteren, en nog een klik om die sortering om te draaien. Deze methode is beter omdat hij eenvoudiger is en bovendien toegepast kan worden nadat de query al is uitgevoerd, wat het systeem flexibeler maakt. De beschreven manier van filters aanbrengen is bijzonder krachtig, en tegelijkertijd eenvoudig te bedienen. Als er bijvoorbeeld in een lijst met objecten, waarvan de kleur bekend is, naar alle groene objecten gezocht wordt, dan vult de gebruiker in de kolom onder `kleur' het woord `groen' in. Is bovendien de vorm bekend, en wil de gebruiker alle ronde groene objecten, dan kan hij dat op dezelfde wijze in de daarvoor bestemde kolom aangeven. Ter vergelijking zou de equivalente SQL-query er in de meest eenvoudig mogelijke versie als volgt uit kunnen zien: select * from objecten where kleur='groen' and vorm='rond' Nu is dit nog een vrij eenvoudige query, maar zoals duidelijk zal worden in hoofdstuk zes kan bij objectrelationele databases de lengte en complexiteit van de query snel toenemen, terwijl de QBE-filters waarmee qbe4or die queries genereert niet veel ingewikkelder worden dat wat hier beschreven is. QBE onderscheidt meerdere soorten queries39, waarmee sorteren, zoeken op onderdelen van strings, vergelijkingen en bewerkingen van getallen, eenvoudige booleaanse bewerkingen, joins en het groeperen van tabellen en gegevens mogelijk is. Een aanzienlijk deel van deze functionaliteit is ook van toepassing op ORDBs. In hoofdstuk zeven wordt uitgelegd hoe dit in qbe4or verwerkt is. Wanneer een op papier gedrukte tabel handmatig wordt doorzocht is de gebruiker op zoek naar een of meerdere objecten waarvan hij eigenschappen, bijvoorbeeld de naam, onthoudt. Het zoeken bestaat uit het overslaan, of negeren, van alles wat daaraan niet beantwoord. Het specificeren van voorwaarden is dus gelijk aan het beperken van de te vinden gegevens. Als de gebruiker niet naar iets specifiek op zoek is, houdt dit in dat hij geen voorwaarden heeft bedacht. Het niet specificeren van eigenschappen in qbe4or moet dus de volledige tabel retourneren, terwijl alles dat in de voorbeeldtabellen wordt ingevuld, een specificatie van zoekvoorwaarden, oftewel een beperking van het zoekresultaat is, en daarmee een formulering van een query.
3.2 Voor- en nadelen `The results of various psychological studies of the language show that it requires less than three hours of instruction for nonprogrammers to acquire the skill to make fairly complicated queries. Such queries would otherwise require the user to know first order predicate calculus.'40 `(...) formbased query mechanisms, such as QBE, have been shown to enhance the user's ability to locate information within traditional database systems'41. QBE is eenvoudig in het gebruik. Mensen hoeven geen progammeur te zijn om er queries mee te formuleren die redelijk ingewikkeld zijn. Dit betekent dat QBE een oplossing voor het in hoofdstuk een gestelde probleem kan zijn, indien het aan te passen valt voor ORDBs. Christopher Staff zet in zijn `Overview of approaches to Multimedia Information Retrieval' een aantal voordelen en nadelen van QBE tegenover elkaar42. De door hem gevonden voordelen zijn de mogelijkheid voor patroonherkenning en -vergelijking, de ondersteuning van zoeken op basis van overeenkomsten, de mogelijkheid tot het classificeren van documenten, de mogelijkheid tot het trainen van het systeem voor automatische herkenning van die classificaties in nieuw materiaal en het afwezig zijn van de noodzaak tot het markeren van tekst. Staff benadert het concept vanuit een multimedia-perspectief; de laatste drie voordelen 38 39 40 41 42
16
Zloof, `Query-by-Example', 325 Zloof, `Query-by-Example', 326 Zloof, `Query-by-Example', 324 Sawyer en Sommerville, `A User Interface Framework for an Object-Oriented Database System', 56 Staff, `Overview of approaches to Multimedia Information Retrieval', 6
3. Query-by-Example zijn speciaal van toepassing op zijn eigen situatie en voor qbe4or niet van belang. De eerste twee echter vormen precies het door Zloof beoogde voordeel wat QBE zo gebruiksvriendelijk maakt: `Various studies have been conducted which investigated the relative merits of performing queries via forms and by query languages. These concluded that users of forms were less likely to make errors, formulated queries more quickly, and were able to do so with more confidence than those using query language.'43 De nadelen die hij noemt zijn het gebrek aan expressie, gebrek aan eenvoud bij het aangeven van uitzonderingen, dat de gebruiker de vorm van het document moet kennen en dat het niet mogelijk is te zoeken aan de hand van tekstuele beschrijvingen. De eerste twee nadelen zijn onverminderd van kracht op objectrelationele systemen, maar wegen in dit geval niet op tegen de voordelen, zoals bleek uit de door Sawyer en Somerville genoemde studies. De overige twee nadelen gaan niet op voor object-relationele systemen, aangezien samenstelling en tekstuele beschrijvingen niet fundamenteel anders in de database opgeslagen zijn dan andere gegevens, waardoor ook daarop gezocht kan worden.
3.3 Recente closed-source toepassingen Sinds de oorspronkelijke ontwikkeling aan het einde van de jaren '70 wordt het concept van QBE in talloze closed-source projecten gebruikt. Afbeelding 344 is een voorbeeld van een QBE-query uit Borland Paradox 4 voor Microsoft Windows 3.x uit de eerste helft van de jaren '90. Het toont nauwkeurig de layout van een QBE-interface zoals door Zloof beschreven in 1977.
Afbeelding 3. QBE in Borlands Paradox voor Windows
De afbeelding hieronder is recenter, en afkomstig uit Microsoft Office 200045. Ook hierbij is het concept van de voorbeeldtabel, waarin de voorwaarden worden aangegeven waaraan de in die kolom te verschijnen informatie aan moet voldoen, volledig gehandhaafd.
43 44 45
Sawyer en Sommerville, `A User Interface Framework for an Object-Oriented Database System', 56 Common Software Overview Carroll, `How to do Most Queries in the Microsoft Access 2000 variant of SQL'
17
qbe4or
Afbeelding 4. QBE in Micrsoft Office 2000 voor Windows
Een zoektocht naar QBE op het internet levert letterlijk duizenden voorbeelden op zoals de twee hierboven. QBE wordt in zijn oorspronkelijke vorm toegepast in applicaties en op websites voor het gemakkelijk doorzoeken van interfaces. Een enkele keer wordt er, zoals in afbeelding 3, gekozen voor ee andere layout46:
Afbeelding 5. Een MySQL-beheerapplicatie in Java
Hoewel het er heel anders uitziet, blijkt bij een iets nadere beschouwing dat het concept volledig overeind is gebleven, hoewel negentig graden tegen de klok in gedraaid. De kolommen zijn nu rijen geworden. De kolomnamen staan onder elkaar, de operator kan uit een menu gekozen worden en de voorwaarde wordt in een veld rechts ingevuld. Na een muisklik op de knop `Execute query' zal er ongetwijfeld een resultaatset worden getoond die aan de aldus geformuleerde query voldoet. Als deze resultaatset de vorm van een tabel heeft waarvan de kolomnamen, zoals te verwachten valt, bovenaan verschijnen in plaats van aan de linkerkant, dan zal de zoekinterface qua layout niet meer de vorm van een voorbeeldtabel hebben gehad, zoals Zloof voorstelt. Hierdoor zal m.i. de intuïtiviteit van het systeem verminderen. Andere voorbeelden van een verandering van de interface die ik op het internet heb gevonden, zoals het opdelen ervan in verschillende tabbladen, vensters of pagina's, hebben eveneens het effect van verminderd comfort.
46
18
Customer Service Call Center Helpdesk software: QBE
3. Query-by-Example
3.4 Conclusie De conclusie die uit de genoemde voorbeelden getokken kan worden is dat het beste bij het QBE-concept van Zloof gebleven kan worden, en dat toevoegingen en veranderingen daaraan moeten worden doorgevoerd met inachtneming van de volgende richtijnen: 1. Het overeenkomen van de voorbeeldtabel met de resultaatsettabel qua layout is van groot belang voor de intuitiviteit van de queryinterface. 2. Het bladeren tussen verschillende vensters tijdens hetformuleren van de query, waarbij de query nooit constant in zijn geheel kan worden overzien is hinderlijk.
19
4. Het object-relationele model
4. Het object-relationele model
4.1 OR versus traditioneel-relationeel `Just as COBOL declined when newer languages such as C, and C++ came into being, relational databases will slowly decline as OR technology takes hold.'47 Object-relationele database-architectuur is een type database-design dat toepasbaar is wanneer een generische aanpak nodig is. Als een database grote hoeveelheden zeer diverse gegevens moet bevatten, is het niet langer handig om een nieuwe tabel te ontwerpen voor elk type, zoals in traditionele database-design gedaan wordt. Daarvoor is OR ontwikkeld. Een object-relationele database is een object-georiënteerde database, geïmplementeerd op een relationele server. Object-relationele database-architectuur is daarom een type relationele database-architectuur. `As an evolutionary technology, the object/relational (OR) approach has inherited the robust transaction- and performance-management features of its relational ancestor and the flexibility of its object-oriented cousin'48. Het bestaat in twee vormen: transaction based en situation based. Een database van de eerste vorm bestaat uit een centrale tabel met louter verwijzende sleutels die het verbinden met een groot aantal tabellen waarin transacties zijn opgeslagen. Gegeven een startsituatie kan een gebruiker elke situatie op een punt in de tijd terugvinden, inclusief de weg er naartoe. Dit type database is vanwege zijn grote mate van abstractie bijzonder ingewikkeld om te bevragen, en heeft een zeer lage performance.
4.2 Situation-based OR Het andere soort bevat slechts enkele tabellen, verdeeld in twee lagen: een metadata-laag waarin de object-, associatie-, methodetypen, hun respectievelijke hiërarchieën en de toegepaste eigenschappen zijn gedefinieerd, en een data-laag waarin de object-instanties, de associaties, methoden en eigenschap-waarden zijn vastgelegd. Elk record in elke tabel heeft ofwel een active-veld of start- en einde-datums. Het nadeel van dit type ten opzichte van transaction-based OR is dat de hoeveelheid data, nodig om hetzelfde te beschrijven, groter is dan bij het eerste type. Het bevragen van dit type is echter veel eenvoudiger en het heeft daardoor een betere performance. qbe4or is gebouwd voor dit type OR. In een situation-based ORDB gebeurt niets anders dan het beschrijven van een domein, in termen van objecten, verbanden en eigenschappen. Dat domein kan een bedrijf zijn, een afdeling, een groep personen, of iets anders. De kern is het object. De Aarde is een object van het type planeet. De Maan is een object van het type maan. `Planeet' en `maan' zijn, in een database die ons zonnestelsel beschrijft, records in de tabel objecttypen. `Aarde' en `Maan' zijn opgeslagen in de tabel objecten. Een veld in die beide laatste records verwijst naar de respectievelijke objecttypen in de eerste tabel. `planeet' en `maan' hebben een associatie met elkaar, vastgelegd in de tabel associatietypen. Een associatie werkt twee kanten op, zodat er in deze tabel twee velden verwijzen naar objecttypen. Hij kan dus ook in beide richtingen worden omschreven: `draait in een baan om' en `is de moederplaneet van'. Beide omschrijvingen zijn in de associatie vastgelegd. Analoog hieraan wordt in de datalaag deze algemene maan-planeet associatie toegepast op `Maan' en `Aarde', met verwijzingen naar die objecten en de associatie.
47 48
Dorsey, `The Promise of the Object-Relational Paradigm' Grimes, `Modeling Object/Relational Databases'
21
qbe4or
Afbeelding 6. Een typische situation-based ORDB met objecten, associaties, methoden en attributen.
Attributen zijn eigenschappen van objecten. Zo bestaat er een eigenschap diameter, toe te passen op zowel maan als planeet, omdat beide objecten een diameter hebben. Dit wordt vastgelegd in de tabel toegepaste attributen. De waarden die hierbij horen komen in de tabel attribuut-waarden, met verwijzende sleutels naar de respectievelijke objecten en de toegepaste attribuut. Ook associaties kunnen attributen hebben. Zo heeft de associatie `draait in een baan om' het attribuut `gemiddelde afstand', met een zekere waarde. Ook kunnen verschillende soorten planeten worden onderscheiden. Jupiter is een gasplaneet, de Aarde is een rotsplaneet. Het is mogelijk om dit verband te definiëren. Beide objecttypen kunnen worden vastgelegd in de objecttypentabel, waarbij beiden als supertype `planeet' krijgen toegewezen. Terwijl beide subtypen elk hun eigen attributen en associaties hebben, zoals bijvoorbeeld de hoeveel oceanen in het ene geval, of het hebben van ringen in het andere, erven ze ook alle associaties en attributen van hun supertype, zoals een omloop rond een ster, en een diameter. Methoden tenslotte zijn acties die kunnen worden toegepast op typen. Een voorbeeld is dat de gemiddelde afstand tussen de Maan en de Aarde langzaam toeneemt. De waarde van het attribuut `gemiddelde afstand', horende bij de associatie `draait in een baan om', zou dus moeten veranderen. Dat kan worden vastgelegd als een methodetype, waarbij het specifieke geval van onze Aarde en onze Maan in de methoden-tabel in de datalaag moeten worden gedefinieerd. De snelheid waarmee dit gebeurt zou dan weer een attribuut hiervan kunnen zijn.
4.3 Complexiteit Dit type ORDB kan nog veel complexer dan hierboven beschreven. Zo voorziet het schema in afbeelding 1 slechts in hiërarchie in de objecttypen, terwijl dit ook goed mogelijk is in de andere meta-datatabellen. En hoewel de hier beschreven manier slechts één-op-veel hiërarchieën toestaat, is het door middel van een extra tabel mogelijk om daar veel-op-veel relaties van te maken, waardoor typen niet slechts een, maar meerdere supertypen kunnen hebben. Om de afbeelding niet al te onoverzichtelijk te maken heb ik een aantal beschreven relaties erin niet weergegeven, zoals de mogelijkheid voor associaties en methoden om attributen te hebben. Het is echter ook nog mogelijk voor attributen en methoden om associaties te hebben, of voor associaties en attributen om methoden te hebben. Dus kunnen ook associaties tussen diverse methoden weer van andere attributen of zelfs methoden worden voorzien. De mogelijke complexiteit in de logica ervan is eindeloos, en wordt in werkelijkheid slechts begrensd door de behoefte van degene die het model ontwerpt. Elke logische mogelijkheid moet worden vastgelegd doordat de ontwerper van het model ruimte heeft aangemaakt voor verwijzende sleutels. Dezelfde complexiteit kan echter ook worden gedefinieerd in veel minder tabellen. Het absolute minimum 22
4. Het object-relationele model dat de volle zojuist beschreven functionaliteit bezit, bestaat uit zes tabellen: de objecttypen, de associatietypen, de tussentabellen voor de beide hiërarchieën, en de datatabellen met de object- en associatieinstanties. Methoden en attributen worden gedefinieerd als associaties. Ter voorbeeld: de leeftijd van een planeet zal meestal worden vastgelegd als een attribuut: `planeet' `is oud' `zoveel jaar'. `is oud' kan echter ook een associatie zijn. Dan wordt `zoveel jaar' geen attribuut-waarde, maar een nieuw object. Voor methoden geldt hetzelfde. Dit is een probleem dat de continue aandacht verdient van degenen die de definities opstellen in de database. Vaak biedt de database niet de mogelijkheid voor attributen om eigen attributen te hebben. Als dat op een dag dan toch moet, had het attribuut beter van voren af aan als associatie kunnen worden vastgelegd. Afhankelijk van de eisen die er aan een ORDB worden gesteld worden logische mogelijkheden daarin aangebracht. Meestal zullen attributen van attributen bijvoorbeeld geen associaties met elkaar hoeven aan te gaan. Het model dat voor dit onderzoek is ontwikkeld, is vormgegeven met als voorbeeld de database waarmee ik bij de N.A.M. gewerkt heb. Er zijn geen aparte tabellen voor de methoden. Ook is er geen mogelijkheid tot hiërarchie in de attributen en de associaties. De laatste betekent dat overeenkomende attributen en associaties voor elk objecttype en associatietype apart moeten worden gedefinieerd. Om al teveel data-redundantie te voorkomen heb ik voor de associaties de omschrijvingen in een aparte tabel ondergebracht. Ook is het niet mogelijk om associaties tussen attributen te definiëren. Deze zaken beperken de functionaliteit van de database niet teveel. Alle principes van situation-based OR zijn in de testdatabase aanwezig, dus is hij geschikt als test-database voor qbe4or.
4.4 Active-flags en start- en eind-data Bij ORDBs is het niet gebruikelijk om gegevens te wissen. In plaats daarvan worden ze gedeactiveerd. In het metadata-niveau heeft elk record een veld, genaamd active, waarin ofwel een Y (voor `yes'), ofwel een N (voor `no') staat. Indien een type zelf niet meer van toepassing is, kan het worden uitgeschakeld door dit veld van een N te voorzien. De interface dient voor de afhandeling hiervan te zorgen, en in elke SQL-query moet hier dus op worden gelet. Hetzelfde geldt voor de toegepaste associaties en attributen. Ook op het data-niveau worden gegevens niet verwijderd. Hier worden ze beëindigd. Elk toegevoegde gegeven krijgt een start- en een eind-datum. Ervoor en erna moeten de gegevens worden genegeerd. Als er op die manier typen zonder instanties voorkomen houdt dat logisch geen probleem in. Als in het omgekeerde geval geldende instanties van een ongeldig type zijn, dan zijn ze eveneens ongeldig. De interface dient er ten allen tijde voor te zorgen dat de gebruiker slechts inactieve gegevens te zien krijgt wanneer daarom expliciet wordt gevraagd. Het moet immers ook mogelijk zijn de niet-actieve gegevens te beheren. De overerving is ook hierop van toepassing. Is een van de supertypen van een objecttype inactief, dan zijn, in een enkelvoudige hiërarchie zoals die van dit onderzoek, al zijn subtypen dat ook. `RDBMSs use Structured Query Language (SQL, currently SQL2) as the data definition language (DDL) and the data manipulation language (DML). SQL includes statements for data definition, modification, querying and constraint specification.'49 Ook qbe4or maakt van een implementatie van SQL gebruik, en wel MySQL.
4.5 Termen Gedurende mijn stage en in de verschillende boeken ben ik voor enkele concepten meerdere overlappende terminologieën tegengekomen. In dit onderzoek is een eenduidig en consequent woordgebruik gebezigd, dat logisch is, en zoveel als mogelijk Nederlandstalig.
4.5.1 SQL Het woord database is Engels. Het staat zowel voor de gegevens en de structuur waarin ze zijn ondergebracht, als voor een engine- en interface-combinatie die deze structuur opslaat en beheert, zoals 49
Devarakonda, `Object-Relational Database Systems - The Road Ahead'
23
qbe4or Microsoft Access of Filemaker. De beschikbare Nederlandse vertalingen als databank, gegevensbank, gegevensbeheer-systeem en dergelijke, zijn niet of nauwelijks in gebruik, en zelf soms ook half Engels. Daarom gebruik ik het woord database om het datamodel en de daarin opgeslagen gegevens als geheel te benoemen. MySQL wordt over het algemeen geen database genoemd, maar een database engine of server, omdat het zelf geen interface heeft, afgezien van enkele terminal-applicaties. Voor beide woorden bestaan geen goede Nederlandse vertalingen die de lading helemaal dekken, dus gebruik ik engine. Hetzelfde geldt voor de onderdelen van een database. Table heeft een prima Nederlands equivalent in tabel, record heeft dat niet. Column, row en field zijn wel weer goed vertaalbaar in kolom, rij en veld. Een tabel is dus verticaal te verdelen in kolommen, en horizontaal in rijen. De gegevens in een rij als bij elkaar behorend geheel noem ik een record, en een enkel onderdeel daarvan is een veld. Gegevens is een goede vertaling voor het Engelse data, maar ik gebruik het woord data nog wel om onderscheid aan te geven met meta-data, of als meervoud voor datum. Voor het woord query bestaat eveneens geen goed Nederlands woord. Een vraag is iets anders, omdat deze term natuurlijke taal impliceert. Hoewel een goede SQL-query soms vrij goed op een volzin kan lijken, is het dat toch niet helemaal. Bovendien is query zeer ingeburgerd onder SQL-gebruikend Nederland, getuige het taalgebruik op vele Nederlandstalige websites op dat gebied, en binnen informatiekunde in Groningen. Als werkwoord wil ik echter wel het woord bevragen gebruiken. Ook dit hoor je vaak, het impliceert geen natuurlijke taal, en tegenstelling tot het woord vragen, geeft het aan dat de query niet aan de database gesteld wordt, maar met behulp ervan beantwoordt wordt. Het woord queriën, dat je ook nog wel eens tegenkomt, vindt ik persoonlijk bijzonder lelijk. Primary key vertaal ik als primaire sleutel, foreign key als verwijzende sleutel. Deze vertalingen zijn gebruikelijk in talloze Nederlandstalige boeken over verwante onderwerpen.
4.5.2 OR Vooral bij OR is er nogal wat overlap in het jargon te vinden. Om te beginnen is het woord object-instantie dubbel-op of verkeerd. Een instantie is al een object. Beter zou zijn objecttype-instantie, omdat een object het resultaat is van een objecttype dat wordt geïnstantieerd. Maar dat is min of meer hetzelfde als zeggen dat ik de broer van mijn broer ben. Het correcte woord is dus object, en waar nodig en duidelijk kan instantie worden gebruikt om de relatie met het type aan te geven. Een object kan een supertype hebben, zowel in het Engels als het Nederlands. Het geheel van supertypen en subtypen van een type vormt, tezamen met het type zelf, een class, of klasse in het Nederlands. Voor attributen bestaat tevens de term eigenschappen. De Engelse vertaling van attribuut is attribute en die van eigenschap is property. In het Engelstalige datamodel voor qbe4or gebruik ik de eerste Engelse term, om voor de duidelijkheid daar met de Nederlandse term zo dicht mogelijk bij te kunnen zitten. Vandaar dat ik het woord attribuut prefereer. Dezelfde overweging heb ik gemaakt bij associatie, association in het Engels. Het Engelse woord role werd bij de N.A.M. gebruikt, maar het Nederlandse rol is daar geen goede vertaling van. Relatie had ook gekund, aangezien het Engelse woord daarvoor relation is, maar dat werkt verwarrend. Die term wil ik namelijk reserveren voor de SQL-relaties tussen de tabellen van het datamodel. Het woord recognized, in bijvoorbeeld recognized attributes, is het beste naar het Nederlands te vertalen als toegepast, en niet letterlijk als herkend, omdat dat semantisch niet overeenkomt. ` (...) the form in which data is presented to the user and the programmer, is known as the logical view of the database. The stored data on a computer disk system is called the internal view. '50 Voor het Engelse woord view in deze context is geen goede Nederlandse vertaling. Ik zal in dit document de termen logische en interne view gebruiken.
50
24
Devarakonda, `Object-Relational Database Systems'
4. Het object-relationele model
4.6 Conclusie ORDB is een bijzonder krachtig concept. Het maakt het mogelijk om een object-georienteerde database te bevragen met behulp van middelen afkomstig van het relationele databasedesign, door eigenschappen van beide concepten in zich te verenigen. Hiervoor maakt het gebruik van een normale relationele engine waarbinnen de objecten, hun attributen en associaties als velden in tabellen vastgelegd worden. Het aantal tabellen waaruit een database bestaat kan hierdoor klein en constant blijven doordat de gegevens en hun aard veel minder invloed op het datamodel uitoefenen dan gebruikelijk. De grotere mate van abstractie ten opzichte van een traditioneel-relationele database maakt hem echter moeilijker te bevragen.
25
5. De database
5. De database
5.1 Het model
Afbeelding 7. Datamodel van de testdatabase van qbe4or
Het model in afbeelding 7 is een schematische weergave van de object-relationele testdatabase voor qbe4or. De DDL-statements zijn opgenomen in dit document als bijlage 10.1. De tabellen worden elk aangeduid met een rechthoek waarin bovenin de naam van de tabel, en daaronder de velden met hun datatypen staan. De aanduiding pk staat voor primary key, primaire sleutel. De database is in hoofdzaak te verdelen in drie verschillende groepen tabellen: het meta-dataniveau (object_types, assoc_types, en attrib_types), het dataniveau (objects, assocs en attrib_vals) en drie extra tabellen (assoc_names, data_types en users). Ondersteund worden objecttypen en associatietypen en hun instanties, alsmede attributen en hun waarden. Per attribuuttype kan een datatype gespecificeerd worden. Objecttypen zijn onder te brengen in een enkelvoudige boomstructuur waardoor overerving van associaties en 27
qbe4or attributen mogelijk is. Zowel objecten als associaties kunnen attributen toegekend krijgen. Alle metadata kan, wanneer nodig, gedeactiveerd worden. Daarvoor dient het veld active. De data zelf heeft altijd een start- en een einddatum waartussen deze geldig is. Onderstaande tabel is een overzicht van de negen tabellen uit het model. tabel
soort
bevat
object_types
meta-data
object type-definities en boomstructuur
assoc_types
meta-data
associatie type-definities
attrib_types
meta-data
attribuut type-definities
objects
data
objectdefinities
assocs
data
toegepaste associaties
attrib_vals
data
toegepaste attributen en -waarden
assoc_names
data
naamparen van associatietypen
data_types
data
datatypen van de attribuuttypen
users
interface
namen, wachtwoorden en homepage-url van elke gebruiker
5.2 Relaties De belangrijkste tabel is object_types. De primaire sleutel is uid (unique identificator). Het veld supertype is een verwijzende sleutel naar de eigen primaire sleutel, waardoor de tabel een recursieve eigenschap krijgt: hij verwijst naar zichzelf in een één-op-veel-relatie. Dit veroorzaakt de genoemde objectboomstructuur. De sleutel uid Verwijst naar het veld type in objects. Hierdoor kunnen de objecten in die tabel van een type worden voorzien. De sleutel verwijst bovendien naar de velden object_type1 en object_type2 in assoc_types, (assocation types)waardoor objecttypen in paren van twee met elkaar kunnen worden geassocieerd. Op het dataniveau worden beide relaties geconcretiseerd doordat de primaire sleutel uid in objects verwijst naar de velden object1 en object2 in assocs. Attribuuttypen kunnen op objecttypen worden toegepast doordat uid tenslotte ook nog verwijst naar het veld object_type in de tabel attrib_types. Ook deze relatie zien we terug in de tabel objects, waarin uid verwijst naar het veld object in de tabel attrib_vals. De tabel assoc_types heeft eveneens een primaire sleutel genaamd uid. Deze verwijst naar het veld assoc_type in de tabel assocs, waardoor de daar gedefinieerde associaties van een type kunnen worden voorzien, analoog aan de genoemde objecttype-object-relatie in de tabellen object_types en objects. Hij verwijst tevens naar het veld assoc_type in de tabel attrib_types, waardoor het mogelijk wordt attributen aan associaties toe te kennen. Het veld names in assoc_types is een verwijzende sleutel naar het veld uid in de tabel assoc_names. In deze tabel staan de naamparen voor de associatietypen. Op dezelfde wijze als bij object_types en assoc_types verwijst ook de primaire sleutel van attrib_types naar een veld attrib_type in attrib_vals, waardoor de in objects en assocs toegepaste attribuut-waarden aan een type gekoppeld worden. De datatypen van de attributen kunnen per attribuuttype worden gespecificeerd. Deze staan in de tabel data_types, waarnaar wordt verwezen met de sleutel datatype. De primaire sleutel van de tabel users tenslotte verwijst naar het laatste veld in elke andere tabel, behalve assoc_names, waardoor elk record in deze tabellen voorzien kan worden van een gebruiker.
28
5. De database
5.3 Conclusie De voorbeelddatabase voor qbe4or is een vrij eenvoudige ORDB, die echter alle principes van dit concept in zich heeft. Hij is bovendien in zijn capaciteiten gelijk aan de database waarmee ik bij de N.A.M. heb gewerkt. Aangezien die database in een praktijksituatie binnen een groot bedrijf werd ingezet maakt dat de hier beschreven database geschikt voor het testen van qbe4or.
29
6. Het bevragen van een ORDB in SQL
6. Het bevragen van een ORDB in SQL
6.1 Een tabel opvragen In een traditioneel-relationele database zijn alle attributen en associaties van elk object te vinden in diezelfde tabel. Om het voorbeeld van de database aan te halen met ons zonnestelsel: een tabel met daarin alle planeten zal tenminste een kolom hebben met een index-nummer, een met de planeet-namen, een met de diameter, de ouderdom en de afstand tot de zon. Daarnaast zullen er kolommen zijn met verwijzende sleutels in een-opveel-relaties naar de tabellen met manen, gassen in de atmosfeer, stoffen in de bodem, etc. Om de gegevens uit een traditioneel-relationele tabel met planeten te halen, volstaat een query als de volgende: select naam, diameter, ouderdom, afstand_tot_zon from planeten
Deze query levert een tabel op die verticaal alle planeten bevat en horizontaal de attributen van elke planeet. Eén-op-veel relaties staan hier niet bij, maar die zijn ook niet in een twee-dimensionale tabel weer te geven. In een ORDB zijn dit altijd associaties. Een-op-een relaties zijn typisch attributen. Zoals uitgelegd in hoofdstuk twee, is het verkrijgen van deze gegevens uit ORDBs niet zo eenvoudig. Alle objecten, associaties en attributen zijn per soort in tabellen gegroepeerd, en niet bij de objecten waarbij ze horen. Verwijzende sleutels zorgen voor de relaties ertussen. Om te beginnen hebben we twee soorten planeten, rots-planeten en gas-planeten. Deze stammen beide van het supertype planeet, waarnaar we op zoek zijn. Een script dat ons alle planeten wil tonen zal dus allereerst op zoek moeten gaan naar alle objecten die van een subtype van planeet zijn. Vervolgens moet worden onderzocht welke attributen toepasbaar zijn op de diverse subtypen. Dat echter kan heel goed per subtype verschillen. Rotsplaneten hebben bijvoorbeeld een populatie (één rotsplaneet dan, althans; het gaat hier om het voorbeeld, niet om de realiteit), bij gasplaneten is dat een onmogelijkheid. De manier om dat op te lossen is het horizontaal tonen van de toegepaste attributen van alle subtypen, en in de velden waar die niet van toepassing zijn de waarde NULL of een leeg veld te tonen. Als laatste moeten de waarden van alle attributen per object worden opgezocht, waarna de tabel getoond kan worden.
6.2 De objecten van een type en zijn subtypen. Om een lijst te krijgen van alle objecten van een type waarvan het nummer bekend is, gebruiken we de volgende query: select name from objects where object_type =
Om de gevraagde tabel te krijgen hebben we echter ook alle objecten van subtypen van het gevraagde type nodig. Subtypen zijn records in de tabel object_types waarvan het veld supertype het gevraagde typenummer bevat, of subtypen daarvan. Deze omschrijving geeft de recursiviteit van dit fenomeen al aan. Om dit te bewerkstelligen moeten we terwijl we een query uitvoeren, afhankelijk van de gevonden resultaten, deze query aanpassen. Dit kan niet in MySQL. De oplossing is het uitvoeren van meerdere queries achter elkaar, waarvan het resultaat van elke query gedeeltelijk bepaalt hoe de volgende luidt. MySQL kent, zoals later in dit hoofdstuk duidelijk wordt, faciliteiten voor het onthouden van tussentijdse 31
qbe4or resultaten, in de vorm van user variables. Het uitvoeren van meerdere opdrachten in een vaststaande volgorde is mogelijk, door de verschillende delen te scheiden door punt-komma's (;). In recursieve of lus-constructies echter, waarbij het aantal keren dat een opdracht dient te worden uitgevoerd kan variëren, is dat niet mogelijk. Interventie van de scripttaal, in dit geval PHP, is dus niet te vermijden. Onderstaande PHP-functie, die alle subtypen van een objecttype opzoekt, maakt per gevonden type een query, en onthoudt de resultaten ervan. function find_subtypes ($tableName, $key, $subtypes) { $result = mysql_query ("select uid from $tableName where supertype = $key and active != 'N'"); while ($row = mysql_fetch_row ($result)) $subtypes = find_subtypes ($tableName, $row[0], $subtypes) . ",$row[0]"; return $subtypes; }
Deze functie bevindt zich in het bestand mysql.inc. Hij is recursief en neemt drie parameters: $tableName is de naam van de tabel, in dit geval object_types. $key is de uid van het type van het huidige object. In $subtypes wordt de komma-gesepareerde lijst bijgehouden. De aanroep ziet er als volgt uit: $children = find_subtypes ('object_types', $currentType, '');
Deze aanroep heeft het type waarvan de supertypen gezocht moeten worden in $currentType. Bij de eerste aanroep is de lijst nog leeg, dus moet als derde parameter een lege lijst worden meegegeven. Het hier gebruikte enkele aanhalingstekens-paar is een manier om dat te doen. De tabel bevat geen veld waarin de subtypen van elk type worden opgesomd. Er is per type slechts een verwijzing naar het supertype. Deze informatie is echter voldoende om de subtypen te kunnen vinden. De functie werkt top-down. Als de functie wordt aangeroepen wordt de database bevraagd naar de uid's van alle typen waarvan het supertype gelijk is aan het huidige typenummer. Dit zijn de directe subtypen van het huidige type. Is het active-veld van een van de gevonden typen ongelijk aan Y, dan wordt het beschouwd als niet-actief, en genegeerd. Daarover later meer. Per gevonden type wordt de functie opnieuw aangeroepen, waardoor ook daarvan de subtypen worden opgezocht. Zijn alle typen gevonden, dan wordt de lijst met door komma's gescheiden type-nummers gegeven aan $children. Als het gevraagde typenummer zich in $currentType bevindt, en de code van de query als volgt luidt: select name from objects where (object_type = $currentType
en deze code zich in $query bevindt, dan kan met $query = $query . str_replace (",", " or object_type = ", $children) . ")”;
de code aan de query worden toegevoegd die zorgt voor een disjunctie met de lijst subtypen. Deze methode is alleen nuttig indien men van een objecttype en zijn subtypen de toegepaste attributen wil weten. Aangezien de tabel attrib_vals over een verwijzende sleutel naar objects beschikt in het veld object, is het, indien er gezocht wordt naar de attributen en hun waarden van een specifiek object, voldoende om via deze relatie het object-uid in attrib_vals op te zoeken. Telkens wanneer deze gevonden wordt betreft het een attribuut-waarde behorende bij het onderhavige object. Het attribuuttype kan vervolgens na worden gegaan doordat hetzelfde record in attrib_vals eveneens een verwijzende sleutel naar het corresponderende type bevat. Er kan in dat geval dus aan worden voorbijgegaan van welke objecttypen de diverse attributen overerft zijn.
32
6. Het bevragen van een ORDB in SQL
6.3 Toegepaste attributen van een bekend object en zijn supertypen Als we zoeken naar de attributen en associaties die van toepassing zijn op een bepaald object, dan zijn daarvoor enkele stappen nodig, afhankelijk van wat we van het object weten. In de eenvoudigste situatie weten we de naam of de waarde van de primaire sleutel. Die staan in hetzelfde record in de tabel objects, respectievelijk als name en uid, dus als we het ene weten, weten we ook het andere. Ook hebben we het typenummer van het object nodig, te vinden in het veld object_type. Dat leidt ons naar de tabellen attrib_types en assoc_types waar we ditzelfde typenummer zullen tegenkomen, indien het object toegepaste attributen en associaties heeft. In attrib_types staat dat in het veld object_type. In elk record waar in dat veld dit nummer staat vinden we de naam van een van de attributen die van toepassing zijn op het object. De waarden die horen bij het attribuut staan in de tabel attrib_vals. In het veld attrib_type in die tabel staat de sleutel die naar de primaire sleutel in attrib_types verwijst en zo voor de relatie zorgt. Om een tabel te krijgen waarin we van één bekend object alle eigen attributen met hun waarden zien, hebben we dus de volgende query nodig: select objects.name as object, attrib_types.name as attribute, attrib_vals.value as value from objects, object_types, attrib_types, attrib_vals where objects.object_type = object_types.uid and objects.object_type = attrib_types.object_type and objects.uid = attrib_vals.object and objects.uid =
Het overerving-principe van OO bepaalt dat objecten niet alleen attributen en associaties van zichzelf hebben, maar bovendien die van hun supertypen krijgen. Als een supertype zelf ook supertypen heeft, moeten uiteraard ook die worden meegenomen. Om te bepalen welke attributen en associaties van toepassing zijn op een object, is het dus niet voldoende om alleen te kijken naar die attributen en associaties die naar het gezochte object verwijzen, maar moet een lijst worden opgesteld van alle supertypen van dat object. Vervolgens kunnen van daaruit de overige attributen en associaties worden bepaald. Om die lijst op te stellen is een lus nodig die voor de object-typenummers zorgt, vergelijkbaar met het algoritme van de functie find_subtypes(), maar dan andersom. Deze lijst moet vanuit het gezochte object naar boven toe, bottom-up, worden samengesteld. Telkens als een supertype gevonden is, moet worden gezocht naar het supertype van dat type. De lijst is compleet als het toptype gevonden is. Dit type heeft als uid `0' en als naam `none'. Het heeft geen instanties, associaties of attributen. Dit is een speciaal type dat niet getoond moet worden na een zoekopdracht. Het bestaat alleen voor dit doel. Onderstaande PHP-functie, zoekt van een type alle supertypen op, en retourneert deze als een kommagesepareerde lijst. function find_supertypes ($tableName, $key, $supertypes) { $result = mysql_query ("select supertype from $tableName where uid=$key"); $row = mysql_fetch_row ($result); if ($row[0] != 0) return find_supertypes ($tableName, $row[0], $supertypes) . ",$row[0]"; }
33
qbe4or
Ook deze functie bevindt zich in het bestand mysql.inc. Hij wordt op dezelfde wijze aangeroepen als find_subtypes(): $parents = find_supertypes ('object_types', $currentType, '');
Deze aanroep veronderstelt dat het type waarvan de supertypen gezocht moeten worden in $currentType staat. Als de functie wordt aangeroepen wordt de database bevraagd naar het supertype van het huidige type $key. Is dit ongelijk aan `0', Dan wordt vanuit dat type de functie opnieuw aangeroepen zodat het op zoek gaat naar het supertype daarvan. Is het toptype gevonden, dan wordt de lijst met door komma's gescheiden supertype-nummers gegeven aan $parents. Als de op de vorige bladzijde genoemde query-code zich in $query bevindt, en eindigt met and (object_type = $currentType";
dan kan met $query = $query . str_replace (",", " or object_type = ", $parents) . ")”;
De code aan de query worden toegevoegd die zorgt voor een disjunctie met de lijst supertypen.
6.4 Niet-geldende data Een record in een ORDB geldt niet indien hij 1. een supertype heeft dat niet geldt; 2. een active-veld heeft met waarde 'N' of 3. een date_start- en een date_end-veld heeft, waar de huidige datum niet op of tussen valt. Zoals in paragraaf 2.2 uitgelegd volgt uit de logische gedachtegang achter het OO-datamodel dat alle objecten van niet-geldende typen eveneens niet gelden. Ook hun attributen en associaties gelden niet. Hierop moet door een interface worden gecontroleerd. Niet-geldende data moet worden genegeerd. Het is meestal niet logisch om te veronderstellen dat iemand gegevens invoert die vanaf het begin af aan ongeldig moeten zijn. Het ongeldig maken van records dient als vervanging voor het definitief wissen daarvan en zal dus een actief proces zijn van de kant van de gebruiker of beheerder van de gegevens. Als de geldigheid niet is aangegeven moet een record daarom als geldig worden gezien. Een type met een activewaarde NULL is dus actief, en een instantie met een date_start-waarde NULL blijft actief totdat daar een datum wordt ingevuld. Als in MySQL bovendien een lege string wordt ingevuld in een datum-veld, dan komt daar de waarde '0000-00-00' te staan. Deze moet daarom als NULL worden behandeld. De controle op de geldigheid van een record vindt in SQL uiteraard plaats in de where-clause van een query. .active kan worden vergeleken met de waarde 'N' en voor de datumvelden kent MySQL de constructie current_date51. Deze bevat de huidige datum, die vergeleken kan worden met andere data. Om te onderzoeken of een object geldig is, moet eerst worden gekeken of al zijn supertypen eveneens geldig zijn. Dit kan in een enkele query worden vastgesteld, maar deze moet door het script worden gegenereerd. Welke typen dat zijn hoeven we niet te weten, aangezien in de query van elk record het supertype-veld met het uid van het volgende record kan worden vergeleken. MySQL neemt daardoor automatisch het goede type. Wel moeten we weten hoe vaak dit dient te gebeuren, oftewel, hoeveel supertypen het gevraagde type 51
34
Lenz, DuBois en Hinz (ed.), MySQL Technical Reference for Version 4.1.1-alpha, 157
6. Het bevragen van een ORDB in SQL heeft. Voor elk supertype dient de tabel object_types een keer geïnstantieerd te worden. Een voorbeeldversie waarbij het gevraagde type twee supertypen heeft, luidt als volgt:
select objects.uid, objects.name from objects, /*1 instantiation per supertype*/ object_types as type1, object_types as type2, object_types as type3 where objects.object_type = type1.uid and objects.uid = <currentType> and ( /* check validity of object */ objects.date_start = NULL or objects.date_start = '0000-00-00' or objects.date_end = NULL or objects.date_end = '0000-00-00' or ( current_date >= objects.date_start and current_date <= objects.date_end ) ) and /*check validity of types */ type1.active <> 'N' and (type2.uid = type1.supertype and type2.active <> 'N') and (type3.uid = type2.supertype and type3.active <> 'N')
Om te komen tot deze query moeten we een standaardquery met een lijst supertypen combineren. De eerste stap daartoe is het bepalen van het aantal supertypen. Er vanuit gaande dat het indexnummer van het gevraagde type zich in $currentType bevindt, is dit in PHP de snelste manier om het aantal supertypes te vinden, met behulp van de beschreven functie find_supertypes(): $parents = find_supertypes ('object_types', $currentType, ''); $parentsAsArray = explode (",", $parents); $numberOfParents = sizeof ($parentsAsArray) - 1;
Vervolgens kunnen we dit aantal gebruiken door met een for-loop de twee variabele delen van de query te genereren: for ($counter = 1; $counter <= $numberOfParents; $counter++) { $next = $counter + 1; $tableInstantiations = $tableInstantiations . "object_types as type$next, "; $tableChecks = $tableChecks . "(type$next.uid = type$counter.supertype and type$next.active <> 'N') and "; } $tableInstantiations = substr ($tableInstantiations, 0, -2); remove last comma and space $tableChecks = substr ($tableChecks, 0, -4); remove last `and'
// //
35
qbe4or
De query zelf bouwen we daarna als volgt op (de scriptvariabelen met daarin de hiervoor opgebouwde codedelen zijn vet afgedrukt): $query = " select objects.uid, objects.name from objects, object_types as type1, $tableInstantiations where objects.object_type = type1.uid and objects.uid = $currentType and ( objects.date_start = NULL or objects.date_start = '0000-00-00' or objects.date_end = NULL or objects.date_end = '0000-00-00' or ( current_date >= objects.date_start and current_date <= objects.date_end ) ) and type1.active != 'N' and $tableChecks";
Deze methode van query-opbouw laat zien dat het mogelijk is om ook de hele geldigheids-controle in elke query in te bouwen, simpelweg door een variabele te maken waarin de benodigde MySQL-code staat, en deze in de query te verwerken. Bovenstaande code controleert het object met uid $currentType zelf en al zijn supertypen op geldigheid. Retourneert hij een uid en een name, dan is het gezochte object geldig. Hij zal geheel of gedeeltelijk in elke query moeten terugkomen, of, als het een serie queries betreft waartussen er niets in de database verandert, in de eerste daarvan. Er zijn ook gevallen waarin er niet getest hoeft te worden op de validiteit van supertypen. Het hierboven beschreven geval heeft als uitgangspunt een willekeurig object in de database. Een zoekopdracht, zoals verkregen door qbe4or, zal echter nooit objecten opleveren uit een niet-geldige klasse. Het is dus onmogelijk dat naar de attributen en associaties daarvan gezocht moet worden.
6.5 Nut en bruikbaarheid van MySQL-variabelen bij OR MySQL beschikt over een mechanisme dat voorziet in het bijhouden van tussentijdse resultaten voor later gebruik binnen dezelfde thread, in de vorm van zogenaamde user variables.52 Dit houdt in dat zolang een gebruikssessie bestaat integer-, real- en string-waarden, verkregen in een query, kunnen worden opgeslagen in variabelen met een naam, beginnend met een @-teken. In een latere query van dezelfde sessie, kunnen deze waarden worden opgevraagd. De waarden zijn niet op te vragen buiten de query, anders dan door een aparte query voor dat doel. Ze zijn dus specifiek voor intern gebruik binnen MySQL bedoeld. Dit lijkt op het eerste gezicht nuttig voor het bevragen van ORDBs, omdat een antwoord vaak niet in een enkele query gevonden kan worden. De resultaten van een query zijn soms alleen nodig in de volgende query, en niet in het script dat de queries aan de engine heeft doorgegeven. Variabelen kunnen echter slechts worden gebruikt in de expressiegedeelten van een query, waar niet expliciet een integer nodig is. Delen querycode opnemen in een variabele is dus niet mogelijk, ook omdat ook een stringwaarde van een variabele niet als code wordt geïnterpreteerd. set @temp=uid; select @temp from objects levert een kolom op 52
36
Lenz, DuBois en Hinz (ed.), MySQL Technical Reference for Version 4.1.1-alpha, 381
6. Het bevragen van een ORDB in SQL met de tekst `uid', en niet de uids van de objecten.
6.6 Het opbouwen van de tabel Voor het opbouwen van een voorbeeldtabel in HTML die verticaal alle rots- en gasplaneten bevat, en horizontaal alle toegepaste attributen, is een PHP-script nodig dat een query genereert, die deze informatie uit de database haalt en dit omzet naar de gevraagde vorm in HTML. Als we alles uit de vorige vijf paragrafen combineren krijgen we de onderstaande query. Hij levert alle attribuut-informatie over alle geldige planeten in de database, in drie kolommen: de eerste bevat de naam van de planeet, de tweede de naam van het attribuut, de derde de waarde. select objects.name as object, attrib_types.name as attrib_type, attrib_vals.value from objects, attrib_vals, attrib_types, /*1 instantiation per supertype for object type validity-check*/ object_types as type1, object_types as type2, object_types as type3 where /* relations */ type1.uid = objects.object_type and objects.uid = attrib_vals.object and attrib_vals.attrib_type = attrib_types.uid and /* subtypes */ (type1.uid = 7 or type1.uid = 8 or type1.uid = 4) and /* check validity of attributes */ ( attrib_vals.date_start = NULL or attrib_vals.date_start = '0000-00-00' or attrib_vals.date_end = NULL or attrib_vals.date_end = '0000-00-00' or ( current_date >= attrib_vals.date_start and current_date <= attrib_vals.date_end ) ) and /* check validity of object */ ( objects.date_start = NULL or objects.date_start = '0000-00-00' or objects.date_end = NULL or objects.date_end = '0000-00-00' or ( current_date >= objects.date_start and current_date <= objects.date_end ) )
37
qbe4or and /* check validity of attribute types */ attrib_types.active != 'N' and /*check validity of object types */ type1.active <> 'N' and (type2.uid = type1.supertype and type2.active <> 'N') and (type3.uid = type2.supertype and type3.active <> 'N') order by object
Het grootste deel van de code gaat over het controleren van de geldigheid van de te tonen records. Zoals aan het einde van paragraaf 4.2 uitgelegd hoeft er niet gezocht te worden naar de supertypen van het object voor de overerving, aangezien in de tabel attrib_vals alle toegepaste objecten een verwijzing naar het object bevatten, of hun type nu toegepast is op het objecttype van het object zelf, of op een van zijn supertypen.
Afbeelding 8. Tabel met geldende objecten van een type en zijn subtypen, met eigen en overerfde attributen
Om tot deze query te komen, is een PHP-script nodig dat aan de hand van de uid van een bekend objecttype, in het geval van dit voorbeeld '4' van 'planeet', deze code genereert, op de in de vorige pagina's beschreven wijze. Het volledige script dat dit doet is in dit document opgenomen als bijlage 2. Voor het genoemde voorbeeld uit de testdatabase ziet zo'n tabel er in qbe4or eruit als afbeelding 3.
38
6. Het bevragen van een ORDB in SQL
6.7 Associaties van een bekend object 6.7.1 Het tonen van associaties en hun attributen De associaties van een object kunnen niet of moeilijk in de hierboven beschreven tabel worden opgenomen, omdat het daarbij vaak om een-op-veel relaties gaat. Om een voorbeeld uit de testdatabase te halen: een associatie tussen een `planet' en een `moon' heet `is orbitted by' gezien vanuit het objecttype `planet' en `orbits' gezien vanuit het objecttype `moon'. In de meeste gevallen komt deze associatie per planeet meerdere keren voor, omdat de planeet wordt vergezeld van meerdere manen. In het geval van Mars, dat maar twee manen heeft, is het wel mogelijk om beide naast elkaar in kolommen te zetten, maar een planeet als Jupiter heeft veel meer manen, om nog over andere associaties te zwijgen. De testdatabase is bovendien een zeer kleine database. We kunnen er daarom vanuit gaan dat het aantal associaties van een enkel object in een werkelijke database nog veel groter is. Deze alle te tonen wordt onverstandig, zeker als het aantal attributen ook groot is. Het is niet goed om teveel informatie op een enkel scherm aan de gebruiker voor te schotelen. Monitoren hebben een beperkt oplossend vermogen, letters hebben een minimumgrootte waarbij ze nog leesbaar zijn en horizontaal of verticaal scrollen om de rest van het scherm tevoorschijn te halen is onprettig53. Er zijn ook associaties die een-op-een relaties voorstellen. In de testdatabase is bijvoorbeeld opgenomen dat enkele planeten een magnetisch veld hebben. Aangezien deze associatie ook eigen attributen heeft is dit niet als een attribuut, maar als een associatie gedefinieerd. Het is dus mogelijk om deze enkelvoudige associaties eruit te filteren en deze wel op te nemen in de tabel. Omdat sommige associaties, zoals die van de manen, bij sommige objecten enkelvoudig zijn en bij een andere meervoudig, kunnen die daardoor ook niet getoond worden. De winst die dit oplevert wordt daardoor marginaal. De meeste associaties zijn namelijk niet enkelvoudig. Ook kan het zijn dat we helemaal niet geïnteresseerd zijn in de associatie zelf maar in een attribuut daarvan. Een voorbeeld uit de testdatabase is de associatie tussen planeet en zonnestelsel. Alle planeten bevinden zich in het Aardse zonnestelsel ('Terran solar system'). Wat per object verschillend is aan die associatie is de rangorde daarin, gedefinieerd als een attribuut. Mercurius, die het dichtst bij de zon staat is nummer een, Pluto nummer negen. Bij deze associatie gaat het om slechts één attribuut, maar het kan heel goed zijn dat er bij een andere associatie veel meer zijn. Meestal zullen we echter zowel geïnteresseerd zijn in de associatie zelf als in zijn attributen. Het is ondoenlijk om bij elke enkelvoudige associatie eerst te bepalen wat er interessant is, om vervolgens vele attributen te tonen. Er is een betere manier om alle associaties die op een object van toepassing zijn te tonen. Men kan de gebruiker van de interface de mogelijkheid te geven een enkel object uit de tabel te kiezen, waarna hij een scherm gepresenteerd krijgt waarop de associaties vermeld zijn. Op dit scherm kunnen ook nogmaals de attributen en hun waarden worden getoond, zodat alle in de database beschikbare informatie over het gevraagde object op dit scherm vermeld wordt. Dit scherm ziet er voor het object `Earth' in qbe4or uit als in afbeelding 9. Aangezien het aantal attributen per associatie zoals gezegd groot kan zijn, en, eveneens zoals gezegd, de hoeveel tegelijkertijd getoonde informatie beperkt gehouden dient te worden, horen deze attributen niet op dit scherm thuis, maar moeten ze met een enkele klik op de betreffende associatie te bereiken zijn in een eigen scherm. Hiervoor moeten de objecten in de tabel aan te klikken zijn en over een link naar een URL beschikken waarin de uid van het gekozen object staat. Een opdracht tot het verkrijgen van deze informatie dient dus nog aan de query in paragraaf 6.6 te worden toegevoegd, en wel als objects.uid. De resultaatset bestaat daardoor dus uit vier kolommen.
53
Een aardige site over de do's & don'ts van webdesign is http://www.webpagesthatsuck.com.
39
qbe4or
Afbeelding 9. Detailscherm voor voorbeeldobject `Earth' met geldende attributen en associaties, direct en overerfd
6.7.2 De query De SQL-query die moet zorgen voor de af te beelden associaties, zonder hun attributen dus, is de meest complexe uit qbe4or. Dat komt ten eerste doordat elke associatie een verbinding is tussen twee objecten. Dat een associatie altijd wordt gedefinieerd vanuit een van de beide objecten naar het andere, het tweede object, toe, betekent dat er allereerst gezocht moet worden naar de eigen associaties van het gevraagde object, en vervolgens naar die associaties waarbij het gevraagde object het tweede object is, datgene waarnaar verwezen wordt. Dit wordt gedaan door een union van twee queries, een in de ene richting, en de andere in de andere richting. In principe gaat dat als volgt: (select assocs.uid, assoc_names.name1 as association, objects.uid, objects.name as object, ... from assocs, assoc_names, assoc_types, objects, ... where assoc_types.uid = assocs.assoc_type and assoc_types.names = assoc_names.uid and objects.uid = assocs.object2 and
40
6. Het bevragen van een ORDB in SQL assocs.user = users.uid and object1 = 8 and ( ... ) union (select assocs.uid, assoc_names.name2, objects.uid, objects.name, ... from assocs, assoc_names, assoc_types, objects, ... where assoc_types.uid = assocs.assoc_type and assoc_types.names = assoc_names.uid and objects.uid = assocs.object1 and assocs.user = users.uid and object2 = 8 and ( ... ) order by association
Ik heb voor dit voorbeeld de geldigheidscontroles en kolommen voor datum- en user-info weggelaten. Deze query levert alle associaties op van object `Earth'. Het eerste gedeelte, voor union levert in de huidige toestand van de testdatabase twee associaties op die gedefinieerd zijn met `Earth' als eerste object, en het tweede deel levert nog een extra associatie, die gedefinieerd is met het object `Sun' als eerste object en `Earth' als tweede. In de query is dit terug te vinden aan de hand van de uid van `Earth', `8', dat in het eerste deel vergeleken wordt met het veld object1 in de tabel assocs en in het tweede deel met het veld object2 in diezelfde tabel. Ten tweede wordt de query nog complexer omdat de geldigheid moet worden gecontroleerd van zowel elke associatie en zijn type, als van de beide objecten, hun typen en supertypen. Dit alles kan gedaan worden volgens de van de attributen bekende methode. Dat het aantal supertypen waarvan de geldigheid getest moet worden per tweede object mogelijkerwijs verschilt zou een probleem opleveren als we niet zouden testen op het niet voorkomen van `N' maar bijvoorbeeld op het wel voorkomen van 'Y' in het active-veld van de typen. De vergelijking x != 'N' levert namelijk FALSE op in de gevallen dat x bestaat maar geen N inhoudt, en indien x niet bestaat, terwijl de vergelijking x == 'Y' slechts TRUE oplevert indien x bestaat en hij Y inhoudt. De eerste vergelijking, met als uitkomst FALSE, is wat we dus willen hebben om een object geldig te verklaren. Deze test moet worden uitgevoerd op alle supertypen van het betreffende type. Net als in paragraaf 6.4 wordt ook hierbij de correcte unificatie van objecten door MySQL automatisch gemaakt zolang het aantal unificaties in de MySQL-query correct wordt aangegeven. De oplossing is dus ook hier uit te zoeken op hoeveel supertypen er maximaal gezocht moet worden. De wijze waarop dat het snelste via bestaande MySQL- en PHP-mechanismen gebeuren kan is in de genoemde paragraaf beschreven.
6.8 Conclusie Zoals eerder aangegeven in hoofdstuk vier is het bevragen van een ORDB veel ingewikkelder dan het 41
qbe4or bevragen van een traditioneel-relationele database. Dit is het gevolg van de grotere mate van abstractie. Veel meer betekenis wordt vastgelegd in de vorm van associaties, en niet in de vorm van velden. Het blijkt echter mogelijk om met, zij het vrij grote, SQL-queries dezelfde gegevens uit een ORDB te halen als in een traditioneel-relationele database. Om dit dynamisch te laten gebeuren is het echter het beste om delen van de query door een scripttaal te laten opstellen. In een onvolledige standaardquery kan deze scripttaal de missende elementen invullen die het onderscheid maken tussen de verschillende objecten in de database.
42
7. qbe4or
7. qbe4or
7.1 Het systeem Het systeem van voorbeeldtabellen kan bij OR databases niet zonder meer worden toegepast. QBE is bedacht en in verregaande mate ontwikkeld in een tijd dat OR nog niet bestond. Het gaat er vanuit dat gegevens netjes bij elkaar in eenvoudige twee-dimensionale tabellen zijn ondergebracht, terwijl, zoals beschreven in hoofdstukken drie en vier, dat bij OR niet het geval is. Aangezien QBE als interface hierop berust moet er dus een manier gevonden worden om de voorbeeldtabellen uit de database alsnog te construeren. Een dergelijke voorbeeldtabel moet dus een tabel zijn met als meest linker kop een typenaam, en daarnaast als overige kolommen attribuutnamen. De zoekvoorwaarden in die kolommen, zoals die volgens het QBE-model gespecificeerd moeten kunnen worden, zijn dus respectievelijk in de eerste kolom namen van het betreffende objecttype en in de overige kolommen waarden die door de bijbehorende attributen kunnen worden aangenomen. Analoog daaraan moet de resultaatset van de zoekopdracht eveneens worden geretourneerd in de vorm van een eenvoudige twee-dimensionale tabel, zoals geformuleerd in de doelstellingen in hoofdstuk een. Deze tabel heeft precies dezelfde kolomnamen als de voor de queryforms gebruikte voorbeeldtabel, en bevat in de eerste kolom alle objecten die aan de gespecificeerde eigenschappen voldoen, en in de overige kolommen de bijbehorende attribuutwaarden. In paragraaf 3.3 is geconcludeerd dat de door de gebruiker ingevoerde QBE-opdrachten als filters werken, en een tabel zonder deze opdrachten een volledige resultaatset moet retourneren. Dit is het geval in de oorspronkelijke situatie, waarin de gebruiker voor het eerst de tabel te zien krijgt. Het weergavescherm verschilt dus alleen van het queryscherm wanneer de gebruiker filters invoert of verwijdert. Dit is ook in overeenstemming met de conclusie uit paragraaf 3.4 die bepaalt dat het zoveel mogelijk overeenkomen van voorbeeldtabel en resultaattabel van groot belang is. Dat QBE oorspronkelijk werd ontworpen voor traditioneel-relationele databases betekent dat een QBEinterface specifiek voor een enkele tabel wordt gebouwd. Bij een ORDB bestaan die tabellen niet en is de gezochte informatie verspreid door de gehele database terug te vinden. Bovendien is het aantal mogelijke verschillende QBE-interfaces bij een ORDB, als men de redenering in bovenstaande paragrafen volgt, even groot als het aantal in de database aanwezige objecttypen. De interfaces moeten dus dynamisch worden opgebouwd. In hoofdstuk zes leg ik uit welke moeilijkheden hierbij komen kijken, en hoe dit met behulp van PHP en MySQL bereikt kan worden voor een enkel objecttype.
7.1.1 Alleen een-op-een-relaties Attributen in een ORDB zijn altijd een-op-een-relaties, zoals uitgelegd in paragraaf 4.2. Associaties zijn dat niet, en kunnen dus niet in een eenvoudige twee-dimensionale tabel worden weergegeven. Dit is echter een voorwaarde voor QBE. Hoewel er interfaces denkbaar zijn die het zoeken op associaties in een ORDB mogelijk maken, is om die reden het QBE-concept daarvoor niet geschikt. Er zijn interfaces denkbaar waarin een-op-veel-relaties door middel van geneste tabellen zichtbaar gemaakt kunnen worden binnen velden of rijen van een normale twee-dimensionale tabel. Het opstellen van een query in een dergelijke interface zou echter een grote mate van deskundigheid van de kant van de gebruiker 43
qbe4or vereisen. Zoals al geconcludeerd was in hoofdstuk twee, is het van belang een interface zo eenvoudig mogelijk te houden. De resultaattabel van de QBE-interface kan evenwel een mechanisme bevatten dat de associaties van de gevonden objecten toont. In qbe4or heb ik dat eveneens verwerkt door de objectnamen in de resultaattabel van hyperlinks naar een detailpagina over het betreffende object te voorzien. Men kan zich bovendien voorstellen dat in een praktijksituatie de lijst met toegepaste associaties op een bepaald object zeer lang is. In dat geval kan er op de tabel waarin in deze in het detailscherm getoond worden zeer goed een QBE-interface worden aangebracht, aangezien deze tabel wel altijd twee-dimensionaal is. In qbe4or heb ik dat gedaan, zoals te zien op de onderstaande schermafbeelding.
Afbeelding 10. Objectdetailscherm met QBE-functionaliteit voor het zoeken naar attributen en associaties.
7.1.2 De navigatieboom Het is in principe mogelijk om alle attributen uit de gehele database naast elkaar bovenaan de voorbeeldtabel 44
7. qbe4or te zetten. De attribuutwaarden die de eigenschappen van de gezochte objecten voorstellen kunnen dan worden ingevuld in de betreffende kolommen, waardoor een query wordt geformuleerd. Deze zoekopdracht kan op dezelfde manier een resultaatset retourneren waarbij van alle gevonden objecten alle attribuutwaarden verschijnen in de juiste kolommen. Het probleem dat dit oplevert is echter dat zelfs bij de testdatabase dit tabellen met teveel kolommen gaat opleveren, en bij een database uit de praktijk kan aangenomen worden dat dat niet minder het geval is. De gebruiker moet daarom de mogelijkheid krijgen vooraf aan te geven wat het type object is dat hij zoekt. Er kan vanuit worden gegaan dat hij dat weet. Immers, als hij zoekt naar alle planeten van een bepaald type, wordt hem gevraagd te zeggen dat hij planeten zoekt. Als hij bijvoorbeeld zoekt naar alle rode planeten, moet hij aangeven dat hij een planeet zoekt. Wel moet de mogelijkheid worden opengehouden dat een gebruiker naar objecten van meerdere typen tegelijk kan zoeken. Een gebruiker kan bijvoorbeeld alle rode hemellichamen willen zoeken. In dat geval wil hij, om bij het voorbeeld te blijven, niet alleen de planeten, maar ook bijvoorbeeld de manen zien. Op planeten en manen zijn gedeeltelijk dezelfde, en gedeeltelijk andere attributen van toepassing. Hier moet dus een tabel gecreëerd worden die kolommen bevat voor het totaal van hun attributen. Als een attribuut van toepassing is op beide typen, dan is daar uiteraard maar een kolom voor nodig. Om dit te bewerkstelligen moet de gebruiker de mogelijkheid hebben om tussen de verschillende dynamisch opgebouwde query-interfaceschermen te navigeren. QBE voorziet daar niet in. Aangezien de relatie tussen objecten en hun super- en subtypen hiërarchisch van aard is, is een zoekboom die de gebruiker in- en uit kan klappen, zoals we die ook zagen bij QBT, zeer geschikt. De gebruiker moet hiermee als het ware kunnen inen uitzoomen op objecttypen, waarbij het aantal en soort attributen als gevolg daarvan verandert. Op een objecttype zijn, zoals uitgelegd in hoofdstuk vier, van toepassing die attributen die er direct op van toepassing zijn, plus degene die hij overerft van zijn supertypen. Echter, om de gebruiker de gelegenheid te geven te zoeken naar alle subtypen van het door hem geselecteerde type, is het noodzakelijk dat hij ook daarvoor voorwaarden kan specificeren. Het resultaat is dus dat bij elk objecttype er kolommen in de zoekinterface moeten verschijnen voor de attributen van alle supertypen én alle subtypen. Hiervoor zijn twee mogelijke oplossingen: 1. Voor elk objecttype worden slechts de kolommen getoond voor de eigen attributen en van zijn subtypen, en de query wordt hiertoe beperkt. Het overschakelen naar een ander objecttype met het bijbehorende queryscherm gebeurt met behulp van de navigatieboom, wat betekent dat daar een nieuwe query kan worden ingevuld die volledig los staat van de vorige. De resultaatset zal slechts treffers bevatten van het gekozen objecttype en zijn subtypen. Dit behoudt de eenvoud van QBE en betekent dat de gebruiker zijn query in een enkele oogopslag kan overzien. De navigatieboom is bovendien niet nodig tijdens het formuleren van de query. 2. Voor elk objecttype worden slechts de kolommen getoond voor die attributen die direct van toepassing zijn op dat type. Om een volledige query te formuleren moet de gebruiker met behulp van de navigatieboom heen- en weerschakelen tussen de verschillende schermen. qbe4or moet de ingevulde waarden in elk scherm onthouden. Zodra in elk scherm de voorwaarden die tezamen de query vormen zijn ingevuld moet de opdracht worden gegeven tot het uitvoeren ervan. Het heen- en weerschakelen kan vervelend zijn, en de gebruiker loopt de kans het overzicht snel te verliezen als hij zijn query niet in een enkele oogopslag kan zien. Mijn voorkeur gaat uit naar de eerste oplossing , in overeenstemming met de conclusie uit paragraaf 3.4 dat de query tijdens het formuleren ervan constant in zijn geheel zichtbaar moet zijn. Dat de resultaatset beperkt wordt tot een deel van de database is niet zo'n nadeel als op het eerste gezicht lijkt. Ik grijp terug naar het laatste voorbeeld om dat te verduidelijken. Stel, de gebruiker is op zoek naar alle rode hemellichamen. Hij selecteert in de navigatieboom het type hemellichaam en krijgt een interface waarin hij onder andere bij het attribuut `kleur', `rood' kan invullen. De resultaatset levert nu alle rode hemellichamen op: planeten, manen, asteroïden, etc. Dat hij geen kunstmatige structuren, of nevels, te zien krijgt die rood zijn, is logisch, want daarom werd niet gevraagd. Deze implementatie heeft, net als in QBT, het effect van inzoomen voor meer precisie. Het is nog steeds 45
qbe4or mogelijk om een groot deel of zelfs de hele database te laten doorzoeken, door een objecttype in de navigatieboom te selecteren dat bovenin de hiërarchie staat. Voor alle attributen van alle subtypen worden immers kolommen getoond. De aan de gebruiker aangeboden interface zal evenwel minder gebruiksvriendelijk zijn dan wanneer de gebruiker qbe4or exacter laat weten naar welk type het is dat hij zoekt.
7.1.2 Performance `It is easy to ignore the need for good performance (...). However, running a small test database is different from running in a production environment.'54 Voor qbe4or maak ik gebruik van een vrij kleine testdatabase. Daardoor is het moeilijk in te schatten hoe snel het systeem zal presteren bij grote queries. Het is, in overeenstemming met in paragraaf 2.1 getrokken conclusies, van belang om de performance altijd zo hoog mogelijk te houden. De in paragraaf 1.4.1., de `nice-to-haves', onder punt drie genoemde cache, is een geschikt middel hiervoor, maar hoeft niet in qbe4or te worden ingebouwd, aangezien deze al in MySQL aanwezig is. `The query cache stores the text of a SELECT query together with the corresponding result that was sent to the client. If an identical query is later received, the server will retrieve the results from the query cache rather than parsing and executing the same query again.'55 `Some tools, (...) are still bringing the full result set of an ad hoc queries (sic.) back to the user's PC prior to displaying anything. This is acceptable for many queries (even on large databases). But if users are routinely bringing back large result sets, then a tool that first downloads all information to the client will not work.'56 De functie show57 onthoudt voortdurend de oorspronkelijke MySQL-query waarvan hij de resultaten moet tonen, en past deze zelf aan alvorens deze aan de database-engine te geven. De resultaatset bevat daardoor slechts het aantal rijen dat er op een scherm past, meestal acht tot vijftien in getal. Bovendien kunnen op die manier door de gebruiker aangegeven sortering en QBE-filters al door de database-engine worden afgehandeld, wat veel sneller gaat dan de volledige resultaatset op te vragen, in een array te zetten en vervolgens te kijken waar de gebruiker om gevraagd heeft.
7.2 Het algoritme voor de interface Het algoritme voor het onderzoeken van het objecttype en aanbieden van interface op het volgende neer: 1. Toon de navigatieboom en wacht tot de gebruiker een objecttype uitkiest. 2. Onderzoek het gekozen objecttype op instanties, attributen, hun waarden en datatypen, zet de gevonden gegevens in een cachetabel met verticaal de instanties en horizontaal de attribuuttypen. 3. Raadpleeg deze tabel en toon hem rechts naast de navigatieboom, gealfabetiseerd op objectnaam. Als de resultaatset te lang is, toon dan alleen de eerste pagina, en biedt een bladermechanisme aan. Toon direct onder de kolomkoppen de invoervelden voor de QBE-filters. Als de gebruiker sinds de laatste keer dat hij van objecttype wisselde filters heeft aangebracht moeten deze in die velden getoond worden. Wacht opnieuw op de gebruiker. 4. Als de gebruiker een ander objecttype uit de boom kiest, ga dan verder bij punt twee. Als hij de sortering verandert of naar een eventuele andere pagina bladert, ga dan verder bij punt drie. Als hij filters invoert of eventueel aanwezige filters wijzigt of verwijdert moeten deze worden doorgevoerd in de resultaattabel alvorens eveneens verder te gaan bij punt drie. Als hij op de naam van een object klikt moet hij worden doorgestuurd naar een pagina die hem de details van dat object toont.
54 55 56 57
46
Dorsey, `Ad Hoc Query Tools: Do They Really Support Ad Hoc Querying?' Lenz, DuBois en Hinz (ed.), MySQL Technical Reference for Version 4.1.1-alpha, 570 Dorsey, `Ad Hoc Query Tools' De code voor deze en aanverwante functies is opgenomen in bijlage 10.6.
7. qbe4or
7.3 De navigatieboom De genoemde navigatieboom komt aan de linkerkant van het scherm te staan. De code hiervoor heb ik opgenomen als bijlagen 10.3 en 10.4. De boom toont in zijn oorspronkelijke staat onder elkaar alleen die objecttypen uit de database die geldig zijn en bovenaan de hiërarchie staan, dat wil zeggen die geen supertypen hebben. Om de metafoor van de boom vol te houden zijn dit de takken die zich aan de stam bevinden. Links van elk type staat een pijltje dat naar rechts wijst. Wordt daarop geklikt, dan worden direct onder dat type, iets ingesprongen, al zijn eigen subtypen getoond. Het pijltje wijst nu naar beneden ten teken dat de tak is uitgeklapt. Ook de subtypen zijn elk van een pijltje voorzien zodat ook deze takken kunnen worden uitgeklapt. Een klik op een naar beneden wijzend pijltje klapt de tak weer in, terwijl een klik op een van de getoonde typen een QBE-tabel rechts van de boom toont.
7.4 De QBE-tabel Deze tabel bevat verticaal alle geldige objecten van het in de boom geselecteerde type en zijn geldige subtypen, en horizontaal alle geldige attributen die op deze typen van toepassing zijn, met de correcte waarden. Direct onder de kolomkoppen staan invoervelden waarin de gebruiker zijn QBE-query kan formuleren door per kolom filters aan te brengen, zoals beschreven door Zloof. Onderaan de tabel bevinden zich twee knoppen voor het instellen en wissen van de aangebrachte filters. De namen van de objecten kunnen worden aangeklikt voor het in paragraaf 7.1.1 genoemde detailscherm. De koppen van de kolommen kunnen worden aangeklikt om de tabel op die kolom te alfabetiseren. Een tweede klik op dezelfde kolom draait de alfabetiseervolgorde om. Als de tabel meer dan vijftien objecten bevat worden deze in pagina's van vijftien objecten getoond. Onderaan de tabel bevindt zich een melding naar welke pagina de gebruiker kijkt en hoeveel pagina's er in totaal zijn. Daaronder bevindt zich wanneer nodig een bladermechanisme. De hiervoor benodigde code heb ik als bijlagen 10.2 en 10.6 opgenomen. Onderstaande afbeelding toont als voorbeeld een scherm aan de hand van de testdatabase.
47
qbe4or
Afbeelding 11. Het QBE-scherm: links de navigatieboom, rechts de tabel.
Op de deze afbeelding heeft de gebruiker gezocht naar alle planeten met een gemiddelde dichtheid van meer dan twee gram per kubieke centimeter en een kleinere massa dan die van de Aarde. De resultaatset is door de gebruiker oplopend gesorteerd op de ontsnappingssnelheid.
7.5 De filters Voor het specificeren van de QBE-filters gebruik ik enkele ingebouwde MySQL-filters. Een filter begint met een operator, zoals =, > of !=. Daarna volgt een waardebeschrijving, hieronder aangegeven door x. Waarden voor niet-numerieke kolommen moeten tussen enkele aanhalingstekens staan. Bij like kunnen %-tekens als wildcard gebruikt worden. Datums kunnen worden gefilterd met operatoren die verder alleen van toepassing zijn op numerieke velden, maar moeten wel tussen aanhalingstekens worden geplaatst. Tussen de operator en de waardebeschrijving mag een spatie worden geplaatst, maar deze wordt door qbe4or verwijderd. 1. ='x' (is gelijk aan x): het attribuut in deze kolom van de te vinden objecten is gelijk aan de zoekterm. Deze is van toepassing op alle datatypen. Bij numerieke typen kunnen de aanhalingstekens weggelaten worden. 2. !='x' (ongelijk aan x): logische operator die van toepassing is op alle attributen. 3. like'%x%' (lijkt op x): x komt exact voor in de attribuut, maar ervoor en erachter kunnen extra strings staan, hier aangeduid met de %-tekens. Deze operator is slechts van toepassing op niet-numerieke waarden. 4. >x, <x (groter of kleiner dan x): deze operator is slechts van toepassing op numerieke en datum-velden. Bij de laatste dienen aanhalingstekens voor en achter x geplaatst te worden. De betekenis van een kleinere en een grotere datum dan x is respectievelijk een datum voor of na x. 48
7. qbe4or 5. >=x, <=x (groter of gelijk aan of kleiner of gelijk aan x): deze operator is slechts van toepassing op numerieke en datum-velden, waarbij dezelfde opmerkingen gelden als bij het punt hierboven.
7.6 Conclusie Om automatisch dynamische QBE-forms te creeëren voor een ORDB moet er zorg voor worden gedragen dat de complexiteit van het onderliggende datamodel niet weerspiegeld wordt in een toenemende complexiteit van de interface. QBE is ontworpen om gebruikers een eenvoudige maar krachtige zoekinterface te bieden. Uit onderzoek is gebleken hoe eenvoudig dit moet zijn. Dit betekent dat de kracht van het ORDB-concept niet tot in het oneindige kan worden uitgebuit middels QBE. Het belangrijkste effect hiervan is dat het niet mogelijk s om middels QBE te zoeken op associaties. Wel is het mogelijk te zoeken op groepen objecten en hiërarchieën. Dit wordt bereikt door middel van een navigatieboom.
49
8. Conclusies
8. Conclusies
8.1 Algemene conclusies Bij het ontwerpen van een QBE-interface voor een object-relationele database loopt men al snel aan tegen de complexiteit van het datamodel, dat ook al de oorspronkelijke reden was voor het bouwen van het systeem. Deze complexiteit zorgt ervoor dat er keuzes gemaakt moeten worden tussen wat wel en niet kan worden getoond op het queryscherm, en dus tussen waarop wel en niet gezocht kan worden. Dit heeft directe gevolgen voor de functionaliteit van het systeem. De kracht van OR, en OO, is onder andere gelegen in de eindeloze mogelijkheden tot het flexibel uitbreiden van de database. In de testdatabase hebben objecten attributen en associaties, en hebben associaties op hun beurt weer attributen. Het was in de database technisch bijzonder eenvoudig geweest om attributen van eigen attributen te kunnen laten voorzien. Een enkele extra verwijzende sleutel in de attribuuttypentabel had daarvoor volstaan. Voor een dynamisch zoeksysteem als qbe4or brengt dit echter grote interfacetechnische en ergonomische moeilijkheden met zich mee. Het probleem is dat een eindeloze nesting van tabellen niet in een enkel twee-dimensionaal scherm of venster getoond kan worden, en dat het systeem, immers gebaseerd op QBE, zijn eenvoud en comfort verliest zodra hij ingewikkeldere, onvermijdbaar uit meerdere schermen bestaande, formulieren aan de gebruiker aanbiedt. QBE werd ontwikkeld in de late jaren '70, in een tijd dat computers ternauwernood over de rekenkracht beschikten die nodig was voor de implementatie van relationele databasemodellen. Met het verstrijken van drie decennia zijn computersystemen krachtiger geworden, maar QBE is nog grotendeels wat het was. De grote eenvoud van het concept, inherent aan de werking van het systeem, is nog volledig intact. Dit kan iedereen dagelijks zien op vele websites en in populaire database applicaties als Microsoft Access, waar QBE wordt toegepast, vrijwel exact zoals in 1970 door Zloof beschreven in het IBM Technical Magazine van april 1977.
8.2 Problemen en oplossingen De problemen die ik tegen ben gekomen bij het ontwikkelen van de interface waren dus van een geheel andere aard dan ik van te voren had bedacht. De techniek van het vertaalproces bleek uiteindelijk algoritmisch zelfs betrekkelijk eenvoudig. De performance van qbe4or kon worden hooggehouden door MySQL een zo groot mogelijk deel van het werk te laten doen. Even belangrijk als het vinden van de gezochte informatie blijkt het snel en comfortabel zoeken te zijn. Het is daarom van groot belang om het queryscherm overzichtelijke te houden. Daarom heb ik afgezien van de mogelijkheid ook te zoeken op een-op-veel-relaties. Bovendien kan een objecttype alleen doorzocht worden op zijn eigen attributen en die van zijn subtypen. Een navigatieboom zorgt voor een mechanisme om zijn supertypen, en daarmee de hele database, te bereiken.
8.3 Gehaalde en niet-gehaalde doelstellingen In paragraaf 1.4.1 is een cachesysteem een van de genoemde extra eigenschappen, omwille van de performance van de interface. Op het eerste gezicht lijkt dit van weinig belang voor het onderzoek zelf. Als 51
qbe4or bij een grote database in een praktijksituatie echter blijkt dat het systeem onbruikbaar traag wordt, kan zelfs gesteld worden dat de doelstelling niet gehaald is, vanwege de in hoofdstuk twee getrokken conclusie dat snelheid een eigenschap is waarmee zoekinterfaces staan of vallen. MySQL beschikt vanaf versie 4.0.1 over een cachesysteem. Vandaar dat deze dus niet in qbe4or hoeft te worden ingebouwd. Het zoeken naar metadata, genoemd in paragraaf 1.4.1, kan met het browser/editor-gedeelte van qbe4or, eveneens middels een QBE-interface. Ook is het daarmee mogelijk te zoeken naar objecten aan de hand van hun metadata. Toch kan slechts ten dele worden beweerd dat dit punt verwezenlijkt is zoals in die paragraaf bedoeld werd, aangezien de gebruiker dit niet in dezelfde interface kan doen als de data-instanties. De in paragraaf 1.4 genoemde doelstellingen, het zoeken naar in de database aanwezige gegevens, het negeren van ongeldige data, en het inbouwen van het overervingprincipe zijn echter alle gehaald, zoals aangetoond in paragraaf 7.2. De hoofdvraag: `Is het mogelijk om een zoekinterface te ontwikkelen die gegevens uit een object-relationele database weet te halen, volgens het Query-By-Example (QBE) interfacemodel,' kan dus positief worden beantwoord.
52
9. Bibliografie
9. Bibliografie
1. Abiteboul, S., `Querying semi-structured data', in: Proceedings of ICDT, s.l. 1997, 1-18 2. Bouma, G., Computationele Taalkunde en Taaltechnologie, Groningen 2000 3. Campbell, R., `SQL Server 7.0 -- The Developer's Product', Access-VB-SQL Advisor Magazine (1998) (http://sqlserveradvisor.com/doc/05243, gezien: 11 jan. 2004) 4. Carroll, J., `How to do Most Queries in the Microsoft Access 2000 variant of SQL' (http://www.rsu.edu/faculty/johnnycarroll/cs3223/fa2002/Lectures/queri es_in_the_MS_Access_2000_SQL.htm, gezien: 23 okt. 2003) 5. Common Software Overview (http://www.epoline.org/pres/common/overview.htm, gezien: 24 okt. 2003) 6. Converse, J. en Park, J., PHP Bible. 2nd edition, Indianapolis 2002 7. Customer Service Call Center Helpdesk software: QBE (http://www.carpiohelpdesk.com/Features/QBE/body_qbe.htm, gezien: 23 okt. 2003) 8. Devarakonda, R.S., `Object-Relational Database Systems - The Road Ahead', ACM Crossroads Student Magazine. The ACM's First Electronic Publication (2001) (http://www.acm.org/crossroads/xrds7-3/ordbms.html, gezien: 21 okt. 2003) 9. Dorsey, P., `Ad Hoc Query Tools: Do They Really Support Ad Hoc Querying?', Infoweek (1995) (http://www.dulcian.com/magazine articles/Ad Hoc Query Tools.htm, gezien: 9 januari 2004) 10.Dorsey, P., `The Promise of the Object-Relational Paradigm', (1999) (http://www.nyoug.org/dorsey1.pdf, gezien: 22. okt. 2003) 11.Frank, M., `Esperant 3.0.', DBMS, vol. 9, nr. 2 (1996), 3612.Fussell, M. L., Foundations of Object Relational Mapping, Sunnyvale 1997 (http://www.chimu.com, gezien: 2 okt. 2003) 13.Gree, J. de, Generating Web Query Interfaces Based on Conceptual Schemas, Brussel 2001 (diss. Brussel) 14.Grimes, S., `Modeling Object/Relational Databases', DBMS, vol. 11, nr. 4 (1998), 5115.Hess, E., `Using Speech Recognition with Microsoft English Query' (http://www.microsoft.com/mind/0699/equery/equery.asp, gezien: 11 jan. 2004) 16.Hull, D., `Using Statistical Testing in the Evaluation of Retrieval Experiments', in: Research and Development in Information Retrieval, s.l. 1993, 329-338 17.Joachims, T., `Text Categorization with Support Vector Machines: Learning with Many Relevant Features', in: Proceedings of ECML-98, 10th European Conference on Machine Learning, Dortmund 53
qbe4or 1997 18.Lenz, A. DuBois, P. en Hinz, S. (ed.), MySQL Technical Reference for Version 4.1.1-alpha, 2003 19.Microsoft TechNet, Developing with English Query (http://www.microsoft.com/technet/treeview/default.asp?url=/technet/pro dtechnol/sql/reskit/sql7res/part12/sqc23.asp, gezien 3 okt. 2003) 20.Nothwest Alliance for Computational Science and Engineering (http://www.nacse.org/hsql/, gezien: 2 okt 2003) 21.Pohlmann, R. en Kraaij, W., `The effect of syntactic phrase indexing on retrieval performance for Dutch texts', in: Devroye, L. en Chrisment, C., (ed.), Proceedings of RIAO'97, s.l. 1997, 176-187 22.Sawyer, P. en Sommerville, I., `A User Interface Framework for an Object-Oriented Database System', in: Peregrinus, P., (ed.), Software Tools for User Interface Design, s.l. 1990 23.Sengupta, A. en Dillon, A., `Query By Templates: A Generalized Approach for Visual Query Formulation for Text Dominated Databases', in: Advances in Digital Libraries, s.l. 1997, 36-47 (http://citeseer.nj.nec.com/19776.html , gezien: 22 okt. 2003). 24.Speedware – Esperant: Enterprise-wide, multi-database Query and Reporting keeps your business on target. (http://bi.speedware.com/products_and_solutions/tools_suite/esperant/, gezien: 11 jan. 2004). 25.Staff, C., Overview of approaches to Multimedia Information Retrieval, Malta 2000 26.Su, L.T., `The relevance of recall and precision in user evaluation', Journal of the American Society for Information Science, 3, nr. 45 (1997), 207-217 27.Technical Architecture Framework for Information Management (TAFIM) (http://wwwlibrary.itsi.disa.mil/tafim/tafim3.0/pages/tafim_8.htm, gezien: 5 januari 2004). 28.Verity Search: The Advantages of Advanced Informattion Retrieval, 2000 29.Walnes, J., `Advanced Object-Relational mapping' (http://orionsupport.com/archive/articles/complex-or.html, gezien: 18 okt. 2003) 30.Webopedia.com, lemma Query By Example (http://www.webopedia.com/TERM/Q/query_by_example.html, gezien: 2 okt. 2003) 31.Wikipedia, The Free Encyclopedia (http://en.wikipedia.org/wiki/Objectrelational_database, gezien: 18 okt. 2003) 32.Zaiane, O., `Object-Relational Databases' (http://www.cs.sfu.ca/CC/354/zaiane/material/notes/Chapter9/node1.html, gezien: 23 okt. 2003) 33.Zloof, M.M., `Query-by-Example: a data base language', IBM Systems Journal,16, nr. 4 (1977), 324-343
54
10. Bijlagen
10. Bijlagen
Alle code in deze bijlagen is geschreven door mij voor qbe4or. De toepasbaarheid van vele van de functies is echter groter doordat het grootste deel is opgezet als een verzameling functies, onderverdeeld in een aantal bibliotheken: 1.
MySQL.inc: functies voor het vergemakkelijken van het gebruik van MySQL. Het grootste gedeelte ervan betreft de functies voor het automatisch genereren van interactieve tabellen uit een MySQL-query. Deze bevat ook de code voor de invoervelden voor de QBE-filters.
2.
Tree.inc: functies voor het tonen van een navigatieboom op basis van een een MySQL-databasetabel.
3.
Standard.inc: algemene functies.
Uit deze bibliotheken heb ik alleen de code overgenomen die voor het QBE-scherm van belang zijn. De functies die alleen het browser/editor-gedeelte van qbe4or dienen zijn niet van belang voor dit onderzoek. Om extra aan de genericiteit van de functies tegemoet te komen zijn de commentaren en variabelenamen in het Engels.
10.1 SQL: de DDL-statements van het datamodel Onderstaand DDL-script genereert de tabellen van de qbe4or-testdatabase. # # # #
MySQL Navigator Xport Database: ordb root@localhost version 29/06/03
# CREATE DATABASE ordb; # USE ordb; # # Table structure for table 'assoc_names' # # DROP TABLE IF EXISTS assoc_names; CREATE TABLE `assoc_names` ( `uid` tinyint(4) NOT NULL default '0', `name1` char(40) default NULL, `name2` char(40) default NULL, PRIMARY KEY (`uid`) ) TYPE=MyISAM; # # Table structure for table 'assoc_types' # # DROP TABLE IF EXISTS assoc_types; CREATE TABLE `assoc_types` ( `uid` int(11) NOT NULL default '0',
55
qbe4or `names` int(11) NOT NULL default '0', `object_type1` int(11) default NULL, `object_type2` int(11) default NULL, `active` char(1) default NULL, `date_cr` date default NULL, `date_lu` date default NULL, `user` int(11) default NULL, PRIMARY KEY (`uid`) ) TYPE=MyISAM; # # Table structure for table 'assocs' # # DROP TABLE IF EXISTS assocs; CREATE TABLE `assocs` ( `uid` int(11) NOT NULL default '0', `assoc_type` int(11) NOT NULL default '0', `object1` int(11) default NULL, `object2` int(11) default NULL, `date_start` date default NULL, `date_end` date default NULL, `date_cr` date default NULL, `date_lu` date default NULL, `user` int(11) default NULL, PRIMARY KEY (`uid`) ) TYPE=MyISAM; # # Table structure for table 'attrib_types' # # DROP TABLE IF EXISTS attrib_types; CREATE TABLE `attrib_types` ( `uid` int(11) NOT NULL default '0', `name` char(40) default NULL, `object_type` int(11) default NULL, `assoc_type` int(11) default NULL, `active` char(1) default NULL, `date_cr` date default NULL, `date_lu` date default NULL, `user` int(11) default NULL, PRIMARY KEY (`uid`) ) TYPE=MyISAM; # # Table structure for table 'attrib_vals' # # DROP TABLE IF EXISTS attrib_vals; CREATE TABLE `attrib_vals` ( `uid` int(11) NOT NULL default '0', `name` varchar(40) default NULL, `object` int(11) default NULL, `assoc` int(11) default NULL, `value` text, `date_start` date default NULL, `date_end` date default NULL, `date_cr` date default NULL, `date_lu` date default NULL, `user` int(11) default NULL, PRIMARY KEY (`uid`) ) TYPE=MyISAM;
56
10. Bijlagen # # Table structure for table 'object_types' # # DROP TABLE IF EXISTS object_types; CREATE TABLE `object_types` ( `uid` int(11) NOT NULL default '0', `supertype` int(11) default NULL, `name` char(40) default NULL, `active` char(1) default NULL, `date_cr` date default NULL, `date_lu` date default NULL, `user` int(11) default NULL, PRIMARY KEY (`uid`) ) TYPE=MyISAM; # # Table structure for table 'objects' # # DROP TABLE IF EXISTS objects; CREATE TABLE `objects` ( `uid` int(11) NOT NULL default '0', `object_type` int(11) NOT NULL default '0', `name` char(40) default NULL, `date_start` date default NULL, `date_end` date default NULL, `date_cr` date default NULL, `date_lu` date default NULL, `user` int(11) default NULL, PRIMARY KEY (`uid`) ) TYPE=MyISAM; # # Table structure for table 'users' # # DROP TABLE IF EXISTS users; CREATE TABLE `users` ( `uid` int(11) NOT NULL default '0', `name` char(50) NOT NULL default '', `passw` char(15) NOT NULL default '', `homepage` char(255) default '', PRIMARY KEY (`uid`) ) TYPE=MyISAM; # # Table structure for table `data_types` # # DROP TABLE IF EXISTS `data_types`; CREATE TABLE `data_types` ( `uid` int(11) NOT NULL default '0', `name` varchar(12) default NULL, PRIMARY KEY (`uid`) ) TYPE=MyISAM;
10.2 PHP: genereren van een HTML-tabel met objecten, hun attributen en QBE-invoervelden Onderstaande code genereert de pagina waarin de navigatieboom en de QBE-tabel worden geplaatst. Deze 57
qbe4or bevat ook de code waarmee het in de boom gekozen objecttype uit de database wordt onderzocht. De gevonden gegevens worden in een nieuwe cache-tabel gezet die bij elk nieuw door de gebruiker gedefinieerd QBE-filter wordt geraadpleegd. Verder bevat deze code de algemene opdrachten die elk script uit qbe4or bevat, zoals sessiebeheer, opnames van functiebibliotheken en een kop- en een voettekst in HTML.
("libs/standard.inc"); ("libs/mysql.inc"); ("libs/qbe4or.inc"); ("libs/tree.inc");
if (!isset($_SESSION['user'])) go_page ("login.html"); else $user = $_SESSION['user']; if (!isset($_SESSION['treeLayout'])) $treeLayout = init_tree(); else $treeLayout = $_SESSION ['treeLayout']; if (isset($_SESSION['tables']))
$tables = $_SESSION['tables'];
if ($command != "changeType") { if (isset($_SESSION['currentType'])) $currentType = $_SESSION['currentType']; else $currentType = 0; } connect ("root", "ordb"); html_start ("qbe", "$user[1]"); if ($command == "expandTree") $treeLayout = expand_branch ($treeLayout, $node); else if ($command == "collapseTree") $treeLayout = collapse_branch ($treeLayout, $node); else if ($command == "changeType") { // do research for new cache table: // delete existing cache table $result = mysql_query ("drop table if exists cache"); // formulate create table and research queries: $createQuery = "create table cache (uid INT"; // fetching object column name $result = mysql_query ("select name from object_types where uid=$currentType"); $row = mysql_fetch_row ($result); $createQuery = $createQuery . ", `$row[0]` VARCHAR(255)"; // generate object types part of research query $children = find_subtypes ('object_types', $currentType, ''); $objectTypes = str_replace (",", " or type1.uid = ", $children); // generate check parts of research query $parents = find_supertypes ('object_types', $currentType, ''); $objectTables = explode (",", $parents);
58
10. Bijlagen $numberOfParents = sizeof ($objectTables) - 1; $tableChecks = " and "; for ($counter = 1; $counter <= $numberOfParents; $counter++) { $next = $counter + 1; $tableInstantiations = $tableInstantiations . ", object_types as type$next"; $tableChecks = $tableChecks . "(type$next.uid = type$counter.supertype and type$next.active != 'N') and "; } $tableChecks = substr ($tableChecks, 0, -4); // remove last `and' // compose research query $researchQuery = " (select objects.uid, objects.name as object, attrib_types.name as attrib_type, attrib_vals.value, data_types.name from objects, attrib_vals, attrib_types, object_types as type1 $tableInstantiations, data_types where type1.uid = objects.object_type and objects.uid = attrib_vals.object and attrib_vals.attrib_type = attrib_types.uid and (type1.uid = $currentType $objectTypes) and ( attrib_vals.date_start = NULL or attrib_vals.date_start = '0000-00-00' or attrib_vals.date_end = NULL or attrib_vals.date_end = '0000-00-00' or ( current_date >= attrib_vals.date_start and current_date <= attrib_vals.date_end ) ) and ( objects.date_start = NULL or objects.date_start = '0000-00-00' or objects.date_end = NULL or objects.date_end = '0000-00-00' or ( current_date >= objects.date_start and current_date <= objects.date_end ) ) and attrib_types.active != 'N'
59
qbe4or and type1.active != 'N' $tableChecks and attrib_types.data_type = data_types.uid ) union (select objects.uid, objects.name as object, NULL, NULL, NULL from objects, object_types as type1 $tableInstantiations where type1.uid = objects.object_type and (type1.uid = $currentType $objectTypes) and type1.active != 'N' $tableChecks ) order by object, attrib_type"; // execute research query //echo $researchQuery; $result = mysql_query ($researchQuery); // fetch attrib type names (horiz) and use them for the create query $numberListRows = mysql_num_rows ($result); $numberColumns = 0; $columnName[0] = NULL; for ($counter = 0; $counter < $numberListRows; $counter++) { $row = mysql_fetch_row($result); $list[$counter][0] $list[$counter][1] $list[$counter][2] $list[$counter][3] $list[$counter][4]
= = = = =
$row[0]; $row[1]; $row[2]; $row[3]; $row[4];
// // // // //
object uid object attrib type attrib value data type