Skip to content
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

DebugPDO executedQueryString - quoting #775

Merged
merged 1 commit into from Oct 18, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 11 additions & 3 deletions runtime/lib/connection/DebugPDOStatement.php
Expand Up @@ -74,7 +74,14 @@ public function getExecutedQueryString(array $values = array())
$size = count($matches[1]);
for ($i = $size - 1; $i >= 0; $i--) {
$pos = $matches[1][$i];
$sql = str_replace($pos, $boundValues[$pos], $sql);

// trimming extra quotes, making sure value is properly quoted afterwards
$boundValue = $boundValues[$pos];
if (is_string($boundValue)) { // quoting only needed for string values
$boundValue = trim($boundValue, "'");
$boundValue = $this->pdo->quote($boundValue);
}
$sql = str_replace($pos, $boundValue, $sql);
}
}

Expand Down Expand Up @@ -120,7 +127,7 @@ public function bindValue($pos, $value, $type = PDO::PARAM_STR)
$valuestr = $type == PDO::PARAM_LOB ? '[LOB value]' : var_export($value, true);
$msg = sprintf('Binding %s at position %s w/ PDO type %s', $valuestr, $pos, $typestr);

$this->boundValues[$pos] = $valuestr;
$this->boundValues[$pos] = $value;

$this->pdo->log($msg, null, __METHOD__, $debug);

Expand All @@ -143,13 +150,14 @@ public function bindValue($pos, $value, $type = PDO::PARAM_STR)
*/
public function bindParam($pos, &$value, $type = PDO::PARAM_STR, $length = 0, $driver_options = null)
{
$originalValue = $value;
$debug = $this->pdo->getDebugSnapshot();
$typestr = isset(self::$typeMap[$type]) ? self::$typeMap[$type] : '(default)';
$return = parent::bindParam($pos, $value, $type, $length, $driver_options);
$valuestr = $length > 100 ? '[Large value]' : var_export($value, true);
$msg = sprintf('Binding %s at position %s w/ PDO type %s', $valuestr, $pos, $typestr);

$this->boundValues[$pos] = $valuestr;
$this->boundValues[$pos] = $originalValue;

$this->pdo->log($msg, null, __METHOD__, $debug);

Expand Down
200 changes: 200 additions & 0 deletions test/testsuite/runtime/connection/PropelPDOTest.php
Expand Up @@ -457,6 +457,206 @@ public function testDebugLog()
$con->setLogger($logger);
$config->setParameter("debugpdo.logging.methods", array('PropelPDO::exec', 'PropelPDO::query', 'DebugPDOStatement::execute'));
}

/**
* Testing if string values will be quoted correctly by DebugPDOStatement::getExecutedQueryString
*/
public function testDebugExecutedQueryStringValue()
{

/**
* @var DebugPDO $con
*/
$con = Propel::getConnection(BookPeer::DATABASE_NAME);

// different method must all result in this given querystring, using a string value
$bindParamStringValue = "%Harry%";
$expectedQuery = "SELECT book.id FROM `book` WHERE book.title LIKE '{$bindParamStringValue}'";

// simple statement without params
$prepStmt = $con->prepare($expectedQuery);
$prepStmt->execute();
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// statement with named placeholder
$prepStmt = $con->prepare("SELECT book.id FROM `book` WHERE book.title LIKE :p1");
$prepStmt->bindValue(':p1', '%Harry%'); // bind value variant
$prepStmt->execute();
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

$prepStmt->bindParam(':p1', $bindParamStringValue); // bind param variant
$prepStmt->execute();
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// passing params directly
$prepStmt->execute(array(':p1' => '%Harry%'));
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');


// statement with named placeholder, this one won't get substituted
$expectedNotSubstitutedQuery = "SELECT book.id FROM `book` WHERE book.title LIKE :name";
$prepStmt = $con->prepare($expectedNotSubstitutedQuery);
$prepStmt->bindValue(':name', '%Harry%'); // bind value variant
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

$prepStmt->bindParam(':name', $bindParamStringValue); // bind param variant
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// passing params directly
$prepStmt->execute(array(':name' => '%Harry%'));
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');


// statement with positional placeholder, this one won't get substituted either
$expectedNotSubstitutedQuery = "SELECT book.id FROM `book` WHERE book.title LIKE ?";
$prepStmt = $con->prepare($expectedNotSubstitutedQuery);
$prepStmt->bindValue(1, '%Harry%');
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

$prepStmt->bindParam(1, $bindParamStringValue);
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// passing params directly
$prepStmt->execute(array('%Harry%'));
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');
}

