/** * Method used to update rows in the DB. Rows are selected based * on selectCriteria and updated using values in updateValues. * <p> * Use this method for performing an update of the kind: * <p> * WHERE some_column = some value AND could_have_another_column = * another value AND so on. * * @param Criteria $updateValues A Criteria object containing values used in set clause. * @param ConnectionInterface $con The ConnectionInterface connection object to use. * * @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. * Note that the return value does require that this information is returned * (supported) by the Propel db driver. * * @throws PropelException */ public function doUpdate($updateValues, ConnectionInterface $con) { /** @var PdoAdapter $db */ $db = Propel::getServiceContainer()->getAdapter($this->getDbName()); $dbMap = Propel::getServiceContainer()->getDatabaseMap($this->getDbName()); // Get list of required tables, containing all columns $tablesColumns = $this->getTablesColumns(); if (empty($tablesColumns) && ($table = $this->getPrimaryTableName())) { $tablesColumns = [$table => []]; } // we also need the columns for the update SQL $updateTablesColumns = $updateValues->getTablesColumns(); // If no columns are changing values, we may get here with // an empty array in $updateTablesColumns. In that case, // there is nothing to do, so we return the rows affected, // which is 0. Fixes a bug in which an UPDATE statement // would fail in this instance. if (empty($updateTablesColumns)) { return 0; } $affectedRows = 0; // initialize this in case the next loop has no iterations. foreach ($tablesColumns as $tableName => $columns) { $whereClause = []; $params = []; $stmt = null; try { $sql = 'UPDATE '; $queryComment = $this->getComment(); if ($queryComment) { $sql .= '/* ' . $queryComment . ' */ '; } // is it a table alias? $realTableName = $this->getTableForAlias($tableName); if ($realTableName) { $updateTable = $realTableName . ' ' . $tableName; $tableName = $realTableName; } else { $updateTable = $tableName; } $sql .= $this->quoteIdentifierTable($updateTable); $sql .= " SET "; $p = 1; foreach ($updateTablesColumns[$tableName] as $col) { $updateColumnName = substr($col, strrpos($col, '.') + 1); // add identifiers for the actual database? $updateColumnName = $this->quoteIdentifier($updateColumnName, $tableName); if ($updateValues->getComparison($col) != Criteria::CUSTOM_EQUAL) { $sql .= $updateColumnName . '=:p' . $p++ . ', '; } else { $param = $updateValues->get($col); $sql .= $updateColumnName . ' = '; if (is_array($param)) { if (isset($param['raw'])) { $raw = $param['raw']; $rawcvt = ''; // parse the $params['raw'] for ? chars for ($r = 0, $len = strlen($raw); $r < $len; $r++) { if ($raw[$r] == '?') { $rawcvt .= ':p' . $p++; } else { $rawcvt .= $raw[$r]; } } $sql .= $rawcvt . ', '; } else { $sql .= ':p' . $p++ . ', '; } if (isset($param['value'])) { $updateValues->put($col, $param['value']); } } else { $updateValues->remove($col); $sql .= $param . ', '; } } } $params = $this->buildParams($updateTablesColumns[$tableName], $updateValues); $sql = substr($sql, 0, -2); if (!empty($columns)) { foreach ($columns as $colName) { $sb = ''; $this->getCriterion($colName)->appendPsTo($sb, $params); $this->replaceNames($sb); $whereClause[] = $sb; } $sql .= ' WHERE ' . implode(' AND ', $whereClause); } $db->cleanupSQL($sql, $params, $updateValues, $dbMap); $stmt = $con->prepare($sql); // Replace ':p?' with the actual values $db->bindValues($stmt, $params, $dbMap, $db); $stmt->execute(); $affectedRows = $stmt->rowCount(); $stmt = null; // close } catch (\Exception $e) { if ($stmt) { $stmt = null; // close } Propel::log($e->getMessage(), Propel::LOG_ERR); throw new PropelException(sprintf('Unable to execute UPDATE statement [%s]', $sql), 0, $e); } } // foreach table in the criteria return $affectedRows; }