Table ‚…‘ does not exist – jak se postavit k problému create table a následnému insertu?
- ares952
- Člen | 16
Ahoj.
Cca před měsícem jsem si stáhnul nette 2.4. Do té doby jsem cca dva
roky používal 2.2.7.
Přepsal jsem celý svůj základ webů a řeším následující problém:
Připomínám, že u Nette 2.2.7 jsem následující problém neměl.
Při instalaci projektu se provádí následující kód:
$this->database->query("
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'primary key',
`username` varchar(255) NOT NULL COMMENT 'unique username',
`password` varchar(255) NOT NULL COMMENT 'password to log-in',
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='Users'");
$user_id = $this->database->table('users')->insert([
"username" => $installationData["username"],
"password" => Passwords::hash($installationData["password"])
])->id;
Při vkládání admin účtu insertem dojde k následující výjimce:
Table 'users' does not exist.
Když se podívám přes mysql admina, tak tabulka existuje.
Pokud provedu refresh, tak dotaz už projde, ale dostanu násleující další
chybu:
Table 'resources' does not exist.
při vytváření a vkládání dat do resources tabulky a tak dále, až se
nakonec všechno vloží.
Podezření mám na databázovou cache.
Jak jsem zjistil, tak:
- Pokud mezi create table a insert vložím
$this->database->getStructure()->rebuild();
potom je vše OK. Dojde k rebuildu cache a insert vloží do tabulky data bez chyby.
- Pokud před create table nedojde k SQL dotazu:
SHOW FULL TABLES
tak create a insert za sebou projdou bez problémů
Problém je, že
SHOW FULL TABLES
se v mém případě zavolá pokud provedu
jakýkoliv select. Tj. první create table a insert projde OK, ale další
už ne.
Můj dotaz vlastně směřuje k tomu, jak bych se měl k problému postavit. Úplně nejvíc by mi vyhovovalo, kdybych se o nic nemusel starat. Prostě provedu dotazy a cache si případný rebuild zajistí sama. Jak toho ale docílit? Jde to vůbec?
No a nedělám vlastně něco úplně špatně?
Podobný problém se řešil zde:
https://forum.nette.org/cs/13163-zjisteni-existence-tabulek-v-db
Tam to autor vyřešil tak, že nejprve vytvořil tabulky a potom v dalším kroku instalace vkládal data. Tomu bych se ale rád vyhnul.
Děkuji za případné náměty :-).
Editoval ares952 (21. 12. 2016 18:20)
- ares952
- Člen | 16
Samozřejmě, že můžu nejdřív založit tabulky a potom provést
v dalším kroku inserty.
V tuhle chvíli má každý model jedinou funkci pro instalaci – tj.
vytvoření tabulky a inserty. Pokud bych to rozdělil (eventuelně
zkontroloval, zda mám všude
CREATE TABLE IF NOT EXISTS
), potom:
- Buď to udělat metodou next, next přes webové rozhraní
- Udělat to automaticky, vytvořit tabulky, provést rebuild a potom inserty
Jenže to znamená při nejmenším upravit průběh instalace. Myslel jsem si, že bude existovat nějaká obezlička, jak se tomu vyhnout.
Co máš na mysli tím vkládáním hodnot přes cizí klíč?
Při vytváření tabulky users
a následném vložení získám
$user_id
, který potom používám při vkládání dat do další
tabulky (kde je user_id
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
).
Podobně to tak dělám vždy. Zjistím cizí klíč a následně vkládám jeho referenci. Nebo jsi měl na mysli něco jiného?
edit:
To už můžu po každém creatu provést rebuild a bude to méně práce.
Editoval ares952 (21. 12. 2016 18:54)
- CZechBoY
- Člen | 3608
Po každým založení tabulky provést rebuild bude asi celkem náročný,
ne?
Nicméně pokud to nechceš vše přepisovat tak asi jediná možnost.
Ještě je krajní možnost zakázat cache pro instalaci (použít třeba jiný/přídavný konfigurák) – což vyjde asi stejně jako ten rebuild.
Editoval CZechBoY (21. 12. 2016 19:46)
- CZechBoY
- Člen | 3608
Structure zjistuje cizi klice klice (pouzivaji se v DiscoveredReflection), typy policek (pouziva se pri pretypovani pri fetchnuti radku), primarni klic (pro joinovani a pro vraceni hodnoty PK pri insertu – opet s DiscoveredReflection).
Ja z vykonostnich duvodu pouzivam StaticReflection, nicmene se volaji
i metody, ktere by se mely volat jen s DiscoveredReflection :-( tak jsem si
zakomentoval pouziti Structure uplne.
Z toho vyplyva, ze mi vzdy pro kazdy sloupec prijde hodnota typu string.