15. API BDE II

Uzamykání

Uzamykací prostředí BDE je hierarchie obsahující tři vrstvy:
Vrstva sezení
Na vrcholu hierarchie uzamykání BDE je vrstva sezení. Sezení nepřímo řídí některé zámky neboť řídí zdroje včetně madel databází a kurzorů tabulek. V jednom sezení může být otevřeno více madel databází; to nastává, když aplikace přistupuje najednou k různým databázím. Když sezení je uzavřeno, pak všechny zdroje přiřazené k sezení jsou uzavřeny a všechny zámky vlastněné těmito zdroji jsou uvolněny.
Sezení přímo vlastní zámky tabulek a zámky záznamů získané aplikací po otevření tabulky. To znamená, že pokud na jedné tabulce v sezení je otevřeno více kurzorů, pak jeden kurzor může uvolnit zámek získaný jiným kurzorem. Sezení je kompletně izolované od ostatních sezení.
Vrstva madla databáze
O jeden krok níže v hierarchii uzamykání BDE je vrstva madla databáze. I když žádné zámky nejsou vlastněny madlem databáze, režim sdílení přiřazený k databázi při jejím otevření určuje zda tabulky v databázi mohou být otevírány výlučně nebo sdíleně. Pokud databáze je otevřena ve výlučném režimu, pak všechny tabulky mohou být otevřeny pouze ve výlučném režimu.
Když databáze je uzavřena, pak všechny zdroje alokované na madlo databáze jsou uvolněny, včetně kurzorů tabulek a zámků tabulek vlastněných těmito kurzory.
Vrstva kurzoru tabulky
Dole v hierarchii uzamykání BDE je vrstva kurzoru. Pouze zámky umístěné na tabulce, když je otevřena funkcí DbiOpenTable jsou vlastněny kurzorem. Když tabulka je otevřena ve výlučném režimu, pak k tabulce nemohou přistupovat další uživatelé. Exklusivní zámek zabraňuje ostatním uživatelům v přístupu k tabulce a v umístění nějakého zámku na ní. Pokud tabulka je otevřena ve sdíleném režimu, pak ostatní kurzory mohou přistupovat k tabulce a mohou na ní zřizovat čtecí nebo zápisové zámky.
Když je kurzor uzamčen, pak všechny exklusivní zámky umístěné na tabulce při jejím otevření jsou uvolněny.
Získané zámky
Všechny zámky získané po otevření tabulky jsou vlastněné sezením (a ne kurzorem). Je několik typů získaných zámků: K testování stavu získaných zámků tabulky použijeme DbiIsTableLocked. Aplikace specifikuje typ zámku (nezamčen, čtecí zámek nebo zápisový zámek) a funkce vrací počet zámků tohoto typu umístěných na tabulce.
Pro tabulky dBASE, FoxPro, Access a Paradox, k testování zda tabulka je fyzicky sdílena na síti nebo lokálním zařízení a otevřena ve sdíleném režimu, použijeme BbiIsTableShared. Pro tabulky SQL tato funkce může být použita k testování zda tabulka byla otevřena ve sdíleném režimu.
Pokud aplikace potřebuje umístit zámek na tabulku, která byla otevřena ve sdíleném režimu, pak volá funkci BDE DbiAcqTableLock. Pokud zámek nemůže být získán je vrácena chyba. DbiAcqTableLock může umístit na tabulku čtecí nebo zápisový zámek.
Zápisový zámek zabraňuje ostatním uživatelům v aktualizaci tabulky. Na tabulce může být umístěn pouze jeden zápisový zámek. Čtecí zámek zabraňuje všem v aktualizaci tabulky a zabraňuje ostatním uživatelům v umístění zápisového zámku na tabulku (data v průběhu čtení nemohou být změněna). Může existovat více čtecích zámků.
Pokud ovladač nepodporuje čtecí zámky, pak čtecí zámky jsou nahrazeny zápisovými. Např. pro tabulky dBASE jsou čtecí zámky nahrazeny zápisovými. Pro tabulky SQL, zápisové zámky jsou stejné jako čtecí a chování se může lišit v závislosti na serveru. Tabulka může získat více než jeden zámek.
K uvolnění zámku tabulkové úrovně umístěným DbiAcqTableLock voláme DbiRelTableLock. Každý získaný zámek vyžaduje uvolnění samostatným voláním DbiRelTableLock.
Trvalý zámek může být umístěn před vytvářením tabulky. Pro tabulky Paradoxu tato služba může být použita k rezervování jména tabulky pro budoucí použití. Pro tabulky SQL, BDE si pamatuje, že zámek byl umístěn a když tabulka je vytvářena během připojení, pak tabulka je uzamčena. Tyto zámky jsou získávány funkcí DbiAcqPersistTableLock. Pro uvolnění trvalých získaných zámků tabulky použijeme DbiRelPersistTableLock.
Aplikace může přidělovat záznamové zámky během získávání záznamů. Většina funkcí BDE, které umožňují získávat záznam poskytují uzavírací volbu; např. DbiGetNextRecord, DbiGetPriorRecord a DbiGetRelativeRecord. Parametr eLock může být použit ke specifikaci některého z následujících záznamových zámků:
 
Nastavení Popis
dbiNOLOCK Bez zámku, umožňuje ostatním uživatelům číst, aktualizovat a uzamykat záznam.
dbiREADLOCK Změněno na zápisový zámek.
dbiWRITELOCK Umožňuje ostatním uživatelům číst záznam, ale zabraňuje v aktualizaci záznamu nebo v umístění zámku na záznam.

Správce uzamykání Paradoxu a dBASE nahrazuje čtecí zámky zápisovými zámky; tedy záznam je nebo není uzamčen.
Protože některé funkce získávání záznamů BDE provádějí jiné operace než uzamykání, pořadí ve kterém tyto operace se vyskytnou, může být důležité:

Přesun kurzoru nastává i když uzamčení je neúspěšné. Např. pokud DbiGetNextRecord je volán se čtecím zámkem, pak kurzor se přesune na následující záznam, záznam je pak uzamčen. Když ale záznam je již ale uzamčen jiným uživatelem, pak pokus o uzamčení je neúspěšné, ale kurzor má změněnou pozici.
K testování stavu uzamčení záznamu použijeme DbiIsRecordLocked. Tato funkce vrací stav uzamčení současného záznamu (uzamčen nebo neuzamčen).
Aplikace může volat funkci DbiRelRecordLock k uvolnění záznamového zámku na současném záznamu nebo uvolnění všech záznamových zámků získaných v současném sezení. Dále DbiModifyRecord poskytuje volbu k uvolnění zámku pro dokončení operace.
Koexistence zámků tabulky
Každý typ zámku tabulkové úrovně umístěný na tabulku ovlivňuje nějaký stupeň přístupu ostatních uživatelů k tabulce. Můžeme použít zámek agresivně k zabránění ostatním uživatelům v přístupu k tabulce, nebo použít zámek defensivně k zabránění ostatním uživatelům umisťovat zámky omezující naši aplikaci přistupovat k tabulce. Následující tabulka zobrazuje výsledek pokusu uživatele 2 umístit tabulkový zámek po úspěšném umístění zámku uživatelem 1.
 
Uživatel 2
Pokus o otevření tabulky ve výlučném režimu. Pokus o získání záznamového zámku Pokus o získání čtecího zámku Pokus o otevření tabulky ve sdíleném režimu.
Uživatel 1
Pokus o otevření tabulky ve výlučném režimu.
neúspěch neúspěch neúspěch neúspěch
Pokus o získání záznamového zámku neúspěch neúspěch neúspěch úspěch
Pokus o získání čtecího zámku neúspěch neúspěch úspěch pro Paradox, neúspěch pro dBASE nebo FoxPro úspěch
Pokus o otevření tabulky ve sdíleném režimu. neúspěch úspěch úspěch úspěch
Strategie uzamykání
Při volbě uzamykají strategie se musíme zabývat jak aplikace potřebuje chránit data před ostatními uživateli a jak data jsou chráněna ostatními uživateli. Každý zpřístupňovaný systém databáze může mít také různá pravidla používaná správcem uzamykání. SQL používá jiná pravidla než Paradox a dBASE.
Specifikace SQL chování uzamykání
V dBASE, Paradoxu, FoxPro a Access záznamové zámky zabraňují jiným uživatelům aktualizovat záznam. SQL ale pracuje se záznamovými zámky jiným způsobem. Pokud záznam v tabulce SQL není v záznamové cache, pak záznam je získáván ze serveru. Klient má lokální kopii záznamu, ale tato kopie nemusí být aktuální, když jiný klient získá stejný záznam ze serveru a modifikuje nebo jej zruší dříve než první klient se pokusí odeslat změny.
Ovladače SQL (a některé ODBC) používají optimistické uzamykání. Optimistický zámek umožňuje aktualizaci uzamčeného zámku jiným uživatelem, ale když aplikace, která umístila zámek se pokusí modifikovat záznam, pak BDE oznámí aplikaci že záznam byl změněn a že požadované operace nemůže být provedena protože někdo změnil data. Aplikace pak zvolí, zda prozkoumá nový záznam a určí zda svoji změnu má ještě provést.

Transakce

Systémy SQL používají zpracování transakcí s commit a rollback které celou řadu operací v transakci udělají trvalými nebo ji celou zruší. Transakce mohou být prováděny na všech platformách SQL podporovaných BDE. Transakce je řada programových příkazů, které přistupují k datům v naši databázi. Když transakce je dokončena, pak celou transakci zapíšeme nebo zrušíme. Při zápisu se všechny změny provedené v transakci stanou trvalými.
V připojení k SQL databázi může být aktivní pouze jedna transakce. Jakýkoliv pokus o spuštění další transakce před dokončením první způsobí chybu.
Operace SQL vždy umisťujeme do kontextu transakce. Když explicitní transakce nenastávají, pak ovladač SQL zpracovává transakce serveru SQL transparentně pro klienta. Všechny úspěšné modifikace dat serveru SQL se bezprostředně stávají trvalými.
K zahájení transakce se používá funkce DbiBeginTran. Po úspěšném volání DbiBeginTran se transakce stává aktivní. Aplikace specifikuje úroveň izolací použitou pro transakci když DbiBeginTran je volána. Možné hodnoty jsou: Schopnosti a chování izolací a možností opakovaného čtení závisí na SQL serveru.
DbiEndTran končí transakci. Aplikace specifikuje typ konce transakce. Možné hodnoty jsou: Kurzory BDE mohou zůstat aktivní i když přiřazené kurzory SQL jsou uzavřeny. BDE spravuje opětovné otevření kurzorů serveru SQL transparentně.
xendCommit a xendABORT drží kurzory, pokud ovladač a databáze podporují držení kurzorů. Pokud databáze nepodporuje držení kurzoru, pak existují čtyři možnosti pro každý otevřený kurzor na chování uživatele BDE:
Transakce na Paradoxu, dBASE, FoxPro a Access
Transakce pro ovladače Paradoxu, dBASE, FoxPro a Access (lokální transakce) umožňují zrušit nebo zapsat změny do standardních tabulek. To umožňuje, aby aplikace prováděla aktualizace konzistentním způsobem. Když lokální transakce je spuštěna na standardní databázi, pak aktualizace prováděné nad tabulkami v této databázi jsou zaznamenány. Každý záznam obsahuje původní obsah aktualizovaného záznamu. Když transakce je aktivní, pak aktualizované záznamy jsou uzamčeny a tyto zámky jsou drženy dokud transakce není ukončena:
Transakce a odložené aktualizace
Když transakce jsou aktivní, pak aktualizace jsou bezprostředně zaslány připojeným tabulkám. Chyby jsou bezprostředně oznamovány klientům. Protože aktualizace jsou bezprostředně zasílány připojeným tabulkám, pak aktualizace jsou viditelné ostatními transakcemi. A protože každý modifikovaný záznam je uzamčen, ostatní uživatelé jej nemohou změnit.
Toto chování se liší od chování odložených aktualizací, kdy aktualizace nejsou zasílány do připojených tabulek dokud nenastane čas zápisu. Tedy chyby nejsou oznamovány dokud nenastane čas zápisu. Zámky jsou drženy pouze v průběhu zápisu. Pokud v průběhu zápisu vznikne chyba, pak klient může zrušit proces zápisu. Pokud klient zruší proces zápisu, pak je obnoven původní stav tabulek.
Hlavní výhodou služby odložených aktualizací je to, že zámky jsou drženy pouze v průběhu zápisu, a tedy není omezován přístupový čas serveru SQL pro ostatní transakce, ale umožňují jiným uživatelům měnit data. Výhody a nevýhody jsou shrnuty v následující tabulce.
 
