Prosím o otestování nette/database 3.2

David Grudl
Nette Core | 8227
+
+3
-

Prosím o otestování Database 3.2.0 RC

composer require nette/database:^3.2.0-RC2

Minimální vyžadovaná verze PHP je 8.1, pro kterou byl kód vylepšen a byly doplněny všechny typehinty. Změny jsou jen drobné:

  • MySQL: nulové datum 0000-00-00 vrací jako null
  • MySQL: decimal bez desetinných míst vrací jako int místo float
  • typ time vrací jako DateTime s datumem 1. 1. 0001 místo aktuálního data

Tedy nasazení by mělo být zcela hladké.

Hikikomori
Člen | 1
+
0
-

Jedna maličkost, Selection::select() má typehint string|array $columns které jsou předané do SqlBuilder::addSelect() kde je ale pouze string $columns.

Možná zapomenutý implode?

kminekmatej
Generous Backer | 38
+
0
-

Minimálně naše integrační testy žádnou chybu nehlásí

Pavel Kravčík
Člen | 1195
+
0
-

Datumy fungují ok, ale rozhodilo to sandál souboru, který volá transakce (při beginTransaction to hlásí neini PDO), příští týden zkusíme víc prověřit.

Kacer_Bob
Člen | 7
+
+1
-

Bylo by možné doplnit v MySQL driveru také podporu pro typ boolean?

MariaDB ani MySQL nemají nativní typ BOOLEAN, ale místo toho používají TINYINT(1).
https://mariadb.com/kb/en/boolean/
https://dev.mysql.com/…a-types.html

Je to analogický případ jako převod decimal na integer.

David Grudl
Nette Core | 8227
+
0
-

To by šlo. Snad to nezpůsobí nějaké nečekané nekompatibility. Vydal jsem to jako v3.2.0-RC2

Marek Bartoš
Nette Blogger | 1274
+
+1
-

int lze předat do float, ale int do bool ne
Bylo by fajn takové změny dělat pod feature flagem, protože každou typovanou aplikaci se zapnutými strict types změna z 1/0 na true/false rozbije.

David Grudl
Nette Core | 8227
+
+1
-

No spíš to dám jako volitelnou možnost.

Pavel Kravčík
Člen | 1195
+
0
-

Pavel Kravčík napsal(a):

Datumy fungují ok, ale rozhodilo to sandál souboru, který volá transakce (při beginTransaction to hlásí neini PDO), příští týden zkusíme víc prověřit.

Nevím proč, ale tohle přestalo fungovat. Příklad jsem zjednodušil, používáme ten callback na zápis entit v ORM například.

  $array1 = [];
  $array1['name'] = 'test1';
  $array1['active'] = 1;

  $array2 = [];
  $array2['name'] = 'test2';
  $array2['active'] = 1;

  $array = [];
  $array[] = $array1;
  $array[] = $array2;

  $this->database->getConnection()->transaction(function() use ($array)
  {
    foreach($array as $row)
	{
	  $this->database->table('xxx')->insert($row);
	}
});
  • 3.1 funguje
  • 3.2 → Typed property Nette\Database\ResultSet::$pdoStatement must not be accessed before initialization
David Grudl
Nette Core | 8227
+
+2
-

Opraveno

Pavel Kravčík
Člen | 1195
+
0
-

David Grudl napsal(a):

Opraveno

Potvrzuji, teď vypadá vše v3.2 ok.

Tomáš Vodička
Člen | 28
+
0
-

V projektu mi po upgradování verze na 3.2.0 začal phpstan hlásit chyby typu

Parameter $Database of method SomeClass::__construct() has invalid type Nette\Database\Explorer
Property SomeClass::$Database has unknown class Nette\Database\Explorer as its type
Call to method fetchAll() on an unknown class Nette\Database\ResultSet

Ve vendoru ty třídy jsou a kód po spuštění funguje.

Pokud phpstan spustím na verzi 3.1.9, tak proběhne bez chyby – vůbec mě nenapadá, čím by to mohlo být

Marek Bartoš
Nette Blogger | 1274
+
+3
-

@TomášVodička To se děje, pokud máš v PHPStanu nastavenou nízkou verzi PHP. Hlásí pak neexistující třídy, i když jen nejsou kompatibilní s aktuální PHP verzí

Tomáš Vodička
Člen | 28
+
0
-

Super, se správně nastavenou verzí už to funguje – díky, to by mě asi jen tak nenapadlo.

h4kuna
Backer | 740
+
0
-

