Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
bea9e3fc
Commit
bea9e3fc
authored
Feb 15, 2014
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixes #1645: Added support for nested DB transactions
parent
f6c0b4c2
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
184 additions
and
45 deletions
+184
-45
database-basics.md
docs/guide/database-basics.md
+26
-2
ActiveRecord.php
extensions/sphinx/ActiveRecord.php
+6
-6
CHANGELOG.md
framework/CHANGELOG.md
+1
-0
ActiveRecord.php
framework/db/ActiveRecord.php
+6
-6
Connection.php
framework/db/Connection.php
+8
-5
Migration.php
framework/db/Migration.php
+4
-4
Schema.php
framework/db/Schema.php
+35
-0
Transaction.php
framework/db/Transaction.php
+56
-21
Schema.php
framework/db/cubrid/Schema.php
+9
-0
PDO.php
framework/db/mssql/PDO.php
+1
-1
Schema.php
framework/db/mssql/Schema.php
+24
-0
Schema.php
framework/db/oci/Schema.php
+8
-0
No files found.
docs/guide/database-basics.md
View file @
bea9e3fc
...
...
@@ -210,7 +210,7 @@ $command->execute();
Transactions
------------
If the underlying DBMS supports transactions, y
ou can perform transactional SQL queries like the following:
Y
ou can perform transactional SQL queries like the following:
```
php
$transaction = $connection->beginTransaction();
...
...
@@ -220,10 +220,34 @@ try {
// ... executing other SQL statements ...
$transaction->commit();
} catch(Exception $e) {
$transaction->roll
b
ack();
$transaction->roll
B
ack();
}
```
You can also nest multiple transactions, if needed:
```
php
// outer transaction
$transaction1 = $connection->beginTransaction();
try {
$connection->createCommand($sql1)->execute();
// inner transaction
$transaction2 = $connection->beginTransaction();
try {
$connection->createCommand($sql2)->execute();
$transaction2->commit();
} catch (Exception $e) {
$transaction2->rollBack();
}
$transaction1->commit();
} catch (Exception $e) {
$transaction1->rollBack();
}
```
Working with database schema
----------------------------
...
...
extensions/sphinx/ActiveRecord.php
View file @
bea9e3fc
...
...
@@ -372,12 +372,12 @@ abstract class ActiveRecord extends BaseActiveRecord
try
{
$result
=
$this
->
insertInternal
(
$attributes
);
if
(
$result
===
false
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
}
else
{
$transaction
->
commit
();
}
}
catch
(
\Exception
$e
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
throw
$e
;
}
}
else
{
...
...
@@ -473,12 +473,12 @@ abstract class ActiveRecord extends BaseActiveRecord
try
{
$result
=
$this
->
updateInternal
(
$attributes
);
if
(
$result
===
false
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
}
else
{
$transaction
->
commit
();
}
}
catch
(
\Exception
$e
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
throw
$e
;
}
}
else
{
...
...
@@ -589,14 +589,14 @@ abstract class ActiveRecord extends BaseActiveRecord
}
if
(
$transaction
!==
null
)
{
if
(
$result
===
false
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
}
else
{
$transaction
->
commit
();
}
}
}
catch
(
\Exception
$e
)
{
if
(
$transaction
!==
null
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
}
throw
$e
;
}
...
...
framework/CHANGELOG.md
View file @
bea9e3fc
...
...
@@ -79,6 +79,7 @@ Yii Framework 2 Change Log
-
Enh #1641: Added
`BaseActiveRecord::updateAttributes()`
(qiangxue)
-
Enh #1646: Added postgresql
`QueryBuilder::checkIntegrity`
and
`QueryBuilder::resetSequence`
(Ragazzo)
-
Enh #1645: Added
`Connection::$pdoClass`
property (Ragazzo)
-
Enh #1645: Added support for nested DB transactions (qiangxue)
-
Enh #1681: Added support for automatically adjusting the "for" attribute of label generated by
`ActiveField::label()`
(qiangxue)
-
Enh #1706: Added support for registering a single JS/CSS file with dependency (qiangxue)
-
Enh #1773: keyPrefix property of Cache is not restricted to alnum characters anymore, however it is still recommended (cebe)
...
...
framework/db/ActiveRecord.php
View file @
bea9e3fc
...
...
@@ -337,12 +337,12 @@ class ActiveRecord extends BaseActiveRecord
try
{
$result
=
$this
->
insertInternal
(
$attributes
);
if
(
$result
===
false
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
}
else
{
$transaction
->
commit
();
}
}
catch
(
\Exception
$e
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
throw
$e
;
}
}
else
{
...
...
@@ -449,12 +449,12 @@ class ActiveRecord extends BaseActiveRecord
try
{
$result
=
$this
->
updateInternal
(
$attributes
);
if
(
$result
===
false
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
}
else
{
$transaction
->
commit
();
}
}
catch
(
\Exception
$e
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
throw
$e
;
}
}
else
{
...
...
@@ -505,14 +505,14 @@ class ActiveRecord extends BaseActiveRecord
}
if
(
$transaction
!==
null
)
{
if
(
$result
===
false
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
}
else
{
$transaction
->
commit
();
}
}
}
catch
(
\Exception
$e
)
{
if
(
$transaction
!==
null
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
}
throw
$e
;
}
...
...
framework/db/Connection.php
View file @
bea9e3fc
...
...
@@ -68,7 +68,7 @@ use yii\caching\Cache;
* // ... executing other SQL statements ...
* $transaction->commit();
* } catch(Exception $e) {
* $transaction->roll
b
ack();
* $transaction->roll
B
ack();
* }
* ~~~
*
...
...
@@ -396,7 +396,7 @@ class Connection extends Component
*/
public
function
getTransaction
()
{
return
$this
->
_transaction
&&
$this
->
_transaction
->
isActive
?
$this
->
_transaction
:
null
;
return
$this
->
_transaction
&&
$this
->
_transaction
->
getIsActive
()
?
$this
->
_transaction
:
null
;
}
/**
...
...
@@ -406,9 +406,12 @@ class Connection extends Component
public
function
beginTransaction
()
{
$this
->
open
();
$this
->
_transaction
=
new
Transaction
([
'db'
=>
$this
]);
$this
->
_transaction
->
begin
();
return
$this
->
_transaction
;
if
((
$transaction
=
$this
->
getTransaction
())
===
null
)
{
$transaction
=
$this
->
_transaction
=
new
Transaction
([
'db'
=>
$this
]);
}
$transaction
->
begin
();
return
$transaction
;
}
/**
...
...
framework/db/Migration.php
View file @
bea9e3fc
...
...
@@ -64,14 +64,14 @@ class Migration extends \yii\base\Component
$transaction
=
$this
->
db
->
beginTransaction
();
try
{
if
(
$this
->
safeUp
()
===
false
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
return
false
;
}
$transaction
->
commit
();
}
catch
(
\Exception
$e
)
{
echo
"Exception: "
.
$e
->
getMessage
()
.
' ('
.
$e
->
getFile
()
.
':'
.
$e
->
getLine
()
.
")
\n
"
;
echo
$e
->
getTraceAsString
()
.
"
\n
"
;
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
return
false
;
}
return
null
;
...
...
@@ -89,14 +89,14 @@ class Migration extends \yii\base\Component
$transaction
=
$this
->
db
->
beginTransaction
();
try
{
if
(
$this
->
safeDown
()
===
false
)
{
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
return
false
;
}
$transaction
->
commit
();
}
catch
(
\Exception
$e
)
{
echo
"Exception: "
.
$e
->
getMessage
()
.
' ('
.
$e
->
getFile
()
.
':'
.
$e
->
getLine
()
.
")
\n
"
;
echo
$e
->
getTraceAsString
()
.
"
\n
"
;
$transaction
->
roll
b
ack
();
$transaction
->
roll
B
ack
();
return
false
;
}
return
null
;
...
...
framework/db/Schema.php
View file @
bea9e3fc
...
...
@@ -290,6 +290,41 @@ abstract class Schema extends Object
}
/**
* @return boolean whether this DBMS supports [savepoint](http://en.wikipedia.org/wiki/Savepoint).
*/
public
function
supportsSavepoint
()
{
return
true
;
}
/**
* Creates a new savepoint.
* @param string $name the savepoint name
*/
public
function
createSavepoint
(
$name
)
{
$this
->
db
->
createCommand
(
"SAVEPOINT
$name
"
)
->
execute
();
}
/**
* Releases an existing savepoint.
* @param string $name the savepoint name
*/
public
function
releaseSavepoint
(
$name
)
{
$this
->
db
->
createCommand
(
"RELEASE SAVEPOINT
$name
"
)
->
execute
();
}
/**
* Rolls back to a previously created savepoint.
* @param string $name the savepoint name
*/
public
function
rollBackSavepoint
(
$name
)
{
$this
->
db
->
createCommand
(
"ROLLBACK TO SAVEPOINT
$name
"
)
->
execute
();
}
/**
* Quotes a string value for use in a query.
* Note that if the parameter is not a string, it will be returned without change.
* @param string $str string to be quoted
...
...
framework/db/Transaction.php
View file @
bea9e3fc
...
...
@@ -7,6 +7,7 @@
namespace
yii\db
;
use
Yii
;
use
yii\base\InvalidConfigException
;
/**
...
...
@@ -25,12 +26,12 @@ use yii\base\InvalidConfigException;
* //.... other SQL executions
* $transaction->commit();
* } catch(Exception $e) {
* $transaction->roll
b
ack();
* $transaction->roll
B
ack();
* }
* ~~~
*
* @property boolean $isActive Whether this transaction is active. Only an active transaction can [[commit()]]
* or [[roll
b
ack()]]. This property is read-only.
* or [[roll
B
ack()]]. This property is read-only.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
...
...
@@ -42,19 +43,18 @@ class Transaction extends \yii\base\Object
*/
public
$db
;
/**
* @var boolean whether this transaction is active. Only an active transaction
* can [[commit()]] or [[rollback()]]. This property is set true when the transaction is started.
* @var integer the nesting level of the transaction. 0 means the outermost level.
*/
private
$_
active
=
false
;
private
$_
level
=
0
;
/**
* Returns a value indicating whether this transaction is active.
* @return boolean whether this transaction is active. Only an active transaction
* can [[commit()]] or [[roll
b
ack()]].
* can [[commit()]] or [[roll
B
ack()]].
*/
public
function
getIsActive
()
{
return
$this
->
_
a
ctive
;
return
$this
->
_
level
>
0
&&
$this
->
db
&&
$this
->
db
->
isA
ctive
;
}
/**
...
...
@@ -63,44 +63,79 @@ class Transaction extends \yii\base\Object
*/
public
function
begin
()
{
if
(
!
$this
->
_active
)
{
if
(
$this
->
db
===
null
)
{
throw
new
InvalidConfigException
(
'Transaction::db must be set.'
);
}
\Yii
::
trace
(
'Starting transaction'
,
__METHOD__
);
$this
->
db
->
open
();
if
(
$this
->
_level
==
0
)
{
Yii
::
trace
(
'Begin transaction'
,
__METHOD__
);
$this
->
db
->
pdo
->
beginTransaction
();
$this
->
_active
=
true
;
$this
->
_level
=
1
;
return
;
}
$schema
=
$this
->
db
->
getSchema
();
if
(
$schema
->
supportsSavepoint
())
{
Yii
::
trace
(
'Set savepoint '
.
$this
->
_level
,
__METHOD__
);
$schema
->
createSavepoint
(
'LEVEL'
.
$this
->
_level
);
}
else
{
Yii
::
info
(
'Transaction not started: nested transaction not supported'
,
__METHOD__
);
}
$this
->
_level
++
;
}
/**
* Commits a transaction.
* @throws Exception if the transaction
or the [[db|DB connection]] is not active.
* @throws Exception if the transaction
is not active
*/
public
function
commit
()
{
if
(
$this
->
_active
&&
$this
->
db
&&
$this
->
db
->
isActive
)
{
\Yii
::
trace
(
'Committing transaction'
,
__METHOD__
);
if
(
!
$this
->
getIsActive
())
{
throw
new
Exception
(
'Failed to commit transaction: transaction was inactive.'
);
}
$this
->
_level
--
;
if
(
$this
->
_level
==
0
)
{
Yii
::
trace
(
'Commit transaction'
,
__METHOD__
);
$this
->
db
->
pdo
->
commit
();
$this
->
_active
=
false
;
return
;
}
$schema
=
$this
->
db
->
getSchema
();
if
(
$schema
->
supportsSavepoint
())
{
Yii
::
trace
(
'Release savepoint '
.
$this
->
_level
,
__METHOD__
);
$schema
->
releaseSavepoint
(
'LEVEL'
.
$this
->
_level
);
}
else
{
throw
new
Exception
(
'Failed to commit transaction: transaction was inactive.'
);
Yii
::
info
(
'Transaction not committed: nested transaction not supported'
,
__METHOD__
);
}
}
/**
* Rolls back a transaction.
* @throws Exception if the transaction
or the [[db|DB connection]] is not active.
* @throws Exception if the transaction
is not active
*/
public
function
roll
b
ack
()
public
function
roll
B
ack
()
{
if
(
$this
->
_active
&&
$this
->
db
&&
$this
->
db
->
isActive
)
{
\Yii
::
trace
(
'Rolling back transaction'
,
__METHOD__
);
if
(
!
$this
->
getIsActive
())
{
throw
new
Exception
(
'Failed to roll back transaction: transaction was inactive.'
);
}
$this
->
_level
--
;
if
(
$this
->
_level
==
0
)
{
Yii
::
trace
(
'Roll back transaction'
,
__METHOD__
);
$this
->
db
->
pdo
->
rollBack
();
$this
->
_active
=
false
;
return
;
}
$schema
=
$this
->
db
->
getSchema
();
if
(
$schema
->
supportsSavepoint
())
{
Yii
::
trace
(
'Roll back to savepoint '
.
$this
->
_level
,
__METHOD__
);
$schema
->
rollBackSavepoint
(
'LEVEL'
.
$this
->
_level
);
}
else
{
throw
new
Exception
(
'Failed to roll back transaction: transaction was inactive.'
);
Yii
::
info
(
'Transaction not rolled back: nested transaction not supported'
,
__METHOD__
);
// throw an exception to fail the outer transaction
throw
new
Exception
(
'Roll back failed: nested transaction not supported.'
);
}
}
}
framework/db/cubrid/Schema.php
View file @
bea9e3fc
...
...
@@ -64,6 +64,15 @@ class Schema extends \yii\db\Schema
'enum'
=>
self
::
TYPE_STRING
,
];
/**
* @inheritdoc
*/
public
function
releaseSavepoint
(
$name
)
{
// does nothing as cubrid does not support this
}
/**
* Quotes a table name for use in a query.
* A simple table name has no schema prefix.
...
...
framework/db/mssql/PDO.php
View file @
bea9e3fc
...
...
@@ -51,7 +51,7 @@ class PDO extends \PDO
/**
* Rollbacks a transaction. It is necessary to override PDO's method as MSSQL PDO driver does not
* natively support transactions.
* @return boolean the result of a transaction rollback.
* @return boolean the result of a transaction roll
back.
*/
public
function
rollBack
()
{
...
...
framework/db/mssql/Schema.php
View file @
bea9e3fc
...
...
@@ -74,6 +74,30 @@ class Schema extends \yii\db\Schema
];
/**
* @inheritdoc
*/
public
function
createSavepoint
(
$name
)
{
$this
->
db
->
createCommand
(
"SAVE TRANSACTION
$name
"
)
->
execute
();
}
/**
* @inheritdoc
*/
public
function
releaseSavepoint
(
$name
)
{
// does nothing as MSSQL does not support this
}
/**
* @inheritdoc
*/
public
function
rollBackSavepoint
(
$name
)
{
$this
->
db
->
createCommand
(
"ROLLBACK TRANSACTION
$name
"
)
->
execute
();
}
/**
* Quotes a table name for use in a query.
* A simple table name has no schema prefix.
* @param string $name table name.
...
...
framework/db/oci/Schema.php
View file @
bea9e3fc
...
...
@@ -34,6 +34,14 @@ class Schema extends \yii\db\Schema
/**
* @inheritdoc
*/
public
function
releaseSavepoint
(
$name
)
{
// does nothing as Oracle does not support this
}
/**
* @inheritdoc
*/
public
function
quoteSimpleTableName
(
$name
)
{
return
'"'
.
$name
.
'"'
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment