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
fe90d4dd
Commit
fe90d4dd
authored
Jan 06, 2013
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
implemented auto-quoting for DB commands.
parent
d15378ef
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
139 additions
and
109 deletions
+139
-109
Command.php
framework/db/Command.php
+18
-21
Connection.php
framework/db/Connection.php
+33
-36
Driver.php
framework/db/Driver.php
+62
-42
QueryBuilder.php
framework/db/QueryBuilder.php
+0
-0
QueryBuilder.php
framework/db/mysql/QueryBuilder.php
+8
-7
CommandTest.php
tests/unit/framework/db/CommandTest.php
+9
-0
ConnectionTest.php
tests/unit/framework/db/ConnectionTest.php
+9
-3
No files found.
framework/db/Command.php
View file @
fe90d4dd
...
...
@@ -62,21 +62,6 @@ class Command extends \yii\base\Component
private
$_params
=
array
();
/**
* Constructor.
* @param Connection $connection the database connection
* @param string $sql the SQL statement to be executed
* @param array $params the parameters to be bound to the SQL statement
* @param array $config name-value pairs that will be used to initialize the object properties
*/
public
function
__construct
(
$connection
,
$sql
=
null
,
$params
=
array
(),
$config
=
array
())
{
$this
->
connection
=
$connection
;
$this
->
_sql
=
$sql
;
$this
->
bindValues
(
$params
);
parent
::
__construct
(
$config
);
}
/**
* Returns the SQL statement for this command.
* @return string the SQL statement to be executed
*/
...
...
@@ -88,14 +73,26 @@ class Command extends \yii\base\Component
/**
* Specifies the SQL statement to be executed.
* Any previous execution will be terminated or cancelled.
* @param string $
value
the SQL statement to be set.
* @param string $
sql
the SQL statement to be set.
* @return Command this command instance
*/
public
function
setSql
(
$
value
)
public
function
setSql
(
$
sql
)
{
$this
->
_sql
=
$value
;
if
(
$sql
!==
$this
->
_sql
)
{
if
(
$this
->
connection
->
enableAutoQuoting
&&
$sql
!=
''
)
{
$sql
=
preg_replace_callback
(
'/(\\{\\{(.*?)\\}\\}|\\[\\[(.*?)\\]\\])/'
,
function
(
$matches
)
{
if
(
isset
(
$matches
[
3
]))
{
return
$this
->
connection
->
quoteColumnName
(
$matches
[
3
]);
}
else
{
$name
=
str_replace
(
'%'
,
$this
->
connection
->
tablePrefix
,
$matches
[
2
]);
return
$this
->
connection
->
quoteTableName
(
$name
);
}
},
$sql
);
}
$this
->
_sql
=
$sql
;
$this
->
_params
=
array
();
$this
->
cancel
();
}
return
$this
;
}
...
...
@@ -110,7 +107,7 @@ class Command extends \yii\base\Component
public
function
prepare
()
{
if
(
$this
->
pdoStatement
==
null
)
{
$sql
=
$this
->
connection
->
expandTablePrefix
(
$this
->
getSql
()
);
$sql
=
$this
->
getSql
(
);
try
{
$this
->
pdoStatement
=
$this
->
connection
->
pdo
->
prepare
(
$sql
);
}
catch
(
\Exception
$e
)
{
...
...
@@ -223,7 +220,7 @@ class Command extends \yii\base\Component
*/
public
function
execute
(
$params
=
array
())
{
$sql
=
$this
->
connection
->
expandTablePrefix
(
$this
->
getSql
()
);
$sql
=
$this
->
getSql
(
);
$this
->
_params
=
array_merge
(
$this
->
_params
,
$params
);
if
(
$this
->
_params
===
array
())
{
$paramLog
=
''
;
...
...
@@ -356,7 +353,7 @@ class Command extends \yii\base\Component
private
function
queryInternal
(
$method
,
$params
,
$fetchMode
=
null
)
{
$db
=
$this
->
connection
;
$sql
=
$
db
->
expandTablePrefix
(
$this
->
getSql
()
);
$sql
=
$
this
->
getSql
(
);
$this
->
_params
=
array_merge
(
$this
->
_params
,
$params
);
if
(
$this
->
_params
===
array
())
{
$paramLog
=
''
;
...
...
framework/db/Connection.php
View file @
fe90d4dd
...
...
@@ -124,7 +124,7 @@ class Connection extends \yii\base\ApplicationComponent
public
$attributes
;
/**
* @var \PDO the PHP PDO instance associated with this DB connection.
* This property is mainly managed by [[open
]] and [[close
]] methods.
* This property is mainly managed by [[open
()]] and [[close()
]] methods.
* When a DB connection is active, this property will represent a PDO instance;
* otherwise, it will be null.
*/
...
...
@@ -132,7 +132,7 @@ class Connection extends \yii\base\ApplicationComponent
/**
* @var boolean whether to enable schema caching.
* Note that in order to enable truly schema caching, a valid cache component as specified
* by [[schemaCacheID]] must be enabled and [[
schemaCacheEnabled
]] must be set true.
* by [[schemaCacheID]] must be enabled and [[
enableSchemaCache
]] must be set true.
* @see schemaCacheDuration
* @see schemaCacheExclude
* @see schemaCacheID
...
...
@@ -159,7 +159,7 @@ class Connection extends \yii\base\ApplicationComponent
/**
* @var boolean whether to enable query caching.
* Note that in order to enable query caching, a valid cache component as specified
* by [[queryCacheID]] must be enabled and [[
queryCacheEnabled
]] must be set true.
* by [[queryCacheID]] must be enabled and [[
enableQueryCache
]] must be set true.
*
* Methods [[beginCache()]] and [[endCache()]] can be used as shortcuts to turn on
* and off query caching on the fly.
...
...
@@ -215,16 +215,24 @@ class Connection extends \yii\base\ApplicationComponent
*/
public
$enableProfiling
=
false
;
/**
* @var string the default prefix for table names. Defaults to null, meaning not using table prefix.
* By setting this property, any token like '{{TableName}}' in [[Command::sql]] will
* be replaced with 'prefixTableName', where 'prefix' refers to this property value.
* For example, '{{post}}' becomes 'tbl_post', if 'tbl_' is set as the table prefix.
*
* Note that if you set this property to be an empty string, then '{{post}}' will be replaced
* with 'post'.
* @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
*/
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 a list of SQL statements that should be executed right after the DB connection is established.
*/
public
$initSQLs
;
...
...
@@ -411,7 +419,12 @@ class Connection extends \yii\base\ApplicationComponent
public
function
createCommand
(
$sql
=
null
,
$params
=
array
())
{
$this
->
open
();
return
new
Command
(
$this
,
$sql
,
$params
);
$command
=
new
Command
(
array
(
'connection'
=>
$this
,
'sql'
=>
$sql
,
));
$command
->
bindValues
(
$params
);
return
$command
;
}
/**
...
...
@@ -513,43 +526,27 @@ class Connection extends \yii\base\ApplicationComponent
/**
* 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 '{{',
* then this method will do nothing.
* @param string $name table name
* @param boolean $simple if this is true, then the method will assume $name is a table name without schema prefix.
* @return string the properly quoted table name
*/
public
function
quoteTableName
(
$name
,
$simple
=
false
)
public
function
quoteTableName
(
$name
)
{
return
$
simple
?
$this
->
getDriver
()
->
quoteSimpleTableName
(
$name
)
:
$
this
->
getDriver
()
->
quoteTableName
(
$name
);
return
$this
->
getDriver
()
->
quoteTableName
(
$name
);
}
/**
* Quotes a column name for use in a query.
* If the column name contains table prefix, the prefix will also be properly quoted.
* 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 '{{',
* then this method will do nothing.
* @param string $name column name
* @param boolean $simple if this is true, then the method will assume $name is a column name without table prefix.
* @return string the properly quoted column name
*/
public
function
quoteColumnName
(
$name
,
$simple
=
false
)
{
return
$simple
?
$this
->
getDriver
()
->
quoteSimpleColumnName
(
$name
)
:
$this
->
getDriver
()
->
quoteColumnName
(
$name
);
}
/**
* Prefixes table names in a SQL statement with [[tablePrefix]].
* By calling this method, tokens like '{{TableName}}' in the given SQL statement will
* be replaced with 'prefixTableName', where 'prefix' refers to [[tablePrefix]].
* Note that if [[tablePrefix]] is null, this method will do nothing.
* @param string $sql the SQL statement whose table names need to be prefixed with [[tablePrefix]].
* @return string the expanded SQL statement
* @see tablePrefix
*/
public
function
expandTablePrefix
(
$sql
)
public
function
quoteColumnName
(
$name
)
{
if
(
$this
->
tablePrefix
!==
null
&&
strpos
(
$sql
,
'{{'
)
!==
false
)
{
return
preg_replace
(
'/{{(.*?)}}/'
,
$this
->
tablePrefix
.
'\1'
,
$sql
);
}
else
{
return
$sql
;
}
return
$this
->
getDriver
()
->
quoteColumnName
(
$name
);
}
/**
...
...
framework/db/Driver.php
View file @
fe90d4dd
...
...
@@ -92,8 +92,7 @@ abstract class Driver extends \yii\base\Object
}
$db
=
$this
->
connection
;
$realName
=
$db
->
expandTablePrefix
(
$name
);
$realName
=
$this
->
getRealTableName
(
$name
);
/** @var $cache \yii\caching\Cache */
if
(
$db
->
enableSchemaCache
&&
(
$cache
=
\Yii
::
$application
->
getComponent
(
$db
->
schemaCacheID
))
!==
null
&&
!
in_array
(
$name
,
$db
->
schemaCacheExclude
,
true
))
{
...
...
@@ -168,37 +167,57 @@ abstract class Driver extends \yii\base\Object
/**
* Refreshes the schema.
* This method cleans up the cached table schema and names
* so that they can be recreated to reflect the database schema change.
* @param string $tableName the name of the table that needs to be refreshed.
* If null, all currently loaded tables will be refreshed.
* This method cleans up all cached table schemas so that they can be re-created later
* to reflect the database schema change.
*/
public
function
refresh
(
$tableName
=
null
)
public
function
refresh
()
{
$db
=
$this
->
connection
;
/** @var $cache \yii\caching\Cache */
if
(
$db
->
enableSchemaCache
&&
(
$cache
=
\Yii
::
$application
->
getComponent
(
$db
->
schemaCacheID
))
!==
null
)
{
if
(
$tableName
===
null
)
{
if
(
$this
->
connection
->
enableSchemaCache
&&
(
$cache
=
\Yii
::
$application
->
getComponent
(
$this
->
connection
->
schemaCacheID
))
!==
null
)
{
foreach
(
$this
->
_tables
as
$name
=>
$table
)
{
$cache
->
delete
(
$this
->
getCacheKey
(
$name
));
}
}
$this
->
_tables
=
array
();
}
else
{
$cache
->
delete
(
$this
->
getCacheKey
(
$tableName
));
unset
(
$this
->
_tables
[
$tableName
]);
}
/**
* Creates a query builder for the database.
* This method may be overridden by child classes to create a DBMS-specific query builder.
* @return QueryBuilder query builder instance
*/
public
function
createQueryBuilder
()
{
return
new
QueryBuilder
(
$this
->
connection
);
}
/**
* Returns all table names in the database.
* This method should be overridden by child classes in order to support this feature
* because the default implementation simply throws an exception.
* @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema.
* If not empty, the returned table names will be prefixed with the schema name.
* @return array all table names in the database.
*/
protected
function
findTableNames
(
$schema
=
''
)
{
throw
new
Exception
(
get_class
(
$this
)
.
' does not support fetching all table names.'
);
}
/**
* 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 '{{',
* then this method will do nothing.
* @param string $name table name
* @return string the properly quoted table name
* @see quoteSimpleTableName
*/
public
function
quoteTableName
(
$name
)
{
if
(
strpos
(
$name
,
'('
)
!==
false
||
strpos
(
$name
,
'[['
)
!==
false
||
strpos
(
$name
,
'{{'
)
!==
false
)
{
return
$name
;
}
if
(
strpos
(
$name
,
'.'
)
===
false
)
{
return
$this
->
quoteSimpleTableName
(
$name
);
}
...
...
@@ -211,25 +230,19 @@ abstract class Driver extends \yii\base\Object
}
/**
* Quotes a simple table name for use in a query.
* A simple table name does not schema prefix.
* @param string $name table name
* @return string the properly quoted table name
*/
public
function
quoteSimpleTableName
(
$name
)
{
return
strpos
(
$name
,
"'"
)
!==
false
?
$name
:
"'"
.
$name
.
"'"
;
}
/**
* 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 '{{',
* then this method will do nothing.
* @param string $name column name
* @return string the properly quoted column name
* @see quoteSimpleColumnName
*/
public
function
quoteColumnName
(
$name
)
{
if
(
strpos
(
$name
,
'('
)
!==
false
||
strpos
(
$name
,
'[['
)
!==
false
||
strpos
(
$name
,
'{{'
)
!==
false
)
{
return
$name
;
}
if
((
$pos
=
strrpos
(
$name
,
'.'
))
!==
false
)
{
$prefix
=
$this
->
quoteTableName
(
substr
(
$name
,
0
,
$pos
))
.
'.'
;
$name
=
substr
(
$name
,
$pos
+
1
);
...
...
@@ -240,8 +253,21 @@ abstract class Driver extends \yii\base\Object
}
/**
* Quotes a simple table name for use in a query.
* A simple table name should contain the table name only without any schema prefix.
* If the table name is already quoted, this method will do nothing.
* @param string $name table name
* @return string the properly quoted table name
*/
public
function
quoteSimpleTableName
(
$name
)
{
return
strpos
(
$name
,
"'"
)
!==
false
?
$name
:
"'"
.
$name
.
"'"
;
}
/**
* Quotes a simple column name for use in a query.
* A simple column name does not contain prefix.
* A simple column name should contain the column name only without any prefix.
* If the column name is already quoted or is the asterisk character '*', this method will do nothing.
* @param string $name column name
* @return string the properly quoted column name
*/
...
...
@@ -251,25 +277,19 @@ abstract class Driver extends \yii\base\Object
}
/**
* Creates a query builder for the database.
* This method may be overridden by child classes to create a DBMS-specific query builder.
* @return QueryBuilder query builder instance
* 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]].
* @param string $name the table name to be converted
* @return string the real name of the given table name
*/
public
function
createQueryBuilder
(
)
public
function
getRealTableName
(
$name
)
{
return
new
QueryBuilder
(
$this
->
connection
);
if
(
$this
->
connection
->
enableAutoQuoting
&&
strpos
(
$name
,
'{{'
)
!==
false
)
{
$name
=
preg_replace
(
'/\\{\\{(.*?)\\}\\}/'
,
'\1'
,
$name
);
return
str_replace
(
'%'
,
$this
->
connection
->
tablePrefix
,
$name
);
}
else
{
return
$name
;
}
/**
* Returns all table names in the database.
* This method should be overridden by child classes in order to support this feature
* because the default implementation simply throws an exception.
* @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema.
* If not empty, the returned table names will be prefixed with the schema name.
* @return array all table names in the database.
*/
protected
function
findTableNames
(
$schema
=
''
)
{
throw
new
Exception
(
get_class
(
$this
)
.
'does not support fetching all table names.'
);
}
}
framework/db/QueryBuilder.php
View file @
fe90d4dd
This diff is collapsed.
Click to expand it.
framework/db/mysql/QueryBuilder.php
View file @
fe90d4dd
...
...
@@ -46,10 +46,11 @@ class QueryBuilder extends \yii\db\QueryBuilder
* @param string $oldName the old name of the column. The name will be properly quoted by the method.
* @param string $newName the new name of the column. The name will be properly quoted by the method.
* @return string the SQL statement for renaming a DB column.
* @throws Exception
*/
public
function
renameColumn
(
$table
,
$oldName
,
$newName
)
{
$quotedTable
=
$this
->
quoteTableName
(
$table
);
$quotedTable
=
$this
->
connection
->
quoteTableName
(
$table
);
$row
=
$this
->
connection
->
createCommand
(
'SHOW CREATE TABLE '
.
$quotedTable
)
->
queryRow
();
if
(
$row
===
false
)
{
throw
new
Exception
(
"Unable to find '
$oldName
' in table '
$table
'."
);
...
...
@@ -64,16 +65,16 @@ class QueryBuilder extends \yii\db\QueryBuilder
foreach
(
$matches
[
1
]
as
$i
=>
$c
)
{
if
(
$c
===
$oldName
)
{
return
"ALTER TABLE
$quotedTable
CHANGE "
.
$this
->
quoteColumnName
(
$oldName
,
tru
e
)
.
' '
.
$this
->
quoteColumnName
(
$newName
,
tru
e
)
.
' '
.
$this
->
connection
->
quoteColumnName
(
$oldNam
e
)
.
' '
.
$this
->
connection
->
quoteColumnName
(
$newNam
e
)
.
' '
.
$matches
[
2
][
$i
];
}
}
}
// try to give back a SQL anyway
return
"ALTER TABLE
$quotedTable
CHANGE "
.
$this
->
quoteColumnName
(
$oldName
,
tru
e
)
.
' '
.
$this
->
quoteColumnName
(
$newName
,
tru
e
);
.
$this
->
connection
->
quoteColumnName
(
$oldNam
e
)
.
' '
.
$this
->
connection
->
quoteColumnName
(
$newNam
e
);
}
/**
...
...
@@ -84,7 +85,7 @@ class QueryBuilder extends \yii\db\QueryBuilder
*/
public
function
dropForeignKey
(
$name
,
$table
)
{
return
'ALTER TABLE '
.
$this
->
quoteTableName
(
$table
)
.
' DROP FOREIGN KEY '
.
$this
->
quoteColumnName
(
$name
);
return
'ALTER TABLE '
.
$this
->
connection
->
quoteTableName
(
$table
)
.
' DROP FOREIGN KEY '
.
$this
->
connection
->
quoteColumnName
(
$name
);
}
}
tests/unit/framework/db/CommandTest.php
View file @
fe90d4dd
...
...
@@ -36,6 +36,15 @@ class CommandTest extends \yiiunit\MysqlTestCase
$this
->
assertEquals
(
$sql2
,
$command
->
sql
);
}
function
testAutoQuoting
()
{
$db
=
$this
->
getConnection
(
false
);
$sql
=
'SELECT [[id]], [[t.name]] FROM {{tbl_customer}} t'
;
$command
=
$db
->
createCommand
(
$sql
);
$this
->
assertEquals
(
"SELECT `id`, `t`.`name` FROM `tbl_customer` t"
,
$command
->
sql
);
}
function
testPrepareCancel
()
{
$db
=
$this
->
getConnection
(
false
);
...
...
tests/unit/framework/db/ConnectionTest.php
View file @
fe90d4dd
...
...
@@ -49,7 +49,7 @@ class ConnectionTest extends \yiiunit\MysqlTestCase
$connection
=
$this
->
getConnection
(
false
);
$this
->
assertEquals
(
123
,
$connection
->
quoteValue
(
123
));
$this
->
assertEquals
(
"'string'"
,
$connection
->
quoteValue
(
'string'
));
$this
->
assertEquals
(
"'It\'s interesting'"
,
$connection
->
quoteValue
(
"It's interesting"
));
$this
->
assertEquals
(
"'It
\
\
's interesting'"
,
$connection
->
quoteValue
(
"It's interesting"
));
}
function
testQuoteTableName
()
...
...
@@ -58,7 +58,10 @@ class ConnectionTest extends \yiiunit\MysqlTestCase
$this
->
assertEquals
(
'`table`'
,
$connection
->
quoteTableName
(
'table'
));
$this
->
assertEquals
(
'`table`'
,
$connection
->
quoteTableName
(
'`table`'
));
$this
->
assertEquals
(
'`schema`.`table`'
,
$connection
->
quoteTableName
(
'schema.table'
));
$this
->
assertEquals
(
'`schema.table`'
,
$connection
->
quoteTableName
(
'schema.table'
,
true
));
$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)'
));
}
function
testQuoteColumnName
()
...
...
@@ -67,7 +70,10 @@ class ConnectionTest extends \yiiunit\MysqlTestCase
$this
->
assertEquals
(
'`column`'
,
$connection
->
quoteColumnName
(
'column'
));
$this
->
assertEquals
(
'`column`'
,
$connection
->
quoteColumnName
(
'`column`'
));
$this
->
assertEquals
(
'`table`.`column`'
,
$connection
->
quoteColumnName
(
'table.column'
));
$this
->
assertEquals
(
'`table.column`'
,
$connection
->
quoteColumnName
(
'table.column'
,
true
));
$this
->
assertEquals
(
'`table`.`column`'
,
$connection
->
quoteColumnName
(
'table.`column`'
));
$this
->
assertEquals
(
'[[column]]'
,
$connection
->
quoteColumnName
(
'[[column]]'
));
$this
->
assertEquals
(
'{{column}}'
,
$connection
->
quoteColumnName
(
'{{column}}'
));
$this
->
assertEquals
(
'(column)'
,
$connection
->
quoteColumnName
(
'(column)'
));
}
function
testGetPdoType
()
...
...
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