Výhody Nevýhody
Transakce Aktualizace jsou bezprostředně zasílány tabulkám. Modifikované záznamy jsou viditelné ostatními uživateli. Modifikované záznamy jsou uzamčeny. Chyby jsou oznamovány okamžitě. Uzamčení pro ostatní uživatele, dokud záznam je modifikován. Lokální transakce mají omezení maximálního počtu uzamčených záznamů.
Odložené aktualizace Zámky jsou drženy pouze v průběhu zápisu (neomezuje v přístupu ostatní transakce). Odložené aktualizace mohou být použity s libovolným kurzorem v tabulce. Nepřekračujeme omezení počtu zámků pro lokální transakce. Umožňuje ostatním uživatelům modifikaci záznamů. Pokud chyba vznikne v průběhu zápisu, a vrátíme tabulku do původního stavu, pak všechny modifikace jsou ztraceny.
Stupně izolace transakcí
Stupeň izolace poskytnutý transakcemi na standardních databázích je stupeň 0. To znamená, že transakce nepřepisuje nečistá data jiné transakce. Protože je podporován pouze stupeň izolace 0, transakce na standardních databázích jsou subjektem následujících omezení: Použitím příslušného uzamykacího mechanismu v průběhu aktualizací, klient může poskytnout vyšší stupeň izolace transakcí. Např. ztracené aktualizace mohou být zachráněny pokud transakce vždy získávají čtecí zámky na modifikované záznamy. Funkce dbiBeginTran podporuje několik úrovní izolací transakcí: xilDIRTYREAD, xilREADCOMMITTED a xilREPEATABLEREAD.
Pro tabulky SQL, příslušné úrovně izolací transakcí, mohou být požadovány dople možností serveru SQL. Úroveň izolace xilREADCOMMITTED zachraňuje ztrátu aktualizací a nečistému čtení. Úroveň izolací xilREPEATABLEREAD zabraňuje neopakovatelnému čtení.
Protože všechny aktualizace jsou atomické, uživatelé budou informováni o konfliktech uzamykání bezprostředně. Detekce uváznutí není prováděna. Uváznutí nastane, když dvě transakce čekají na zámky držené navzájem. Pokud je libovolný konflikt uzamykání mezi různými transakcemi, pak klientovi je vrácena chybová zpráva. Když uváznutí nastane, pak klient může rozhodnout o zrušení transakce.
Použití transakcí
BDE poskytuje dvě API funkce: DbiBeginTran (zahájení transakce) a DbiEndTran (ukončení transakce):
DBIResult DBIFN DbiBeginTran ( // Zahájení transakce
   hDBIDb         hDb,         // Madlo databáze
   eXILType       eXIL,        // Úroveň izolace transakcí
   phDBIXact      phXact       // Vraceno. Madlo Xact
);
DBIResult DBIFN DbiEndTran (   // Konec transakce
   hDBIDb         hDb,         // Madlo databáze
   hDBIXact       hXact,       // Madlo Xact
   eXEnd          eEnd         // Typ ukončení transakce
);
typedef enum            // Úrovně izolace transakcí
{
      xilDIRTYREAD,     // Čtení netrvalých změn
      xilREADCOMMITTED, // Trvalé změny, bez zjevování
      xilREPEATABLEREAD // Plná opakovatelnost čtení
} eXILType;
typedef enum            // Konec řízení transakce
{
      xendCOMMIT,       // Trvalý zápis transakce
      xendCOMMITKEEP,   // Trvalý zápis transakce, držení kurzorů
      xendABORT         // Zrušení transakce
} eXEnd;
Následující výsledky nastanou když jsou aktivní transakce:
  1. Pokud jsou aktivní transakce v sezení, pak DbiCloseSession uzavírá toto sezení a jeho aktivní transakce jsou zrušeny. Podobně DbiExit ruší aktivní transakce v systému.
  2. V případě standardních databází (lokální transakce), DbiModifyRecord, DbiInsertRecord a DbiDeleteRecord jsou používány k provádění záznamu transakcí. Deník je udržován, pokud transakce je aktivní. Je zrušen po trvalém zápisu nebo zrušení transakce.

Dotazování databází

API BDE umožňuje, aby klient používal SQL nebo QBE pro přístup k tabulkám dBASE, FoxPro, Access a Paradoxu stejně jako k SQL tabulkám.
Skupina funkcí rozhraní dotazu BDE je poskytnuta pro předávání dotazů SQL nebo QBE na serverové i na PC založené zdroje.
Dotazování Paradoxu, dBASE, FoxPro a Access
Společný modul dotazů umožňuje vývojářům BDE aplikací přistupovat k tabulkám ve standardních databázích pomocí jazyků SQL nebo QBE. Ve standardních databázích jsou podporovány dvě kategorie příkazů SQL (Lokálního SQL): Když zapisujeme příkazy SQL pro použití na tabulkách dBASE, FoxPro, Access a Paradoxu je nutno dodržovat následující pojmenovací konvence:
Jména tabulek, které obsahují tečku musí být uvedeny v uvozovkách nebo apostrofech. Např.
select * from 'c:\sample.dat\table'
select * from "table.dbf"
Jména tabulek mohou obsahovat přezdívky stylu BDE. Např.
select * from ":data:table"
Jména, která jsou klíčovými slovy musí být uvedeny v uvozovkách. Např.
select passid from "password"
Jména, která obsahují mezeru musí být uvedeny v uvozovkách. Např.
select * from "old table"
Jména položek, které mají mezeru musí být zapsány v uvozovkách. Např.
select e."Emp Id" from Employee e
Jména položek, která jsou klíčovými slovy musí být v uvozovkách. Např.
select t."date" from Table t
Jména tabulek zapsaná v uvozovkách musí používat korelační jména.
V DML jsou podporovány následující klauzule: SELECT, WHERE, ORDER BY, GROUP BY, UNION a HAVING a je možno používat následující agregační funkce: SUM, AVG, MIN, MAX a COUNT. Typ položky vracený agregačními funkcemi je DOUBLE. Jsou podporovány následující operátory: +, -, *, /, =, <, >, <>, <=, >=, NOT. Operace UPDATE, INSERT a DELETE jsou plně podporovány na úrovni vstupu SQL 92. Např.
DELETE FROM "Current Cust.db" C
WHERE C."CustID" IN
  (SELECT O."CustID"
  FROM "Old Cust.db" O)
Dále je podporováno: Syntaxe DDL pro tabulky Paradoxu, dBASE, FoxPro a Access je omezena na CREATE TABLE (nebo INDEX) a DROP TABLE (nebo INDEX). Např.
create table parts ( part_no char(6), part_name char(20) )
Následující příklad ukazuje jak DDL SQL může být prováděno prostřednictvím BDE:
hDBICur hCur;
pBYTE szQuery = "create table 'c:\\example\\test.dbf' "
       "( fld1 int, fld2 date)";
rslt = DbiQExecDirect(hDb, langSQL, szQuery, &hCur);
Dotazování různých databází
Prostřednictvím rozhraní BDE, vývojář aplikace může používat SQL ke spojování tabulek v různých datových zdrojích. Následující příkaz SQL ukazuje spojení tří tabulek z různých platforem pomocí přezdívek:
select distinct c.cust_no, c.state, o.order_no, i.price
 from ':Local_alias:customer.db' c,
      ':IB_alias:order' o,
      ':SYB_alias:lineitem' i
 where o.cust_no = c.cust_no and o.order_no = i.order_no
Přímé provádění dotazů
Pro jednoduché dotazy, kde není nutná speciální příprava použijeme DbiQExecDirec. Tato funkce bezprostředně připraví a provede dotaz SQL nebo QBE a vrací kurzor na výsledkovou množinu, pokud je generována. Aplikace předává madlo databáze, specifikuje zda jazyk dotazu je SQL nebo QBE a předává řetězec dotazu.
S jazykem dotazu SQL, pokud specifikované madlo databáze ukazuje na serverovou databázi, pak je očekáván přirozený dialekt serveru SQL. Pokud madlo databáze referuje na standardní databázi, pak příkaz SQL je omezen na podporovanou podmnožinu společným modulem dotazu.
Následující příklad ukazuje jak dotaz SQL je prováděn funkcí DbiQExecDirect:
DBIResult rslt;
hDBICur   hCur;
pBYTE     szQuery =  "Select t.name, t.age "
          "from EMPLOYEE t "
          "where t.age > 30 "
          "and t.salary > 1000000 ";
rslt = DbiQExecDirect(hDb, qrylangSQL, szQuery, &hCur);
Postupné provádění dotazů
Některé dotazy vyžadují příkazové madlo a vyžadují postupné provádění. Příkazové madlo je vyžadováno pokud aplikace potřebuje řídit typ tabulky ve výsledkové množině nebo ke spojování s parametry pro dotazy. Pro každý stav dotazu je používána samostatná funkce:
  1. K získání nového příkazového madla, voláme DbiQAlloc.
  2. Ke změně vlastností v příkazovém madlu voláme DbiSetProp. Zde je také možno určit, zda chceme "živou" výsledkovou množinu, tj. modifikovatelnou.
  3. Pro přípravu dotazu voláme DbiQPrepare.
  4. Pro provedení připraveného dotazu voláme DbiQExec.
  5. Pro uvolnění zdrojů spojených s dotazem voláme DbiQFree.
