Commit 597082a1 by Qiang Xue

Automatic table and column name quoting.

parent 2dbfda65
......@@ -99,7 +99,7 @@ class DbCache extends Cache
$query = new Query;
$query->select(array('data'))
->from($this->cacheTable)
->where('id = :id AND (expire = 0 OR expire >' . time() . ')', array(':id' => $key));
->where('[[id]] = :id AND ([[expire]] = 0 OR [[expire]] >' . time() . ')', array(':id' => $key));
if ($this->db->enableQueryCache) {
// temporarily disable and re-enable query caching
$this->db->enableQueryCache = false;
......@@ -125,7 +125,7 @@ class DbCache extends Cache
$query->select(array('id', 'data'))
->from($this->cacheTable)
->where(array('id' => $keys))
->andWhere('(expire = 0 OR expire > ' . time() . ')');
->andWhere('([[expire]] = 0 OR [[expire]] > ' . time() . ')');
if ($this->db->enableQueryCache) {
$this->db->enableQueryCache = false;
......@@ -227,7 +227,7 @@ class DbCache extends Cache
{
if ($force || mt_rand(0, 1000000) < $this->gcProbability) {
$this->db->createCommand()
->delete($this->cacheTable, 'expire > 0 AND expire < ' . time())
->delete($this->cacheTable, '[[expire]] > 0 AND [[expire]] < ' . time())
->execute();
}
}
......
......@@ -84,42 +84,21 @@ class Command extends \yii\base\Component
/**
* Specifies the SQL statement to be executed.
* Any previous execution will be terminated or cancelled.
* The previous SQL execution (if any) will be cancelled, and [[params]] will be cleared as well.
* @param string $sql the SQL statement to be set.
* @return Command this command instance
*/
public function setSql($sql)
{
if ($sql !== $this->_sql) {
if ($this->db->enableAutoQuoting && $sql != '') {
$sql = $this->expandSql($sql);
}
$this->cancel();
$this->_sql = $sql;
$this->_sql = $this->db->quoteSql($sql);
$this->_params = array();
}
return $this;
}
/**
* Expands a SQL statement by quoting table and column names and replacing table prefixes.
* @param string $sql the SQL to be expanded
* @return string the expanded SQL
*/
protected function expandSql($sql)
{
$db = $this->db;
return preg_replace_callback('/(\\{\\{(.*?)\\}\\}|\\[\\[(.*?)\\]\\])/', function($matches) use($db) {
if (isset($matches[3])) {
return $db->quoteColumnName($matches[3]);
} else {
$name = str_replace('%', $db->tablePrefix, $matches[2]);
return $db->quoteTableName($name);
}
}, $sql);
}
/**
* Prepares the SQL statement to be executed.
* For complex SQL statement that is to be executed multiple times,
* this may improve performance.
......
......@@ -223,21 +223,10 @@ class Connection extends Component
* @var string the common prefix or suffix for table names. If a table name is given
* as `{{%TableName}}`, then the percentage character `%` will be replaced with this
* property value. For example, `{{%post}}` becomes `{{tbl_post}}` if this property is
* set as `"tbl_"`. Note that this property is only effective when [[enableAutoQuoting]]
* is true.
* @see enableAutoQuoting
* set as `"tbl_"`.
*/
public $tablePrefix;
/**
* @var boolean whether to enable automatic quoting of table names and column names.
* Defaults to true. When this property is true, any token enclosed within double curly brackets
* (e.g. `{{post}}`) in a SQL statement will be treated as a table name and will be quoted
* accordingly when the SQL statement is executed; and any token enclosed within double square
* brackets (e.g. `[[name]]`) will be treated as a column name and quoted accordingly.
* @see tablePrefix
*/
public $enableAutoQuoting = true;
/**
* @var array mapping between PDO driver names and [[Schema]] classes.
* The keys of the array are PDO driver names while the values the corresponding
* schema class name or configuration. Please refer to [[\Yii::createObject()]] for
......@@ -518,6 +507,27 @@ class Connection extends Component
}
/**
* Processes a SQL statement by quoting table and column names that are enclosed within double brackets.
* Tokens enclosed within double curly brackets are treated as table names, while
* tokens enclosed within double square brackets are column names. They will be quoted accordingly.
* Also, the percentage character "%" in a table name will be replaced with [[tablePrefix]].
* @param string $sql the SQL to be quoted
* @return string the quoted SQL
*/
public function quoteSql($sql)
{
$db = $this;
return preg_replace_callback('/(\\{\\{([\w\-\. ]+)\\}\\}|\\[\\[([\w\-\. ]+)\\]\\])/',
function($matches) use($db) {
if (isset($matches[3])) {
return $db->quoteColumnName($matches[3]);
} else {
return str_replace('%', $this->tablePrefix, $db->quoteTableName($matches[2]));
}
}, $sql);
}
/**
* Returns the name of the DB driver for the current [[dsn]].
* @return string name of the DB driver
*/
......
......@@ -248,7 +248,7 @@ abstract class Schema extends \yii\base\Object
/**
* Quotes a table name for use in a query.
* If the table name contains schema prefix, the prefix will also be properly quoted.
* If the table name is already quoted or contains special characters including '(', '[[' and '{{',
* If the table name is already quoted or contains '(' or '{{',
* then this method will do nothing.
* @param string $name table name
* @return string the properly quoted table name
......@@ -256,7 +256,7 @@ abstract class Schema extends \yii\base\Object
*/
public function quoteTableName($name)
{
if (strpos($name, '(') !== false || strpos($name, '[[') !== false || strpos($name, '{{') !== false) {
if (strpos($name, '(') !== false || strpos($name, '{{') !== false) {
return $name;
}
if (strpos($name, '.') === false) {
......@@ -273,7 +273,7 @@ abstract class Schema extends \yii\base\Object
/**
* Quotes a column name for use in a query.
* If the column name contains prefix, the prefix will also be properly quoted.
* If the column name is already quoted or contains special characters including '(', '[[' and '{{',
* If the column name is already quoted or contains '(', '[[' or '{{',
* then this method will do nothing.
* @param string $name column name
* @return string the properly quoted column name
......@@ -320,13 +320,13 @@ abstract class Schema extends \yii\base\Object
/**
* Returns the real name of a table name.
* This method will strip off curly brackets from the given table name
* and replace the percentage character in the name with [[Connection::tablePrefix]].
* and replace the percentage character '%' with [[Connection::tablePrefix]].
* @param string $name the table name to be converted
* @return string the real name of the given table name
*/
public function getRealTableName($name)
{
if ($this->db->enableAutoQuoting && strpos($name, '{{') !== false) {
if (strpos($name, '{{') !== false) {
$name = preg_replace('/\\{\\{(.*?)\\}\\}/', '\1', $name);
return str_replace('%', $this->db->tablePrefix, $name);
} else {
......
......@@ -78,7 +78,8 @@ class DbTarget extends Target
public function export($messages)
{
$tableName = $this->db->quoteTableName($this->logTable);
$sql = "INSERT INTO $tableName (level, category, log_time, message) VALUES (:level, :category, :log_time, :message)";
$sql = "INSERT INTO $tableName ([[level]], [[category]], [[log_time]], [[message]])
VALUES (:level, :category, :log_time, :message)";
$command = $this->db->createCommand($sql);
foreach ($messages as $message) {
$command->bindValues(array(
......
......@@ -144,7 +144,7 @@ class DbSession extends Session
$query = new Query;
$data = $query->select(array('data'))
->from($this->sessionTable)
->where('expire>:expire AND id=:id', array(':expire' => time(), ':id' => $id))
->where('[[expire]]>:expire AND [[id]]=:id', array(':expire' => time(), ':id' => $id))
->createCommand($this->db)
->queryScalar();
return $data === false ? '' : $data;
......@@ -214,7 +214,7 @@ class DbSession extends Session
public function gcSession($maxLifetime)
{
$this->db->createCommand()
->delete($this->sessionTable, 'expire<:expire', array(':expire' => time()))
->delete($this->sessionTable, '[[expire]]<:expire', array(':expire' => time()))
->execute();
return true;
}
......
......@@ -59,7 +59,6 @@ class ConnectionTest extends \yiiunit\MysqlTestCase
$this->assertEquals('`table`', $connection->quoteTableName('`table`'));
$this->assertEquals('`schema`.`table`', $connection->quoteTableName('schema.table'));
$this->assertEquals('`schema`.`table`', $connection->quoteTableName('schema.`table`'));
$this->assertEquals('[[table]]', $connection->quoteTableName('[[table]]'));
$this->assertEquals('{{table}}', $connection->quoteTableName('{{table}}'));
$this->assertEquals('(table)', $connection->quoteTableName('(table)'));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment