public function exportData($export, $reporter) { $this->conn->beginTransaction(); try { $lastExportedAt = (int) $export['lastExportedAt']; $areas = $this->conn->fetchAll('SELECT a.`id`, a.`name`, t.`id` AS `territoryId`, t.`name` AS `territoryName`, a.`customData`, a.`lastUpdatedAt` ' . 'FROM `' . CoreTables::AREA_TBL . '` a ' . 'INNER JOIN `' . CoreTables::TERRITORY_TBL . '` t ON t.`id` = a.`territoryId` ' . 'WHERE a.`projectId` = :projectId AND a.`statusId` = :statusId', [':projectId' => $export['projectId'], ':statusId' => $export['areaStatusId']]); $block = new ExportBlock(); foreach ($areas as $area) { $block->addId($area['id']); if ($area['lastUpdatedAt'] > $lastExportedAt) { $area['customData'] = json_decode($area['customData']); $block->addUpdatedId($area['id']); $block->addUpdate($area); } } $event = new ExportEvent($export['projectId'], $export['lastExportedAt'], $reporter); $event->addBlock('area', $block); $event = $this->eventDispatcher->dispatch(ExportEvents::EXPORT_ONGOING, $event); $this->conn->executeQuery('UPDATE `' . ExportTables::DATA_EXPORT_TBL . '` SET `lastExportedAt` = :time WHERE `id` = :id', [':time' => time(), ':id' => $export['id']]); $this->conn->commit(); return $event->output(); } catch (Exception $ex) { $this->conn->rollBack(); throw $ex; } }
/** * @inheritdoc */ protected function tearDown() { parent::tearDown(); if ($this->shouldPreventCommits === true && $this->sharedConnection !== null) { $this->sharedConnection->rollBack(); $this->sharedConnection = null; } Mockery::close(); }
protected function doEnd() { $this->cleanUpExecutionStateTable(); $this->cleanUpExecutionTable(); if (!$this->isCancelled()) { $this->conn->commit(); } else { $this->conn->rollBack(); // ? } }
/** * Closes the transaction. If the transaction has been marked to rollback, it is rolled back. Otherwise * it is committed. The method does nothing, if the transaction is not open. */ public function closeTransaction() { if ($this->inTransaction) { $this->inTransaction = false; if ($this->shouldCommit) { $this->conn->commit(); } else { $this->conn->rollBack(); } $this->shouldCommit = true; } }
protected function performRollBack($identifier = NULL) { if ($identifier === NULL) { return $this->conn->rollBack(); } $this->conn->rollbackSavepoint($identifier); }
/** * Convert the tables in the current database to use given character set and collation. * * @param string $characterSet Character set to convert to * @param string $collation Collation to set, must be compatible with the character set * @param string $outputPathAndFilename * @param boolean $verbose * @throws ConnectionException * @throws DBALException */ protected function convertToCharacterSetAndCollation($characterSet = 'utf8', $collation = 'utf8_unicode_ci', $outputPathAndFilename = null, $verbose = false) { $statements = ['SET foreign_key_checks = 0']; $statements[] = 'ALTER DATABASE ' . $this->connection->quoteIdentifier($this->persistenceSettings['backendOptions']['dbname']) . ' CHARACTER SET ' . $characterSet . ' COLLATE ' . $collation; $tableNames = $this->connection->getSchemaManager()->listTableNames(); foreach ($tableNames as $tableName) { $statements[] = 'ALTER TABLE ' . $this->connection->quoteIdentifier($tableName) . ' DEFAULT CHARACTER SET ' . $characterSet . ' COLLATE ' . $collation; $statements[] = 'ALTER TABLE ' . $this->connection->quoteIdentifier($tableName) . ' CONVERT TO CHARACTER SET ' . $characterSet . ' COLLATE ' . $collation; } $statements[] = 'SET foreign_key_checks = 1'; if ($outputPathAndFilename === null) { try { $this->connection->beginTransaction(); foreach ($statements as $statement) { if ($verbose) { $this->outputLine($statement); } $this->connection->exec($statement); } $this->connection->commit(); } catch (\Exception $exception) { $this->connection->rollBack(); $this->outputLine($exception->getMessage()); $this->outputLine('[ERROR] The transaction was rolled back.'); } } else { file_put_contents($outputPathAndFilename, implode(';' . PHP_EOL, $statements) . ';'); } }
/** * Rolls back the transaction. * It makes sure that the connection is in the correct state regardless of what happened before. * Correct state means that connection is not rollback only and does not have a transaction nesting level > 0 * * @throws \Exception */ public function rollBack() { try { /** * Roll back all the way as this is supposed to be the top level transaction and we want to reset * the nesting level */ $transactionNestingLevel = $this->connection->getTransactionNestingLevel(); for ($i = 0; $i < $transactionNestingLevel - 1; $i++) { $this->connection->rollBack(); } $this->connection->rollBack(); } catch (\Exception $e) { $rethrowable = $this->attemptToReconnectPresumedLostConnection($e); /** * If connection is functional we need to make sure the connection is not rollback only. * This can only be achieved by starting a transaction and rolling it back (the "why" is found in * lines 1277-1279 of Doctrine\DBAL\Connection). */ if ($rethrowable === $e) { $this->connection->beginTransaction(); $this->connection->rollBack(); } throw $rethrowable; } }
/** * Insert multiple rows, if a row with a duplicate key is found will update the row * This function assumes that 'id' is the primary key, and is used as a fallback for databases that don't support real upserts * * @param string $table * @param array $rows array of column => value * @param null $lastInsertId Optional reference to populate with the last auto increment id * @return int The number of affected rows * * @throws \Doctrine\DBAL\ConnectionException * @throws \Exception */ public function massUpsert($table, array $rows, &$lastInsertId = null) { if (empty($rows)) { return 0; } $rowsToInsert = []; $rowsToUpdate = []; foreach ($rows as $row) { if (!empty($row['id'])) { $rowsToUpdate[] = $row; } else { $rowsToInsert[] = $row; } } $this->db->beginTransaction(); try { $effected = $this->massInsert($table, $rowsToInsert); $lastInsertId = $this->getLastInsertId($table) - (count($rowsToInsert) - 1); foreach ($rowsToUpdate as $row) { $id = $row['id']; unset($row['id']); $effected += $this->db->update($this->db->quoteIdentifier($table), $this->quoteIdentifiers($row), ['id' => $id]); } $this->db->commit(); } catch (\Exception $e) { $this->db->rollBack(); throw $e; } return $effected; }
/** * @param string $version * @param \DateTime $apply_at * @throws \Exception */ public function fixVersion($version, \DateTime $apply_at = null) { if ($apply_at === null) { $apply_at = new \DateTime(); } $this->createTable(); $this->doctrine->beginTransaction(); try { $this->doctrine->delete(self::TABLE_NAME, array('version' => $version)); $this->doctrine->insert(self::TABLE_NAME, array('version' => $version, 'apply_at' => $apply_at->format('Y-m-d\\TH:i:s'))); $this->doctrine->commit(); } catch (\Exception $ex) { $this->doctrine->rollBack(); throw $ex; } }
/** * Rollback a transaction. * * @return void */ public function rollBack() { try { $this->connection->rollBack(); } catch (DBALException $e) { throw new QueryException($e->getMessage(), $e->getCode(), $e); } }
/** * @param callable $callback * * @return bool|int * @throws \Doctrine\DBAL\ConnectionException */ public function executeTransactionalQuery(callable $callback) { $this->connection->beginTransaction(); try { $result = $callback(); $this->connection->commit(); } catch (\Exception $e) { $this->connection->rollBack(); $this->logger->error('database', $e); $result = false; } return $result; }
/** * Salva a lista de presença (salva as faltas) de uma data específica no banco de dados. * * @param Connection $conn * @param DateTime $date Data da lista de presença * @param array $types Tipos de presença * @param array $students Alunos * @throws Exception */ public static function insertNewList(Connection $conn, DateTime $date, array $types, array $students = []) { $conn->beginTransaction(); try { foreach ($types as $type) { $conn->delete('attendance', ['attendance_date' => $date, 'attendance_type_id' => $type], ['date', PDO::PARAM_INT]); } foreach ($students as $student) { $conn->insert('attendance', ['enrollment_id' => $student['id'], 'attendance_type_id' => $student['type'], 'attendance_date' => $date], [PDO::PARAM_INT, PDO::PARAM_INT, 'date']); } $conn->commit(); } catch (Exception $ex) { $conn->rollBack(); throw $ex; } }
/** * @param DBPatcher\PatchFile $patchFile * @param \Doctrine\DBAL\Connection $connection * @return DBPatcher\PatchFile */ function applySqlPatch($patchFile, $connection) { if ($patchFile->extension === 'sql') { $sqlCommands = file_get_contents($patchFile->filename); $connection->beginTransaction(); try { $connection->exec($sqlCommands); } catch (\Doctrine\DBAL\DBALException $e) { $connection->rollBack(); return array(DBPatcher\PatchFile::copyWithNewStatus($patchFile, DBPatcher\PatchFile::STATUS_ERROR), $e->getMessage()); } $connection->commit(); return array(DBPatcher\PatchFile::copyWithNewStatus($patchFile, DBPatcher\PatchFile::STATUS_INSTALLED)); } return array(DBPatcher\PatchFile::copyWithNewStatus($patchFile, DBPatcher\PatchFile::STATUS_ERROR)); }
/** * Deletes all nodes with edges from database * * @throws DatabaseErrorException */ public function delete() { try { $this->dbal->setAutoCommit(false); $this->dbal->beginTransaction(); $this->dbal->executeQuery('DELETE FROM relations'); $this->dbal->executeQuery('DELETE FROM organizations'); $this->dbal->commit(); $this->dbal->setAutoCommit(true); } catch (\Doctrine\DBAL\ConnectionException $exception) { throw new DatabaseErrorException($exception); } catch (\Doctrine\DBAL\DBALException $exception) { $this->dbal->rollBack(); $this->dbal->setAutoCommit(true); throw new DatabaseErrorException($exception); } }
/** * @param array $data * @param string $namespace * @param int $localeId * @param int $shopId * @throws \Exception */ public function write($data, $namespace, $localeId, $shopId) { if (empty($data)) { throw new \Exception('You called write() but provided no data to be written'); } if (!isset($this->db)) { throw new \Exception('Required database connection is missing'); } $this->db->beginTransaction(); try { // If no update are allowed, we can speed up using INSERT IGNORE if (!$this->update) { $this->insertBatch($data, $namespace, $localeId, $shopId); } else { $rows = $this->db->fetchAll('SELECT * FROM s_core_snippets WHERE shopID = :shopId AND localeID = :localeId AND namespace = :namespace', array('shopId' => $shopId, 'localeId' => $localeId, 'namespace' => $namespace)); foreach ($data as $name => $value) { $row = null; // Find the matching value in db, if it exists foreach ($rows as $key => $values) { if ($values['name'] == $name) { $row = $values; unset($rows[$key]); break; } } if ($row !== null) { // Found a matching value, try update $this->updateRecord($value, $row); } else { // No matching value, just insert a new one $this->insertRecord($name, $value, $namespace, $localeId, $shopId); } } } $this->db->commit(); } catch (\Exception $e) { $this->db->rollBack(); throw new \Exception(sprintf('An error occurred when importing namespace "%s" for locale "%s"', $namespace, $localeId), 0, $e); } }
/** * Generates the next unused value for the given sequence name. * * @param string $sequenceName * * @return integer * * @throws \Doctrine\DBAL\DBALException */ public function nextValue($sequenceName) { if (isset($this->sequences[$sequenceName])) { $value = $this->sequences[$sequenceName]['value']; $this->sequences[$sequenceName]['value']++; if ($this->sequences[$sequenceName]['value'] >= $this->sequences[$sequenceName]['max']) { unset($this->sequences[$sequenceName]); } return $value; } $this->conn->beginTransaction(); try { $platform = $this->conn->getDatabasePlatform(); $sql = "SELECT sequence_value, sequence_increment_by " . "FROM " . $platform->appendLockHint($this->generatorTableName, \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE) . " " . "WHERE sequence_name = ? " . $platform->getWriteLockSQL(); $stmt = $this->conn->executeQuery($sql, array($sequenceName)); if ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { $row = array_change_key_case($row, CASE_LOWER); $value = $row['sequence_value']; $value++; if ($row['sequence_increment_by'] > 1) { $this->sequences[$sequenceName] = array('value' => $value, 'max' => $row['sequence_value'] + $row['sequence_increment_by']); } $sql = "UPDATE " . $this->generatorTableName . " " . "SET sequence_value = sequence_value + sequence_increment_by " . "WHERE sequence_name = ? AND sequence_value = ?"; $rows = $this->conn->executeUpdate($sql, array($sequenceName, $row['sequence_value'])); if ($rows != 1) { throw new \Doctrine\DBAL\DBALException("Race-condition detected while updating sequence. Aborting generation"); } } else { $this->conn->insert($this->generatorTableName, array('sequence_name' => $sequenceName, 'sequence_value' => 1, 'sequence_increment_by' => 1)); $value = 1; } $this->conn->commit(); } catch (\Exception $e) { $this->conn->rollBack(); throw new \Doctrine\DBAL\DBALException("Error occurred while generating ID with TableGenerator, aborted generation: " . $e->getMessage(), 0, $e); } return $value; }
/** * rolls back the current transaction. * * @return void */ public function rollBack() { self::$transactionActive = false; self::setForce(false); parent::rollBack(); }
public function rollback() { $this->connection->rollBack(); }
public function rollBack() { if ($this->usesFixtures()) { try { return $this->callWithFixtures('rollBack', func_get_args()); } catch (ConnectionException $e) { // That's ok! } } else { parent::rollBack(); } }
/** * Save a workflow definition to the database. * * @param ezcWorkflow $workflow * @throws ezcWorkflowDefinitionStorageException */ public function save(\ezcWorkflow $workflow) { // Verify the workflow. $workflow->verify(); if (strlen($workflow->name) == 0) { throw new \ezcWorkflowDefinitionStorageException(); } $platform = $this->conn->getDatabasePlatform(); // what mode of saving should it be? Update or Re-Generate? // // Conditions that an update sufficies: // 1. No node has been deleted // 2. No node has changed its meaning (action class or type) // 3. For simplicitly only zero or one new nodes will be created. $hasExistingNodeIds = array(); $newNodes = 0; foreach ($workflow->nodes as $node) { $oid = spl_object_hash($node); if (!isset($this->nodeMap[$oid])) { $newNodes++; } else { $hasExistingNodeIds[] = $this->nodeMap[$oid]; } } $canBeUpdate = false; if ($newNodes < 2 && count(array_diff($hasExistingNodeIds, $this->workflowNodeIds[$workflow->id])) == 0 && $workflow->id) { $canBeUpdate = true; } $this->workflowNodeIds[$workflow->id] = array(); try { $this->conn->beginTransaction(); $workflowVersion = $this->getCurrentVersion($workflow->name) + 1; $this->conn->update($this->options->workflowTable(), array('workflow_outdated' => 1), array('workflow_name' => $workflow->name)); $date = new \DateTime("now"); if ($canBeUpdate) { $this->conn->update($this->options->workflowTable(), array('workflow_version' => $workflowVersion, 'workflow_created' => $date->format($platform->getDateTimeFormatString())), array('workflow_id' => $workflow->id)); } else { $data = array('workflow_name' => $workflow->name, 'workflow_version' => $workflowVersion, 'workflow_created' => $date->format($platform->getDateTimeFormatString()), 'workflow_outdated' => 0); // For sequences: get id before insert if ($platform->prefersSequences()) { $id = (int) $this->conn->fetchColumn($platform->getSequenceNextValSQL($this->options->workflowSequence())); $data['workflow_id'] = $id; $workflow->id = $id; } $this->conn->insert($this->options->workflowTable(), $data); if ($platform->prefersIdentityColumns()) { $workflow->id = (int) $this->conn->lastInsertId(); } $workflow->definitionStorage = $this; } // Write node table rows. $nodeMap = array(); foreach ($workflow->nodes as $node) { /* @var $node \ezcWorkflowNode */ $oid = spl_object_hash($node); if ($canBeUpdate && isset($this->nodeMap[$oid])) { $nodeId = (int) $this->nodeMap[$oid]; $this->conn->update($this->options->nodeTable(), array('node_configuration' => $this->options->getSerializer()->serialize($node->getConfiguration())), array('node_id' => $nodeId)); } else { $data = array('workflow_id' => (int) $workflow->id, 'node_class' => get_class($node), 'node_configuration' => $this->options->getSerializer()->serialize($node->getConfiguration())); if ($platform->prefersSequences()) { $nodeId = (int) $this->conn->fetchColumn($platform->getSequenceNextValSQL($this->options->nodeSequence())); $data['node_id'] = $nodeId; } $this->conn->insert($this->options->nodeTable(), $data); if ($platform->prefersIdentityColumns()) { $nodeId = (int) $this->conn->lastInsertId(); } } $nodeMap[$nodeId] = $node; $this->workflowNodeIds[$workflow->id][] = $nodeId; $this->nodeMap[$oid] = $nodeId; } if ($canBeUpdate) { // Delete all the node connections, NodeMap Keys are casted to (int) so usage here is safe. $query = "DELETE FROM " . $this->options->nodeConnectionTable() . " " . "WHERE incoming_node_id IN (" . implode(",", array_keys($nodeMap)) . ") OR " . "outgoing_node_id IN (" . implode(",", array_keys($nodeMap)) . ")"; $this->conn->executeUpdate($query); } foreach ($workflow->nodes as $node) { foreach ($node->getOutNodes() as $outNode) { $incomingNodeId = null; $outgoingNodeId = null; foreach ($nodeMap as $_id => $_node) { if ($_node === $node) { $incomingNodeId = $_id; } else { if ($_node === $outNode) { $outgoingNodeId = $_id; } } if ($incomingNodeId !== NULL && $outgoingNodeId !== NULL) { break; } } $data = array('incoming_node_id' => $incomingNodeId, 'outgoing_node_id' => $outgoingNodeId); if ($platform->prefersSequences()) { $id = (int) $this->conn->fetchColumn($platform->getSequenceNextValSQL($this->options->nodeConnectionSequence())); $data['id'] = $id; } $this->conn->insert($this->options->nodeConnectionTable(), $data); } } unset($nodeMap); if ($canBeUpdate) { $this->conn->delete($this->options->variableHandlerTable(), array('workflow_id' => (int) $workflow->id)); } foreach ($workflow->getVariableHandlers() as $variable => $class) { $this->conn->insert($this->options->variableHandlerTable(), array('workflow_id' => (int) $workflow->id, 'variable' => $variable, 'class' => $class)); } $this->conn->commit(); } catch (\Exception $e) { $this->conn->rollBack(); throw new \ezcWorkflowDefinitionStorageException("Error while persisting workflow: " . $e->getMessage()); } }
/** * @group DBAL-81 */ public function testRollBackStartsTransactionInNoAutoCommitMode() { $driverMock = $this->getMock('Doctrine\\DBAL\\Driver'); $driverMock->expects($this->any())->method('connect')->will($this->returnValue(new DriverConnectionMock())); $conn = new Connection(array('platform' => new Mocks\MockPlatform()), $driverMock); $conn->setAutoCommit(false); $conn->connect(); $conn->rollBack(); $this->assertTrue($conn->isTransactionActive()); }
/** */ private function abortTransaction() { $this->connection->rollBack(); $this->stagedEvents = []; }
/** * Execute this migration version up or down and and return the SQL. * We are only allowing the addSql call and the schema modification to take effect in the up and down call. * This is necessary to ensure that the migration is revertable. * The schema is passed to the pre and post method only to be able to test the presence of some table, And the * connection that can get used trough it allow for the test of the presence of records. * * @param string $direction The direction to execute the migration. * @param boolean $dryRun Whether to not actually execute the migration SQL and just do a dry run. * @param boolean $timeAllQueries Measuring or not the execution time of each SQL query. * * @return array $sql * * @throws \Exception when migration fails */ public function execute($direction, $dryRun = false, $timeAllQueries = false) { $this->sql = []; $transaction = $this->migration->isTransactional(); if ($transaction) { //only start transaction if in transactional mode $this->connection->beginTransaction(); } try { $migrationStart = microtime(true); $this->state = self::STATE_PRE; $fromSchema = $this->schemaProvider->createFromSchema(); $this->migration->{'pre' . ucfirst($direction)}($fromSchema); if ($direction === self::DIRECTION_UP) { $this->outputWriter->write("\n" . sprintf(' <info>++</info> migrating <comment>%s</comment>', $this->version) . "\n"); } else { $this->outputWriter->write("\n" . sprintf(' <info>--</info> reverting <comment>%s</comment>', $this->version) . "\n"); } $this->state = self::STATE_EXEC; $toSchema = $this->schemaProvider->createToSchema($fromSchema); $this->migration->{$direction}($toSchema); $this->addSql($this->schemaProvider->getSqlDiffToMigrate($fromSchema, $toSchema)); $this->executeRegisteredSql($dryRun, $timeAllQueries); $this->state = self::STATE_POST; $this->migration->{'post' . ucfirst($direction)}($toSchema); if (!$dryRun) { if ($direction === self::DIRECTION_UP) { $this->markMigrated(); } else { $this->markNotMigrated(); } } $migrationEnd = microtime(true); $this->time = round($migrationEnd - $migrationStart, 2); if ($direction === self::DIRECTION_UP) { $this->outputWriter->write(sprintf("\n <info>++</info> migrated (%ss)", $this->time)); } else { $this->outputWriter->write(sprintf("\n <info>--</info> reverted (%ss)", $this->time)); } if ($transaction) { //commit only if running in transactional mode $this->connection->commit(); } $this->state = self::STATE_NONE; return $this->sql; } catch (SkipMigrationException $e) { if ($transaction) { //only rollback transaction if in transactional mode $this->connection->rollBack(); } if ($dryRun === false) { // now mark it as migrated if ($direction === self::DIRECTION_UP) { $this->markMigrated(); } else { $this->markNotMigrated(); } } $this->outputWriter->write(sprintf("\n <info>SS</info> skipped (Reason: %s)", $e->getMessage())); $this->state = self::STATE_NONE; return []; } catch (\Exception $e) { $this->outputWriter->write(sprintf('<error>Migration %s failed during %s. Error %s</error>', $this->version, $this->getExecutionState(), $e->getMessage())); if ($transaction) { //only rollback transaction if in transactional mode $this->connection->rollBack(); } $this->state = self::STATE_NONE; throw $e; } }
/** * Safe rollback. * * @return void */ public function rollback() { if ($this->db->isTransactionActive()) { $this->db->rollBack(); } }
/** * {@inheritDoc} */ public function rollBack() { $this->connect('master'); return parent::rollBack(); }
/** * Rollback a transaction */ public function rollbackTransaction() { $this->resConnection->rollBack(); }
/** */ protected function abortTransaction(EventSourcedEntity $eventSourcedEntity) { $this->connection->rollBack(); $this->stagedEvents = []; }