Funkce DbiQAlloc alokuje příkazové madlo vyžadované funkcemi přípravy dotazu. Specifikujeme madlo databáze a jazyk dotazu a je vráceno příkazové madlo. DbiQAlloc je nezbytným prvním krokem ve všech připravovaných dotazech.
DbiSetProp je použita k nastavení vlastností objektu na specifikované hodnoty. V tomto případě objekt je příkazové madlo vrácené DbiQAlloc. Nastavované vlastnosti mohou být typ výsledkové tabulky, stupeň živosti nebo režim dotazu pro spojování parametrů. Následující příklady ukazují jak nastavovat  tyto vlastnosti:
DbiSetProp(hStmt, stmtANSTYPE, (UINT32) szPARADOX);
DbiSetProp(hStmt, stmtLIVENESS, (UINT32) wantLIVE);
Funkce DbiQPrepare je použita pro přípravu dotazu pro následující provádění. Akceptuje madlo příkazu obsahující připravovaný dotaz.
Předcházející příklad ukazuje jak můžeme specifikovat naše preference pro živou nebo zrušitelnou výsledkovou množinu v průběhu provádění dotazu. Zrušitelná výsledková množina se podobá kopii původních dat vybraných dotazem. Živá výsledková množina je pohledem na původní data a pokud živou výsledkovou množinu modifikujeme, pak změny se projeví na původních datech.
Když specifikujeme naše preference na živou výsledkovou množinu, pak Správce dotazu se pokusí nám poskytnou živou výsledkovou množinu. Někdy to ale není možné. Po provedení dotazu a návratu výsledkové množiny můžeme zjistit, zda se jedná o živou množinu prozkoumáním vlastnosti bTempTable kurzoru. Je-li tato vlastnost false, pak se jedná o živou výsledkovou množinu.
Dotazy SQL na servery SQL vracejí chybu, pokud výsledek nemůže být živý. bTempTable je přípustná pro lokální dotazy.
Možné hodnoty pro životnost jsou:
 
Hodnota Popis
wantCANNED Zrušitelná výsledková množina
wantLIVE Živá výsledková množina
wantSPEED Rozhoduje Správce dotazu (na základě rychlejší metody)
wantDEFAULT Stejné jako wantCANNED

DbiQExec provádí předem připravený dotaz identifikovaný předaným příkazovým madlem a vrací kurzor na výsledkovou množinu (je-li generována). Pro všechny dotazy (lokální i vzdálené) připravený dotaz může být proveden několikrát, ale pouze když nevyřízené výsledky byly přečteny nebo zrušeny (pomocí DbiCloseCursor).
Funkce DbiQFree je vždy použita jako poslední krok v provádění připravovaných dotazů k uvolnění všech systémových zdrojů alokovaných v průběhu a použití dotazu.

Získávání a nastavování vlastností

Každý objekt BDE je definován množinou vlastností. Vlastnosti definující objekt závisí na typu objektu. Např. session je objekt BDE a jeho vlastnosti zahrnují sesMAXPROPS, sesSESSIONNAME a sesCFGMODE2. Každý typ objektu má své vlastní vlastnosti. Hodnoty jsou při vytváření objektu přiřazeny k vlastnostem. Např. jméno tabulky je přiřazeno vlastnosti curTABLENAME objektu kurzoru, když tabulka je otevřena pomocí DbiOpenTable.
Hodnoty některých vlastností mohou být změněny funkcí DbiSetProp. K nastavení vlastnosti, aplikace předává madlo objektu, jméno měněné vlastnosti a novou hodnotu vlastnosti. K získání současné hodnoty vlastnosti použijeme DbiGetProp. K získání madla objektu použijeme DbiGetObjFromName. K získání madla databáze kurzoru použijeme DbiGetObjFromObj.
Následující příklad ukazuje metody pro získávání jména/typu tabulky, když vše co je dostupné je kurzor tabulky.
UINT16      iLen;
DBITBLNAME  tblName;
DBINAME     tblType, dbName;
// Kurzor tabulky umožňuje přistup ke jménu a typu tabulky
DbiGetProp(hCursor, curTABLENAME, (pVOID) tblName,
           sizeof(tblName), &iLen);
DbiGetProp(hCursor, curTABLETYPE, (pVOID) tblType,
           sizeof(tblType), &iLen);
// Můžeme také přistupovat k vlastnostem databáze (jako je
// jméno databáze přiřazené ke kurzoru).
DbiGetProp(hCursor, dbDATABASENAME, (pVOID) dbName,
           sizeof(dbName), &iLen);
Vlastnosti objektů
Každý objekt je definován svoji vlastní množinou vlastností jak je uvedeno v následující tabulce. Ne všechny ovladače podporují všechny vlastnosti.
 
Vlastnost
System
Session
Database
Driver
Cursor
Statement
sysMAXPROPS
x
x
x
x
x
x
sysLOWMEMUSAGE
x
x
x
x
x
x
sesMAXPROPS
x
x
 
x
x
sesSESSIONNAME
x
x
 
x
x
sesNETFILE  
x
x
 
x
x
sesCFGNAME  
x
x
 
x
x
sesCFGUPDATE  
x
x
 
x
x
sesCFGMODE2  
x
x
 
x
x
dbBATCHCOUNT
x
dbBLOBCOUNT
x
dbBLOBSIZE
x
dbMAXPROPS
x
 
x
x
dbDATABASENAME
x
 
x
x
dbDATABASETYPE
x
 
x
x
dbASYNCSUPPORT
x
dbPROCEDURES
x
dbDEFAULTTXNISO
x
dbNATIVEHNDL
x
dbNATIVEPASSTHRUHNDL
x
dbUSESCHEMAFILE
x
dbSERVERVERSION
x
x
dbTRACEMODE
drvMAXPROPS  
x
x
x
drvDRIVERTYPE  
x
x
drvDRIVERVERSION  
x
x
cfgREFRESH
x
x
curGETEXTENDEDINFO
x
curMAXPROPS
x
curMAXROWS
x
x
x
curTABLENAME
x
curTABLETYPE
x
curTABLELEVEL
x
curFILENAME
x
curXLTMODE
x
curSEQREADON
x
curONEPASSON
x
curUPDATETS
x
curSOFTDELETEON
x
curLANGDRVNAME
x
curPDXMAXPROPS
x
curDBMAXPROPS
x
curINEXACTON
x
curNATIVEHNDL
x
curUPDLOCKMODE
x
stmtMAXPROPS
x
stmtPARAMCOUNT
x
stmtUNIDIRECTIONAL
x
stmtANSTYPE
x
stmtLIVENESS
x
stmtQRYMODE
x
stmtBLANKS
x
stmtDATEFORMAT
x
stmtNUMBERFORMAT
x
stmtAUXTBLS
x
stmtTBLVECTOR
x
stmtALLPROPS
x
stmtALLPROPSSIZE
x
stmtANSNAME
x
stmtNATIVEHNDL
x
stmtCURSORNAME
x
stmtROWCOUNT
x
stmtCONSTRAINED
x
stmtFIELDDESCS
x
stmtCURPROPS
x

