Skip to content

Commit bf790e6

Browse files
committed
POC but we cannot convert error to UCViolation again
1 parent d2b49c4 commit bf790e6

File tree

4 files changed

+70
-46
lines changed

4 files changed

+70
-46
lines changed

src/Driver/OCI8/Exception/Error.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ public static function new($resource): self
3636
//ORA-00001: unique constraint (DOCTRINE.GH3423_UNIQUE) violated
3737
[$firstMessage, $secondMessage] = explode("\n", $message, 2);
3838

39-
[$code, $message] = explode(': ', $secondMessage, 2);
40-
$code = (int) str_replace('ORA-', '', $code);
39+
[$causeCode, $causeMessage] = explode(': ', $secondMessage, 2);
40+
$causeCode = (int) str_replace('ORA-', '', $causeCode);
41+
42+
$cause = new self($causeMessage, null, $causeCode);
4143
}
4244

43-
return new self($message, null, $code);
45+
return new self($message, null, $code, $cause ?? null);
4446
}
4547
}

src/Driver/PDO/Exception.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,12 @@ public static function new(PDOException $exception): self
3939
//ORA-00001: unique constraint (DOCTRINE.GH3423_UNIQUE) violated
4040
[$firstMessage, $secondMessage] = explode("\n", $message, 2);
4141

42-
[$code, $message] = explode(': ', $secondMessage, 2);
43-
$code = (int) str_replace('ORA-', '', $code);
42+
[$causeCode, $causeMessage] = explode(': ', $secondMessage, 2);
43+
$causeCode = (int) str_replace('ORA-', '', $causeCode);
44+
45+
$cause = new self($causeMessage, null, $causeCode, $exception);
4446
}
4547

46-
return new self($message, $sqlState, $code, $exception);
48+
return new self($message, $sqlState, $code, $cause ?? $exception);
4749
}
4850
}

tests/Driver/PDO/ExceptionTest.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,12 @@ public function testExposesUnderlyingErrorOnOracle(): void
7474

7575
$exception = Exception::new($pdoException);
7676

77-
self::assertSame(1, $exception->getCode());
78-
self::assertStringContainsString(
79-
'unique constraint (DOCTRINE.C1_UNIQUE) violated',
80-
$exception->getMessage()
81-
);
77+
self::assertSame(2091, $exception->getCode());
78+
self::assertStringContainsString('transaction rolled back', $exception->getMessage());
79+
80+
$previous = $exception->getPrevious();
81+
self::assertNotNull($previous);
82+
self::assertSame(1, $previous->getCode());
83+
self::assertStringContainsString('unique constraint (DOCTRINE.C1_UNIQUE) violated', $previous->getMessage());
8284
}
8385
}

tests/Functional/UniqueConstraintViolationsTest.php

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,25 @@ public function testTransactionalViolatesDeferredConstraint(): void
8080
{
8181
$this->skipIfDeferrableIsNotSupported();
8282

83-
$this->connection->transactional(function (Connection $connection): void {
84-
$connection->executeStatement(sprintf('SET CONSTRAINTS "%s" DEFERRED', $this->constraintName));
85-
86-
$connection->executeStatement('INSERT INTO unique_constraint_violations VALUES (1)');
83+
try {
84+
$this->connection->transactional(function (Connection $connection): void {
85+
$connection->executeStatement(sprintf('SET CONSTRAINTS "%s" DEFERRED', $this->constraintName));
8786

88-
$this->expectUniqueConstraintViolation();
89-
});
87+
$connection->executeStatement('INSERT INTO unique_constraint_violations VALUES (1)');
88+
});
89+
} catch (Throwable $throwable) {
90+
$this->expectUniqueConstraintViolation($throwable);
91+
}
9092
}
9193

9294
public function testTransactionalViolatesConstraint(): void
9395
{
9496
$this->connection->transactional(function (Connection $connection): void {
95-
$this->expectUniqueConstraintViolation();
96-
$connection->executeStatement('INSERT INTO unique_constraint_violations VALUES (1)');
97+
try {
98+
$connection->executeStatement('INSERT INTO unique_constraint_violations VALUES (1)');
99+
} catch (Throwable $throwable) {
100+
$this->expectUniqueConstraintViolation($throwable);
101+
}
97102
});
98103
}
99104

@@ -107,14 +112,16 @@ public function testTransactionalViolatesDeferredConstraintWhileUsingTransaction
107112

108113
$this->connection->setNestTransactionsWithSavepoints(true);
109114