/**
* Testing if integer values will be quoted correctly by DebugPDOStatement::getExecutedQueryString
*/
public function testDebugExecutedQueryIntegerValue() {

/**
* @var DebugPDO $con
*/
$con = Propel::getConnection(BookPeer::DATABASE_NAME);

// different method must all result in this given querystring, using an integer value
$bindParamIntegerValue = 123;
$expectedQuery = "SELECT book.title FROM `book` WHERE book.id = {$bindParamIntegerValue}";

// simple statement without params
$prepStmt = $con->prepare($expectedQuery);
$prepStmt->execute();
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// statement with named placeholder
$prepStmt = $con->prepare("SELECT book.title FROM `book` WHERE book.id = :p1");
$prepStmt->bindValue(':p1', 123); // bind value variant
$prepStmt->execute();
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

$prepStmt->bindParam(':p1', $bindParamIntegerValue); // bind param variant
$prepStmt->execute();
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// passing params directly
$prepStmt->execute(array(':p1' => 123));
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');


// statement with named placeholder, this one won't get substituted
$expectedNotSubstitutedQuery = "SELECT book.title FROM `book` WHERE book.id = :name";
$prepStmt = $con->prepare($expectedNotSubstitutedQuery);
$prepStmt->bindValue(':name', 123); // bind value variant
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

$prepStmt->bindParam(':name', $bindParamIntegerValue); // bind param variant
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// passing params directly
$prepStmt->execute(array(':name' => 123));
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');


// statement with positional placeholder, this one won't get substituted either
$expectedNotSubstitutedQuery = "SELECT book.title FROM `book` WHERE book.id = ?";
$prepStmt = $con->prepare($expectedNotSubstitutedQuery);
$prepStmt->bindValue(1, 123);
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

$prepStmt->bindParam(1, $bindParamIntegerValue);
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// passing params directly
$prepStmt->execute(array(123));
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');
}

/**
* Testing if numeric values will be quoted correctly by DebugPDOStatement::getExecutedQueryString
* Numeric values sometimes will get handled differently, since there are numeric values which are non-integer
*/
public function testDebugExecutedQueryNumericValue() {

/**
* @var DebugPDO $con
*/
$con = Propel::getConnection(BookPeer::DATABASE_NAME);

// different method must all result in this given querystring, using an integer value
$bindParamNumericValue = 0002000;
$expectedQuery = "SELECT book.title FROM `book` WHERE book.id = {$bindParamNumericValue}";

// simple statement without params
$prepStmt = $con->prepare($expectedQuery);
$prepStmt->execute();
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// statement with named placeholder
$prepStmt = $con->prepare("SELECT book.title FROM `book` WHERE book.id = :p1");
$prepStmt->bindValue(':p1', 0002000); // bind value variant
$prepStmt->execute();
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

$prepStmt->bindParam(':p1', $bindParamNumericValue); // bind param variant
$prepStmt->execute();
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// passing params directly
$prepStmt->execute(array(':p1' => 0002000));
$this->assertEquals($expectedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');


// statement with named placeholder, this one won't get substituted
$expectedNotSubstitutedQuery = "SELECT book.title FROM `book` WHERE book.id = :name";
$prepStmt = $con->prepare($expectedNotSubstitutedQuery);
$prepStmt->bindValue(':name', 0002000); // bind value variant
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

$prepStmt->bindParam(':name', $bindParamNumericValue); // bind param variant
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// passing params directly
$prepStmt->execute(array(':name' => 0002000));
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');


// statement with positional placeholder, this one won't get substituted either
$expectedNotSubstitutedQuery = "SELECT book.title FROM `book` WHERE book.id = ?";
$prepStmt = $con->prepare($expectedNotSubstitutedQuery);
$prepStmt->bindValue(1, 0002000);
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

$prepStmt->bindParam(1, $bindParamNumericValue);
$prepStmt->execute();
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');

// passing params directly
$prepStmt->execute(array(0002000));
$this->assertEquals($expectedNotSubstitutedQuery, $con->getLastExecutedQuery(), 'DebugPDO failed to quote prepared statement on execute properly');
}
}

class myLogger
Expand Down
2 changes: 1 addition & 1 deletion test/testsuite/runtime/query/ModelCriteriaTest.php
Expand Up @@ -326,7 +326,7 @@ public function testWhereTypeValue()
);
$this->assertCriteriaTranslation($c, $sql, $params, 'where() accepts a complex calculation');
$c->find($this->con);
$expected = "SELECT book.id, book.title, book.isbn, book.price, book.publisher_id, book.author_id FROM `book` WHERE LOCATE('foo', book.title) = true";
$expected = "SELECT book.id, book.title, book.isbn, book.price, book.publisher_id, book.author_id FROM `book` WHERE LOCATE('foo', book.title) = 1";
$this->assertEquals($expected, $this->con->getLastExecutedQuery());
}

Expand Down