Získávací schéma a systémové informace

Některé funkce BDE vracejí schéma nebo systémové informace. Některé funkce ve formátu DbiOpenxxxList mohou být použity pro návrat kurzoru paměťové tabulky, jejíž záznamy obsahují požadované informace. Ostatní funkce ve formátu DbiGetxxxDescs vracejí informace přímo ve strukturách popisů a polích podporovaných aplikací.
Funkce BdiOpenList
Tato funkční volání vracejí madlo kurzoru na tabulku v paměti s požadovanými informacemi. Tento kurzor je určen pouze pro čtení a aplikace tedy nemůže modifikovat požadované informace. Z této tabulky informace mohou být získávány normálním způsobem. Každý záznam může být čten z předdefinované struktury přiřazené k funkci. Tyto struktury jsou uvedeny v souboru IDAPI.H.
 
Seznam funkcí Struktura virtuální tabulky vracených informací
DbiOpenDatabaseList DBDesc
DbiOpenDriverList Virtuální tabulka obsahuje pouze jednu položku CHAR
DbiOpenFamilyList FMLDesc
DbiOpenFieldList FLDDesc
DbiOpenFieldTypesList FLDType
DbiOpenFileList FILEDesc
DbiOpenFunctionArgList DBIFUNCArgDesc
DbiOpenFunctionList DBIFUNCDesc
DbiOpenIndexList IDXDesc
DbiOpenIndexTypesList IDXType
DbiOpenLdList LDDesc
DbiOpenLockList LOCKDesc
DbiOpenRintList RINTDesc
DbiOpenSecurityList SECDesc
DbiOpenTableList TBLBaseDesc, TBLExtDesc, TBLFullDesc
DbiOpenTableTypesList TBLType
DbiOpenUserList USERDesc
DbiOpenVchkList VCHKDesc

Následující příklad ukazuje použití statické struktury jako vyrovnávací paměti záznamů:
DBIResult   rslt;
hDBICur     hListCur;
IDXDesc     idxDesc;
// Otevřené schéma tabulky obsahující jeden záznam pro každý index
// současně dostupný v dané tabulce.
rslt = DbiOpenIndexList(hDb, "Sample", szPARADOX, &hListCur);
if (rslt == DBIERR_NONE)
{
  // Použití cyklu k získání všech deskriptorů indexů
  while (DbiGetNextRecord(hListCur, dbiNOLOCK,
             (pBYTE) &idxDesc, NULL) == DBIERR_NONE)
  {
     ...
  }
  // Uzavření seznamu indexů
  DbiCloseCursor(&hListCur);
}

Funkce DbiGetDescs
Tyto funkce jsou volány pro získání popisujících informací v předané struktuře.
 
Seznam funkcí Struktura virtuální tabulky vracených informací
DbiGetDatabaseDesc Struktura DBDesc
DbiGetDriverDesc Struktura DRVType
DbiGetFieldDescs Pole struktur FLDDesc
DbiGetFieldTypeDesc Struktura FLDType
DbiGetIndexDesc Struktura IDXDesc
DbiGetIndexDescs Pole struktur IDXDesc
DbiGetIndexTypeDesc IDXType
DbiGetTableTypeDesc Struktura TBLType
DbiQGetBaseDescs Struktura STMTBaseDesc

Následující příklad ukazuje jak získat všechny deskriptory indexů v jednom funkčním volání.
DBIResult   rslt;
hDBICur     hCursor;
CURProps    curProps;
pIDXDesc    pIdxArray;
// Otevření tabulky
rslt = DbiOpenTable(hDb, "Sample", szPARADOX, NULL, NULL, 0,
   dbiREADWRITE, dbiOPENSHARED, xltFIELD,TRUE, NULL, &hCursor);
if (rslt == DBIERR_NONE)
{
  // Získání vlastností pro kurzor
  DbiGetCursorProps(hCursor, &curProps);
  // Alokování vyrovnávací paměti pro deskriptory indexů
  pIdxArray = (pIDXDesc) malloc(sizeof(IDXDesc)*curProps.iIndexes);
  // Získání indexů
  rslt = DbiGetIndexDescs(hCursor, pIdxArray);
  if (rslt == DBIERR_NONE)
  {
    ...
  }
  // Úklid
  free((pCHAR) pIdxArray);
  DbiCloseCursor(&hCursor);
}

Vytváření tabulek

Aplikace může vytvářet trvalé tabulky pomocí funkce BDE DbiCreateTable. Může také vytvářet dočasné tabulky voláním DbiCreateTempTable a tabulky v paměti voláním DbiCreateMemTable.
Trvalé tabulky jsou pojmenované a jsou uložené na disk. K vytvoření trvalé tabulky, aplikace nejprve vytvoří pro každou položku strukturu deskriptoru položky FLDDesc a pro každý index strukturu deskriptoru indexu IDXDesc. Pro tabulky SQL a Paradoxu, aplikace může také definovat strukturu deskriptoru pro každé testování přípustnosti VCHKDesc, strukturu deskriptoru pro každé testování referenční integrity RINTDesc a každé testování bezpečnosti SECDesc.
Dále aplikace vytváří strukturu deskriptoru tabulky CRTblDesc definující obecné atributy tabulky a přebírající ukazatele na pole struktur deskriptorů položek, indexů, přípustností, referenční integrity a bezpečnosti vytvořené dříve. Nakonec aplikace volá DbiCreateTable a předává ji strukturu CRTblDesc.
Když vytváříme tabulku Paradoxu, dBASE, FoxPro nebo Access, pak v posledních třech položkách struktury CRTblDesc mohou být obsaženy volitelné parametry závisejícím na ovladači. K získání seznamu a popisu těchto volitelných parametrů pro ovladač, aplikace volá DbiOpenCfgInfoList, předáním cesty vytvářecích voleb ovladače tabulky v konfiguračním souboru. Tato funkce vrací paměťovou tabulku s požadovanými informacemi.
Dočasné tabulky jsou zrušeny při uzavření kurzoru. Aplikace může vytvářet dočasné tabulky stejně jako vytváří trvalé tabulky, pouze místo volání DbiCreateTable je použito DbiCreateTempTable.
Paměťové tabulky nemohou být ukládány jako trvalé tabulky. Aplikace může vytvořit paměťovou tabulku voláním DbiCreateMemTable a předáním pole struktur položkových deskriptorů FLDDesc. Jsou podporovány pouze logické typy BDE.
Omezení integrity
Když vytváříme tabulku pomocí funkce BDE DbiCreateTable, pak můžeme použít omezení integrity k zajištění aby odkazy v položkách klíče v sekundární tabulce (ve stejné databázi) nebo cizích tabulek (v různých databázích) byly udržovány položkami klíče v primární tabulce. Např. pokud několik tabulek se odkazuje na primární klíč jiné tabulky, pak musí být zajištěno, aby záznamy na které se odkazujeme nemohly být zrušeny.
Omezení integrity primárních a cizích klíčů nejsou implementována ve všech SQL serverech.
Podpora primárního klíče:
  1. Určíme, které položky nebo množiny položek budou pracovat jako primární klíč pro vytvářenou tabulku. Pro tabulku dBASE, zvolíme index, který bude pracovat jako primární klíč vytvářené tabulky.
  2. Vložímu tuto informaci do struktury IDXDesc.
  3. Nastavíme IDXDesc.bPrimary = TRUE;
  4. Připojíme strukturu IDXDesc k ukazateli CRTBLDesc.pidxDesc.
