tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

Omlouváme se, provoz fóra byl ukončen

Oracle, rowCount(), count() a detectTypes()

před 11 lety

m0t3jl
Člen | 293
  1. Mám drobný problém s metodami rowCount() a count() nad instancí DibiResult s databází Oracle. Metoda fetch() mi záznamy vrátí, ale rowCount() a count() tvrdí, že záznamů je 0.
  2. Je něco v nepořádku, nebo proč nefunguje metoda detectType()? Zkoušel jsem přenositelnost aplikace, takže jsem jednoduše změnil config.ini (používám Nette) a ejhle, většina věcí závislých na tom, že čísla se z DB skutečně načítají jako int a float, přestala fungovat…

před 11 lety

m0t3jl
Člen | 293

Trochu více jsem se do toho ponořil a doplňuji další poznatky:

v Oracle ovladači se pro uzjištění počtu řádků používá funkce oci_num_rows, ta ale podle php.net NEVRACÍ počet SELECTnutých řádků, vrací počet fetchnutých řádků, a to je veliký rozdíl. Pokud jde o mně, domnívám se, že count() i rowCount() by měly obě vracet vždy stejný počet řádků v jakémkoliv čase existence instance DibiResult (nehledě na to, jestli už bylo něco fetchnuto, nebo ne).

před 11 lety

David Grudl
Nette Core | 6806

Asi takto – databázi Oracle nemám a ani nechci ji „krást“, takže jsi nejspíš první tester Oracle driveru. Budu rád, pokud mi napíšeš co opravit nebo rovnou pošleš opravený driver. Sám to nemám jak otestovat.

před 11 lety

m0t3jl
Člen | 293

(Dá se volně stáhnout Oracle XE ;))

ad rowCount() a count() – tady Dibi narazí na to, že v té OCI8 knihovně prostě není možnost, jak si zjistit počet řádků vrácených SELECTem, když ještě nebyly fetchnuté. Teď rychle mě konkrétní řešení nenapadá, ale myslím, že moc možností asi nebude. Nějak by se určitě dalo zneužít sloupce rownum, který Oracle používá jako náhradu za LIMIT a OFFSET. Pak mě napadá fetchnout všechny záznamy dopředu, což by ale značně snížilo odezvu systému.

ad detectType) tam by bylo dobré, kdyby se dalo přidat do detekce typů, aby se načítaly datové typy z databází i s rozsahem, protože Oracle nemá dat. typ INTEGER, nebo tak něco. Je jen NUMBER(X,Y) a integer se pozná podle toho, že Y = 0 :(.

před 11 lety

phx
Člen | 652

Ohledne snizeni vykonu: Ono fetchnuti by se mohlo provest pouze pri zavolani fce na zjisteni pocet rakdu. Mohlo by to doprovazet nejaky warnin, ze to neni optimalni a ze je lepsi pouzit … (Oracle moc neznam, takze tezko rict, ale asi SELECT COUNT(*)… nebo ono ROWNUM)

před 11 lety

David Grudl
Nette Core | 6806

m0t3jl napsal(a):

ad rowCount() a count() – tady Dibi narazí na to, že v té OCI8 knihovně prostě není možnost, jak si zjistit počet řádků vrácených SELECTem, když ještě nebyly fetchnuté.

To nevadí, je řada driverů které tohle neumí. oci_num_rows() nahradím vyhozením výjimky.

Pak mě napadá fetchnout všechny záznamy dopředu, což by ale značně snížilo odezvu systému.

Automaticky by se to dělal nemělo, ale uživatel tak samozřejmě postupovat může.

ad detectType) tam by bylo dobré, kdyby se dalo přidat do detekce typů, aby se načítaly datové typy z databází i s rozsahem, protože Oracle nemá dat. typ INTEGER, nebo tak něco. Je jen NUMBER(X,Y) a integer se pozná podle toho, že Y = 0 :(.

Tam se detekuje podle řetězce, který vrátí funkce oci_field_type. Vrací v řetězci i ty závorky a čísla? (tj NUMBER(X,Y)). Nebo je tam ještě funkce oci_field_type_raw, ta vrací co?

…nebo možná by bylo nejjednodušší NUMBER automaticky typovat na float.

před 11 lety

simon
Člen | 98

Oracle se nemusi krast, staci si stahnou Oracle 10g Express Edition, a ted koukam ze uz je i 11g…

před 11 lety

David Grudl
Nette Core | 6806

O existenci Express Edition jsem nevěděl, nicméně stejně mi stáhnout nejde :-(

před 11 lety

m0t3jl
Člen | 293

ad rowCount) možná bych na tvém místě nevyhazoval vyjímku, ale jen upravil PHPDoc count a rowCount() v oracle.php a vepsal do toho, že si lidi mají dát pozor, že to vrací počet již fetchnutých záznamů, ne selectnutých.

ad detekce typů) u INTEGERU i FLOATu vrátí oci_field_type vždy NUMBER; jestli to má být int, nebo float, by se mělo rozhodovat podle oci_field_scale (stejná syntaxe jako oci_field_type), pokud vrátí 0 → číslo je int, pokud něco jiného než 0 → číslo je float.

