@@ -265,18 +265,29 @@ public function transactionRollback() {
265
265
public function dryRun ($ callback = null ) {
266
266
$ result = null ;
267
267
$ exception = null ;
268
- if ($ this ->pdo ->inTransaction ()) {
269
- throw new \Exception ('Connection is already in a transaction. Dry-run not possible. ' );
270
- }
271
- $ this ->transactionStart ();
272
- try {
273
- $ result = call_user_func ($ callback , $ this );
274
- } catch (\Exception $ e ) {
275
- $ exception = $ e ;
276
- }
277
- $ this ->transactionRollback ();
278
- if ($ exception !== null ) {
279
- throw $ exception ;
268
+ if (!$ this ->pdo ->inTransaction ()) {
269
+ $ this ->transactionStart ();
270
+ try {
271
+ $ result = call_user_func ($ callback , $ this );
272
+ } catch (\Exception $ e ) {
273
+ $ exception = $ e ;
274
+ }
275
+ $ this ->transactionRollback ();
276
+ if ($ exception !== null ) {
277
+ throw $ exception ;
278
+ }
279
+ } else {
280
+ $ uniqueId = $ this ->genUniqueId ();
281
+ $ this ->exec ("SAVEPOINT {$ uniqueId }" );
282
+ try {
283
+ $ result = call_user_func ($ callback , $ this );
284
+ } catch (\Exception $ e ) {
285
+ $ exception = $ e ;
286
+ }
287
+ $ this ->exec ("ROLLBACK TO {$ uniqueId }" );
288
+ if ($ exception !== null ) {
289
+ throw $ exception ;
290
+ }
280
291
}
281
292
return $ result ;
282
293
}
@@ -296,14 +307,26 @@ public function transaction($tries = 1, $callback = null) {
296
307
throw new \Exception ('$callback must be a callable ' );
297
308
}
298
309
$ e = null ;
299
- for (; $ tries --;) {
310
+ if (!$ this ->pdo ->inTransaction ()) {
311
+ for (; $ tries --;) {
312
+ try {
313
+ $ this ->transactionStart ();
314
+ $ result = call_user_func ($ callback , $ this );
315
+ $ this ->transactionCommit ();
316
+ return $ result ;
317
+ } catch (\Exception $ e ) {
318
+ $ this ->transactionRollback ();
319
+ }
320
+ }
321
+ } else {
322
+ $ uniqueId = $ this ->genUniqueId ();
300
323
try {
301
- $ this ->transactionStart ( );
324
+ $ this ->exec ( " SAVEPOINT { $ uniqueId }" );
302
325
$ result = call_user_func ($ callback , $ this );
303
- $ this ->transactionCommit ( );
326
+ $ this ->exec ( " RELEASE SAVEPOINT { $ uniqueId }" );
304
327
return $ result ;
305
328
} catch (\Exception $ e ) {
306
- $ this ->transactionRollback ( );
329
+ $ this ->exec ( " ROLLBACK TO { $ uniqueId }" );
307
330
}
308
331
}
309
332
throw $ e ;
@@ -355,4 +378,21 @@ private function exceptionHandler($fn) {
355
378
$ this ->exceptionInterpreter ->throwMoreConcreteException ($ e );
356
379
}
357
380
}
381
+
382
+ /**
383
+ * @return string
384
+ */
385
+ private function genUniqueId () {
386
+ // Generate a unique id from a former random-uuid-generator
387
+ return sprintf ('ID%04x%04x%04x%04x%04x%04x%04x%04x ' ,
388
+ mt_rand (0 , 0xffff ),
389
+ mt_rand (0 , 0xffff ),
390
+ mt_rand (0 , 0xffff ),
391
+ mt_rand (0 , 0x0fff ) | 0x4000 ,
392
+ mt_rand (0 , 0x3fff ) | 0x8000 ,
393
+ mt_rand (0 , 0xffff ),
394
+ mt_rand (0 , 0xffff ),
395
+ mt_rand (0 , 0xffff )
396
+ );
397
+ }
358
398
}
0 commit comments