Sloupce primárního klíče musí být NOT NULL, což znamená že VCHKDDesc pro každý sloupec musí být VCHKDesc.bRequired = TRUE. Výjimkou je Paradox, který může mít jeden prázdný záznam.
Tabulka může mít pouze jeden primární klíč.
Tabulka s omezením primárního klíče (tabulková úroveň) je vytvořena a je také vytvořen unikátní index (vzestupný) na těchto sloupcích. Pro dBASE může být použit i sestupný index. Pro vzdálené databáze, tento index může být přidán nebo zrušen pomocí CREATE INDEX nebo DROP INDEX.
Podpora cizího klíče:
  1. Určíme které tabulky (jiné tabulky) se budou odkazovat na vytvářenou tabulku. Pokud to podporuje server, pak se může jednat i o stejnou tabulku.
  2. Určíme, které sloupce této tabulky ukazují na sloupce jiných tabulek.
  3. Určíme, co bude akce referenční integrity pro rušení. Pokud je požadováno kaskádovité rušení, pak nastavíme RINTDesc.eDelOp = rintCASCADE. Je-li to podporováno.
  4. Vložíme tyto informace do struktury RINTDesc.
  5. Připojíme RINTDesc k ukazaleli CRTBLDesc.printDesc.
Může být více než jeden cizí klíč v tabulce.
Poznámka: Některé servery, jako InterBase 4.0, vytvářejí indexy na sloupcích cizího klíče v tabulce.
Modifikování struktury tabulky
Po vytvoření tabulky, ji aplikace může modifikovat pomocí funkcí BDE takto: Aplikace může přidávat index k tabulce voláním DbiAddIndex a předáním struktury IDXDesc zaplněnou příslušnou položkou.
Aplikace může zrušit index voláním DbiDeleteIndex. Aplikace může tabulku specifikovat jménem nebo na tabulce otevřít kurzor. Rušený index nemůže být aktivní.
Aplikace může regenerovat indexy dBASE, FoxPro, Access nebo Paradoxu voláním dvou funkcí BDE. DbiRegenIndex regeneruje jednoduché indexy, zatímco DbiRegenIndexes je zapotřebí použít k regeneraci složitých indexů. Aplikace specifikuje index jménem.
Současně pouze pro tabulky Paradoxu, dBASE, FoxPro a Access, aplikace může volat DbiDoRestructure k modifikaci existujících typů položek, přidávání nových položek, rušení položky, změně pořadí položek, změně indexů nebo referenční integrity. Aplikace předává strukturu deskriptoru tabulky CRTblDesc.

Používání zpětného volání

Někdy aplikace potřebuje oznámit specifický typ události modulu přístupu k databázi pro dokončení operace nebo poskytnutí informací uživateli. Výhodou použití zpětného volání je, že BDE může získat reakci uživatele a to bez přerušení normálního běhu aplikace.
Ve funkcích zpětného volání musí být přísně dodrženy tato pravidla: Aplikace může volit oznamování z mnoha různých typů událostí, v závislosti na registrovaném typu zpětného volání. Aplikace může specifikovat následující typy zpětného volání pomocí DbiRegisterCallback.
 
Zpětné volání Popis
cbGENPROGRESS Informuje aplikaci o zpracovávání v průběhu velké dávkové operace.
cbRESTRUCTURE Předává informace o probíhajících akcích a vyžaduje reakci od volajícího.
cbBATCHRESULT Výsledek dávkového zpracováni.
cbTABLECHANGED Oznamuje uživateli, že tabulka byla změněna.
cbCANCELQRY Umožňuje uživateli zrušit dotaz Sybase.
cbINPUTREQ Ovladač BDE vyžaduje vstup od uživatele.
cbDBASELOGIN Umožňuje klientu přístup k zakódovaným tabulkám dBASE.
cbFIELDRECALC Rekalkulace položek.
cbDBLOGIN Přihlášení k databázi.
cbDELAYEDUPD Zpětné volání odložených aktualizací.
cbNBROFCBS Počet zpětných volání.
cbTRACE Sledování.

Deklarace funkcí zpětného volání a přiřazené seznamy parametrů, návratové typy funkcí a typy dat zpětného volání jsou definovány v hlavičkovém souboru IDAPI.H, který je aplikačním rozhraním k BDE.
Aplikace reaguje na zpětné volání návratovým kódem, který je příkazem k provedení příslušné akce:
 
Návratový kód Popis akce
cbrUSEDEF Proveď implicitní akci.
cbrCONTINUE Pokračuj.
cbrABORT Zrušení operace.
cbrCHKINPUT Předání vstupu.
cbrYES Provedení požadované akce.
cbrNO Neprovedení požadované akce.
cbrPARTIALASSIST Asistence v kompletování práce.

Předpokládejme, že aplikace musí překopírovat tabulku s řádově milionem záznamů a že chceme periodicky zobrazovat na obrazovce informaci o průběhu kopírováni. Můžeme postupovat takto:

  1. Zapíšeme tělo zpětně volané funkce, deklarované s přiřazeným předdefinovaným seznamem parametrů:

  2. typedef CBRType far *pCBRType;
    typedef CBRType (DBIFN * pfDBICallBack)
    (
    CBType         ecbType,       // Typ zpětného volání
    UINT32         iClientData,   // Klientská data zpětného volání
    pVOID          pCbInfo        // Zpětné volání informující klienta
    Input
    );
  3. Aplikace alokuje paměť pro vyrovnávací paměť pCbBuf použitou k předávání dat oběma směry mezi aplikací a funkcí a ukazatel na strukturu CBPROGRESSDesc.

  4. typedef struct
    {
    INT16         iPercentDone;        // Procento dokončení
    DBIMSG        szMsg;               // Zpráva k zobrazení
    } CBPROGRESSDesc;
    typedef CBPROGRESSDesc far * pCBPROGRESSDesc;
  5. K registraci zpětného volání aplikace volá DbiRegisterCallback s předáním cbGENPROGRESS jako hodnotu pro ecbType.
  6. Aplikace zajistí volání DbiBatchMove.
  7. BDE vrací procento dokončení (v parametru iPercentDone struktury CBPROGRESSDesc), nebo řetězec zprávy k zobrazení na stavovém řádku. Aplikace může předpokládat, že pokud hodnota iPercentDone je záporná, pak řetězec zprávy je přípustný; jinak aplikace může použít hodnotu iPercentDone. Formát řetězce zprávy je <Text String><:><Value>, což usnadňuje internacionalizaci aplikace. Např. Records copied: 250
  8. K pokračování aplikace vrací kód cbrUSEDEF. Aplikace může zrušit zpracování návratem hodnoty cbrABORT.
Nezávislé datové zdroje
Můžeme použit tyto techniky k dosažení nezávislých datových zdrojů: Aplikace může určovat, které přezdívky jsou dostupné voláním BDE funkce DbiOpenDatabaseList. Tato funkce uvádí seznam všech přezdívek databáze z konfiguračního souboru.

Filtrování záznamů

