Prosím o otestování Nette Database 4.0 RC
- David Grudl
- Nette Core | 8218
Prosím o otestování nové velké verze Nette Database 4.0 RC
composer require nette/database:^4.0.0-dev
Nová verze představuje především velkou architektonickou změnu. Není už pevně spojená s PDO. A je možné doplnit drivery pro další databázové rozšíření v PHP. Například mysqli, které přinese možnost spouštět dotazy paralelně, což může být hodně zajímavé.
Další novinkou je spojení tříd Nette\Database\Connection
a
Explorer
do jedné. Ono to tak kdysi v NDB bylo a myslím, že je
dobré se k tomuto konceptu vrátit. Názvy těchto tříd jsou nyní
aliasy.
Novinkou je možnost konfigurovat, jak se převádí hodnoty načtené z databáze, a to pomocí
database:
dsn: ...
options:
convertBoolean: true # MySQL tinyint(1) / BIT v SQLServer převádí na boolean
convertDateTime: true # zda převádět data na objekty DateTime
convertDecimal: true # zda převádet na int/float nebo ponechat string
newDateTime: true # používá Nette\Database\DateTime místo Nette\Utils\DateTime
Všechny tyto volby jsou zapnuté by default, stejně jako volba newDateTime
.
Změny:
- Metoda
getInsertId()
nyní vrací integery místo řetězců - Metoda
DriverException::getCode()
vrací číselný driver-specific kód místo řetězce SQLstate - Z kódu jsem dal pryč rozhraní
IRow
aIRowContainer
, které imho k ničemu užitečnému nebyly - Deprecated jsou metody poplatné čistě PDO:
Connection::getPdo()
,getDsn()
Mám připravených pár bombastických novinek, které vyžadují novou architekturu Nette Database 4.0
A ačkoliv je nová verze pod kapotou kompletně předělaná, snažil jsem se, aby nezpůsobovala žádné nekompatibility. Na svých projektech jsem nepotřeboval cokoliv upravovat. Tak prosím ověřte, jestli na nějaké nekompatibility nenarazíte, ať je můžeme vychytat.
Je to někdo, kdo si vytvářel pro NDB vlastní databázový driver?
- kminekmatej
- Generous Backer | 38
Ahoj,
já mám ve svém projektu definován přístup ke dvěma databázím a po
přepnutí na DB4 mi nejde vybuildit container. Error log: https://cloud.kminet.eu/…9TmJDBpRMKjD . Config db
vypadá takto:
database:
default:
dsn: 'mysql:host=localhost;dbname=admin.boost.space'
user: dbuser
password: 'dbpwd'
b:
dsn: 'mysql:host=localhost;dbname=boost.space'
user: dbuser
password: 'dbpwd'
reflection: conventional
- ViPEr*CZ*
- Člen | 817
Zkousim na jedne mensi appce.
Dostavam se na
Argument #1 ($dateTime) must be of type Nette\Utils\DateTime, Nette\Database\DateTime
Coz jsem teda vyresil asi na dvou mistech. Asi muze byt opruz kdyz to je na
vice mistech.
Ale melo by to jit resit strojove.
Jen jsem to chtel rovnou checknout na PHP 8.4 a koukam, ze mame
za-lockovano
nette/routing v3.1.0 requires php 8.1 – 8.3 → your php version
(8.4.0beta4) does not satisfy that requirement
Na 8.3.11 to frci :-)
- smuuf
- Člen | 1
DB driver
My vlastní DB driver používáme – vypadá nějak takto:
<?php
declare(strict_types=1);
namespace App\Infra\Database\Drivers;
use Nette\Database\Driver;
use Nette\Database\Connection;
use Nette\Database\Drivers\MySqlDriver;
final class AcmeMysqlDbDriver extends MySqlDriver {
/** @var bool Does this driver support setting isolation level for transaction? */
public const SUPPORTS_ISOLATION_LEVEL = true;
/** @var int Max execution time for each query (in seconds) within a DB connection. */
private const MAX_STATEMENT_TIME = 60 * 10;
/**
* @param array{
* charset?: string,
* sqlmode?: string,
* supportBooleans?: bool,
* } $options
*/
public function initialize(Connection $connection, array $options): void {
parent::initialize($connection, $options);
$connection->query(sprintf(
'SET SESSION max_statement_time=%d;',
self::MAX_STATEMENT_TIME,
));
// https://jira.mariadb.org/browse/MDEV-20083
// https://mariadb.com/kb/en/conversion-of-big-in-predicates-into-subqueries/
// Disable this "optimization", because our queries are MUCH faster (in
// another words: they finish and do not hang.)
$connection->query('SET SESSION in_predicate_conversion_threshold=0;');
// NOTE: Cannot use PHP8,1 first-class callable syntax as we sometimes
// need to serialize DB connection - e.g. in tests - where PHP
// would complain about serializing a closure.
$connection->setRowNormalizer(
[BothWaysDbRowKeysNormalizer::class, 'normalizeRow'],
);
}
public function isSupported(string $item): bool {
return in_array($item, [
Driver::SupportSelectUngroupedColumns,
Driver::SupportMultiColumnAsOrCond,
Driver::SupportSubselect,
], true);
}
}
Jak je vidět, využíváme inicializaci driveru pro nastavení potřebných
věcí pro dané spojení – doufám, že tahle možnost bude
v 4.0 zachovaná. V https://github.com/…Explorer.php#L35
vidím možný list $onConnect
callbacků, kam by se toto dalo
strčit, ale jelikož není zřejmé, jak (kdy přesně) se v rámci Nette DI
bude připojení ve finále inicializovat, tak netuším, zda budu mít možnost
nějaké $onConnect[] = ...
udělat ještě před tím, než se
zavolá connect()
– snad ano.
Row normalizer
Pokud koukám správně, tak v aktuálním masteru také vidím, že je
„row normalized“ deprecated:
[...] is deprecated, configure 'convert*' options instead.
, viz https://github.com/…Explorer.php#L202
Row normalizer používáme ke modifikování dat array (slovníku)
daného řádku – v našem případě hodnotu pod klíčem
(sloupcem) this_is_some_column
chceme mít k dispozici i pod
klíčem thisIsSomeColumn
, takže potřebujeme duplikovat klíče
se změněným case (což bychom btw. nemuseli duplikovat, kdyby se kdysi
nezavrhly věci typu https://github.com/…se/issues/90).
Čili jelikož potřebujeme modifikovat celý array, tak nějaké:
class Explorer
{
...
private const TypeConverterOptions = ['convertBoolean', 'convertDateTime', 'convertDecimal', 'newDateTime'];
...
}
… je nám docela k ničemu. Bylo by fajn udržet možnost si připravit data řádku tak, jak my potřebujeme. Pokud se možnost toto dělat někde v 4.0 schovává, tak jsem to nebyl schopen rozpoznat – a kdyby to nešlo, tak to bude upgrade na Nette Database 4.0 silně blokovat.
Zmizelé getDsn()
V naší appce databázi shardujeme – máme hlavní DB + zcela separátně jiné, menší databáze. Pro spojení k tomuhle všemu používáme Nette Database/Explorer a kvůli tomu musíme v kódu managovat vytváření instancí spojení a Explorerů pro každý shard.
K tomu se nám náramně hodí getDsn()
, které je aktuálně
k dispozici (např. jako klíč pro kešování zmiňovaných instancí,
ale i další věci, které jsou složitější k vysvětlení).
Hlasoval bych pro zachování možnosti získat z PDO driveru zpět
DSN – které tam, jestli koukám správně, stejně bude moct
být: https://github.com/…O/Driver.php#L24
Editoval smuuf (9. 10. 10:13)