Moved transaction isolation functionality to transaction drivers
This commit is contained in:
parent
a452ccb620
commit
256fbd5331
@ -73,63 +73,6 @@ class Doctrine_Connection_Firebird extends Doctrine_Connection {
|
||||
$this->options['server_version'] = '';
|
||||
parent::__construct($manager, $adapter);
|
||||
}
|
||||
/**
|
||||
* Set the transacton isolation level.
|
||||
*
|
||||
* @param string standard isolation level (SQL-92)
|
||||
* READ UNCOMMITTED (allows dirty reads)
|
||||
* READ COMMITTED (prevents dirty reads)
|
||||
* REPEATABLE READ (prevents nonrepeatable reads)
|
||||
* SERIALIZABLE (prevents phantom reads)
|
||||
*
|
||||
* @param array some transaction options:
|
||||
* 'wait' => 'WAIT' | 'NO WAIT'
|
||||
* 'rw' => 'READ WRITE' | 'READ ONLY'
|
||||
* @return void
|
||||
*/
|
||||
public function setTransactionIsolation($isolation, $options = array()) {
|
||||
switch ($isolation) {
|
||||
case 'READ UNCOMMITTED':
|
||||
$ibase_isolation = 'READ COMMITTED RECORD_VERSION';
|
||||
break;
|
||||
case 'READ COMMITTED':
|
||||
$ibase_isolation = 'READ COMMITTED NO RECORD_VERSION';
|
||||
break;
|
||||
case 'REPEATABLE READ':
|
||||
$ibase_isolation = 'SNAPSHOT';
|
||||
break;
|
||||
case 'SERIALIZABLE':
|
||||
$ibase_isolation = 'SNAPSHOT TABLE STABILITY';
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Connection_Firebird_Exception('isolation level is not supported: ' . $isolation);
|
||||
}
|
||||
|
||||
if( ! empty($options['wait'])) {
|
||||
switch ($options['wait']) {
|
||||
case 'WAIT':
|
||||
case 'NO WAIT':
|
||||
$wait = $options['wait'];
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Connection_Firebird_Exception('wait option is not supported: ' . $options['wait']);
|
||||
}
|
||||
}
|
||||
|
||||
if( ! empty($options['rw'])) {
|
||||
switch ($options['rw']) {
|
||||
case 'READ ONLY':
|
||||
case 'READ WRITE':
|
||||
$rw = $options['wait'];
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Connection_Firebird_Exception('wait option is not supported: ' . $options['rw']);
|
||||
}
|
||||
}
|
||||
|
||||
$query = 'SET TRANSACTION ' . $rw . ' ' . $wait .' ISOLATION LEVEL ' . $ibase_isolation;
|
||||
$this->dbh->query($query);
|
||||
}
|
||||
/**
|
||||
* Set the charset on the current connection
|
||||
*
|
||||
|
@ -22,15 +22,15 @@ Doctrine::autoload('Doctrine_Connection_Common');
|
||||
/**
|
||||
* Doctrine_Connection_Mysql
|
||||
*
|
||||
* @package Doctrine
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @package Doctrine
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @version $Revision$
|
||||
* @category Object Relational Mapping
|
||||
* @link www.phpdoctrine.com
|
||||
* @since 1.0
|
||||
*/
|
||||
* @version $Revision$
|
||||
* @category Object Relational Mapping
|
||||
* @link www.phpdoctrine.com
|
||||
* @since 1.0
|
||||
*/
|
||||
class Doctrine_Connection_Mysql extends Doctrine_Connection_Common {
|
||||
/**
|
||||
* @var string $driverName the name of this connection driver
|
||||
@ -69,47 +69,5 @@ class Doctrine_Connection_Mysql extends Doctrine_Connection_Common {
|
||||
parent::__construct($manager, $adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* getTransactionIsolation
|
||||
*
|
||||
* @return string returns the current session transaction isolation level
|
||||
*/
|
||||
public function getTransactionIsolation() {
|
||||
$ret = $this->dbh->query('SELECT @@tx_isolation')->fetch(PDO::FETCH_NUM);
|
||||
return $ret[0];
|
||||
}
|
||||
/**
|
||||
* Set the transacton isolation level.
|
||||
*
|
||||
* example :
|
||||
*
|
||||
* <code>
|
||||
* $conn->setTransactionIsolation('READ UNCOMMITTED');
|
||||
* </code>
|
||||
*
|
||||
* @param string standard isolation level
|
||||
* READ UNCOMMITTED (allows dirty reads)
|
||||
* READ COMMITTED (prevents dirty reads)
|
||||
* REPEATABLE READ (prevents nonrepeatable reads)
|
||||
* SERIALIZABLE (prevents phantom reads)
|
||||
*
|
||||
* @throws Doctrine_Connection_Mysql_Exception if using unknown isolation level
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @return void
|
||||
*/
|
||||
public function setTransactionIsolation($isolation) {
|
||||
switch ($isolation) {
|
||||
case 'READ UNCOMMITTED':
|
||||
case 'READ COMMITTED':
|
||||
case 'REPEATABLE READ':
|
||||
case 'SERIALIZABLE':
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Connection_Mysql_Exception('Isolation level ' . $isolation . ' is not supported.');
|
||||
}
|
||||
|
||||
$query = "SET SESSION TRANSACTION ISOLATION LEVEL $isolation";
|
||||
return $this->dbh->query($query);
|
||||
}
|
||||
}
|
||||
|
@ -22,14 +22,14 @@ Doctrine::autoload('Doctrine_Connection');
|
||||
/**
|
||||
* Doctrine_Connection_Oracle
|
||||
*
|
||||
* @package Doctrine
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @category Object Relational Mapping
|
||||
* @link www.phpdoctrine.com
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
*/
|
||||
* @package Doctrine
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @category Object Relational Mapping
|
||||
* @link www.phpdoctrine.com
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
*/
|
||||
class Doctrine_Connection_Oracle extends Doctrine_Connection {
|
||||
/**
|
||||
* @var string $driverName the name of this connection driver
|
||||
@ -101,40 +101,6 @@ class Doctrine_Connection_Oracle extends Doctrine_Connection {
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
/**
|
||||
* Set the transacton isolation level.
|
||||
*
|
||||
* example:
|
||||
*
|
||||
* <code>
|
||||
* $conn->setTransactionIsolation('READ UNCOMMITTED');
|
||||
* </code>
|
||||
*
|
||||
* @param string standard isolation level
|
||||
* READ UNCOMMITTED (allows dirty reads)
|
||||
* READ COMMITTED (prevents dirty reads)
|
||||
* REPEATABLE READ (prevents nonrepeatable reads)
|
||||
* SERIALIZABLE (prevents phantom reads)
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @return void
|
||||
*/
|
||||
public function setTransactionIsolation($isolation) {
|
||||
switch($isolation) {
|
||||
case 'READ UNCOMMITTED':
|
||||
$isolation = 'READ COMMITTED';
|
||||
break;
|
||||
case 'READ COMMITTED':
|
||||
case 'REPEATABLE READ':
|
||||
case 'SERIALIZABLE':
|
||||
$isolation = 'SERIALIZABLE';
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Connection_Oracle_Exception('Isolation level ' . $isolation . ' is not supported.');
|
||||
}
|
||||
|
||||
$query = 'ALTER SESSION ISOLATION LEVEL ' . $isolation;
|
||||
return $this->dbh->query($query);
|
||||
}
|
||||
/**
|
||||
* returns the next value in the given sequence
|
||||
*
|
||||
|
@ -22,15 +22,15 @@ Doctrine::autoload("Doctrine_Connection_Common");
|
||||
/**
|
||||
* Doctrine_Connection_Pgsql
|
||||
*
|
||||
* @package Doctrine
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @package Doctrine
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @version $Revision$
|
||||
* @category Object Relational Mapping
|
||||
* @link www.phpdoctrine.com
|
||||
* @since 1.0
|
||||
*/
|
||||
* @version $Revision$
|
||||
* @category Object Relational Mapping
|
||||
* @link www.phpdoctrine.com
|
||||
* @since 1.0
|
||||
*/
|
||||
class Doctrine_Connection_Pgsql extends Doctrine_Connection_Common {
|
||||
/**
|
||||
* @var string $driverName the name of this connection driver
|
||||
@ -109,10 +109,9 @@ class Doctrine_Connection_Pgsql extends Doctrine_Connection_Common {
|
||||
* @param integer $limit limit the number of rows
|
||||
* @param integer $offset start reading from given offset
|
||||
* @param boolean $isManip if the query is a DML query
|
||||
|
||||
* @return string modified query
|
||||
*/
|
||||
public function modifyLimitQuery($query, $limit=false, $offset=false, $isManip = false) {
|
||||
public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false) {
|
||||
if ($limit > 0) {
|
||||
$query = rtrim($query);
|
||||
|
||||
@ -128,39 +127,14 @@ class Doctrine_Connection_Pgsql extends Doctrine_Connection_Common {
|
||||
. $from . ' ' . $where . ' LIMIT ' . $limit . ')';
|
||||
|
||||
} else {
|
||||
if($limit !== false) {
|
||||
$query .= ' LIMIT ' . $limit;
|
||||
}
|
||||
if($offset !== false) {
|
||||
$query .= ' OFFSET ' . $offset;
|
||||
}
|
||||
if($limit !== false) {
|
||||
$query .= ' LIMIT ' . $limit;
|
||||
}
|
||||
if($offset !== false) {
|
||||
$query .= ' OFFSET ' . $offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
/**
|
||||
* Set the transacton isolation level.
|
||||
*
|
||||
* @param string standard isolation level
|
||||
* READ UNCOMMITTED (allows dirty reads)
|
||||
* READ COMMITTED (prevents dirty reads)
|
||||
* REPEATABLE READ (prevents nonrepeatable reads)
|
||||
* SERIALIZABLE (prevents phantom reads)
|
||||
* @return void
|
||||
*/
|
||||
public function setTransactionIsolation($isolation) {
|
||||
switch ($isolation) {
|
||||
case 'READ UNCOMMITTED':
|
||||
case 'READ COMMITTED':
|
||||
case 'REPEATABLE READ':
|
||||
case 'SERIALIZABLE':
|
||||
break;
|
||||
throw new Doctrine_Connection_Pgsql_Exception('Isolation level '.$isolation.' is not supported.');
|
||||
}
|
||||
|
||||
$query = 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL ' . $isolation;
|
||||
return $this->dbh->query($query);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -22,15 +22,15 @@ Doctrine::autoload("Doctrine_Connection_Common");
|
||||
/**
|
||||
* Doctrine_Connection_Sqlite
|
||||
*
|
||||
* @package Doctrine
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @package Doctrine
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @version $Revision$
|
||||
* @category Object Relational Mapping
|
||||
* @link www.phpdoctrine.com
|
||||
* @since 1.0
|
||||
*/
|
||||
* @version $Revision$
|
||||
* @category Object Relational Mapping
|
||||
* @link www.phpdoctrine.com
|
||||
* @since 1.0
|
||||
*/
|
||||
class Doctrine_Connection_Sqlite extends Doctrine_Connection_Common {
|
||||
/**
|
||||
* @var string $driverName the name of this connection driver
|
||||
@ -82,33 +82,6 @@ class Doctrine_Connection_Sqlite extends Doctrine_Connection_Common {
|
||||
$this->dbh->sqliteCreateFunction('concat', array('Doctrine_Expression_Sqlite', 'concatImpl'));
|
||||
$this->dbh->sqliteCreateFunction('now', 'time', 0);
|
||||
}
|
||||
/**
|
||||
* Set the transacton isolation level.
|
||||
*
|
||||
* @param string standard isolation level
|
||||
* READ UNCOMMITTED (allows dirty reads)
|
||||
* READ COMMITTED (prevents dirty reads)
|
||||
* REPEATABLE READ (prevents nonrepeatable reads)
|
||||
* SERIALIZABLE (prevents phantom reads)
|
||||
* @return void
|
||||
*/
|
||||
public function setTransactionIsolation($isolation) {
|
||||
switch ($isolation) {
|
||||
case 'READ UNCOMMITTED':
|
||||
$isolation = 0;
|
||||
break;
|
||||
case 'READ COMMITTED':
|
||||
case 'REPEATABLE READ':
|
||||
case 'SERIALIZABLE':
|
||||
$isolation = 1;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Connection_Sqlite_Exception('Isolation level ' . $isolation . 'is not supported.');
|
||||
}
|
||||
|
||||
$query = "PRAGMA read_uncommitted=$isolation";
|
||||
return $this->_doQuery($query, true);
|
||||
}
|
||||
/**
|
||||
* Returns the current id of a sequence
|
||||
*
|
||||
|
@ -67,4 +67,65 @@ class Doctrine_Transaction_Firebird extends Doctrine_Transaction {
|
||||
|
||||
return $this->conn->getDbh()->query($query);
|
||||
}
|
||||
/**
|
||||
* Set the transacton isolation level.
|
||||
*
|
||||
* @param string standard isolation level (SQL-92)
|
||||
* READ UNCOMMITTED (allows dirty reads)
|
||||
* READ COMMITTED (prevents dirty reads)
|
||||
* REPEATABLE READ (prevents nonrepeatable reads)
|
||||
* SERIALIZABLE (prevents phantom reads)
|
||||
*
|
||||
* @param array some transaction options:
|
||||
* 'wait' => 'WAIT' | 'NO WAIT'
|
||||
* 'rw' => 'READ WRITE' | 'READ ONLY'
|
||||
*
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @throws Doctrine_Transaction_Exception if using unknown isolation level or unknown wait option
|
||||
* @return void
|
||||
*/
|
||||
public function setTransactionIsolation($isolation, $options = array()) {
|
||||
switch ($isolation) {
|
||||
case 'READ UNCOMMITTED':
|
||||
$nativeIsolation = 'READ COMMITTED RECORD_VERSION';
|
||||
break;
|
||||
case 'READ COMMITTED':
|
||||
$nativeIsolation = 'READ COMMITTED NO RECORD_VERSION';
|
||||
break;
|
||||
case 'REPEATABLE READ':
|
||||
$nativeIsolation = 'SNAPSHOT';
|
||||
break;
|
||||
case 'SERIALIZABLE':
|
||||
$nativeIsolation = 'SNAPSHOT TABLE STABILITY';
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Transaction_Exception('isolation level is not supported: ' . $isolation);
|
||||
}
|
||||
|
||||
if( ! empty($options['wait'])) {
|
||||
switch ($options['wait']) {
|
||||
case 'WAIT':
|
||||
case 'NO WAIT':
|
||||
$wait = $options['wait'];
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Transaction_Exception('wait option is not supported: ' . $options['wait']);
|
||||
}
|
||||
}
|
||||
|
||||
if( ! empty($options['rw'])) {
|
||||
switch ($options['rw']) {
|
||||
case 'READ ONLY':
|
||||
case 'READ WRITE':
|
||||
$rw = $options['wait'];
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Transaction_Exception('wait option is not supported: ' . $options['rw']);
|
||||
}
|
||||
}
|
||||
|
||||
$query = 'SET TRANSACTION ' . $rw . ' ' . $wait .' ISOLATION LEVEL ' . $nativeIsolation;
|
||||
|
||||
$this->conn->getDbh()->query($query);
|
||||
}
|
||||
}
|
||||
|
@ -67,4 +67,42 @@ class Doctrine_Transaction_Mysql extends Doctrine_Transaction {
|
||||
|
||||
return $this->conn->getDbh()->query($query);
|
||||
}
|
||||
/**
|
||||
* Set the transacton isolation level.
|
||||
*
|
||||
* @param string standard isolation level
|
||||
* READ UNCOMMITTED (allows dirty reads)
|
||||
* READ COMMITTED (prevents dirty reads)
|
||||
* REPEATABLE READ (prevents nonrepeatable reads)
|
||||
* SERIALIZABLE (prevents phantom reads)
|
||||
*
|
||||
* @throws Doctrine_Transaction_Exception if using unknown isolation level
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @return void
|
||||
*/
|
||||
public function setTransactionIsolation($isolation) {
|
||||
switch ($isolation) {
|
||||
case 'READ UNCOMMITTED':
|
||||
case 'READ COMMITTED':
|
||||
case 'REPEATABLE READ':
|
||||
case 'SERIALIZABLE':
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Transaction_Exception('Isolation level ' . $isolation . ' is not supported.');
|
||||
}
|
||||
|
||||
$query = "SET SESSION TRANSACTION ISOLATION LEVEL $isolation";
|
||||
|
||||
return $this->conn->getDbh()->query($query);
|
||||
}
|
||||
/**
|
||||
* getTransactionIsolation
|
||||
*
|
||||
* @return string returns the current session transaction isolation level
|
||||
*/
|
||||
public function getTransactionIsolation() {
|
||||
$ret = $this->conn->getDbh()->query('SELECT @@tx_isolation')->fetch(PDO::FETCH_NUM);
|
||||
return $ret[0];
|
||||
}
|
||||
}
|
||||
|
@ -66,4 +66,33 @@ class Doctrine_Transaction_Oracle extends Doctrine_Transaction {
|
||||
|
||||
return $this->conn->getDbh()->query($query);
|
||||
}
|
||||
/**
|
||||
* Set the transacton isolation level.
|
||||
*
|
||||
* @param string standard isolation level
|
||||
* READ UNCOMMITTED (allows dirty reads)
|
||||
* READ COMMITTED (prevents dirty reads)
|
||||
* REPEATABLE READ (prevents nonrepeatable reads)
|
||||
* SERIALIZABLE (prevents phantom reads)
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @throws Doctrine_Transaction_Exception if using unknown isolation level
|
||||
* @return void
|
||||
*/
|
||||
public function setTransactionIsolation($isolation) {
|
||||
switch($isolation) {
|
||||
case 'READ UNCOMMITTED':
|
||||
$isolation = 'READ COMMITTED';
|
||||
break;
|
||||
case 'READ COMMITTED':
|
||||
case 'REPEATABLE READ':
|
||||
case 'SERIALIZABLE':
|
||||
$isolation = 'SERIALIZABLE';
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Transaction_Exception('Isolation level ' . $isolation . ' is not supported.');
|
||||
}
|
||||
|
||||
$query = 'ALTER SESSION ISOLATION LEVEL ' . $isolation;
|
||||
return $this->dbh->query($query);
|
||||
}
|
||||
}
|
||||
|
@ -67,5 +67,30 @@ class Doctrine_Transaction_Pgsql extends Doctrine_Transaction {
|
||||
$query = 'ROLLBACK TO SAVEPOINT '.$savepoint;
|
||||
|
||||
return $this->conn->getDbh()->query($query);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Set the transacton isolation level.
|
||||
*
|
||||
* @param string standard isolation level
|
||||
* READ UNCOMMITTED (allows dirty reads)
|
||||
* READ COMMITTED (prevents dirty reads)
|
||||
* REPEATABLE READ (prevents nonrepeatable reads)
|
||||
* SERIALIZABLE (prevents phantom reads)
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @throws Doctrine_Transaction_Exception if using unknown isolation level or unknown wait option
|
||||
* @return void
|
||||
*/
|
||||
public function setTransactionIsolation($isolation) {
|
||||
switch ($isolation) {
|
||||
case 'READ UNCOMMITTED':
|
||||
case 'READ COMMITTED':
|
||||
case 'REPEATABLE READ':
|
||||
case 'SERIALIZABLE':
|
||||
break;
|
||||
throw new Doctrine_Connection_Pgsql_Exception('Isolation level '.$isolation.' is not supported.');
|
||||
}
|
||||
|
||||
$query = 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL ' . $isolation;
|
||||
return $this->dbh->query($query);
|
||||
}
|
||||
}
|
||||
|
@ -30,4 +30,35 @@ Doctrine::autoload('Doctrine_Transaction');
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Transaction_Sqlite extends Doctrine_Transaction { }
|
||||
class Doctrine_Transaction_Sqlite extends Doctrine_Transaction {
|
||||
/**
|
||||
* Set the transacton isolation level.
|
||||
*
|
||||
* @param string standard isolation level
|
||||
* READ UNCOMMITTED (allows dirty reads)
|
||||
* READ COMMITTED (prevents dirty reads)
|
||||
* REPEATABLE READ (prevents nonrepeatable reads)
|
||||
* SERIALIZABLE (prevents phantom reads)
|
||||
* @throws PDOException if something fails at the PDO level
|
||||
* @throws Doctrine_Transaction_Exception if using unknown isolation level
|
||||
* @return void
|
||||
*/
|
||||
public function setTransactionIsolation($isolation) {
|
||||
switch ($isolation) {
|
||||
case 'READ UNCOMMITTED':
|
||||
$isolation = 0;
|
||||
break;
|
||||
case 'READ COMMITTED':
|
||||
case 'REPEATABLE READ':
|
||||
case 'SERIALIZABLE':
|
||||
$isolation = 1;
|
||||
break;
|
||||
default:
|
||||
throw new Doctrine_Transaction_Exception('Isolation level ' . $isolation . 'is not supported.');
|
||||
}
|
||||
|
||||
$query = 'PRAGMA read_uncommitted = '.$isolation;
|
||||
|
||||
return $this->conn->getDbh()->query($query);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user