protected function execute(InputInterface $input, OutputInterface $output) { $file = $input->getArgument('file'); if (!is_file($file)) { throw new RuntimeException('File does not exists'); } $verbose = $output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL; if (!$verbose) { $this->logger->pushHandler(new NullHandler()); } try { $this->connection->beginTransaction(); $result = $this->importService->import(file_get_contents($file)); $this->connection->commit(); $output->writeln('Import successful!'); $output->writeln('The following actions were done:'); $output->writeln(''); foreach ($result as $message) { $output->writeln('- ' . $message); } } catch (\Exception $e) { $this->connection->rollback(); $output->writeln('An exception occured during import. No changes are applied to the database.'); $output->writeln(''); $output->writeln('Message: ' . $e->getMessage()); $output->writeln('Trace: ' . $e->getTraceAsString()); } if (!$verbose) { $this->logger->popHandler(); } }
/** * @param CommitId $commitId * @param Contract $streamContract * @param Identifier $streamId * @param $expectedStreamRevision * @param EventEnvelope[] $eventEnvelopes * @throws \Doctrine\DBAL\ConnectionException * @throws \Exception * @return void */ public function commit(CommitId $commitId, Contract $streamContract, Identifier $streamId, $expectedStreamRevision, array $eventEnvelopes) { $this->connection->beginTransaction(); $now = (new DateTimeImmutable('now', new DateTimeZone('UTC')))->format("Y-m-d H:i:s"); try { $this->controlOptimisticConcurrency($streamContract, $streamId, $expectedStreamRevision); $nextStreamRevision = $expectedStreamRevision; foreach ($eventEnvelopes as $eventEnvelope) { $this->connection->executeQuery(Insert::into(self::TABLE_NAME), ['streamContract' => (string) $streamContract, 'streamId' => (string) $streamId, 'streamRevision' => ++$nextStreamRevision, 'eventContract' => (string) $eventEnvelope->getEventContract(), 'eventPayload' => (string) $eventEnvelope->getEventPayload(), 'eventId' => (string) $eventEnvelope->getEventId(), 'commitId' => $commitId, 'utcCommittedTime' => $now]); } $this->connection->commit(); } catch (Exception $exception) { $this->connection->rollback(); throw $exception; } }
/** * {@inheritdoc} */ public function register(EventDispatcher $dispatcher) { $dispatcher->addListener(RouteMatchedEvent::class, function (RouteMatchedEvent $event) { $annotation = $this->getTransactionalAnnotation($event->getRouteMatch()); if ($annotation) { $this->connection->setTransactionIsolation($annotation->getIsolationLevel()); $this->connection->beginTransaction(); } }); $dispatcher->addListener(ControllerInvocatedEvent::class, function (ControllerInvocatedEvent $event) { $annotation = $this->getTransactionalAnnotation($event->getRouteMatch()); if ($annotation) { if ($this->connection->isTransactionActive()) { $this->connection->rollback(); } } }); }
/** * Delete a workflow by its ID * * @param int $workflowId * @return void */ public function delete($workflowId) { $this->conn->beginTransaction(); try { // delete only those two, the rest should be deleted automatically through cascading foreign keys $this->conn->delete($this->options->variableHandlerTable(), array('workflow_id' => $workflowId)); $this->conn->delete($this->options->workflowTable(), array('workflow_id' => $workflowId)); $this->conn->commit(); } catch (\Exception $e) { $this->conn->rollback(); } }
/** * Executes an insert into the database * * @param array $updateData * @param $id * @return int * @throws Exception * @throws \Doctrine\DBAL\ConnectionException * @throws \Exception */ public function executeUpdate(array $updateData, $id) { $this->connection->beginTransaction(); try { $primaryKey = ['id' => $id]; $rows = $this->connection->update($this->table, $updateData, $primaryKey); $this->connection->commit(); return $rows; } catch (\Exception $exception) { $this->connection->rollback(); throw $exception; } }
/** * @param iterable $metadatas list of \Doctrine\ORM\Mapping\ClassMetadata * * @throws \Exception */ public function truncateMetadatas($metadatas) { $this->reset(); $this->connection->beginTransaction(); try { $this->disableDatabaseForeignKeyChecks(); /* @var $classMetadata \Doctrine\ORM\Mapping\ClassMetadata */ foreach ($metadatas as $classMetadata) { if ($classMetadata->isMappedSuperclass === false) { $this->truncateTable($classMetadata->getTableName()); foreach ($classMetadata->getAssociationMappings() as $field) { if (isset($field['joinTable']) && isset($field['joinTable']['name'])) { $this->truncateTable($field['joinTable']['name']); } } } } $this->enableDatabaseForeignKeyChecks(); $this->connection->commit(); } catch (\Exception $e) { $this->connection->rollback(); throw $e; } }
/** * Update Website SQL entry according to the BackBee installation. * * @param array Website configuration, must contains 'domain' and 'label' keys * @return array|InvalidArgumentException Returns domain and label set up in database or an Exception */ public function updateWebsite($configuration) { if (!is_array($configuration) || !isset($configuration['domain']) || !isset($configuration['label'])) { throw new \InvalidArgumentException('array expected with domain and label keyes'); } $domain = $configuration['domain']; $label = $configuration['label']; try { $this->connection->beginTransaction(); $stmt = $this->connection->executeUpdate('UPDATE site SET server_name = ? , label = ?', array($domain, $label)); $this->connection->commit(); } catch (\PDOException $e) { $this->connection->rollback(); throw new \RuntimeException($e->getMessage(), (int) $e->getCode(), $e); } return $configuration; }
/** * {@inheritdoc} */ public function flush() { if (!$this->data) { return; } try { $this->conn->beginTransaction(); $stmt = $this->conn->prepare('INSERT INTO metrics (metric, measurement, created) VALUES (?, ?, ?)'); foreach ($this->data as $measurement) { $stmt->bindParam(1, $measurement[0]); $stmt->bindParam(2, $measurement[1]); $stmt->bindParam(3, $measurement[2]); $stmt->execute(); } $this->conn->commit(); } catch (Exception $e) { $this->conn->rollback(); } $this->data = array(); }
/** * Generate the next unused value for the given sequence name * * @param string * @return int */ 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 occured while generating ID with TableGenerator, aborted generation: " . $e->getMessage(), 0, $e); } return $value; }
/** * {@inheritdoc} */ public function write($sessionId, $data) { // Session data can contain non binary safe characters so we need to encode it. $encoded = base64_encode($data); // We use a MERGE SQL query when supported by the database. // Otherwise we have to use a transactional DELETE followed by INSERT to prevent duplicate entries under high concurrency. try { $mergeSql = $this->getMergeSql(); if (null !== $mergeSql) { $mergeStmt = $this->con->prepare($mergeSql); $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); $mergeStmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT); $mergeStmt->execute(); return true; } $this->con->beginTransaction(); try { $deleteStmt = $this->con->prepare("DELETE FROM {$this->table} WHERE {$this->idCol} = :id"); $deleteStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); $deleteStmt->execute(); $insertStmt = $this->con->prepare("INSERT INTO {$this->table} ({$this->idCol}, {$this->dataCol}, {$this->timeCol}) VALUES (:id, :data, :time)"); $insertStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); $insertStmt->bindParam(':data', $encoded, \PDO::PARAM_STR); $insertStmt->bindValue(':time', time(), \PDO::PARAM_INT); $insertStmt->execute(); $this->con->commit(); } catch (\Exception $e) { $this->con->rollback(); throw $e; } } catch (\Exception $e) { throw new \RuntimeException(sprintf('Exception was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e); } return true; }
/** * @return bool */ public function rollBack() { $this->connection->rollback(); return true; }
public function testRollbackWithNoActiveTransaction_ThrowsException() { $this->setExpectedException('Doctrine\\DBAL\\ConnectionException'); $this->_conn->rollback(); }
/** * {@inheritDoc} */ public function rollback() { $this->connect('master'); return parent::rollback(); }
/** * {@inheritDoc} */ public function rollbackSave() { $this->referencesToUpdate = $this->referencesToDelete = array(); $this->conn->rollback(); }
/** * Execute this migration version up or down and and return the SQL. * * @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->sm->createSchema(); $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 = clone $fromSchema; $this->migration->{$direction}($toSchema); $this->addSql($fromSchema->getMigrateToSql($toSchema, $this->platform)); $this->executeRegisteredSql($dryRun, $timeAllQueries); $this->state = self::STATE_POST; $this->migration->{'post' . ucfirst($direction)}($toSchema); $this->executeRegisteredSql($dryRun, $timeAllQueries); 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; } }
/** * Cause a rollback of this Unit of Work * * @access public * @return void * */ protected function rollback() { $this->dbal->rollback(); }
/** * Execute this migration version up or down and and return the SQL. * * @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 = array(); $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->sm->createSchema(); $this->migration->{'pre' . ucfirst($direction)}($fromSchema); if ($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 = clone $fromSchema; $this->migration->{$direction}($toSchema); $this->addSql($fromSchema->getMigrateToSql($toSchema, $this->platform)); if (!$dryRun) { if (!empty($this->sql)) { foreach ($this->sql as $key => $query) { $queryStart = microtime(true); if (!isset($this->params[$key])) { $this->outputWriter->write(' <comment>-></comment> ' . $query); $this->connection->exec($query); } else { $this->outputWriter->write(sprintf(' <comment>-</comment> %s (with parameters)', $query)); $this->connection->executeQuery($query, $this->params[$key], $this->types[$key]); } $this->outputQueryTime($queryStart, $timeAllQueries); } } else { $this->outputWriter->write(sprintf('<error>Migration %s was executed but did not result in any SQL statements.</error>', $this->version)); } if ($direction === 'up') { $this->markMigrated(); } else { $this->markNotMigrated(); } } else { foreach ($this->sql as $query) { $this->outputWriter->write(' <comment>-></comment> ' . $query); } } $this->state = self::STATE_POST; $this->migration->{'post' . ucfirst($direction)}($toSchema); $migrationEnd = microtime(true); $this->time = round($migrationEnd - $migrationStart, 2); if ($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 === '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 array(); } 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; } }
/** * Tears down the fixture, for example, closes a network connection. * This method is called after a test is executed. */ protected function tearDown() { $this->connection->rollback(); }
protected function execute(InputInterface $input, OutputInterface $output) { $class = $input->getArgument('class'); if (class_exists($class)) { $adapter = new $class(); $helper = $this->getHelper('question'); if ($adapter instanceof AdapterInterface) { // parse definition $definition = Parser::decode(file_get_contents($adapter->getDefinition()), false); $instructions = $this->parser->parse($definition); $rows = array(); $hasRoutes = false; foreach ($instructions as $instruction) { $rows[] = [$instruction->getName(), $instruction->getDescription()]; if ($instruction instanceof Instruction\Route) { $hasRoutes = true; } } // show instructions $output->writeLn('Loaded definition ' . $adapter->getDefinition()); $output->writeLn(''); $output->writeLn('The adapter will install the following entries into the system.'); $table = new Table($output); $table->setHeaders(['Type', 'Description'])->setRows($rows); $table->render($output); // confirm $question = new ConfirmationQuestion('Do you want to continue (y/n)? ', false); if ($helper->ask($input, $output, $question)) { // if the adapter installs new routes ask for a base path if ($hasRoutes) { $output->writeLn(''); $output->writeLn('The adapter inserts new routes into the system.'); $output->writeLn('Please specify a base path under which the new routes are inserted.'); $filter = new PathFilter(); $question = new Question('Base path (i.e. /acme/service): ', '/'); $question->setValidator(function ($answer) use($filter) { if (!$filter->apply($answer)) { throw new \RuntimeException(sprintf($filter->getErrorMessage(), 'Base path')); } return $answer; }); $basePath = $helper->ask($input, $output, $question); } else { $basePath = null; } try { $this->connection->beginTransaction(); $this->installer->install($instructions, $basePath); $this->connection->commit(); $output->writeln('Registration successful'); } catch (\Exception $e) { $this->connection->rollback(); $output->writeln('An exception occured during installation of the adapter. No changes are applied to the database.'); $output->writeln(''); $output->writeln('Message: ' . $e->getMessage()); $output->writeln('Trace: ' . $e->getTraceAsString()); } } else { $output->writeln('Abort'); } } else { $output->writeln('Class does not implement the AdapterInterface'); } } else { $output->writeln('Provided adapter class does not exist'); } }
/** * {@inheritDoc} */ public function rollback() { $this->conn->rollback(); }
/** * Performs a rollback on the underlying database connection and closes the * EntityManager as it may now be in a corrupted state. */ public function rollback() { $this->_conn->rollback(); $this->close(); }