objektumorientált adatbázisnyelvek
DESCRIPTION
Objektumorientált adatbázisnyelvek. Objektumleíró nyelv Objektumlekérdező nyelv. Objektumelvű adatbáziskezelők. Szabványosító csoport: ODMG = Object Data Management Group. ODL = Object Description Language, mint az SQL CREATE TABLE része . - PowerPoint PPT PresentationTRANSCRIPT
1
Objektumorientált adatbázisnyelvek
Objektumleíró nyelvObjektumlekérdező nyelv
2
Objektumelvű adatbáziskezelők
Szabványosító csoport: ODMG = Object Data Management Group.
ODL = Object Description Language, mint az SQL CREATE TABLE része.
OQL = Object Query Language, az SQL-t próbálja utánozni OO keretrendszerben.
3
Keretrendszer --- 1
Az ODMG elképurlése szerint az OO-DBMS gyártok megvalósítanak egy OO nyelvet, mint a C++, olyan kiterjesztésekkel (OQL), amelyekkel a programozó zökkenőmentesen átviheti az adatokat az adatbázis és a „gazdanyelv” között.
4
Keretrendszer --- 2
Az ODL-t tartós osztályok definiálására használjuk, amelyek objektumai maradandóan tárolhatók az adatbázisban. Az ODL osztályok olyanok, mint az
egyedhalmazok bináris kapcsolatokkal és metódusokkal.
Az ODL osztálydefiníciók a kibővített OO gazdanyelv részei.
5
ODL áttekintés
Egy osztálydeklaráció tartalmazza:1. Az osztály nevét.2. Választhatóan kulcsdeklaráció(ka)t.3. Extens deklaráció = az osztály létező
objektumait tartalmazó halmaz neve.4. Elemdeklarációkat. Egy elem lehet
attribútum, kapcsolat vagy metódus.
6
Osztálydefiníciók
class <név> {<elemdeklarációk pontosvesszővel tagolt listája>
}
7
Attribútum- és kapcsolatdeklarációk
Az attribútumok (általában) osztályhoz nem kapcsolódó típusú elemek.
attribute <típus> <név>; A kapcsolatok egy objektumot egy
vagy több, azonos osztálybeli objektumhoz kapcsolják.
relationship <típus> <név>inverse <kapcsolat>;
8
Inverz kapcsolatok
Tegyük fel, hogy a C osztály R kapcsolatban áll a D osztállyal.
Ekkor a D osztálynak valamilyen S kapcsolatban kell állnia a C osztállyal.
R-nek és S-nek egymás inverzének kell lennie. Ha a d R kapcsolatban van c-vel, akkor c-
nek S kapcsolatban kell lennie d-vel
9
Példa: Attribútumok és kapcsolatok
class Kocsma {attribute string név;attribute string cím;relationship Set<Sör> árul inverse Sör::kapható;
}class Sör {
attribute string név;attribute string gyártó;relationship Set<Kocsma> kapható inverse Kocsma::árul;
}
Az árul kapcsolat típusaSör objektumok halmaza.
A :: operátor összekapcsoljaa jobb oldalon álló nevet azazt tartalmazó környezettel,amely a bal oldalon áll.
10
Kapcsolatok típusai
Egy kapcsolat típusa lehet:1. Osztály, pl. Kocsma. Ebben az esetben
egy objektum csak egy Kocsma objektummal állhat kapcsolatban.
2. Set<Kocsma>: az objektum Kocsma objektumok halmazával van kapcsolatban.
3. Bag<Kocsma>, List<Kocsma>, Array<Kocsma>: az objektum Kocsma objektumokból álló zsákkal, listával vagy tömbbel van kapcsolatban.
11
Kapcsolatok multiplicitása
Minden ODL kapcsolat bináris. A sok-sok kapcsolatok típusa Set<…> a
kapcsolat és inverz oldalon is. A sok-egy kapcsolatok típusa Set<…>
az „egy” oldalon és csak osztály a „sok” oldalon.
Az egy-egy kapcsolatok típusa mindkét irányban az osztály.
12
Példa: Multiplicitások
class Ivó { …relationship Set<Sör> szeret inverse Sör::rajongók;relationship Sör kedvencSör inverse Sör::nagyRajongók;
}class Sör { …
relationship Set<Ivó> rajongók inverse Ivó::szeret;relationship Set<Ivó> nagyRajongók inverse Ivó::kedvencSör;
}
Sok-sok: Set<…>mindkét irányban.
Sok-egy: Set<…>csak az „egy” oldalon.
13
Másik példa multiplicitásra
class Ivó {attribute … ;relationship Ivó férj inverse feleség;relationship Ivó feleség inverse férj;relationship Set<Ivó> haverok
inverse haverok;}
férj és feleség:egy-egy kapcsolatokés egymás inverzei
haverok: sok-sok kapcsolat és a sajátinverze. Nem kell a ::, ha az inverzugyanabban az osztályban van.
14
Többirányú kapcsolat kezelése
Az ODL nem támogatja a 3- vagy többirányú kapcsolatokat.
Szimulálhatjuk a többirányú kapcsolatokat egy „kapcsoló” osztállyal, amelynek objektumai reprezentálják az összekapcsolandó objektum n-eseket.
15
Kapcsoló osztályok
Tegyük fel, hogy az X, Y és Z osztályokat akarjuk összekapcsolni R kapcsolattal.
Vegyünk fel egy C osztályt, amelynek objektumai az (x, y, z) hármasokat reprezentálják az X, Y, Z osztályokból.
Három sok-egy kapcsolatra lesz szükségünk (x, y, z)-ből x, y és z mindegyikéhez.
16
Példa: Kapcsoló osztály
Tegyük fel, hogy van Kocsma és Sör osztályunk és szeretnénk reprezentálni, hogy melyik kocsma milyen áron adja a söröket. A Kocsma és Sör közti sok-sok
kapcsolatnak nem lehet ár attribútuma, szemben az E/K modellel.
Egy megoldás: készítsünk egy Ár osztályt és egy összekapcsoló BBP osztályt, amely az egymáshoz kapcsolódó kocsmákat, söröket és árakat reprezentálja.
17
Példa, folytatás
Mivel az Ár objektumok csak számok, egy jobb megoldás:
1. Adjunk a BBP objektumokhoz egy ár attribútumot.
2. Használjunk két sok-egy kapcsolatot a BBP objektum és az általa reprezentált Kocsma és Sör objektumok között.
18
Példa, befejezés
Itt a BBP definíciója:class BBP {
attribute ár:real;relationship Kocsma aKocsma inverse Kocsma::toBBP;relationship Sör aSör inverse Beer::toBBP;
} A Kocsma és Sör osztályokat módosítsuk,
hogy mindkettőnek legyen toBBP tulajdonsága, amelyek típusa Set<BBP>.
19
Struktúrák és felsorolások
Az attribútumok lehetnek struktúrák (mint a C-ben) vagy felsorolások.
Így deklaráljuk:attribute [Struct vagy Enum] <struct
vagy enum neve> { <részletek> }<attribútum neve>;
A részletek mezőnevek és -típusok Struct-nál, konstansok listája Enum-nál.
20
Példa: Struct és Enum
class Kocsma {attribute string név;attribute Struct CímT
{int irsz, string város, string utca} cím;attribute Enum Eng
{ MINDEN, SÖR, SEMMI } engedély;relationship …
}
A struktura ésfelsorolás neve
attribútumok neve
21
Struct és Enum újrahasznosítása
Hivatkozhatunk egy Struct vagy Enum nevére másik osztálydefinícióban. Használjuk a :: operátort a forrásosztály
jelölésére. Példa:class Ivó {
attribute string név;attribute Struct Kocsma::CímT cím; …
Ugyanazt azirsz-város-utcacímtípust használjuk
22
Metódusdeklarációk
Egy osztálydefiníció tartalmazhatja az osztályban levő metódusok deklarációit.
Az információ tartalma:1. Visszatérésí érték típusa, ha van.2. Metódus neve.3. Argumentumok módja és típusa (nincs
név). A mód lehet in, out és inout.
4. Kivételek, amelyeket a metódus kiválthat.
23
Példa: Metódusok
real átlag(in string)raises(nincsJegy);
1. Az átlag függvény egy valós számot ad vissza (feltehetőleg egy hallgató átlagát).
2. Az átlagnak egy argumentuma van, egy string (feltehetőleg a hallgató neve) és nem módosítja az argumentumát.
3. Az átlag kiválthatja a nincsJegy kivételt.
24
Az ODL típusrendszer
Alaptípusok: int, real/float, string, felsorolás típusok és osztályok.
Típuskonstruktorok: Struct a struktúrákhoz. Kollekció típusok : Set, Bag, List, Array és
Dictionary ( = leképezés egy értelmezési tartományból egy képhalmazba).
A kapcsolatok típusa csak osztály vagy egy osztályra alkalmazott kollekció lehet.
25
ODL alosztályok
A szokásos objektumorientált alosztályok.
A szülőosztályt kettősponttal és névvel jelöljük.
Az alosztályban csak az egyedi tulajdonságait soroljuk fel. Megörökli a szülőosztály
tulajdonságait is.
26
Példa: Alosztályok
Az ale a sör alosztálya:class Ale:Sör {
attribute string szín;
}
27
ODL kulcsok
Deklarálhat akárhány kulcsot egy osztályhoz.
Az osztály neve után adjuk meg:(key <kulcslista>)
Egynél több attribútumot tartalmazó kulcsot az attribútumok köré tett külön zárójellel jelöljük.
28
Példa: Kulcsok
class Sör (key név) { … a név a sör kulcsa.class Kurzus (key (tanszék,szám),(hely, idő)){
a tanszék és szám az egyik kulcs, a hely és idő a másik.
29
Extensek
Minden osztályhoz tartozik egy extens, amely az osztályhoz tartozó létező objektumokat tartalmazó halmaz. Az extens hasonló egy relációhoz,
amelynek az osztály a sémája. Az extenst az osztály neve után
tüntetjük fel a kulcsokkal együtt, így:(extent <extens neve> … )
30
Példa: Extensek
class Sör
(extent Sörök key név) { …
} Konvenció szerint egyes számot
használunk az osztály nevének, többes számot a hozzá tartozó extensnek.
31
OQL
Az OQL az objektumorientált lekérdezés szabványa.
Az ODL-t használja sémadefiníciós nyelvként.
Az OQL típusai olyanok, mint az ODL-ben.
A relációk szerepét a Set(Struct) és a Bag(Struct) játssza.
32
Útvonal-kifejezések
Legyen x a C osztály egy objektuma.1. Ha a egy attribútuma C-nek, akkor x.a
az attribútum értéke.2. Ha r egy kapcsolata C-nek, akkor x.r az
az érték, amelyhez x kapcsolódik r által. Lehet egy objektum vagy objektumok
halmaza, r típusától függően.
3. Ha m egy metódusa C-nek, akkor x.m(…) az m x-re való alkalmazásának eredménye.
33
Futó példa
class Eladás (extent Eladások) {attribute real ár;relationship Kocsma kocsma inverse Kocsma::eladottSörök;relationship Sör sör inverse Sör::eladói;
}class Kocsma (extent Kocsmák) {
attribute string név;attribute string cím;relationship Set<Eladás> eladottSörök inverse Eladás::kocsma;
}
34
Futó példa, befejezés
class Sör (extent Sörök) {attribute string név;attribute string gyártó;relationship Set<Eladás> eladói inverse Eladás::sör;
}
35
Példa: Útvonal-kifejezések
Legyen s egy Eladás típusú változó, azaz kocsma-sör-ár objektum.
1. s.ár = az ár az s objektumban.2. s.kocsma.cím = s-ből a kocsma
kapcsolat mentén elért kocsma címe Itt a pontok egymásba ágyazása helyes,
mert s.bar egy objektum, nem objektumok kollekciója.
36
Példa: A pont helytelen használata
Nem használhatjuk a pontot, ha a bal oldalon egy kollekció áll, hanem csak akkor, ha egyetlen objektum.
Példa (helytelen), ahol b egy Kocsma:
b.eladottSörök.árEz a kifejezés Eladás típusú objektumokhalmaza. Nincs neki ára.
37
OQL Select-From-Where
Relációjellegű kollekciókat számolhatunk ki OQL utasítással:
SELECT <értéklista>FROM <kollekciók és típusjellemzők
listája>WHERE <feltétel>
38
FROM részmondat
Minden tagja az alábbi formájú:<kollekció> <tag neve> Kollekció lehet:
1. Valamelyik osztály extense.2. Egy kifejezés, amelynek értéke
kollekció, pl. b.eladottSörök .
39
Példa
Kérdezzük le Józsi kocsmájában az itallapot.
SELECT s.sör.név, s.árFROM Eladások sWHERE s.kocsma.név = "Józsi
kocsmája"Az Eladások az összesEladás objektumottartalmazó extens.s sorra felveszimindegyik objektumértékét.
Helyes kifejezések.s.sör egy sörobjektum, s.kocsmaegy Kocsmaobjektum.
Az OQLidézőjeleket használ.
40
Másik példa
Ez is megszerzi Józsi itallapját:SELECT s.sör.név, s.árFROM Kocsmák b,
b.eladottSörök sWHERE b.név = "Józsi
kocsmája"b.eladottSörök egy Eladás objektumokbólálló halmaz, most pedig egy tipikus eladásobjektum, amely Józsi kocsmájávalkapcsolatos.
41
Trükkök útvonal-kifejezésekkel
Ha egy útvonal-kifejezés egy objektumot jelöl, akkor kiterjesztheti egy ponttal és az objektum egy tulajdonságával. Példa: s, s.kocsma, s.kocsma.név
H a egy útkifejezése kollekciót jelöl, akkor nem terjesztheti ki, de felhasználhatja a FROM részmondatban. Példa: b.eladottSörök
42
Az eredmény típusa Alapértelmezésben a select-from-where
eredményének típusa egy struktúrákból álló zsák. A struktúrának egy-egy mezője van a
SELECT részmondat minden tagjához. A neve és típusa megegyezik az útvonal-kifejezés utolsó elemével.
Ha a SELECT csak egytagú, akkor technikailag az eredmény egy egymezős struktúra. Viszont az egyelemű struktúra azonosítható
az egy elemmel.
43
Példa: Eredménytípus
SELECT s.sör.név, s.ár
FROM Kocsmák b, b.eladottSörök s
WHERE b.név = "Józsi kocsmája" Típusa:
Bag(Struct(név: string, ár: real))
44
Mezők átnevezése
Mezők átnevezéséhez tegyük elé az új nevet és egy kettőspontot.
Példa:SELECT sör: s.sör.név, s.ár
FROM Kocsmák b, b.eladottSörök s
WHERE b.név = "Józsi kocsmája" Az eredmény típusa:
Bag(Struct(sör: string, ár: real)).
45
Struktúrák halmazának előállítása
Adjuk hozzá a DISTINCT kulcsszót a SELECT után, így az eredmény egy halmaz lesz és a duplikált elemek törlődnek.
Példa:SELECT DISTINCT s.sör.név, s.árFROM Kocsmák b, b.eladottSörök sWHERE b.név = "Józsi kocsmája" Az eredmény típusa:
Set(Struct(név: string, ár: string))
46
Struktúrák listájának előállítása
Használjuk az ORDER BY részmondatot, mint az SQL-ben, így az eredmény egy lista lesz, amelyben a struktúrák az ORDER BY-ban felsorolt mezők szerinti sorrendben lesznek. Növekvő (ASC) az alapértelmezett;
csökkenő (DESC) is lehetséges. A lista elemeit indexekkel érhetjük el:
[1], [2],… Az SQL kurzorokhoz hasonló
lehetőségeket ad.
47
Példa: Listák
Legyen joeMenu egy gazdanyelvi változó ezzel a típussal:
List(Struct(név:string, ár:real))joeMenu =SELECT s.sör.név, s.árFROM Kocsmák b, b.eladottSörök sWHERE b.név = "Józsi kocsmája"ORDER BY s.ár;
48
Példa, folytatás
Most a joeMenu értéke egy lista, amelynek elemei a Józsi által eladott sörök név-ár párjai.
Elérhetjük az első (legolcsóbb) elemet joeMenu[1], a következőt joeMenu[2] alakban stb.
Példa: Józsi legolcsóbb sörének neve:legolcsóbb = joeMenu[1].név;
49
Példa, befejezés
Miután kiértékeltük a joeMenu-t, kiírhatjuk Józsi itallapját efféle kóddal:
cout << "Sör\tÁr\n\n";
for (i=1; i<=COUNT(joeMenu); i++) cout << joeMenu[i].name << “\t” << joeMenu[i].price << “\n”;
COUNT megadja akollekció elemszámát.
50
Alkérdések
Egy select-from-where kifejezés körülvehető zárójelekkel és felhasználható alkérdésként többféle módon, pl.
1. FROM részmondatban kollekcióként.2. EXISTS és FOR ALL kifejezésben.
51
Példa: Alkérdés FROM-ban
Keressük meg a Józsi által kínált sörök gyártóit:
SELECT DISTINCT b.gyártóFROM (
SELECT s.sör FROM Eladások sWHERE s.kocsma.név = "Józsi kocsmája"
) b
Sör objektumokzsákja, a Józsi általeladott sörökkel
Technikailag egytagú struktúra Sör objektummal,de azonosítható magával az objektummal
52
Kvantorok
Két logikai értékű kifejezés, amely a WHERE részmondatban használható:
FOR ALL x IN <kollekció> : <feltétel>EXISTS x IN <kollekció> : <feltétel> Igaz akkor és csak akkor, ha minden
(ill. legalább egy) eleme a kollekciónak kielégíti a feltételt.
53
Példa: EXISTS
Keressük meg azoknak a kocsmáknak a nevét, amelyeknél kapható legalább egy 1000 Ft-nál drágább sör.
SELECT b.név FROM Kocsmák bWHERE EXISTS s IN
b.eladottSörök :s.ár > 1000
Legalább egy b-hez tartozó Eladás objektumára nagyobb, mint 1000
54
Másik kvantoros példa
Keressük meg azoknak a kocsmáknak a nevét, amelyek összes 1000 Ft-nál drágább sörét a Pete’s gyártja.
SELECT b.név FROM Kocsmák bWHERE FOR ALL be IN (
SELECT s.sör FROM b.eladottSörök sWHERE s.ár > 1000
) : be.gyártó = "Pete’s"
Sör objektumok zsákja(struktúrákon belül),b bár 1000 Ft-náldrágább söreivel.
Az egytagú struktúrák automatikusan kibontásrakerülnek, így be tekinthető Sör objektumnak.
55
Egyszerű kényszerítések
Ahogy már láttuk, az egytagú struktúra automatikusan konvertálódik az egy tag értékévé. Struct(f : x) kényszerül x-szé.
Az egyetlen elemet tartalmazó kollekció kényszeríthető az elemmé, de ehhez szükséges az ELEMENT operátor. Pl. ELEMENT(Bag(x )) = x.
56
Példa: ELEMENT
Adjuk értékül a valós típusú p-nek, hogy mennyiért adja Józsi a Bud-ot.
p = ELEMENT(SELECT s.ár FROM Eladások sWHERE s.kocsma.név = "Józsi kocsmája"
AND s.sör.név = "Bud"
); Egyelemű zsák egy struktúrával, amelynekegyetlen tagja a Bud ára Józsinál
57
Aggregációk
AVG, SUM, MIN, MAX és COUNT használható minden kollekcióra, ha van értelme.
Példa: Számítsuk ki a Józsi által eladott sörök átlagárát.
x = AVG(SELECT s.ár FROM Eladások sWHERE s.kocsma.név = "Józsi
kocsmája");
Zsák olyan struktúrákkal, amelyek a Józsi általeladott sörök árait tartalmazzák
58
Csoportosítás
Emlékezzünk az SQL csoportosításra:1. Rekordok csoportjai bizonyos
(csoportosító) attribútumok alapján2. A SELECT részmondat csak olyan
elemeket tud kivenni a csoportból, amelyeknek van értelme: Csoporton belüli aggregáció. Csoportosító attribútumok, amelyek értéke a
csoporton belül konstans.
59
OQL csoportosítás
Az OQL többféle módon kibővíti a csoportosítás fogalmát:
1. Bármilyen kollekció csoportokra bontható.
2. A csoportok az eredeti kollekció objektumainak tetszőleges függvénye alapján létrejöhetnek.
3. A lekérdezés eredménye a csoportok bármilyen függvénye lehet.
60
Az OQL GROUP BY vázlataKezdeti kollekcióFROM, WHERE
alapján
Köztes kollekció,függvényértékekkel
és partíciókkal
Kimenetikollekció
Csoportosítás függvényérték szerint
SELECT részmondat tagjai
61
Példa: GROUP BY
Ezeket a fogalmakat egy példán keresztül nézzük át: „Határozzuk meg minden kocsmában a sörök átlagárát.”
SELECT kocsmaNév, átlagÁr: AVG(SELECT p.s.ár FROM partition p)
FROM Eladások sGROUP BY kocsmaNév: s.kocsma.név
62
Kezdeti kollekció
A FROM és WHERE (itt hiányzik) alapján: FROM Eladások s
A kezdeti kollekció egy zsák struktúrákkal, amelyek egyetlen mezője a FROM részmondat „tipikus eleme”.
Itt egy zsák Struct(s: obj ) alakú struktúrákkal, ahol obj is egy Eladás objektum.
63
Köztes kollekció
Általában egy zsák struktúrákkal, amelyek rendelkeznek egy-egy taggal a GROUP BY részmondat minden függvényéhez, ezenkívül egy partition nevű taggal.
A partíció értéke az eredeti kollekció azon elemeinek halmaza, amelyek a vizsgált struktúrával azonos csoportba tartoznak.
64
Példa: Köztes kollekció
SELECT kocsmaNév, átlagÁr: AVG(SELECT p.s.ár FROM partition p)
FROM Eladások sGROUP BY kocsmaNév:
s.kocsma.névEgy csoportosító függvény. A nevekocsmaNév, típusa string. A közteskollekció struktúrák halmaza, ahol amezők kocsmaNév: string éspartition: Set<Struct{s: Eladás}>
65
Példa: Tipikus tag
Egy tipikus tag a köztes kollekcióban a példánkban:
Struct(kocsmaNév = "Józsi kocsmája",partition = {s1, s2,…,sn })
A partíció minden eleme egy si Eladás objektum, ahol si .kocsma.név értéke „Józsi kocsmája”.
66
A kimeneti kollekció
A kimeneti kollekciót a SELECT részmondat számolja ki, szokás szerint.
GROUP BY részmondat nélkül a SELECT részmondat a kezdeti kollekcióból állítja elő a kimenetét.
GROUP BY esetén a SELECT eredménye a köztes kollekcióból számítódik ki.
67
Példa: Kimeneti kollekció
SELECT kocsmaNév, átlagÁr: AVG(SELECT p.s.ár FROM partition p)
Kiveszi a kocsmaNévmezőt a csoportstruktúrájából.
A csoport partíció minden p tagjábólkiveszi az s mezőt (az Eladás objektumot),abból pedig az árat.
Átlagolja az árakat,ezáltal létrehozza akimeneti kollekcióstruktúráiban az átlagÁrmező értékeit
Tipikus kimeneti struktúra:Struct(kocsmeNév = "Józsi kocsmája", átlagÁr = 2.83)
68
Kevésbé tipikus példa Minden sörhöz számoljuk össze, hány
kocsma kér érte „alacsony” (<400 Ft) és hány „magas” (>800 Ft) árat.
Stratégia --- csoportosítsunk három érték szerint:
1. A sör neve.2. Egy logikai függvény, amely igazat ad
vissza akkor és csak akkor, ha az ár alacsony.
3. Egy logikai függvény, amely igazat ad vissza akkor és csak akkor, ha az ár magas.
69
A lekérdezés
SELECT sörNév, alacsony, magas,darab: COUNT(partition)
FROM Sörök b, b.eladói sGROUP BY sörNév: b.név,
alacsony: s.ár < 2.00, magas: s.ár > 4.00
Kezdeti kollekció: struktúrák az alábbi formában:Struct(b: Sör objektum, s: Eladás objektum),ahol s.sör = b.
70
A köztes kollekció
Egy halmaz az alábbi szerkezetű struktúrákkal:
1. sörNév: string2. alacsony: boolean3. magas: boolean4. partition: Set<Struct{b: Sör, s:
Eladás}>
71
Tipikus struktúra a köztes kollekcióban
Salacsony stb. Sör-Eladás párok halmazai.
Az alacsony és magas nem lehet egyszerre igaz, így az a csoport mindig üres lesz.
sörNév alacsony magas partition
Bud TRUE FALSE Salacsony
Bud FALSE TRUE Smagas
Bud FALSE FALSE Sközép
72
A kimeneti kollekció
SELECT sörNév, alacsony, magas,
darab: COUNT(partition) Lemásolja a köztes struktúrák első
három komponensét és számoljuk meg a partícióban levő párokat, pl.
sörNév alacsony
magas Darab
Bud TRUE FALSE 27