Skip to content

Add PDOStatement::activeQueryString() #2159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 26 additions & 8 deletions ext/pdo/pdo_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,12 @@ static PHP_METHOD(PDOStatement, execute)
* quoted.
*/

/* string is leftover from previous calls so PDOStatement::activeQueryString() can access */
if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
efree(stmt->active_query_string);
}
stmt->active_query_string = NULL;

ret = pdo_parse_params(stmt, stmt->query_string, stmt->query_stringlen,
&stmt->active_query_string, &stmt->active_query_stringlen);

Expand All @@ -504,10 +510,6 @@ static PHP_METHOD(PDOStatement, execute)
RETURN_FALSE;
}
if (stmt->methods->executer(stmt)) {
if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
efree(stmt->active_query_string);
}
stmt->active_query_string = NULL;
if (!stmt->executed) {
/* this is the first execute */

Expand All @@ -526,10 +528,6 @@ static PHP_METHOD(PDOStatement, execute)

RETURN_BOOL(ret);
}
if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
efree(stmt->active_query_string);
}
stmt->active_query_string = NULL;
PDO_HANDLE_STMT_ERR();
RETURN_FALSE;
}
Expand Down Expand Up @@ -2092,6 +2090,22 @@ static PHP_METHOD(PDOStatement, closeCursor)
}
/* }}} */

/* {{{ proto string PDOStatement::activeQueryString()
Fetch the last executed query string associated with the statement handle */
static PHP_METHOD(PDOStatement, activeQueryString)
{
PHP_STMT_GET_OBJ;

if (stmt->active_query_string) {
RETURN_STRING(stmt->active_query_string);
} else if (stmt->query_string) {
RETURN_STRING(stmt->query_string);
} else {
RETURN_FALSE;
}
}
/* }}} */

/* {{{ proto void PDOStatement::debugDumpParams()
A utility for internals hackers to debug parameter internals */
static PHP_METHOD(PDOStatement, debugDumpParams)
Expand Down Expand Up @@ -2170,6 +2184,7 @@ const zend_function_entry pdo_dbstmt_functions[] = {
PHP_ME(PDOStatement, setFetchMode, arginfo_pdostatement_setfetchmode, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, nextRowset, arginfo_pdostatement__void, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, closeCursor, arginfo_pdostatement__void, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, activeQueryString, arginfo_pdostatement__void, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, debugDumpParams, arginfo_pdostatement__void, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, __wakeup, arginfo_pdostatement__void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(PDOStatement, __sleep, arginfo_pdostatement__void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
Expand Down Expand Up @@ -2316,6 +2331,9 @@ PDO_API void php_pdo_free_statement(pdo_stmt_t *stmt)
if (stmt->methods && stmt->methods->dtor) {
stmt->methods->dtor(stmt);
}
if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
efree(stmt->active_query_string);
}
if (stmt->query_string) {
efree(stmt->query_string);
}
Expand Down
51 changes: 51 additions & 0 deletions ext/pdo/tests/active_query_string.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
--TEST--
PDO Common: PDOStatement::activeQueryString()
--SKIPIF--
<?php
if (!extension_loaded('pdo')) die('skip');
$dir = getenv('REDIR_TEST_DIR');
if (false == $dir) die('skip no driver');
require_once $dir . 'pdo_test.inc';
PDOTest::skip();

$db = PDOTest::factory();
if (!$db->getAttribute(PDO::ATTR_EMULATE_PREPARES) && !$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true)) die('skip driver cannot emulate prepared statements');
?>
--FILE--
<?php
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.dirname(__FILE__) . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';

$db = PDOTest::factory();
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

$stmt = $db->query('SELECT 1');
var_dump($stmt->activeQueryString()); // works with statements without bound values

$stmt = $db->prepare('SELECT :bool, :int, :string, :null');
$stmt->bindValue(':bool', true, PDO::PARAM_BOOL);
$stmt->bindValue(':int', 123, PDO::PARAM_INT);
$stmt->bindValue(':string', 'foo', PDO::PARAM_STR);
$stmt->bindValue(':null', null, PDO::PARAM_NULL);

var_dump($stmt->activeQueryString()); // will return unparsed query before execution

$stmt->execute();
var_dump($stmt->activeQueryString()); // will return parsed query after execution
var_dump($stmt->activeQueryString()); // can be called repeatedly

$stmt->execute();
var_dump($stmt->activeQueryString()); // works if the statement is executed again

$stmt->bindValue(':int', 456, PDO::PARAM_INT);
$stmt->execute();
var_dump($stmt->activeQueryString()); // works with altered values

?>
--EXPECT--
string(8) "SELECT 1"
string(34) "SELECT :bool, :int, :string, :null"
string(26) "SELECT 1, 123, 'foo', NULL"
string(26) "SELECT 1, 123, 'foo', NULL"
string(26) "SELECT 1, 123, 'foo', NULL"
string(26) "SELECT 1, 456, 'foo', NULL"
5 changes: 5 additions & 0 deletions ext/pdo_dblib/dblib_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@ static int dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
static int dblib_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
{
switch (attr) {
case PDO_ATTR_EMULATE_PREPARES:
/* this is the only option available, but expose it so common tests and whatever else can introspect */
ZVAL_TRUE(return_value);
break;

case PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER:
ZVAL_BOOL(return_value, ((pdo_dblib_db_handle *)dbh->driver_data)->stringify_uniqueidentifier);
break;
Expand Down