?
avatar franzpeter
franzpeter
5 Mar 2015

Steps to reproduce the issue

Install Joomla with mysqlpdo. Create a query using fetch_assoc().

Expected result

working query

Actual result

PHP Fatal error:  Call to undefined method PDOStatement::fetch_Assoc()

System information (as much as possible)

Joomla 3.4 using pdomysql
php 5.4.3
mysql 5.5.3.8

Additional comments

The pdo.php contains that protected function
protected function fetchAssoc($cursor = null)
{
if (!empty($cursor) && $cursor instanceof PDOStatement)
{
return $cursor->fetch(PDO::FETCH_ASSOC);
}

    if ($this->prepared instanceof PDOStatement)
    {
        return $this->prepared->fetch(PDO::FETCH_ASSOC);
    }
}

But if using with database type MySQL (PDO) it produces an error

avatar franzpeter franzpeter - open - 5 Mar 2015
avatar PhilETaylor
PhilETaylor - comment - 5 Mar 2015

another myslq pdo issue /me will take a look shortly...

avatar franzpeter
franzpeter - comment - 5 Mar 2015

The mysqlpdo should normally provide nearly the same features as the native pdo. If it is mysqli it even offers prepared statements.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6321.
avatar PhilETaylor
PhilETaylor - comment - 5 Mar 2015

Just but there is a Joomla layer before you get to raw pdo - so that needs testing.

avatar PhilETaylor
PhilETaylor - comment - 5 Mar 2015

Please can you provide a Gist of PHP code that is failing because of this? I would like to see your example.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6321.

avatar mbabker mbabker - change - 5 Mar 2015
Priority Critical Medium
avatar franzpeter
franzpeter - comment - 5 Mar 2015

You create a query like:
$q = 'SELECT * FROM #__any_table';
$db->setQuery($q);
if($cursor = $db->execute($q)) {
while($var=$cursor->fetch_Assoc()) {
$q='INSERT into #__another_table….';
$db->setQuery($q);
$db->execute();
}
}

Those queries are quite common for insert, delete, update a.s.o..
I think that with a prepared statement it will produce the same error!


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6321.
avatar PhilETaylor
PhilETaylor - comment - 5 Mar 2015

I think this is more likely to be you using unpublished API - as no where in the Joomla Core code do we use ->fetch_Assoc()

Maybe you should use something like:

$q = 'SELECT * FROM #__extensions';
$db->setQuery($q);
$var = $db->loadAssoc(); // Generate an associative array of the first row
var_dump($var);

Which works with pdomysql

doc: https://docs.joomla.org/JDatabase/loadAssoc

You should be interacting with the Joomla API and not trying to bypass that and run PDO commands generically :)

avatar PhilETaylor
PhilETaylor - comment - 5 Mar 2015

or even loadAssocList see: https://docs.joomla.org/JDatabase/loadAssocList
which is what I think you really want :)

avatar franzpeter
franzpeter - comment - 5 Mar 2015

Working with a cursor is a common way. PDO does not produce such an error doing so. I think only pdomysql produces that problem. The difference between your suggested loadAssocList and the other way is that AssocList does produce memory limit errors on large database tables while the other way does NOT produce memory errors. You produce a query and executing it delivers jAust the values for the cursor. LoadAssocList will load the whole query with all table values. Of code you you can limit the result set but you need more code to achieve the same result. If all database layers allow to use it except of the pdomysql, I would say that pdomysql has a problem.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6321.
avatar mbabker
mbabker - comment - 5 Mar 2015

The error is right in that there isn't a fetch_Assoc method on the PDOStatement object. In your code, try replacing the while with this: $var = $cursor->fetch(PDO::FETCH_ASSOC).

avatar PhilETaylor
PhilETaylor - comment - 5 Mar 2015

This is the Joomla project, you are using the Joomla database object - NOT raw PDO.

If you want to use raw PDO commands then you can create a raw pdo connection, but as it is the Joomla Database API provides an interface to the parts of PDO (and other drivers) that it needs to for its own use, and the major user cases.

From what I can see (in bed!) none of the Joomla database drivers give you raw access to fetch_Assoc() functions at all, only though loadAssocList and loadAssoc

The Joomla Database Driver for PDO does have this function

protected function fetchAssoc($cursor = null)
which doesnt look like its available in any other Joomla Database Driver

avatar mbabker
mbabker - comment - 5 Mar 2015

Also, FWIW, it seems you should be able to do this using Joomla's PDO wrapper (untested, but just reading code it makes sense).

Instead of your while($var=$cursor->fetch_Assoc()) use while($var = $db->loadNextAssoc())

Admittedly the PDO API isn't one I'm too familiar with right now, but I think this gives you roughly the same features. Of course, I could be wrong and not realize it.

avatar brianteeman brianteeman - change - 6 Mar 2015
Labels Added: ?
avatar franzpeter
franzpeter - comment - 6 Mar 2015

Thanks mbabker. Just thought it would make sense to keep the pdomysql compatible with the other db layers from joomla. By default, all contain the possibility to use fetchAssoc or fetchObject with cursor.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6321.
avatar mbabker
mbabker - comment - 6 Mar 2015

From what I can tell, none of the drivers allow public access to the fetchAssoc or fetchObject methods (they all are protected) so you'd need to go through one of our public APIs to get to those. Of course with a cursor, it seems you'd be able to bypass our API and use the direct database API for the object (like mysqli_fetch_assoc). At a glance I'm not seeing anything about the PDO based classes that's different from their non-PDO counterparts, but considering the class is derived from the Framework, I guess it's possible there could be a difference we missed somewhere.

avatar franzpeter
franzpeter - comment - 6 Mar 2015

Michael, thanks for your patience with me. What I do not understand is that Joomla (for example the mysqli driver) does the following thing:
protected function fetchAssoc($cursor = null)
{
return mysqli_fetch_assoc($cursor ? $cursor : $this->cursor);
}
I understand that with my method I deliver values to return mysqli_fetch_assoc($cursor ? $cursor : $this->cursor); and not to protected function fetchAssoc($cursor = null). It would be more useful, just my humble opinion, to allow to set the cursor to some value, if desired, instead to use null as fixed.
But maybe I tell something wrong.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6321.
avatar mbabker
mbabker - comment - 6 Mar 2015

Since those methods are all protected, the only way you'd really be able to use them right now is to subclass our database classes. I do agree with being able to supply your own data into them (and you can within the right scope), but to do it external to the database classes requires us to make those methods public instead of protected.

avatar franzpeter
franzpeter - comment - 6 Mar 2015

Agree with you.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6321.
avatar PhilETaylor
PhilETaylor - comment - 6 Mar 2015

So can this be closed as an issue bug against Joomla now?

avatar mbabker
mbabker - comment - 6 Mar 2015

I think so. If anything we're looking at a feature proposal/API change (making the fetch* methods public versus protected) at this point.

avatar brianteeman brianteeman - change - 6 Mar 2015
Status New Closed
Closed_Date 0000-00-00 00:00:00 2015-03-06 17:20:02
avatar brianteeman brianteeman - close - 6 Mar 2015
avatar brianteeman brianteeman - close - 6 Mar 2015

Add a Comment

Login with GitHub to post a comment