LOBy v OCI

Jazyk C

K práci s LOBy se v OCI používají proměnné typu OCILobLocator reprezentující lokátory LOBů.
Tyto lokátory jsou používány všemi funkcemi, které pracují s LOBy.
Chceme-li s LOBem pracovat, je třeba alokovat jeho lokátor a inicializovat ho.

Alokace

Pro lokátor je třeba alokovat paměť funkcí OCIDescriptorAlloc, které předáme jako typ deskriptoru konstantu OCI_DTYPE_FILE (externí LOB) nebo OCI_DTYPE_LOB (interní LOB) - tyto lokátory nelze zaměňovat, ačkoliv jsou v C stejného typu.

OCIDescriptorAlloc(*environment,*lob,type,size,...)
Alokuje a vrací lokátor externího (type = OCI_DTYPE_FILE) nebo interního (OCI_DTYPE_LOB) LOBu.
Rezervuje pro něj paměť velikosti size.

OCIDescriptorFree(*locator,*type)
Uvolní lokátor a paměť, kterou měl alokovánu.


Inicializace

Před použitím lokátoru ho musíme inicializovat. Máme několik možností:

Práce s LOBy

Když máme alokován interní LOB, lze z něj číst a zapisovat do něj. Do externího LOBu nelze přes OCI zapisovat.

OCILobRead(...,*lob,*buffer,buffer_length,offset,callback,...)
Načte specifikovanou část LOBu do bufferu.
Pokud nebyla načtena všechna požadovaná data, vrací funkce chybu OCI_NEED_DATA a aplikace může funkci volat znovu, dokud nedostane vše.
Data lze číst také callback funkcí, pokud je na ni předán ukazatel.

OCILobWrite(...)
Analogie funkce pro čtení.
Zapisovat však lze jen do interních LOBů.
Přemaže data uložená v LOBu novými.

OCILobWriteAppend(...)
Data se připisují na konec existujícího LOBu, není zde proto parametr offset.
Jinak podobné funkci OCILobWrite.

OCILobGetLength(...,*lob,*length)
Do length vloží délku LOBu, tj. počet znaků pro znakové LOBy nebo počet byte pro BLOB resp. BFILE.

Příklad použití od Oraclu:
cdemolb.h,cdemolb.c


Pro interní LOBy můžeme používat tyto funkce:

OCILobAppend(...,*src_lob,*dst_lob),
OCILobCopy(...,*src_lob,*dst_lob,amount,src_offset,dst_offset),
OCILobErase(...,*lob,amount,offset),
OCILobTrim(...,*lob,new_length),


Pro externí LOBy lze použít následující funkce:

OCILobFileOpen(...,*lob,OCI_FILE_READONLY)
Otevře na serveru soubor externího LOBu.

OCILobFileClose(...,*lob)
Uzavře na serveru soubor externího LOBu.

OCILobFileGetName(...,*lob,*directory_alias,*alias_length,*file_name,*name_length)
Vrací alias adresáře a název souboru LOBu.

OCILobFileSetName(...,*lob,*directory_alias,*alias_length,*file_name,*name_length)
Nastaví alias adresáře a název souboru LOBu.

OCILobFileIsOpen(...,*lob,*is_open)
Zjistí, zda je soubor otevřen.

OCILobFileExists(...,*lob,*is_exists)
Zjistí, zda soubor existuje.


Otevírání a uzavírání LOBů

Každý LOB na serveru může je buď otevřený nebo uzavřený.
Je-li s uzavřeným LOBem manipulováno, automaticky se otevře, provede se požadovaná operace a po skončení této operace se uzavře. Po uzavření LOBu se provedou triggery, jsou-li nějaké definovány.
Sérii úprav LOBu lze obklopit funkcemi pro otevření a uzavření LOBu tak, aby se během těchto úprav nevyvolávaly triggery.

OCILobOpen(...,*lob,mode),
Otevře LOB pro čtení (mode=OCI_LOB_READONLY) resp. čtení a zápis (mode=OCI_LOB_READWRITE).
Stejný účinek má také funkce OCILobOpen() používaná pro externí LOBy.

OCILobClose(...,*lob),
Uzavře LOB.
Stejný účinek má také funkce OCILobClose() používaná pro externí LOBy.

OCILobIsOpen(...,*lob,mode),
Zjistí, zda je LOB otevřen.


Bufferování dat LOBů u klienta

Při práci s interními LOBy lze zvýšit výkon aplikace, které provádí mnoho čtení nebo zápisů krátkých úseků LOBů.
Dosáhneme toho zapnutím bufferování na straně klienta.

OCILobEnableBuffering(...,*lob),
Zapne bufferování.

OCILobDisableBuffering(...,*lob),
Zruší bufferování.

OCILobFlushBuffer(...,*lob),
Zapíše obsah bufferu na server.


