Spatne určená cizí tabulka, jde si rucne nadefinovat strukturu databáze

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

Ahoj,
občas se mi stává že se nette databaze netrefí když nacucává řádek z cizí tabulky

$jabko->hruska
$jabko->ref('hruska')

Pokud zadám i sloupec s cizím klíčem tak už funguje

$tabulkaA->ref('hruska', 'hruskaId)

Věčinou si to plete tabulky se stejným začátkem názvu (jabko, jabkoHruska). Cizí klíče jsem kontroloval, používám innodb tabulky, temp jsem zkoušel promáznout.

Dá se ručně nadefinovat struktura DB?

vvoody
Člen | 910
+
0
-

murdej napsal(a):

Dá se ručně nadefinovat struktura DB?

Čo ti v tom bráni? Dôležité je ju navrhnúť tak aby použitá Reflecion správne určovala väzby.

murdej
Člen | 26
+
0
-

vvoody napsal(a):

murdej napsal(a):

Dá se ručně nadefinovat struktura DB?

Čo ti v tom bráni? Dôležité je ju navrhnúť tak aby použitá Reflecion správne určovala väzby.

Navrženou ji mám dobře, problém je v tom Reflection dělá občas chyby. Takže přeformuluji dotaz:

Dá se nette database vnutit rucne napsana struktura db aby nepoužíval reflection ke zjišťování?

nanuqcz
Člen | 822
+
0
-

vvody: murdej to asi myslel tak, že by chtěl NetteDB nějak přímo vnutit informace o tom, jak struktura DB vypadá.

Taky se mi totiž občas stává, že přestože používám Innodb a cizí klíče mám správně nastavené, tak se na některé cizí tabulky přes tečkovou/dvojtečkovou notaci nedostanu. (Bohužel jsem nepřišel na žádný konkrétní postup, jak tuto chybu cíleně způsobit, tak jsem o tom ani nepsal. Navíc u mě se to projevuje na jednom větším projektu, který ani neběží na nejaktuálnějším Nette.)

vvoody
Člen | 910
+
0
-

Tak keď vám nevyhovuje discovered reflection tak si ju treba ohnúť. Ak nechápete jej pravidlám tak uveďte reálny príklad, čiže sql dump tabuliek a kód ktorý vyhadzuje výnimku alebo nepracuje tak ako by ste chceli. Rád poradím, keď budem toho schopný. Najlepšie je to na vašom kóde a nie na hruškách a jabĺčkách ;)

murdej napsal(a):

Dá se nette database vnutit rucne napsana struktura db aby nepoužíval reflection ke zjišťování?

Áno dá, nette reflection nepoužije ak v selectoch nejoinujes a väzobné dáta získavaš pomocou funkcií ref a related tak, že vždy uvedieš oba parametre.

hrach
Člen | 1834
+
0
-

Furt melete o tom, ze je treba ohnout neco, ale vubec neni jasny, kde je chyba. Koukej sem dat poradny priklad. Konkretni dump dvou tabulke a vazem mezi nimi. ;)

enumag
Člen | 2118
+
0
-

@hrach: +1

Kromě toho nikde nezaznělo, že @murdej opravdu používá discovered reflexi a nemá omylem zapnutou conventional, s tou by to samozřejmě fungovat nemohlo.

murdej
Člen | 26
+
0
-

Toto je kus kódu který dělal problémy:

// Načtu záznam z tabulky productSell
$productSell = $this->context->productSells->find(1);

// Toto vrátí správný záznam z tabulky product
$product = $product->ref('product', 'productId');

// Toto vrátí záznam z packageProduct
$product = $productSell->product;

Takže je to trochu jinak než jsem psal v prvním příspěvku, vypadá to že si to plete tam kde jsou stejné konce názvů tabulek, ne začátky.

Edit: Dělalo to problémy i u tečkové notace u where ale ten kus kódu už nemám přepsal jsem ho. Ale příčina bude podle mě stejná jako u toho kódu výše.

Db dump:

CREATE TABLE `packageProduct` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `packageId` int(10) unsigned NOT NULL,
  `productId` int(10) unsigned NOT NULL,
  `amount` double DEFAULT NULL,
  `fromCredit` tinyint(1) NOT NULL,
  `priceCredit` decimal(10,0) DEFAULT NULL,
  `priceDirect` decimal(10,0) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_packageProduct_package1_idx` (`packageId`),
  KEY `fk_packageProduct_product1_idx` (`productId`),
  CONSTRAINT `fk_packageProduct_package1` FOREIGN KEY (`packageId`) REFERENCES `package` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `fk_packageProduct_product1` FOREIGN KEY (`productId`) REFERENCES `product` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;

CREATE TABLE `product` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(200) COLLATE utf8_czech_ci NOT NULL,
  `description` text COLLATE utf8_czech_ci NOT NULL,
  `price` decimal(10,0) NOT NULL,
  `enabled` tinyint(1) NOT NULL,
  `customerOnly` tinyint(1) NOT NULL,
  `packageId` int(10) unsigned DEFAULT NULL,
  `productId` int(10) unsigned DEFAULT NULL,
  `isCategory` tinyint(1) NOT NULL,
  `position` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_product_package1_idx` (`packageId`),
  KEY `fk_product_product1_idx` (`productId`),
  CONSTRAINT `fk_product_package1` FOREIGN KEY (`packageId`) REFERENCES `package` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `fk_product_product1` FOREIGN KEY (`productId`) REFERENCES `product` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;

CREATE TABLE `productSell` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `productId` int(10) unsigned NOT NULL,
  `prepaidId` int(10) unsigned DEFAULT NULL,
  `packageProductId` int(10) unsigned DEFAULT NULL,
  `directpaidId` int(10) unsigned DEFAULT NULL,
  `priceDirectpaid` decimal(10,0) DEFAULT NULL,
  `priceCredit` decimal(10,0) DEFAULT NULL,
  `productAmount` decimal(10,0) DEFAULT NULL,
  `utSell` int(10) unsigned NOT NULL,
  `createUserId` int(10) unsigned NOT NULL,
  `cancelUserId` int(10) unsigned DEFAULT NULL,
  `cancelUt` int(10) unsigned DEFAULT NULL,
  `cancelNote` text COLLATE utf8_czech_ci,
  PRIMARY KEY (`id`),
  KEY `fk_productSell_product1_idx` (`productId`),
  KEY `fk_productSell_prepaid1_idx` (`prepaidId`),
  KEY `fk_productSell_packageProduct1_idx` (`packageProductId`),
  KEY `fk_productSell_directPaid1_idx` (`directpaidId`),
  KEY `createUserId` (`createUserId`),
  KEY `cancelUserId` (`cancelUserId`),
  CONSTRAINT `fk_productSell_prepaid1` FOREIGN KEY (`prepaidId`) REFERENCES `prepaid` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `productSell_ibfk_1` FOREIGN KEY (`packageProductId`) REFERENCES `packageProduct` (`id`),
  CONSTRAINT `productSell_ibfk_2` FOREIGN KEY (`productId`) REFERENCES `product` (`id`),
  CONSTRAINT `productSell_ibfk_3` FOREIGN KEY (`directpaidId`) REFERENCES `directpaid` (`id`),
  CONSTRAINT `productSell_ibfk_4` FOREIGN KEY (`createUserId`) REFERENCES `user` (`id`),
  CONSTRAINT `productSell_ibfk_5` FOREIGN KEY (`cancelUserId`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;

Editoval murdej (18. 2. 2013 7:01)

redhead
Člen | 1313
+
0
-

Řekl bych, že problém bude tady

Pokud reflexe objeví ty sloupce v pořadí [packageProductId, productId] tak vrátí packageProduct místo product. Jestli to je bug, nevím, v Nette\Database se vyzná snad jen @hrach :D

EDIT: nepodařilo se mi to ale reprodukovat. I když změním pořadí sloupců, tak je vždy první productId a až pak packageProductId (samozřejmě mažu cache).

Editoval redhead (18. 2. 2013 15:55)

hrach
Člen | 1834
+
0
-

Nette Database aplikuje (jak spravně zminuje redhead) first-match. Nicméně, aby to mělo nějakou logiku, tak si všechny klíče řadí dle délky. Díky tomu je prostě jednoduché špatný resolve vyřešit tím, že uvedu delší matchovací část :)

V tomto konkrétním příkladu: to, že $productSell->product; matche packageProductId opravdu vypada na chybu, protoze productId je kratsi. Vzhledem k tomu, ze redheadovi se to nepodarilo reprodukovat, tak si rikam, jestli nebude problem jeste nekde u tebe. Jakou mas verzi nette?

redhead
Člen | 1313
+
0
-

@hrach: to, že se mi to nepodařilo reprodukovat, moc neznamená, vzhledem k tomu, že ten DB dump je nepoužitelný pro copy n' paste. Musel jsem ho promazat tak, aby prošel import. Mohl jsem tedy umazat něco, co to dělá…

murdej
Člen | 26
+
0
-

Verzi mam (version 2.0.8 released on 2013–01–01, https://nette.org) pro PHP 5.3+