public static function doBackupRecord(\Criteria $criteria, PropelPDO $con) { $db = Propel::getDB($criteria->getDbName()); $dbMap = Propel::getDatabaseMap($criteria->getDbName()); $keys = $criteria->keys(); if (!empty($keys)) { $tableName = $criteria->getTableName($keys[0]); } else { throw new PropelException("Database insert attempted without anything specified to insert"); } $tableMap = $dbMap->getTable($tableName); $whereClause = array(); $peer = $tableMap->getPeerClassname(); $versionTable = $peer::$workspaceBehaviorVersionName; $originTable = $tableMap->getName(); $tables = $criteria->getTablesColumns(); if (empty($tables)) { throw new \PropelException("Empty Criteria"); } $fields = array_keys($tableMap->getColumns()); $fields = implode(', ', $fields); foreach ($tables as $tableName => $columns) { $whereClause = array(); $params = array(); $stmt = null; try { foreach ($columns as $colName) { $sb = ""; $criteria->getCriterion($colName)->appendPsTo($sb, $params); $whereClause[] = $sb; } $sql = sprintf("INSERT INTO %s (%s) SELECT %s FROM %s WHERE %s", $versionTable, $fields, $fields, $originTable, implode(" AND ", $whereClause)); $stmt = $con->prepare($sql); $db->bindValues($stmt, $params, $dbMap); $stmt->execute(); $stmt->closeCursor(); } catch (Exception $e) { Propel::log($e->getMessage(), Propel::LOG_ERR); throw new PropelException(sprintf('Unable to execute INSERT INTO statement [%s]', $sql), $e); } } // for each table }
/** * 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 $selectCriteria A Criteria object containing values used in where * clause. * @param $updateValues A Criteria object containing values used in set * clause. * @param PropelPDO $con The PropelPDO 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 static function doUpdate(Criteria $selectCriteria, Criteria $updateValues, PropelPDO $con) { $db = Propel::getDB($selectCriteria->getDbName()); $dbMap = Propel::getDatabaseMap($selectCriteria->getDbName()); // Get list of required tables, containing all columns $tablesColumns = $selectCriteria->getTablesColumns(); if (empty($tablesColumns)) { $tablesColumns = array($selectCriteria->getPrimaryTableName() => array()); } // we also need the columns for the update SQL $updateTablesColumns = $updateValues->getTablesColumns(); $affectedRows = 0; // initialize this in case the next loop has no iterations. foreach ($tablesColumns as $tableName => $columns) { $whereClause = array(); $params = array(); $stmt = null; try { $sql = 'UPDATE '; if ($queryComment = $selectCriteria->getComment()) { $sql .= '/* ' . $queryComment . ' */ '; } // is it a table alias? if ($tableName2 = $selectCriteria->getTableForAlias($tableName)) { $udpateTable = $tableName2 . ' ' . $tableName; $tableName = $tableName2; } else { $udpateTable = $tableName; } if ($db->useQuoteIdentifier()) { $sql .= $db->quoteIdentifierTable($udpateTable); } else { $sql .= $udpateTable; } $sql .= " SET "; $p = 1; foreach ($updateTablesColumns[$tableName] as $col) { $updateColumnName = substr($col, strrpos($col, '.') + 1); // add identifiers for the actual database? if ($db->useQuoteIdentifier()) { $updateColumnName = $db->quoteIdentifier($updateColumnName); } 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 = self::buildParams($updateTablesColumns[$tableName], $updateValues); $sql = substr($sql, 0, -2); if (!empty($columns)) { foreach ($columns as $colName) { $sb = ""; $selectCriteria->getCriterion($colName)->appendPsTo($sb, $params); $whereClause[] = $sb; } $sql .= " WHERE " . implode(" AND ", $whereClause); } $stmt = $con->prepare($sql); // Replace ':p?' with the actual values self::populateStmtValues($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), $e); } } // foreach table in the criteria return $affectedRows; }
/** * 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 $selectCriteria A Criteria object containing values used in where * clause. * @param $updateValues A Criteria object containing values used in set * clause. * @param $con The Connection 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 Creole db driver. * @throws PropelException */ public static function doUpdate(Criteria $selectCriteria, Criteria $updateValues, Connection $con) { $db = Propel::getDB($selectCriteria->getDbName()); $dbMap = Propel::getDatabaseMap($selectCriteria->getDbName()); // Get list of required tables, containing all columns $tablesColumns = $selectCriteria->getTablesColumns(); // we also need the columns for the update SQL $updateTablesColumns = $updateValues->getTablesColumns(); $affectedRows = 0; // initialize this in case the next loop has no iterations. foreach ($tablesColumns as $tableName => $columns) { $whereClause = array(); $selectParams = array(); foreach ($columns as $colName) { $sb = ""; $selectCriteria->getCriterion($colName)->appendPsTo($sb, $selectParams); $whereClause[] = $sb; } $rs = null; $stmt = null; try { $sqlSnippet = implode(" AND ", $whereClause); if ($selectCriteria->isSingleRecord()) { // Get affected records. $sql = "SELECT COUNT(*) FROM " . $tableName . " WHERE " . $sqlSnippet; $stmt = $con->prepareStatement($sql); self::populateStmtValues($stmt, $selectParams, $dbMap); $rs = $stmt->executeQuery(ResultSet::FETCHMODE_NUM); $rs->next(); if ($rs->getInt(1) > 1) { $rs->close(); throw new PropelException("Expected to update 1 record, multiple matched."); } $rs->close(); } $sql = "UPDATE " . $tableName . " SET "; foreach ($updateTablesColumns[$tableName] as $col) { $sql .= substr($col, strpos($col, '.') + 1) . " = ?,"; } $sql = substr($sql, 0, -1) . " WHERE " . $sqlSnippet; Propel::log($sql, Propel::LOG_DEBUG); $stmt = $con->prepareStatement($sql); // Replace '?' with the actual values self::populateStmtValues($stmt, array_merge(self::buildParams($updateTablesColumns[$tableName], $updateValues), $selectParams), $dbMap); $affectedRows = $stmt->executeUpdate(); $stmt->close(); } catch (Exception $e) { if ($rs) { $rs->close(); } if ($stmt) { $stmt->close(); } Propel::log($e->getMessage(), Propel::LOG_ERR); throw new PropelException("Unable to execute UPDATE statement.", $e); } } // foreach table in the criteria return $affectedRows; }
/** * Executes query build by createSelectSql() and returns ResultSet. * * @param Criteria $criteria A Criteria. * @param Connection $con A connection to use. * @return ResultSet The resultset. * @throws PropelException * @see createSelectSql() */ public static function doSelect(Criteria $criteria, $con = null) { $arrTables = array_keys($criteria->getTablesColumns()); if (sizeof($arrTables) > 1) { $arrJoins = array(); foreach ($criteria->getJoins() as $objJoin) { if (false) { $objJoin = new Join(); } $arrJoins[] = $objJoin->getLeftTableName(); $arrJoins[] = $objJoin->getRightTableName(); } array_unique($arrJoins); $arrMissedJoinsWhatever = array_diff($arrTables, $arrJoins); } // endif $dbMap = Propel::getDatabaseMap($criteria->getDbName()); if ($con === null) { $con = Propel::getConnection($criteria->getDbName()); } $stmt = null; try { // Transaction support exists for (only?) Postgres, which must // have SELECT statements that include bytea columns wrapped w/ // transactions. if ($criteria->isUseTransaction()) { $con->begin(); } $params = array(); $sql = self::createSelectSql($criteria, $params); $stmt = $con->prepareStatement($sql); $stmt->setLimit($criteria->getLimit()); $stmt->setOffset($criteria->getOffset()); self::populateStmtValues($stmt, $params, $dbMap); $rs = $stmt->executeQuery(ResultSet::FETCHMODE_NUM); if ($criteria->isUseTransaction()) { $con->commit(); } } catch (Exception $e) { if ($stmt) { $stmt->close(); } if ($criteria->isUseTransaction()) { $con->rollback(); } Propel::log($e->getMessage(), Propel::LOG_ERR); throw new PropelException($e); } if (isset($arrMissedJoinsWhatever) && sizeof($arrMissedJoinsWhatever)) { $strBody = "The probable error, a lack of joins tables " . var_export($arrMissedJoinsWhatever, true) . " in query: \n\n" . $sql; // $strBody .= "\n\n".sfContext::getInstance()->getRequest()->getUri(); throw new Exception($strBody); } // endif return $rs; }