Některé funkce však nelze používat se zapnutým bufferováním:
OCILobAppend(), OCILobCopy(), OCILobErase(), OCILobGetLength(), OCILobLoadFromFile(), OCILobTrim(), OCILobWriteAppend()


Dočasné LOBy

Dočasné LOBy mají data uložena na serveru, avšak lokátor mají pouze u klienta.
Jejich životnost je omezena obvykle po dobu trvání session, lze ale nastavit jinak.
Na dočasný LOB je možné aplikovat funkce používané pro standardní LOBy.
Používají se jako lokální pomocné proměnné.

OCILobCreateTemporary(...,*lob,type,cache,duration),
Vytváří dočasný LOB, který je inicializován jako prázdný.
Typ LOBu je jedna z hodnot OCI_TEMP_BLOB, OCI_TEMP_CLOB, OCI_TEMP_NCLOB.
Parametr cache udává, zda se má na serveru umístit LOB do cache.
Dobu života LOBu lze ovlivnit parametrem duration:
OCI_DURATION_SESSION... LOB je automaticky zrušen po odhlášení,
OCI_DURATION_CALL ... LOB je zrušen po dokončení volání následující OCI funkce.

OCILobFreeTemporary(...,*lob),
Zruší dočasný LOB - lokátor i data.

OCILobIsTemporary(...,*lob),
Zjistí, zda je daný LOB dočasný.

Příklad použití od Oraclu:
TLOBS.C

PHP

Interně pracuje přes OCI v jazyce C.
Nejsou podporovány všechny funkce OCI, ale základní ano.

Vybrané OCI funkce v PHP:

OciLogon(user,password,connection_string) Přihlásí se k databázi.
  
OciLogoff(connection) Odhlásí se od databáze (automaticky po ukončení skriptu).
  
OciParse(connection,SQL) Vrací statement jako identifikátor zpracovaného výrazu na serveru.
  
OciExecute(statement[,mode]) Vykoná na serveru rozparsovaný výraz statement.
Transakce je automaticky potvrzena, pokud není uveden mod OCI_DEFAULT.
  
OciCommit(connection) Potvrdí probíhající transakci.
  
OciRollback(connection) Zruší probíhající transakci.
  
OciFetch(statement) Do interního bufferu PHP vloží jednu řádku z výsledku (sekvenčně).
  
OciResult(statement,column_name) Z řádku uloženém v interním bufferu vybere hodnotu v zadaném sloupci.
  
OciBindByName(statement,sql_var,variable,length[,type]) Vytvoří vazbu proměnné PHP variable na zástupnou proměnnou v SQL sql_var.
Pokud je proměnná LOB, musí být specifikován typ:
OCI_B_FILE, OCI_B_CFILE, OCI_B_CLOB nebo OCI_B_BLOB.
Délka dat v proměnné nesmí přesáhnout length, u LOBů se nepoužívá.
  
OciNewDescriptor(connection,type) Alokuje a vrací lokátor externího (type = OCI_D_FILE) nebo interního (OCI_D_LOB) LOBu.
  
OciFreeDesc(locator) Zruší lokátor a uvolní paměť.

Lokátor, jenž je vrácen funkcí OciNewDescriptor, je objekt, který má pro interní LOBy tři metody: Pokud je LOB externí, je implementována jen metoda Load.

Příklad:
<?php

/* Prihlaseni k databazi ************************************************/ 

  $connection = OciLogon("scott","tiger","DB");

/* Vytvoreni tabulky ****************************************************/ 
  
  $statement = OciParse($connection,
    "CREATE TABLE Tab(Jmeno VARCHAR(20), Data CLOB)");
  @OciExecute($statement);

  OciFreeStatement($statement);

/* Ulozeni LOBu do tabulky **********************************************/

  $statement = OciParse($connection,
    "INSERT INTO Tab(Jmeno,Data) 
     VALUES('lob.txt',EMPTY_CLOB()) 
     RETURNING Data INTO :lob");
  
  //Pripojeni lokatoru LOBu:
  $locator = OciNewDescriptor($connection,OCI_D_LOB);
  OciBindByName($statement,":LOB",&$locator,-1,OCI_B_CLOB);
  
  OciExecute($statement,OCI_DEFAULT);
  
  //Nacteni LOBu ze souboru:
  $locator->SaveFile("lob.txt");

  OciCommit($connection);
  
  OciFreeStatement($statement);

/* Nacteni LOBu z tabulky ***********************************************/
  
  $statement = OciParse($connection,"SELECT Jmeno,Data FROM Tab");
  
  OciExecute($statement,OCI_DEFAULT);

  while (OciFetch($statement))
  { $lob = OciResult($statement,"DATA");
    echo $lob->Load()."<BR>";
  }  

  OciCommit($connection);
  
  OciFreeStatement($statement);
?>