Hi!
Based on some discussions with Facebook, Tuenti and Andrey we have
developed an "unofficial" MySQL Server patch. Furthermore we have added
a new function to ext/mysqli which only purpose is to access
functionality available only with a patched MySQL Server. Therefore we
have not committed this new function into the PHP CVS but only made
available on Launchpad [1]. The license is - as usual - PHP license. If
you want it in the PHP CVS, we can add it, but I am -1.
Let me give details: the background.
When fetching data from MySQL in PHP using any of mysql_query(),
mysqli_query() or mysqli_real_query(), you will get a result set that
consists of PHP string and PHP NULL variables. The reason for that is
that the protocol used between the client and server is text based. The
client (PHP) receives all results as strings. Regardless of the SQL type
used in MySQL, you will get a string. For example, INTEGER 1234
becomes string "1234"
If you use Prepared Statements you will get typed results, sort of
native types as I like to call them. As far as possible you will get
typed results. For example, INTEGER 1234 from MySQL becomes integer 1234
in PHP. That is because MySQL is using a different protocol using
different data encoding: the binary protocol for sending data to the client.
There is a number of reasons why you want native types / typed results
in PHP. Comparing $some_int_as_string with 1234 is slower than comparing
$some_int_as_int with 1234 - no type conversions need to be done before
the comparison can be done. $some_int_as_string requires a few bytes
more than $some_int_as_int to be stored. And, of course,
$some_int_as_string === 1234 will evaluate to false. Last but not least
its a convenience feature.
On the server side the binary protocol can save a few cast operations
and on the wire the footprint can (does not have to be!) a little smaller.
How big is the difference for the average user? Rather minimal. But
under high load you appreciate each and every possible optimization.
Putting it into a larger scale, memory savings inside PHP can translate
into memory savings in caches such as APC and memcached.
How can you get types results?
You can get typed results with any of [mysql_query(),] mysqli_query() or
mysqli_real_query() by either:
a) patching the server
b) casting upon fetch inside PHP using meta data information
NOTE: b) = PHP 5.3+, ext/mysqli using mysqlnd
Andrey has hacked a patch for the server. The server patch is by no
means official - its a suggestion for those who want to experiement. I
don't know if the patch will ever go into MySQL. The patch will make the
server use the binary protocol for mysqli_query() after setting an
option. To be able to set this new option, available only with a patched
server, we have exported the C function mysql_set_server_option() to
ext/mysqli as mysqli_set_server_option(). This is not in the PHP CVS
currently because:
1) you need it for nothing but accessing a patched server
2) you can mess around with MYSQL_OPTION_MULTI_STATEMENTS_ON which
has been keept away from the mysqli API so far and encapsulated in an
extra function mysqli_multi_query().
3) we try to block you from messing around with
MYSQL_OPTION_MULTI_STATEMENTS_ON
Therefore: no functionality hidden that is available in the regular
MySQL Server. The function would be API bloat in regular PHPs. So, we
keep like 10 lines of code only in our bazaar repository at Launchpad [1].
b) is in the PHP CVS. Its available with ext/mysqli when compiled
against mysqlnd. Here's a simple usage example:
$link = mysqli_connect("localhost", "root", "root");
mysqli_query($link, "USE test");
mysqli_query($link, "DROP TABLE IF EXISTS test");
mysqli_query($link, "CREATE TABLE test(col1 INT, col2 FLOAT)");
mysqli_query($link, "INSERT INTO test(col1, col2) VALUES(1, 12345.67)");
$res = mysqli_query($link, "SELECT col1, col2, col2 * 2 AS _col3 FROM
test");
var_dump(mysqli_fetch_assoc($res));
mysqli_free_result($res);
/* mysqlnd only */
mysqli_options($link, MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true);
$res = mysqli_query($link, "SELECT col1, col2, col2 * 2 AS _col3 FROM
test");
var_dump(mysqli_fetch_assoc($res));
mysqli_free_result($res);
mysqli_close($link);
--->
array(3) {
["col1"]=>
string(1) "1"
["col2"]=>
string(7) "12345.7"
["_col3"]=>
string(14) "24691.33984375"
}
array(3) {
["col1"]=>
int(1)
["col2"]=>
float(12345.7)
["_col3"]=>
float(24691.33984375)
}
I'll be in meetings for the rest of the day, please be patient if I
don't reply to questions immediately. More details and thoughts on the
idea can be found at [2].
Ulf
[1] https://code.launchpad.net/~andrey-mysql/php-mysqlnd/binary_protocol
[2] http://blog.ulf-wendel.de/?p=198
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php