Skip to content

Commit

Permalink
Merge pull request propelorm#1727 from mringler/feature/write_failed_…
Browse files Browse the repository at this point in the history
…queries_to_log

Show failed queries and SQL error in debug mode exception
  • Loading branch information
dereuromark authored May 3, 2021
2 parents cc16d3d + 93f059b commit 8383788
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 116 deletions.
5 changes: 0 additions & 5 deletions phpstan-baseline.neon

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

121 changes: 67 additions & 54 deletions src/Propel/Runtime/ActiveQuery/Criteria.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use Propel\Runtime\ActiveQuery\Criterion\LikeCriterion;
use Propel\Runtime\ActiveQuery\Criterion\RawCriterion;
use Propel\Runtime\Connection\ConnectionInterface;
use Propel\Runtime\Connection\ConnectionWrapper;
use Propel\Runtime\Connection\StatementWrapper;
use Propel\Runtime\Exception\LogicException;
use Propel\Runtime\Exception\PropelException;
use Propel\Runtime\Propel;
Expand Down Expand Up @@ -2461,41 +2463,31 @@ public function doInsert(?ConnectionInterface $con = null)
$this->add($pk->getFullyQualifiedName(), $id);
}

$sql = null;
try {
$qualifiedCols = $this->keys(); // we need table.column cols when populating values
$columns = []; // but just 'column' cols for the SQL
foreach ($qualifiedCols as $qualifiedCol) {
$columns[] = substr($qualifiedCol, strrpos($qualifiedCol, '.') + 1);
}
$qualifiedCols = $this->keys(); // we need table.column cols when populating values
$columns = []; // but just 'column' cols for the SQL
foreach ($qualifiedCols as $qualifiedCol) {
$columns[] = substr($qualifiedCol, strrpos($qualifiedCol, '.') + 1);
}
$columns = array_map([$this, 'quoteIdentifier'], $columns);
$columnCsv = implode(',', $columns);

// add identifiers
$columns = array_map([$this, 'quoteIdentifier'], $columns);
$tableName = $this->quoteIdentifierTable($tableName);

$sql = 'INSERT INTO ' . $tableName
. ' (' . implode(',', $columns) . ')'
. ' VALUES (';
// . substr(str_repeat("?,", count($columns)), 0, -1) .
for ($p = 1, $cnt = count($columns); $p <= $cnt; $p++) {
$sql .= ':p' . $p;
if ($p !== $cnt) {
$sql .= ',';
}
}
$sql .= ')';
$parameterIndexes = (count($columns) === 0) ? [] : range(1, count($columns));
$parameterPlaceholders = preg_filter('/^/', ':p', $parameterIndexes); // prefix each element with ':p'
$parameterPlaceholdersCsv = implode(',', $parameterPlaceholders);

$params = $this->buildParams($qualifiedCols);
$tableName = $this->quoteIdentifierTable($tableName);
$sql = "INSERT INTO $tableName ($columnCsv) VALUES ($parameterPlaceholdersCsv)";

$stmt = null;
$params = $this->buildParams($qualifiedCols);
try {
$db->cleanupSQL($sql, $params, $this, $dbMap);

$stmt = $con->prepare($sql);
$db->bindValues($stmt, $params, $dbMap, $db);
$stmt->execute();
} catch (Exception $e) {
Propel::log($e->getMessage(), Propel::LOG_ERR);

throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e);
$this->handleStatementException($e, $sql, $con, $stmt);
}

// If the primary key column is auto-incremented, get the id now.
Expand Down Expand Up @@ -2551,8 +2543,6 @@ public function getPrimaryKey(?Criteria $criteria = null)
* @param array|\Propel\Runtime\ActiveQuery\Criteria $updateValues A Criteria object containing values used in set clause.
* @param \Propel\Runtime\Connection\ConnectionInterface $con The ConnectionInterface connection object to use.
*
* @throws \Propel\Runtime\Exception\PropelException
*
* @return int The number of rows affected by last update statement.
* For most uses there is only one update statement executed, so this number will
* correspond to the number of rows affected by the call to this method.
Expand Down Expand Up @@ -2658,22 +2648,12 @@ public function doUpdate($updateValues, ConnectionInterface $con)
}

$db->cleanupSQL($sql, $params, $updateValues, $dbMap);

$stmt = $con->prepare($sql);

// Replace ':p?' with the actual values
$db->bindValues($stmt, $params, $dbMap);

$stmt->execute();

$affectedRows = $stmt->rowCount();

