ramblings on PHP, SQL, the web, politics, ultimate frisbee and what else is on in my life
back 1  2  »  

Next MDB2 releases are around the corner

I fixed a serious BC issue that I introduced in the last releases of the MySQL drivers, that would cause issues with servers that do not support InnoDB. I switched to forcing the InnoDB table handler. The fix is to simply not force any table handler and use the server default. There were also some minor bug fixes in several of the other drivers. More importantly however I am pretty happy with the nested transaction API as well as improvements to the debug callback mechanism.

I have mentioned the nested transaction support previously. Since then we have added support for SAVEPOINTs. This feature allows you to define a savepoint within a transaction to which you can rollback to, instead of rolling back the entire transaction. By default the nested transaction API will automatically use SAVEPOINTs to give really tight control in an entirely transparent fashion.

I have also discussed the debug callback mechanism before. This time I have expanded the debug callback mechanism to enable passing more context information to the debug callback. So for example when calling beginTransaction it will pass the optional $savepoint parameter to the callback. More importantly I have added a debug() call at the end of the _doQuery(), prepare() and execute() methods. In order to differntiate the call at the beginning from the call at the end I am passing a context key "time" (not entirely happy with this naming .. suggestions welcome) with "pre" or "post" as the value. This enables people to for example implement query benchmarking. This could be useful to implement a portable MySQL style slow query log. Note that in order to not break BC for older debug handlers I have added a new option "debug_expanded_output" which needs to be set to true to get this additional context information and to get "post" callback calls.

The only two bug reports I am currently hoping to get resolved before the next release are:

Patches welcome :)
Expect the new releases in the next week or so.

Comments



Re: Next MDB2 releases are around the corner

Hi Lucas,

I am using MDb2 2.1 with MySQL 5.0, INNODB engine, EUC_JP character set and find out that MDB2 2.1 always return an empty page, no error occurs when the MySQL server is down. PEAR::isError can not catch this kind of situation.


<?php

require_once("../library/pear/PEAR.php");
require_once '../library/pear/MDB2.php';
$db_engine = 'mysql';           
$db_user = 'user';   //Username
$db_pass = 'pass';   //Password
$db_host = 'localhost';         //Host
$db_name = 'db_name';   //Database name

$dsn = $db_engine.'://'.
$db_user.':'.
$db_pass.'@'.
$db_host.'/'.
$db_name;
$mdb2 = &MDB2::factory($dsn);
if (PEAR::isError($mdb2))
{
    echo "Server seems to be down or your user/pass is not valid";
    var_dump($mdb2);
}
?>

Is it a bug or am I missing something?

Re: Next MDB2 releases are around the corner

If you pass thew "debug" option as true in the factory call like so:


<?php
$mdb2 =& MDB2::factory($dsn, array('debug' = true));
?>

You would find out that there are problems with including the driver files. This is due to the fact that you seem to not have setup your include_path setting according to PEAR standards:
http://pear.php.net/manual/en/installation.shared.php
(I did not quickly find a better page that explains it. Scroll to the buttom. There it explains how to set the include path at runtime. Alternatively you can modify the include path setting in your php.ini)

Re: Next MDB2 releases are around the corner

In my production code, I have set ini like this

ini_set(
"include_path", (
"../library/pear/" .
ini_get("include_path")
)

);

And it works smoothly until I shut down MYSQL Server. Before that, I can make queries, generate SQL error....

I tried to run my code in Zend IDE debug mode and found that if I made a call to $mdb2 = &MDB2::factory($dsn); then no error would be caught until I used that $mdb2 to call a query API like query($sql) then the code would run to line 332 (MDB2/Driver/mysql.php)

[php]
$connection = @call_user_func_array($connect_function, $params);
@ini_restore('track_errors');
if (!$connection) {
if (($err = @mysql_error()) != ) {
return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, $err);
} else {
return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, $php_errormsg);
}
}

[/php]

The error will be caught in

if (($err = @mysql_error()) != )

But this error will be only caught if I make a call to a query API explicitly. Therefore:

$mdb2 = &MDB2::factory($dsn);
if (PEAR::isError($mdb2))
{

///......
}

can not used to check if I can make a connection to mysql server with provided dsn

So

$mdb2 = &MDB2::factory($dsn);
$res = $mdb2->query('Select * from me');
if (PEAR::isError($res))
{

echo "Can not connect to the database server";
$mdb2->errorMessage();
}

wil work for my purpose.

Is it a bug or a desired behaviour?

Thanks Lucas Smith

Regards,

Dinh

Re: Next MDB2 releases are around the corner

Hi Lucas,

If I replace factory() or singleton() with connect() then I can check connection error with

if (PEAR::isError($mdb2))
{

///......
}

Regards

Dinh

Re: Next MDB2 releases are around the corner

Yes this is the desired behaviour. MDB2 by default uses what is called as "lazy connect". That means a connection is only established as soon as you actually need one. By calling connect() or query() for example.

Re: Next MDB2 releases are around the corner

Another name idea for your time context key: 'when'
And the values: 'before', 'after'

Re: Next MDB2 releases are around the corner

Consider automatic paramaterization. So instead of
$db->queryOne("select * from table where id = ".$db->quote($id));

you can do:

$db->queryOne(array("select * from table where id = ?",$id));

it promotes the use of parameterization and is more readable. I have lazy programers that like to write things like:

$db->queryOne("select * from table where id = ".$id)

which is, of course, dangerous.

Also please fix STRICT warnings.

I can send you a diff, but it's pretty easy to do yourself.

Thanks,

Ryan

Re: Next MDB2 releases are around the corner

This is already supported via the Extended module and the get*() methods:


<?php
$mdb2->loadModule('Extended');
$query = 'select name, create_date from table where id = ?';
$mdb2->extended->getOne($query, array('text', 'timestamp'), array(42), array('integer'));
?>

Re: Next MDB2 releases are around the corner

What's the MDB2 equivalent to the mysql_error() and mysql_errno() functions? When something goes wrong with my query, all I'm getting is "MDB2 Error: syntax error"

Before you can post a comment please solve the following captcha.
your name


1  2  »