Pak bych ještě upozornil na BINARY_FLOAT a BINARY_DOUBLE – to jsou taky datové typy, které reprezentují float, podle dokumentace mají být operace nad nimi „extrémně rychlé“ ;). Jestli to půjde, přidej, prosím, i detekci pro ně.

P. S.: Ani si ten Oracle XE nestahuj, stejně je to strašná věc. Od Oraclu za něco stojí jen ty placené a stejně si myslím, že nebýt některých vysoce enterprise vlastností, bychom si vystačili s PostgreSQL ;).

před 11 lety

m0t3jl
Člen | 293

phx napsal(a):

Ohledne snizeni vykonu: Ono fetchnuti by se mohlo provest pouze pri zavolani fce na zjisteni pocet rakdu. Mohlo by to doprovazet nejaky warnin, ze to neni optimalni a ze je lepsi pouzit … (Oracle moc neznam, takze tezko rict, ale asi SELECT COUNT(*)… nebo ono ROWNUM)

Něco takového (COUNT, nebo ROWNUM) by se dalo použít, ale už to počítá s tím, že by se muselo nějak nadetekovat, že SQL, které uživatel zadal, je SELECT a ne třeba UPDATE …

před 11 lety

David Grudl
Nette Core | 6806

K dispozici je update.

S tím že NUMBER se vždy detekuje jako float, nakonec totéž platí i pro typy DECIMAL a NUMERIC u jiných databáze. Rozlišení na integer by vyžadovalo komplikovanější zásah.

rowCount vyhodí výjimku, stejně jako je tomu u bufferovaných spojení s MySQL, SQLite nebo přes PDO. Počet řádků se dá tedy zjistit přes count($result->fetchAll()). Z toho je programátorovi zřejmé, že dochází k načtení všech řádků, takže spíš zvolí zápis $all = $result->fetchAll(); ... count($all) ... a tím optimalizuje kód.

před 11 lety

m0t3jl
Člen | 293

David Grudl napsal(a):

K dispozici je update.

S tím že NUMBER se vždy detekuje jako float, nakonec totéž platí i pro typy DECIMAL a NUMERIC u jiných databáze. Rozlišení na integer by vyžadovalo komplikovanější zásah.

rowCount vyhodí výjimku, stejně jako je tomu u bufferovaných spojení s MySQL, SQLite nebo přes PDO. Počet řádků se dá tedy zjistit přes count($result->fetchAll()). Z toho je programátorovi zřejmé, že dochází k načtení všech řádků, takže spíš zvolí zápis $all = $result->fetchAll(); ... count($all) ... a tím optimalizuje kód.

Myslím, že to tak prozatím můžeme vyřešit.

před 11 lety

simon
Člen | 98

Ted jsem to zkousel a stahnout jde.
Jdi na http://www.oracle.com/…winsoft.html
musis tam zvolit accept, maj to trapne reseny pres JS, tak kdyby to neslo tak preklikni na decline a zpatky na accept. Vyber si treba Oracle Database 10g Express Edition (Universal) a pak zadej uzivatelsky jmeno a heslo a zacne se to stahovat. Bohuzel musis byt zaregistrovany.

před 11 lety

David Grudl
Nette Core | 6806

Mně se právě nepodařilo zaregistrovat. Ale serepes…

před 11 lety

simon
Člen | 98

Tak to pak jo, je to dlouho co jsem se tam registroval. Kdyby si po ty databazi joo tolik touzil tak ti ji muzu hodit nekam na ftp.

před 11 lety

simon
Člen | 98

Ale stejne je zajimavy ze si dal do kupy driver bez toho aby byl otestovanej. Nerikam tim ze to delas spatne nebo ze to je chyba, jen to je zajimavy ze to vlastne vubec „nejak“ funguje:D