110-
$this->connection->transactional(function (Connection $connection): void {
111-
$connection->executeStatement(sprintf('SET CONSTRAINTS "%s" DEFERRED', $this->constraintName));
112-
$connection->beginTransaction();
113-
$connection->executeStatement('INSERT INTO unique_constraint_violations VALUES (1)');
114-
$connection->commit();
115-
116-
$this->expectUniqueConstraintViolation();
117-
});
115+
try {
116+
$this->connection->transactional(function (Connection $connection): void {
117+
$connection->executeStatement(sprintf('SET CONSTRAINTS "%s" DEFERRED', $this->constraintName));
118+
$connection->beginTransaction();
119+
$connection->executeStatement('INSERT INTO unique_constraint_violations VALUES (1)');
120+
$connection->commit();
121+
});
122+
} catch (Throwable $throwable) {
123+
$this->expectUniqueConstraintViolation($throwable);
124+
}
118125
}
119126

120127
public function testTransactionalViolatesConstraintWhileUsingTransactionNesting(): void
@@ -130,12 +137,10 @@ public function testTransactionalViolatesConstraintWhileUsingTransactionNesting(
130137

131138
try {
132139
$this->connection->executeStatement('INSERT INTO unique_constraint_violations VALUES (1)');
133-
} catch (Throwable $t) {
140+
} catch (Throwable $throwable) {
134141
$this->connection->rollBack();
135142

136-
$this->expectUniqueConstraintViolation();
137-
138-
throw $t;
143+
$this->expectUniqueConstraintViolation($throwable);
139144
}
140145
});
141146
}
@@ -148,8 +153,11 @@ public function testCommitViolatesDeferredConstraint(): void
148153
$this->connection->executeStatement(sprintf('SET CONSTRAINTS "%s" DEFERRED', $this->constraintName));
149154
$this->connection->executeStatement('INSERT INTO unique_constraint_violations VALUES (1)');
150155

151-
$this->expectUniqueConstraintViolation();
152-
$this->connection->commit();
156+
try {
157+
$this->connection->commit();
158+
} catch (Throwable $throwable) {
159+
$this->expectUniqueConstraintViolation($throwable);
160+
}
153161
}
154162

155163
public function testInsertViolatesConstraint(): void
@@ -161,9 +169,7 @@ public function testInsertViolatesConstraint(): void
161169
} catch (Throwable $t) {
162170
$this->connection->rollBack();
163171

164-
$this->expectUniqueConstraintViolation();
165-
166-
throw $t;
172+
$this->expectUniqueConstraintViolation($t);
167173
}
168174
}
169175

@@ -183,9 +189,11 @@ public function testCommitViolatesDeferredConstraintWhileUsingTransactionNesting
183189
$this->connection->executeStatement('INSERT INTO unique_constraint_violations VALUES (1)');
184190
$this->connection->commit();
185191

186-
$this->expectUniqueConstraintViolation();
187-
188-
$this->connection->commit();
192+
try {
193+
$this->connection->commit();
194+
} catch (Throwable $throwable) {
195+
$this->expectUniqueConstraintViolation($throwable);
196+
}
189197
}
190198

191199
public function testCommitViolatesConstraintWhileUsingTransactionNesting(): void
@@ -206,9 +214,7 @@ public function testCommitViolatesConstraintWhileUsingTransactionNesting(): void
206214
} catch (Throwable $t) {
207215
$this->connection->rollBack();
208216

209-
$this->expectUniqueConstraintViolation();
210-
211-
throw $t;
217+
$this->expectUniqueConstraintViolation($t);
212218
}
213219
}
214220

@@ -228,22 +234,34 @@ private function skipIfDeferrableIsNotSupported(): void
228234
self::markTestSkipped('Only databases supporting deferrable constraints are eligible for this test.');
229235
}
230236

231-
private function expectUniqueConstraintViolation(): void
237+
private function expectUniqueConstraintViolation(Throwable $throwable): void
232238
{
233239
if ($this->connection->getDatabasePlatform() instanceof SQLServerPlatform) {
234-
$this->expectExceptionMessage(sprintf("Violation of UNIQUE KEY constraint '%s'", $this->constraintName));
240+
self::assertStringContainsString(
241+
sprintf("Violation of UNIQUE KEY constraint '%s'", $this->constraintName),
242+
$throwable->getMessage()
243+
);
235244

236245
return;
237246
}
238247

239248
if ($this->connection->getDatabasePlatform() instanceof DB2Platform) {
240249
// No concrete message is provided
241-
$this->expectException(DriverException::class);
250+
self::assertInstanceOf(DriverException::class, $throwable);
251+
252+
return;
253+
}
254+
255+
if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) {
256+
self::assertInstanceOf(DriverException::class, $throwable);
257+
$previous = $throwable->getPrevious();
258+
$this->assertNotNull($previous);
259+
self::assertInstanceOf(UniqueConstraintViolationException::class, $previous);
242260

243261
return;
244262
}
245263

246-
$this->expectException(UniqueConstraintViolationException::class);
264+
self::assertInstanceOf(UniqueConstraintViolationException::class, $throwable);
247265
}
248266

249267
protected function tearDown(): void

0 commit comments

Comments
 (0)