Tato sekce je úvodem k vytváření výrazového stromu použitého v DbiAddFilter. Výrazový strom budeme potřebovat zapisovat pouze tehdy, když chceme efektivně generovat vysoce omezený pohled na data v tabulce, kvalifikované více neindexovanými položkami.
Filtr je mechanismus, kvalifikující data testováním všech záznamů. Jako základní příklad předpokládejme, že chceme otevřít tabulku Customer, ale zobrazit pouze ty zákazníky, kteří žijí v Kalifornii. Pro použití filtru je důležité to, že můžeme zapsat aplikaci definující filtr pro otevřený kurzor na tabulce Customer, kde customer.state= CA. Když filtr je aktivován, pak BDE získává pouze ty záznamy, které splňují podmínku a tak naše aplikace může vidět a zpracovávat pouze tyto záznamy. Např. když naše aplikace volá DbiGetNextRecord, pak všechny záznamy, kde zákazník nežije v Kalifornii jsou přeskočeny.
K definování filtru, aplikace volá DbiAddFilter a předává madlo kurzoru a specifikující podmínku filtru. Funkce vrací madlo filtru aplikaci. Parametr DbiAddFilter pcanExpr ukazuje na výrazový strom typu pBYTE. Aplikace může použít výrazový strom ke specifikaci filtrovací podmínky.
Výhodou používání výrazového stromu k definování podmínky filtru je to, že BDE jej může použít k optimalizaci operací filtru. Úroveň optimalizace závisí na úrovni podpory ovladače pro rozklad výrazového stromu.
Po definování filtru, filtr musí být aktivován voláním DbiActivateFilter.
Použití výrazového stromu
Výrazový strom je výraz filtru typu pBYTE přetypovaný na pCANExpr. Je to třídílný blok paměti složený z: Povšimněte si, že hlavička obsahující strukturu CANExpr je 10 slabik dlouhá, a tedy Oblast uzlů začíná s ofsetem 10:


První uzel v Oblasti uzlů je canBinary specifikující operand:
canExpr.iFirstNode = 10 (kde 10 je ofset pro celý výrazový strom)
canExpr.iLiteralStart = 48 (kde 48 je ofset pro celý výrazový strom)
canBinary.Operand1 = 12 (kde 12 je ofset v Oblasti uzlů)
canBinary.Operand2 = 24 (kde 24 je ofset v Oblasti uzlů)
canField.iNameOffset = 0 (kde 0 je ofset v Oblasti literálů)
canConst.iOffset = strlen( <fieldName> )+1 (kde hodnota konstanty je právě za jménem položky v Oblasti literálů)

Příklad:
Normálně používáme strom výrazů k získání pohledu pomocí podmínky stromu, která může být značně složitá. Pro srozumitelnost, v tomto příkladě, použijeme jednoduchý filtr, k zobrazení pouze těch záznamů kde "CUST_NO>1500". Naší úlohou je vytvoření stromu výrazu CUST_NO > 1500.00 k předání DbiAddFilter. Následující graf tento výrazový strom popisuje:

Stejný výrazový strom je definován v C jako parametr k předání funkci DbiAddFilter. Následující příklad předpokládá, že překladač alokuje souvisle deklarované proměnné ve fyzické souvislé paměti:
void Filter (void)
{
    hDBIDb          hDb = 0;            // Madlo databáze.
    hDBICur         hCur = 0;           // Madlo tabulky.
    DBIResult       rslt;               // Hodnota vrácená z funkcí IDAPI.
    pBYTE           pcanExpr;     // Struktura obsahující informace filtru.
    hDBIFilter      hFilter;            // Madlo filtru.
    UINT16          uSizeNodes;         // Velikost uzlu ve stromu.
    UINT16          uSizeCanExpr;       // Velikost informací hlavičky.
    UINT32          uSizeLiterals;      // Velikost literálů.
    UINT32          uTotalSize;         // Celková velikost výrazu filtru.
    UINT32          uNumRecs = 10;      // Počet záznamů k zobrazení.
    CANExpr         canExp;             // Obsah informací hlavičky.
    struct {
        CANBinary BinaryNode;
        CANField  FieldNode;
        CANConst  ConstantNode;
    }
    Nodes = {                           // Uzly stromu filtru.
    {
        // Posunutí 0
        nodeBINARY,                     // canBinary.nodeClass
        canGT,                          // canBinary.canOp
        sizeof(Nodes.BinaryNode),       // canBinary.iOperand1
        sizeof(Nodes.BinaryNode) + sizeof(Nodes.FieldNode),
                                        // canBinary.iOperand2
                                        // Posunutí v poli Nodes
    },
    {
        // Posunutí sizeof(Nodes.BinaryNode)
        nodeFIELD,                      // canField.nodeClass
        canFIELD,                       // canField.canOp
        1,                              // canField.iFieldNum
        0,                              // canField.iNameOffset: szField je
                                        //   literál s posunutím 0
    },
    {
        // Posunutí sizeof(Nodes.BinaryNode) + sizeof(Nodes.FieldNode)
        nodeCONST,                      // canConst.nodeClass
        canCONST,                       // canConst.canOp
        fldFLOAT,                       // canConst.iType
        sizeof(fConst),                 // canConst.iSize
        8,                              // canConst.iOffset: fconst je
                                // literal s posunutím strlen(szField) + 1
    }};
static const char szTblName[] = "cust";     // Jméno tabulky
static const char szTblType[] = szDBASE;    // Typ tabulky
static const char szField[]   = "CUST_NO";  // Jméno položky pro třetí uzel
static const DFLOAT fConst    = 1500.0; // Hodnota konstanty pro druhý uzel.

Hlavička výrazového stromu definuje:

Hlavička má tento tvar:
#define CANEXPRVERSION 2
typedef struct{
 UINT16 iVer;
 UINIT16 iTotalSize;
 UINT16 iNodes;
 UINT16 iNodeStart;
 UINT16 iLiteralStart;
} CANExpr;
typedef CANExpr far *pCANExpr;
typedef pCANExpr far *ppCANExpr;

Oblast uzlů výrazového stromu
Každý uzel formuje větev stromu a definuje podmínku. Uzly mohou definovat operátory nebo operandy. Operand uzlu ukládá posunutí jména položky nebo konstanty v oblasti literárů. Hodnoty jsou uložené v oblasti literálů. Položkový uzel ukazuje na posunutí umístění jména položky obsahující literál, tj. znakový řetězec jména položky, který musí být ukončen znakem s kódem nula. Uzel konstanty ukazuje na hodnotu konstanty v oblasti literálů.
Uzly operátorů jsou různých typů:

Relační uzly operátorů
 
Výčtový typ Popis
canISBLANK Unární, prázdný operand
canNOTBLANK Unární, neprázdný operand
canEQ Binární, rovno
canNE Binární, nerovno
canGT Binární, větší než
canLT Binární, menší než
canGE Binární, větší nebo rovno
canLE Binární, menší nebo rovno

Logické uzly operátorů
 
Výčtový typ Popis
canNOT Unární, NOT
canAND Binární, AND
canOR Binární OR

Aritmetické uzly operátorů
 
Výčtový typ Popis
canMINUS Unární, minus. Není podporováno všemi ovladači SQL.
canADD Binární, součet. Není podporováno všemi ovladači SQL.
canSUB Binární, rozdíl. Není podporováno všemi ovladači SQL.
canMUL Binární, násobení. Není podporováno všemi ovladači SQL.
canDIV Binární, dělení. Není podporováno všemi ovladači SQL.
canMOD Binární, celočíselné dělení. Není podporováno všemi ovladači SQL.
canREM Binární, zbytek po dělení. Není podporováno všemi ovladači SQL.

Různé uzly operátorů
 
Výčtový typ Popis
canCONTINUE Unární; zastavuje vyhodnocování výrazu, když je operand vyhodnocen jako false (umožňuje zastavit  na horní hranici hodnoty filtru).

Uzly operátorů ukazují na posunutí jejich uzlů operandů.

Oblast literálů
Oblast literálů je použit k ukládání jmen položek použitých jednotlivými uzly položek a konstantní hodnoty použité jednotlivými uzly konstant. Jméno položky je tvořeno literálem. Hodnoty konstant musí být reprezentovány pouze logickými typy BDE.
Např. následující logická podmínka je reprezentována jako parametr výrazového stromu:
CUST_NO <= 1500 AND CUST_NO >= 1300
Následující příklad předpokládá, že překladač alokuje souvisle deklarované proměnné ve fyzické souvislé paměti
static const char szTblName[] = "cust";     // Jméno tabulky
static const char szTblType[] = szDBASE;    // Typ tabulky
static const char szField[]   = "CUST_NO";  // Jméno pro první uzel položky
static const char szField2[]  = "CUST_NO";  // Jméno pro druhý uzel položky
static const DFLOAT fConst    = 1500.0;     // Hodnota prvního uzlu konstanty
static const DFLOAT fConst2   = 1300.0;     // Hodnota druhého uzlu konstanty
void Filter (void)
{
    hDBIDb          hDb = 0;            // Madlo databáze.
    hDBICur         hCur = 0;           // Madlo tabulky.
    DBIResult       rslt;               // Vrácená hodnota funkcemi IDAPI.
    pBYTE           pcanExpr;    // Struktura obsahující informace filtru.
    hDBIFilter      hFilter;            // Madlo filtru.
    UINT16          uSizeNodes;         // Velikost uzlů ve stromu.
    UINT16          uSizeCanExpr;       // Velikost informací hlavičky.
    UINT32          uSizeLiterals;      // Velikost literálů.
    UINT32          uTotalSize;         // Celková velikost výrazu filtru.
    UINT32          uNumRecs = 10;      // Počet záznamů k zobrazení.
    CANExpr         canExp;             // Obsah informací hlavičky.
    struct {
        CANBinary MainNode;
        CANBinary BinaryNode1;
        CANField  FieldNode1;
        CANConst  ConstantNode1;
        CANBinary BinaryNode2;
        CANField  FieldNode2;
        CANConst  ConstantNode2;
    }
    Nodes = {                           // Uzly stromu filtru.
    {
        // Posunutí 0
        nodeBINARY,                     // canBinary.nodeClass
        canAND,                         // canBinary.canOp
        sizeof(Nodes.MainNode),         // canBinary.iOperand1
        sizeof(Nodes.MainNode)
          + sizeof(Nodes.BinaryNode1)
          + sizeof(Nodes.FieldNode1)
          + sizeof(Nodes.ConstantNode1),// canBinary.iOperand2
                                        //   Posunutí v poli Nodes
    },
    {
        // Posunutí sizeof(Nodes.MainNode)
        nodeBINARY,                     // canBinary.nodeClass
        canLE,                          // canBinary.canOp
        sizeof(Nodes.MainNode)
          + sizeof(Nodes.BinaryNode1),  // canBinary.iOperand1
        sizeof(Nodes.MainNode)
          + sizeof(Nodes.BinaryNode1)
          + sizeof(Nodes.FieldNode1),   // canBinary.iOperand2
                                        //   Posunutí v poli Nodes
    },
    {
        // Posunutí sizeof(Nodes.MainNode) + sizeof(Nodes.BinaryNode1)
        nodeFIELD,                      // canField.nodeClass
        canFIELD,                       // canField.canOp
        1,                              // canField.iFieldNum
        0 ,                             // canField.iNameOffset: szField je
                       // literal s posunutím 0 (začátek oblasti literálů)
    },
    {
        // Posunutí sizeof(Nodes.MainNode) + sizeof(Nodes.BinaryNode1)
        //   + sizeof(Nodes.FieldNode1)
        nodeCONST,                      // canConst.nodeClass
        canCONST,                       // canConst.canOp
        fldFLOAT,                       // canConst.iType
        sizeof(fConst),                 // canConst.iSize
        sizeof(szField),                // canConst.iOffset: fConst je
                                        // literal s posunutím sizeof(szField)
    },
    {
        // posunutí sizeof(Nodes.MainNode) + sizeof(Nodes.BinaryNode1)
        //   + sizeof(Nodes.FieldNode1) + sizeof(Nodes.ConstantNode1)
        nodeBINARY,                     // canBinary.nodeClass
        canGE,                          // canBinary.canOp
        sizeof(Nodes.MainNode)
          + sizeof(Nodes.BinaryNode1)
          + sizeof(Nodes.FieldNode1)
          + sizeof(Nodes.ConstantNode1)
          + sizeof(Nodes.BinaryNode2),  // canBinary.iOperand1
        sizeof(Nodes.MainNode)
          + sizeof(Nodes.BinaryNode1)
          + sizeof(Nodes.FieldNode1)
          + sizeof(Nodes.ConstantNode1)
          + sizeof(Nodes.BinaryNode2)
          + sizeof(Nodes.FieldNode2),   // canBinary.iOperand2
                                        //   Posunití v poli Nodes
    },
    {
        // Posunutí sizeof(Nodes.MainNode) + sizeof(Nodes.BinaryNode1)
        //   + sizeof(Nodes.FieldNode1) + sizeof(Nodes.ConstantNode1)
        //   + sizeof(Nodes.BinaryNode2)
        nodeFIELD,                      // canField.nodeClass
        canFIELD,                       // canField.canOp
        2,                              // canField.iFieldNum
        sizeof(szField)+sizeof(fConst), // canField.iNameOffset: szField2 je
                                     // literal s posunutím sizeof(fConst)
                                     // + velikost první položky
    },
    {
        // Posunutí sizeof(Nodes.MainNode) + sizeof(Nodes.BinaryNode1)
        //   + sizeof(Nodes.FieldNode1) + sizeof(Nodes.FieldNode1)
        //   + sizeof(Nodes.BinaryNode2) + sizeof(Nodes.FieldNode2)
        nodeCONST,                      // canConst.nodeClass
        canCONST,                       // canConst.canOp
        fldFLOAT,                       // canConst.iType
        sizeof(fConst2),                // canConst.iSize
        sizeof(szField)
          + sizeof(fConst)
          + sizeof(szField2),           // canConst.iOffset: fconst je
                              // literal s posunutím sizeof(fConst)+ velikost
                              // první položku + druhé položky
}};
Následující graf reprezentuje stejný výraz (posunutí jsou uvedena v závorkách).

Hlavička:                - - - - - - - - - - - - - - - - - - - - - - - - -
Binární uzel:                                  AND (0)
Binární uzly:                       LE (12)                 GE (50)
Uzly konstant a položek:    FIELD (24)  CONST (36) FIELD (62)   CONST (74)
Oblast literálů:            CUST_NO (0) 1500 (8)   CUST_NO (16) 1300 (24)
 
15. API BDE II