Ahoj, zkusil jsem větev v3.2.x-dev 73b0cc7, abych potvrdil issue a narazil jsem na to, že třídy s autowired: off jsou pomocí search také nalezeny. Viz tento komit. Nějak tomu nerozumí, co bylo motivací? Celkem toho hojně využívám a přišlo mi logické, že pokud si registruju třídu nastavím ji autowired: off, tak ji Search nenajde. Takto mi to vyhazuje výjimky: Multiple services of type Garage\Model\Blinds\Blind\Pauseable found: protože mám několik implementací s tímto interface Garage\Model\Blinds\Blind\Pauseable. Všechny implementace tedy musí dát do ignorace pro Search.

Ale pak se nemohu dostat přes stejnou hlášku s tím, že tentokrát mám službu pro Presenter.

Service of type Garage\Presenters\V1Module\GaragePresenter: Service of type Garage\Model\PiGpio\Pin required by $garageButton in GaragePresenter::__construct() not found.

services:
	- Garage\Presenters\V1Module\GaragePresenter(@garagePin)

	garagePin:
		factory: @pin.write.factory::create(Garage\Model\Relay1::PIN_GARAGE) # vytváří Garage\Model\PiGpio\Pin
		autowired: no
final class GaragePresenter extends BasePresenter
{

	public function __construct(private readonly Pin $garageButton)
	{
		parent::__construct();
	}
}

Ve stable 3.2 toto funguje.

Editoval h4kuna (20. 2. 8:09)

David Grudl
Nette Core | 8227
+
+1
-

@h4kuna čtu to asi po desáté, ale stále nechápu. Zkus ten příklad prosím zjednodušit.

h4kuna
Backer | 740
+
0
-

Dobře,

zjednodušil jsem ten první případ co jsem popisoval, definuji si několik implementací jednoho rozhraní. Pak mám accessor, který má logiku a vybírá mi instanci implementace. A tu konkrétní instanci pak přijímá nějaká třída.

ve verzi 3.2.0, toto funguje dostanu v App\Foo\MyClass objekt App\Foo\FooA.

ve verzi v3.2.x-dev 73b0cc7 Service of type App\Foo\MyClass: Multiple services of type App\Foo\BarInterface found: 01, 010, 011 (required by $a in MyClass::__construct())

services:
	a:
		factory: App\Foo\FooA
		autowired: false
	b:
		factory: App\Foo\FooB
		autowired: false

	- App\Foo\FooAccessor()::get('a')
	- App\Foo\MyClass
namespace App\Foo;

interface BarInterface
{
	function run(): void;
}
namespace App\Foo;

final class FooA implements BarInterface
{
	function run(): void
	{
	}

}
namespace App\Foo;

final class FooB implements BarInterface
{
	function run(): void
	{

	}

}
namespace App\Foo;

final class MyClass
{
	public function __construct(private BarInterface $a)
	{
	}
}
namespace App\Foo;

use Nette\DI\Container;

class FooAccessor
{
	public function __construct(private Container $container)
	{
	}


	public function get(string $name): BarInterface
	{
		// if (condition)

		return $this->container->createService($name);
	}

}

Úplně „easy“ :D

EDIT:
Aby mi to fungovalo ve 3.2-dev musím do neonu přidat

search:
	- in: %appDir%
		exclude:
			classes:
				- App\Foo\FooB
				- App\Foo\FooA
  • zapomněl jsem Accessor třídu

@DavidGrudl je to takto už srozumitelné a v pořádku?

Editoval h4kuna (23. 2. 12:25)

kminekmatej
Generous Backer | 38
+
+3
-

Hlásím že ve verzi 3.2.3 se mi opět objevila asi již opravovaná chyba:

Typed property Nette\Database\ResultSet::$pdoStatement must not be accessed before initialization

Verze 3.1.9 to nedělá (protože types)
Stack trace je následovný:
$explorer->beginTransaction(); zavolá ->query('::beginTransaction')
Query který začíná na :: v ResultSet konstruktoru neinituje private readonly ?\PDOStatement $pdoStatement.
Nicméně v ConnectionPanel::logQuery() se volá $result->getRowCount().
Tam to spadne na:

return $this->pdoStatement ? $this->pdoStatement->rowCount() : null;

Můžu zítra připravit PR s opravou na

return isset($this->pdoStatement) ? $this->pdoStatement->rowCount() : null;

(Nevím jestli obdobně neupravit ještě getColumnCount())

Editoval kminekmatej (20. 8. 17:16)

MKI-Miro
Člen | 278
+
0
-

Ja dostavam

Nette\InvalidArgumentException

Missing parameter ‚featureToggles.narrowPregMatches‘. search►

kminekmatej
Generous Backer | 38
+
0
-

Aha, koukám že v master branchi je to už předělané z PDOStatement na Result. Tak to neřešim, počkám si na release. To půjde do 4.0 ?