assertFalse($con->getAttribute(PropelPDO::PROPEL_ATTR_CACHE_PREPARES)); $con->setAttribute(PropelPDO::PROPEL_ATTR_CACHE_PREPARES, true); $this->assertTrue($con->getAttribute(PropelPDO::PROPEL_ATTR_CACHE_PREPARES)); $con->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); $this->assertEquals(PDO::CASE_LOWER, $con->getAttribute(PDO::ATTR_CASE)); } public function testNestedTransactionCommit() { $con = Propel::getConnection(BookPeer::DATABASE_NAME); $driver = $con->getAttribute(PDO::ATTR_DRIVER_NAME); $this->assertEquals(0, $con->getNestedTransactionCount(), 'nested transaction is equal to 0 before transaction'); $this->assertFalse($con->isInTransaction(), 'PropelPDO is not in transaction by default'); $con->beginTransaction(); $this->assertEquals(1, $con->getNestedTransactionCount(), 'nested transaction is incremented after main transaction begin'); $this->assertTrue($con->isInTransaction(), 'PropelPDO is in transaction after main transaction begin'); try { $a = new Author(); $a->setFirstName('Test'); $a->setLastName('User'); $a->save($con); $authorId = $a->getId(); $this->assertNotNull($authorId, "Expected valid new author ID"); $con->beginTransaction(); $this->assertEquals(2, $con->getNestedTransactionCount(), 'nested transaction is incremented after nested transaction begin'); $this->assertTrue($con->isInTransaction(), 'PropelPDO is in transaction after nested transaction begin'); try { $a2 = new Author(); $a2->setFirstName('Test2'); $a2->setLastName('User2'); $a2->save($con); $authorId2 = $a2->getId(); $this->assertNotNull($authorId2, "Expected valid new author ID"); $con->commit(); $this->assertEquals(1, $con->getNestedTransactionCount(), 'nested transaction decremented after nested transaction commit'); $this->assertTrue($con->isInTransaction(), 'PropelPDO is in transaction after main transaction commit'); } catch (Exception $e) { $con->rollBack(); throw $e; } $con->commit(); $this->assertEquals(0, $con->getNestedTransactionCount(), 'nested transaction decremented after main transaction commit'); $this->assertFalse($con->isInTransaction(), 'PropelPDO is not in transaction after main transaction commit'); } catch (Exception $e) { $con->rollBack(); } AuthorPeer::clearInstancePool(); $at = AuthorPeer::retrieveByPK($authorId); $this->assertNotNull($at, "Committed transaction is persisted in database"); $at2 = AuthorPeer::retrieveByPK($authorId2); $this->assertNotNull($at2, "Committed transaction is persisted in database"); } /** * @link http://propel.phpdb.org/trac/ticket/699 */ public function testNestedTransactionRollBackRethrow() { $con = Propel::getConnection(BookPeer::DATABASE_NAME); $driver = $con->getAttribute(PDO::ATTR_DRIVER_NAME); $con->beginTransaction(); try { $a = new Author(); $a->setFirstName('Test'); $a->setLastName('User'); $a->save($con); $authorId = $a->getId(); $this->assertNotNull($authorId, "Expected valid new author ID"); $con->beginTransaction(); $this->assertEquals(2, $con->getNestedTransactionCount(), 'nested transaction is incremented after nested transaction begin'); $this->assertTrue($con->isInTransaction(), 'PropelPDO is in transaction after nested transaction begin'); try { $con->exec('INVALID SQL'); $this->fail("Expected exception on invalid SQL"); } catch (PDOException $x) { $con->rollBack(); $this->assertEquals(1, $con->getNestedTransactionCount(), 'nested transaction decremented after nested transaction rollback'); $this->assertTrue($con->isInTransaction(), 'PropelPDO is in transaction after main transaction rollback'); throw $x; } $con->commit(); } catch (Exception $x) { $con->rollBack(); } AuthorPeer::clearInstancePool(); $at = AuthorPeer::retrieveByPK($authorId); $this->assertNull($at, "Rolled back transaction is not persisted in database"); } /** * @link http://propel.phpdb.org/trac/ticket/699 */ public function testNestedTransactionRollBackSwallow() { $con = Propel::getConnection(BookPeer::DATABASE_NAME); $driver = $con->getAttribute(PDO::ATTR_DRIVER_NAME); $con->beginTransaction(); try { $a = new Author(); $a->setFirstName('Test'); $a->setLastName('User'); $a->save($con); $authorId = $a->getId(); $this->assertNotNull($authorId, "Expected valid new author ID"); $con->beginTransaction(); try { $a2 = new Author(); $a2->setFirstName('Test2'); $a2->setLastName('User2'); $a2->save($con); $authorId2 = $a2->getId(); $this->assertNotNull($authorId2, "Expected valid new author ID"); $con->exec('INVALID SQL'); $this->fail("Expected exception on invalid SQL"); } catch (PDOException $e) { $con->rollBack(); // NO RETHROW } $a3 = new Author(); $a3->setFirstName('Test2'); $a3->setLastName('User2'); $a3->save($con); $authorId3 = $a3->getId(); $this->assertNotNull($authorId3, "Expected valid new author ID"); $con->commit(); $this->fail("Commit fails after a nested rollback"); } catch (PropelException $e) { $this->assertTrue(true, "Commit fails after a nested rollback"); $con->rollback(); } AuthorPeer::clearInstancePool(); $at = AuthorPeer::retrieveByPK($authorId); $this->assertNull($at, "Rolled back transaction is not persisted in database"); $at2 = AuthorPeer::retrieveByPK($authorId2); $this->assertNull($at2, "Rolled back transaction is not persisted in database"); $at3 = AuthorPeer::retrieveByPK($authorId3); $this->assertNull($at3, "Rolled back nested transaction is not persisted in database"); } public function testNestedTransactionForceRollBack() { $con = Propel::getConnection(BookPeer::DATABASE_NAME); $driver = $con->getAttribute(PDO::ATTR_DRIVER_NAME); // main transaction $con->beginTransaction(); $a = new Author(); $a->setFirstName('Test'); $a->setLastName('User'); $a->save($con); $authorId = $a->getId(); // nested transaction $con->beginTransaction(); $a2 = new Author(); $a2->setFirstName('Test2'); $a2->setLastName('User2'); $a2->save($con); $authorId2 = $a2->getId(); // force rollback $con->forceRollback(); $this->assertEquals(0, $con->getNestedTransactionCount(), 'nested transaction is null after nested transaction forced rollback'); $this->assertFalse($con->isInTransaction(), 'PropelPDO is not in transaction after nested transaction force rollback'); AuthorPeer::clearInstancePool(); $at = AuthorPeer::retrieveByPK($authorId); $this->assertNull($at, "Rolled back transaction is not persisted in database"); $at2 = AuthorPeer::retrieveByPK($authorId2); $this->assertNull($at2, "Forced Rolled back nested transaction is not persisted in database"); } public function testLatestQuery() { $con = Propel::getConnection(BookPeer::DATABASE_NAME); $con->setLastExecutedQuery(123); $this->assertEquals(123, $con->getLastExecutedQuery(), 'PropelPDO has getter and setter for last executed query'); } public function testLatestQueryMoreThanTenArgs() { $con = Propel::getConnection(BookPeer::DATABASE_NAME); $c = new Criteria(); $c->add(BookPeer::ID, array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), Criteria::IN); $books = BookPeer::doSelect($c, $con); $expected = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` WHERE book.ID IN (1,1,1,1,1,1,1,1,1,1,1,1)"; $this->assertEquals($expected, $con->getLastExecutedQuery(), 'PropelPDO correctly replaces arguments in queries'); } public function testQueryCount() { $con = Propel::getConnection(BookPeer::DATABASE_NAME); $count = $con->getQueryCount(); $con->incrementQueryCount(); $this->assertEquals($count + 1, $con->getQueryCount(), 'PropelPDO has getter and incrementer for query count'); } public function testUseDebug() { $con = Propel::getConnection(BookPeer::DATABASE_NAME); $con->useDebug(false); $this->assertEquals(array('PDOStatement'), $con->getAttribute(PDO::ATTR_STATEMENT_CLASS), 'Statement is PDOStatement when debug is false'); $con->useDebug(true); $this->assertEquals(array('DebugPDOStatement', array($con)), $con->getAttribute(PDO::ATTR_STATEMENT_CLASS), 'statement is DebugPDOStament when debug is true'); } public function testDebugLatestQuery() { $con = Propel::getConnection(BookPeer::DATABASE_NAME); $c = new Criteria(); $c->add(BookPeer::TITLE, 'Harry%s', Criteria::LIKE); $con->useDebug(false); $this->assertEquals('', $con->getLastExecutedQuery(), 'PropelPDO reinitializes the latest query when debug is set to false'); $books = BookPeer::doSelect($c, $con); $this->assertEquals('', $con->getLastExecutedQuery(), 'PropelPDO does not update the last executed query when useLogging is false'); $con->useDebug(true); $books = BookPeer::doSelect($c, $con); $latestExecutedQuery = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` WHERE book.TITLE LIKE 'Harry%s'"; if (!Propel::getDB(BookPeer::DATABASE_NAME)->useQuoteIdentifier()) { $latestExecutedQuery = str_replace('`', '', $latestExecutedQuery); } $this->assertEquals($latestExecutedQuery, $con->getLastExecutedQuery(), 'PropelPDO updates the last executed query when useLogging is true'); BookPeer::doDeleteAll($con); $latestExecutedQuery = "DELETE FROM `book`"; $this->assertEquals($latestExecutedQuery, $con->getLastExecutedQuery(), 'PropelPDO updates the last executed query on delete operations'); $sql = 'DELETE FROM book WHERE 1=1'; $con->exec($sql); $this->assertEquals($sql, $con->getLastExecutedQuery(), 'PropelPDO updates the last executed query on exec operations'); $sql = 'DELETE FROM book WHERE 2=2'; $con->query($sql); $this->assertEquals($sql, $con->getLastExecutedQuery(), 'PropelPDO updates the last executed query on query operations'); $stmt = $con->prepare('DELETE FROM book WHERE 1=:p1'); $stmt->bindValue(':p1', '2'); $stmt->execute(); $this->assertEquals("DELETE FROM book WHERE 1='2'", $con->getLastExecutedQuery(), 'PropelPDO updates the last executed query on prapared statements'); $con->useDebug(false); $this->assertEquals('', $con->getLastExecutedQuery(), 'PropelPDO reinitializes the latest query when debug is set to false'); $con->useDebug(true); } public function testDebugQueryCount() { $con = Propel::getConnection(BookPeer::DATABASE_NAME); $c = new Criteria(); $c->add(BookPeer::TITLE, 'Harry%s', Criteria::LIKE); $con->useDebug(false); $this->assertEquals(0, $con->getQueryCount(), 'PropelPDO does not update the query count when useLogging is false'); $books = BookPeer::doSelect($c, $con); $this->assertEquals(0, $con->getQueryCount(), 'PropelPDO does not update the query count when useLogging is false'); $con->useDebug(true); $books = BookPeer::doSelect($c, $con); $this->assertEquals(1, $con->getQueryCount(), 'PropelPDO updates the query count when useLogging is true'); BookPeer::doDeleteAll($con); $this->assertEquals(2, $con->getQueryCount(), 'PropelPDO updates the query count on delete operations'); $sql = 'DELETE FROM book WHERE 1=1'; $con->exec($sql); $this->assertEquals(3, $con->getQueryCount(), 'PropelPDO updates the query count on exec operations'); $sql = 'DELETE FROM book WHERE 2=2'; $con->query($sql); $this->assertEquals(4, $con->getQueryCount(), 'PropelPDO updates the query count on query operations'); $stmt = $con->prepare('DELETE FROM book WHERE 1=:p1'); $stmt->bindValue(':p1', '2'); $stmt->execute(); $this->assertEquals(5, $con->getQueryCount(), 'PropelPDO updates the query count on prapared statements'); $con->useDebug(false); $this->assertEquals(0, $con->getQueryCount(), 'PropelPDO reinitializes the query count when debug is set to false'); $con->useDebug(true); } public function testDebugLog() { $con = Propel::getConnection(BookPeer::DATABASE_NAME); $config = Propel::getConfiguration(PropelConfiguration::TYPE_OBJECT); // save data to return to normal state after test $logger = $con->getLogger(); $testLog = new myLogger(); $con->setLogger($testLog); $logEverything = array('PropelPDO::exec', 'PropelPDO::query', 'PropelPDO::beginTransaction', 'PropelPDO::commit', 'PropelPDO::rollBack', 'DebugPDOStatement::execute'); Propel::getConfiguration(PropelConfiguration::TYPE_OBJECT)->setParameter("debugpdo.logging.methods", $logEverything); $con->useDebug(true); // test transaction log $con->beginTransaction(); $this->assertEquals('log: Begin transaction', $testLog->latestMessage, 'PropelPDO logs begin transation in debug mode'); $con->commit(); $this->assertEquals('log: Commit transaction', $testLog->latestMessage, 'PropelPDO logs commit transation in debug mode'); $con->beginTransaction(); $con->rollBack(); $this->assertEquals('log: Rollback transaction', $testLog->latestMessage, 'PropelPDO logs rollback transation in debug mode'); $con->beginTransaction(); $testLog->latestMessage = ''; $con->beginTransaction(); $this->assertEquals('', $testLog->latestMessage, 'PropelPDO does not log nested begin transation in debug mode'); $con->commit(); $this->assertEquals('', $testLog->latestMessage, 'PropelPDO does not log nested commit transation in debug mode'); $con->beginTransaction(); $con->rollBack(); $this->assertEquals('', $testLog->latestMessage, 'PropelPDO does not log nested rollback transation in debug mode'); $con->rollback(); // test query log $con->beginTransaction(); $c = new Criteria(); $c->add(BookPeer::TITLE, 'Harry%s', Criteria::LIKE); $books = BookPeer::doSelect($c, $con); $latestExecutedQuery = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` WHERE book.TITLE LIKE 'Harry%s'"; $this->assertEquals('log: ' . $latestExecutedQuery, $testLog->latestMessage, 'PropelPDO logs queries and populates bound parameters in debug mode'); BookPeer::doDeleteAll($con); $latestExecutedQuery = "DELETE FROM `book`"; $this->assertEquals('log: ' . $latestExecutedQuery, $testLog->latestMessage, 'PropelPDO logs deletion queries in debug mode'); $latestExecutedQuery = 'DELETE FROM book WHERE 1=1'; $con->exec($latestExecutedQuery); $this->assertEquals('log: ' . $latestExecutedQuery, $testLog->latestMessage, 'PropelPDO logs exec queries in debug mode'); $con->commit(); // return to normal state after test $con->setLogger($logger); $config->setParameter("debugpdo.logging.methods", array('PropelPDO::exec', 'PropelPDO::query', 'DebugPDOStatement::execute')); } } class myLogger { public $latestMessage = ''; public function __call($method, $arguments) { $this->latestMessage = $method . ': ' . array_shift($arguments); } }