Database a detekcia typu – chyba pri dátovom type TINYINT

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
dakota
Člen | 148
+
0
-

Nette Framework 2.0-dev rev. f8b6f0f released on 2011–02–24

V Nette\Database pri detekcii typu ak ide o dátový typ TINYINT tak to vyhadzuje chybu:

PHP Notice: Undefined index:  native_type in ...\libs\Nette\Database\Statement.php:103

Ide asi o bug v PHP, kde PDO v getColumnMeta nevráti pri TINYINT, YEAR a BIT native_type http://bugs.php.net/bug.php?….

Chybu som spozoroval v PHP 5.2 aj 5.3

Tiež by som chcel upozorniť na chybu v DatabasePanel kde sa zobrazuje iný počet dotazov a čas v tabe a iný v paneli – v paneli sa k počte dotazov a k času pripočitajú aj explain dotazy.

Editoval dakota (24. 2. 2011 19:16)

David Grudl
Nette Core | 8228
+
0
-

fixed

dakota
Člen | 148
+
0
-

Pritom sa TINYINT nezkonvertuje na integer ale zostane string. Je táto detekcia typu spoľahlivá? V dokumentácii php je funkcia PDOStatement->getColumnMeta() označená ako experimentálna.

Editoval dakota (25. 2. 2011 14:29)

David Grudl
Nette Core | 8228
+
0
-

Bohužel nic spolehlivějšího neznám. PDO je, zdá se, zatím hodně nedotažené.

jtousek
Člen | 951
+
0
-

Nemá na to Jakub Vrána nějaký recept? Nebo v NotORM použil taky tohle?

dakota
Člen | 148
+
0
-

V NotORM automatické pretypovanie nie je. Nebolo by lepšie to dať konfigurovateľné $detectTypes = TRUE|FALSE – kvôli problému s native_type, tiež niektoré PDO drivery nemusia podporovať getColumnMeta.

Editoval dakota (25. 2. 2011 14:27)

David Grudl
Nette Core | 8228
+
0
-

No pokud to nepodporují, tak se to přetypovávat nebude. Nenapadá mě důvod, proč by někdo přetypování vypínal, pokud do DB uložím integer, tak očekávám integer i na výstupu. Takže spíš bych udělal fix pro špatně fungující getColumnMeta() (je to experimental už 5 let a koukám, že od 5.3 do vrací nesmyslně i položku len).

jtousek
Člen | 951
+
0
-

Jenom bacha na boolean v PostgreSQL…

David Grudl
Nette Core | 8228
+
0
-

Nefunguje? Postgres tu nemám, můžete někdo prosím ověřit, že se všechny typy přetypovávají správně?

dakota
Člen | 148
+
0
-

Asi je to len dočasne zle fungujúce (revízia z 24.02.2011): po type TINYINT – chybajúci native_type – dôjde k tomu že sa na detekciu typu používa zlý index stĺpca (na základe count($this->types)) a tym prestane správne pretypovávať ostatné zvyšné stĺpce.

$this->types = array();
foreach ($row as $key => $foo) {
	$type = $this->getColumnMeta(count($this->types));
	if (isset($type['native_type'])) {
		$this->types[$key] = NDatabaseReflection::detectType($type['native_type']);
	}
}

Editoval dakota (25. 2. 2011 20:27)

jtousek
Člen | 951
+
0
-

Otestovat bohužel nemůžu. Já jen, že PostgreSQL nesmyslně vrací boolean hodnoty jako „t“ a „f“. Převádět to na PHP boolean mě (spolu s dalšími věcmi) otrávilo do té míry, že jsem postgres na VPSku odinstaloval.

Ondřej Mirtes
Člen | 1536
+
0
-

Průšvih je, že když to přijde z databáze, tak nevíš, jestli máš uložený string ‚t‘ nebo true, resp. string ‚f‘ nebo false. Řešením je uložit si informaci o typu sloupce ještě někam vedle v PHP.

PostgreSQL je jinak skvělá databáze :)

David Grudl
Nette Core | 8228
+
0
-

Boolean by to mělo zvládat bez obtíží https://github.com/…tatement.php#L126

PaBi3
Bronze Partner | 62
+
0
-

Je korektné chovanie, že napr. pri inserte, či update nie sú vstupné údaje normalizované na správne typy?

V prípade, že používam PostgreSQL a vložím nejaké údaje do tabuľky, ktorá má stĺpec typu boolean, tak sa vyhodí PDOException: Datatype mismatch: 7 ERROR: column "visible" is of type boolean but expression is of type integer.

Jan Tvrdík
Nette guru | 2595
+
0
-

V snažíš se tam vložit boolean nebo integer?

PaBi3
Bronze Partner | 62
+
0
-

Áno. Ak chceš napr. vložiť PHP boolean hodnotu do PostgreSQL so stĺpcom boolean, tak sa nepretypuje.

Ako workaround máš možnosť boolean vkladať ako string true/false. Myslím, že v dibi existovalo detectTypes, ktoré typy automaticky rozpoznalo a tento problém riešilo.

<?php
$db->table('test')->insert(array('somebool' => true)); // vyhodí PDOException
$db->table('test')->insert(array('somebool' => 'true')); // prejde
?>
David Grudl
Nette Core | 8228
+
0
-

To se může vyhodnotit dvěma způsoby, zkus teda obojí:

$database->query('INSERT INTO tbl VALUES(?)', array(TRUE, FALSE));

$database->query('INSERT INTO tbl VALUES(?, ?)', TRUE, FALSE);

Které z toho selže?

PaBi3
Bronze Partner | 62
+
0
-

Selže iba to prvé za predpokladu štruktúry:

create table tbl (
	data1 boolean,
	data2 boolean
);

Lenže je bežnou praxou insertovať rovno údaje z formulára. Napr.:

<?php
$form = $form->getValues();
$database->table('tbl')->insert($values);
?>

To týmto pádom nefunguje, ak mám v tabuľke boolean stĺpec.

Editoval PaBi3 (24. 3. 2011 15:42)

dakota
Člen | 148
+
0
-

PDO v MySQL v getColumnMeta() nevráti pri TINYINT, YEAR a BIT native_type,

Ak je niektorý z stĺpcov typu TINYINT, YEAR a BIT, tak v MySQL pri načítaní dat sú ostatné zvyšné stĺpce nesprávne pretypované – je to spôsobené chybným count($this->types).

Uprava Database\Statement::normalizeRow() – doplnené else {…}:

foreach ($row as $key => $foo) {
	$type = $this->getColumnMeta(count($this->types));
	if (isset($type['native_type'])) {
		$this->types[$key] = Reflection\DatabaseReflection::detectType($type['native_type']);
	} else {
		$this->types[$key] = NULL;
		// prip. $this->types[$key] = Reflection\DatabaseReflection::FIELD_UNKNOWN;
	}
}

Editoval dakota (2. 6. 2011 12:35)

hrach
Člen | 1838
+
0
-

zaslan pullrequest