$stmt = null; // close
} catch (Exception $e) {
$stmt = null; // close
Propel::log($e->getMessage(), Propel::LOG_ERR);

throw new PropelException(sprintf('Unable to execute UPDATE statement [%s]', $sql), 0, $e);
$this->handleStatementException($e, $sql, $con, $stmt);
}
}

Expand Down Expand Up @@ -2710,7 +2690,6 @@ public function buildParams($columns, ?Criteria $values = null)
* @param \Propel\Runtime\Connection\ConnectionInterface|null $con
*
* @throws \Propel\Runtime\Exception\LogicException
* @throws \Propel\Runtime\Exception\PropelException
*
* @return \Propel\Runtime\DataFetcher\DataFetcherInterface
*/
Expand Down Expand Up @@ -2746,14 +2725,14 @@ public function doCount(?ConnectionInterface $con = null)
$this->clearSelectColumns()->addSelectColumn('COUNT(*)');
$sql = $this->createSelectSql($params);
}

$stmt = null;
try {
$stmt = $con->prepare($sql);
$db->bindValues($stmt, $params, $dbMap);
$stmt->execute();
} catch (Exception $e) {
Propel::log($e->getMessage(), Propel::LOG_ERR);

throw new PropelException(sprintf('Unable to execute COUNT statement [%s]', $sql), 0, $e);
$this->handleStatementException($e, $sql, $con, $stmt);
}

return $con->getDataFetcher($stmt);
Expand Down Expand Up @@ -2839,9 +2818,7 @@ public function doDelete(?ConnectionInterface $con = null)
$stmt->execute();
$affectedRows = $stmt->rowCount();
} catch (Exception $e) {
Propel::log($e->getMessage(), Propel::LOG_ERR);

throw new PropelException(sprintf('Unable to execute DELETE statement [%s]', $sql), 0, $e);
$this->handleStatementException($e, $sql, $con, $stmt);
}
}

Expand All @@ -2853,8 +2830,6 @@ public function doDelete(?ConnectionInterface $con = null)
*
* @param \Propel\Runtime\Connection\ConnectionInterface|null $con A connection object
*
* @throws \Propel\Runtime\Exception\PropelException
*
* @return \Propel\Runtime\DataFetcher\DataFetcherInterface A dataFetcher using the connection, ready to be fetched
*/
public function doSelect(?ConnectionInterface $con = null)
Expand All @@ -2867,22 +2842,60 @@ public function doSelect(?ConnectionInterface $con = null)

$params = [];
$sql = $this->createSelectSql($params);
$stmt = null;
try {
$stmt = $con->prepare($sql);
$db->bindValues($stmt, $params, $dbMap);
$stmt->execute();
} catch (Exception $e) {
if (isset($stmt)) {
$stmt = null; // close
}
Propel::log($e->getMessage(), Propel::LOG_ERR);

throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), null, $e);
$this->handleStatementException($e, $sql, $con, $stmt);
}

return $con->getDataFetcher($stmt);
}

/**
* Logs an exception and adds the complete SQL statement to the exception.
*
* @param \Exception $e The initial exception.
* @param string|null $sql The SQL statement which triggered the exception.
* @param \Propel\Runtime\Connection\ConnectionInterface|null $con Used to determine if debug mode is enabled. In debug mode, exception messages
* are more verbose, but might unveil sensitive data.
* @param \Propel\Runtime\Connection\StatementInterface|\PDOStatement|null $stmt The prepared statement.
*
* @throws \Propel\Runtime\Exception\PropelException
*
* @return void
*/
protected function handleStatementException(Exception $e, ?string $sql, ?ConnectionInterface $con = null, $stmt = null): void
{
$internalMessage = $e->getMessage();
Propel::log($internalMessage, Propel::LOG_ERR);

$isDebugMode = $this->connectionIsInDebugMode($con);
if ($isDebugMode && $stmt instanceof StatementWrapper) {
$sql = $stmt->getExecutedQueryString();
}
$publicMessage = "Unable to execute statement [$sql]";
if ($isDebugMode) {
$publicMessage .= "\nReason: [$internalMessage]";
}

throw new PropelException($publicMessage, 0, $e);
}

/**
* Check if the connection has debug mode enabled
*
* @param \Propel\Runtime\Connection\ConnectionInterface|null $con
*
* @return bool
*/
protected function connectionIsInDebugMode(?ConnectionInterface $con): bool
{
return ($con instanceof ConnectionWrapper && $con->useDebug);
}

// Fluid operators

/**
Expand Down
Loading

0 comments on commit 8383788

Please sign in to comment.