phinx icon indicating copy to clipboard operation
phinx copied to clipboard

Fails if supplied PDO has default mode set FETCH_ASSOC

Open keithy opened this issue 5 years ago • 4 comments

Obvious work around - dont supply pdo connection with PDO::FETCH_ASSOC set as default. But... it could be a little more resilient.

trips over:

SQLiteAdapter.php -- public function hasTable($tableName)
   ...
        $rows = $this->fetchAll(sprintf('SELECT name FROM sqlite_master WHERE ...
        foreach ($rows as $row) {
            $tables[] = strtolower($row[0]); <<<< oops
        }

keithy avatar Jun 06 '19 07:06 keithy

The specific failure has already been fixed by fad5984d304793f43cc1c8bf91969bf0d3f3bfee several days ago.

More generally, the PdoAdapter::fetchRow() and PdoAdapter::fetchAll() methods should perhaps specify PDO::FETCH_ASSOC or PDO::FETCH_BOTH explicitly, as associative keys are relied on throughout.

JKingweb avatar Jun 06 '19 12:06 JKingweb

Anyone up for a PR here?

dereuromark avatar Aug 28 '19 10:08 dereuromark

With the merging of #1627, it is now possible to also specify a fetch_mode as a configuration option. I would expect that for sending in a PDO connection explicitly or using that configuration option, it would mean that the end-user would then expect the results of fetch and fetchAll to return the results in the specified fetch mode (or else what would be the point?).

The solution (to me) would be to add a new parameter $mode to the two functions that you could specify a fetch mode. However, what would be an appropriate type for these functions where for PdoAdapter it would use integer, but for AdapterInterface which may be plugged into something other than PDO, is integer still appropriate? Strings that roughly correspond to the PDO fetch modes?

MasterOdin avatar May 10 '20 15:05 MasterOdin

An example testcase that fails on the current implementation:

    public function testConnectionWithFetchModeNum()
    {
        $options = $this->adapter->getOptions();
        $options['fetch_mode'] = 'num';
        $this->adapter->setOptions($options);
        $this->assertInstanceOf('PDO', $this->adapter->getConnection());
        $this->assertSame(\PDO::FETCH_NUM, $this->adapter->getConnection()->getAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE));
        $table = new \Phinx\Db\Table('ntable', [], $this->adapter);
        $table->addColumn('column1', 'string')
              ->save();
        $this->assertTrue($this->adapter->hasTable('ntable'));
        $this->assertCount(2, $this->adapter->getColumns('ntable'));
    }

MasterOdin avatar May 10 '20 15:05 MasterOdin