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
d794a813
Commit
d794a813
authored
Mar 04, 2012
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
...
parent
62336b43
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
189 additions
and
340 deletions
+189
-340
ActiveFinder.php
framework/db/ar/ActiveFinder.php
+114
-169
ActiveQuery.php
framework/db/ar/ActiveQuery.php
+1
-5
JoinElement.php
framework/db/ar/JoinElement.php
+18
-116
Command.php
framework/db/dao/Command.php
+1
-1
QueryBuilder.php
framework/db/dao/QueryBuilder.php
+52
-47
ActiveRecordTest.php
tests/unit/framework/db/ar/ActiveRecordTest.php
+3
-2
No files found.
framework/db/ar/ActiveFinder.php
View file @
d794a813
...
@@ -17,22 +17,8 @@ use yii\db\Exception;
...
@@ -17,22 +17,8 @@ use yii\db\Exception;
/**
/**
* ActiveFinder.php is ...
* ActiveFinder.php is ...
* todo: add SQL monitor
* todo: base limited with has_many, bySQL, lazy loading
* todo: better handling on join() support in QueryBuilder: use regexp to detect table name and quote it
* todo: quoting column names in 'on' clause
* todo: do not support anonymous parameter binding
* todo: add ActiveFinderBuilder
* todo: quote join/on part of the relational query
* todo: modify QueryBuilder about join() methods
* todo: unify ActiveFinder and ActiveRelation in query building process
* todo: intelligent table aliasing (first table name, then relation name, finally t?)
* todo: allow using tokens in primary query fragments
* todo: findBySql
* todo: base limited
* todo: lazy loading
* todo: scope
* todo: test via option
todo: inner join with one or multiple relations as filters
joinType should default to inner join in this case
*
*
* @property integer $count
* @property integer $count
*
*
...
@@ -45,10 +31,6 @@ class ActiveFinder extends \yii\base\Object
...
@@ -45,10 +31,6 @@ class ActiveFinder extends \yii\base\Object
* @var \yii\db\dao\Connection
* @var \yii\db\dao\Connection
*/
*/
public
$connection
;
public
$connection
;
/**
* @var ActiveQuery
*/
public
$query
;
public
function
__construct
(
$connection
)
public
function
__construct
(
$connection
)
{
{
...
@@ -56,16 +38,25 @@ class ActiveFinder extends \yii\base\Object
...
@@ -56,16 +38,25 @@ class ActiveFinder extends \yii\base\Object
}
}
/**
/**
* @param \yii\db\ar\ActiveQuery $query
* @param ActiveQuery $query
* @param bool $all
* @return array
*/
*/
public
function
findRecords
(
$query
)
public
function
findRecords
(
$query
)
{
{
if
(
!
empty
(
$query
->
with
))
{
return
$this
->
findRecordsWithRelations
(
$query
);
}
if
(
$query
->
sql
!==
null
)
{
if
(
$query
->
sql
!==
null
)
{
$sql
=
$query
->
sql
;
$sql
=
$query
->
sql
;
}
else
{
}
else
{
$this
->
initFrom
(
$query
);
if
(
$query
->
from
===
null
)
{
$modelClass
=
$query
->
modelClass
;
$tableName
=
$modelClass
::
tableName
();
if
(
$query
->
tableAlias
!==
null
)
{
$tableName
.=
' '
.
$query
->
tableAlias
;
}
$query
->
from
=
array
(
$tableName
);
}
$this
->
applyScopes
(
$query
);
$this
->
applyScopes
(
$query
);
$sql
=
$this
->
connection
->
getQueryBuilder
()
->
build
(
$query
);
$sql
=
$this
->
connection
->
getQueryBuilder
()
->
build
(
$query
);
if
(
strpos
(
$sql
,
'@.'
)
!==
false
)
{
if
(
strpos
(
$sql
,
'@.'
)
!==
false
)
{
...
@@ -93,11 +84,11 @@ class ActiveFinder extends \yii\base\Object
...
@@ -93,11 +84,11 @@ class ActiveFinder extends \yii\base\Object
$class
=
$query
->
modelClass
;
$class
=
$query
->
modelClass
;
if
(
$query
->
indexBy
===
null
)
{
if
(
$query
->
indexBy
===
null
)
{
foreach
(
$rows
as
$row
)
{
foreach
(
$rows
as
$row
)
{
$records
[]
=
$class
::
create
Record
(
$row
);
$records
[]
=
$class
::
create
(
$row
);
}
}
}
else
{
}
else
{
foreach
(
$rows
as
$row
)
{
foreach
(
$rows
as
$row
)
{
$records
[
$row
[
$query
->
indexBy
]]
=
$class
::
create
Record
(
$row
);
$records
[
$row
[
$query
->
indexBy
]]
=
$class
::
create
(
$row
);
}
}
}
}
}
}
...
@@ -110,136 +101,52 @@ class ActiveFinder extends \yii\base\Object
...
@@ -110,136 +101,52 @@ class ActiveFinder extends \yii\base\Object
}
}
private
$_joinCount
;
private
$_tableAliases
;
/**
* @param ActiveQuery $query
* @return array
*/
public
function
findRecordsWithRelations
(
$query
)
public
function
findRecordsWithRelations
(
$query
)
{
{
// todo: handle findBySql() and limit cases
$this
->
_joinCount
=
0
;
$joinTree
=
$this
->
buildRelationalQuery
();
$this
->
_tableAliases
=
array
();
$joinTree
=
new
JoinElement
(
$this
->
_joinCount
++
,
$query
,
null
,
null
);
if
(
$this
->
sql
===
null
)
{
$this
->
buildJoinTree
(
$joinTree
,
$query
->
with
);
$this
->
initFrom
(
$element
->
query
);
$this
->
initJoinTree
(
$joinTree
);
$command
=
$element
->
query
->
createCommand
(
$this
->
getDbConnection
());
$this
->
sql
=
$command
->
getSql
();
}
else
{
$command
=
$this
->
getDbConnection
()
->
createCommand
(
$this
->
sql
);
$command
->
bindValues
(
$element
->
query
->
params
);
}
$rows
=
$command
->
queryAll
();
if
(
isset
(
$joinTree
))
{
foreach
(
$rows
as
$row
)
{
$joinTree
->
populateData
(
$row
);
}
return
array_values
(
$joinTree
->
records
);
}
if
(
$this
->
asArray
)
{
$q
=
new
Query
;
if
(
$this
->
indexBy
===
null
)
{
$this
->
buildJoinQuery
(
$joinTree
,
$q
);
return
$rows
;
$rows
=
$q
->
createCommand
(
$this
->
connection
)
->
queryAll
();
}
foreach
(
$rows
as
$row
)
{
$records
=
array
();
$joinTree
->
createRecord
(
$row
);
foreach
(
$rows
as
$row
)
{
$records
[
$row
[
$this
->
indexBy
]]
=
$row
;
}
return
$records
;
}
else
{
$records
=
array
();
$class
=
$this
->
modelClass
;
if
(
$this
->
indexBy
===
null
)
{
foreach
(
$rows
as
$row
)
{
$records
[]
=
$class
::
populateData
(
$row
);
}
}
else
{
$attribute
=
$this
->
indexBy
;
foreach
(
$rows
as
$row
)
{
$record
=
$class
::
populateData
(
$row
);
$records
[
$record
->
$attribute
]
=
$record
;
}
}
return
$records
;
}
}
}
protected
function
initFrom
(
$query
)
return
$query
->
indexBy
!==
null
?
$joinTree
->
records
:
array_values
(
$joinTree
->
records
);
{
if
(
$query
->
from
===
null
)
{
$modelClass
=
$query
->
modelClass
;
$tableName
=
$modelClass
::
tableName
();
if
(
$query
->
tableAlias
!==
null
)
{
$tableName
.=
' '
.
$query
->
tableAlias
;
}
$query
->
from
=
array
(
$tableName
);
}
}
}
protected
function
applyScopes
(
$query
)
protected
function
applyScopes
(
$query
)
{
{
$class
=
$query
->
modelClass
;
$class
::
defaultScope
(
$query
);
if
(
is_array
(
$query
->
scopes
))
{
if
(
is_array
(
$query
->
scopes
))
{
$class
=
$query
->
modelClass
;
$class
::
defaultScope
(
$query
);
$scopes
=
$class
::
scopes
();
$scopes
=
$class
::
scopes
();
foreach
(
$query
->
scopes
as
$name
=>
$params
)
{
foreach
(
$query
->
scopes
as
$name
=>
$params
)
{
if
(
is_integer
(
$name
))
{
if
(
is_integer
(
$name
))
{
$name
=
$params
;
$name
=
$params
;
$params
=
array
();
$params
=
array
();
}
}
if
(
!
isset
(
$scopes
[
$name
]))
{
if
(
isset
(
$scopes
[
$name
]))
{
array_unshift
(
$params
,
$query
);
call_user_func_array
(
$scopes
[
$name
],
$params
);
}
else
{
throw
new
Exception
(
"
$class
has no scope named '
$name
'."
);
throw
new
Exception
(
"
$class
has no scope named '
$name
'."
);
}
}
array_unshift
(
$params
,
$query
);
call_user_func_array
(
$scopes
[
$name
],
$params
);
}
}
}
}
}
}
private
$_joinCount
;
private
$_tableAliases
;
protected
function
buildQuery
()
{
$this
->
_joinCount
=
0
;
$joinTree
=
new
JoinElement
(
$this
->
_joinCount
++
,
$element
->
query
,
null
,
null
);
$this
->
buildJoinTree
(
$joinTree
,
$element
->
query
->
with
);
$this
->
_tableAliases
=
array
();
$this
->
buildTableAlias
(
$joinTree
);
$query
=
new
Query
;
foreach
(
$joinTree
->
children
as
$child
)
{
$child
->
buildQuery
(
$query
);
}
$select
=
$joinTree
->
buildSelect
(
$element
,
$element
->
query
->
select
);
if
(
!
empty
(
$query
->
select
))
{
$element
->
query
->
select
=
array_merge
(
$select
,
$query
->
select
);
}
else
{
$element
->
query
->
select
=
$select
;
}
if
(
!
empty
(
$query
->
where
))
{
$element
->
query
->
andWhere
(
'('
.
implode
(
') AND ('
,
$query
->
where
)
.
')'
);
}
if
(
!
empty
(
$query
->
having
))
{
$element
->
query
->
andHaving
(
'('
.
implode
(
') AND ('
,
$query
->
having
)
.
')'
);
}
if
(
!
empty
(
$query
->
join
))
{
if
(
$element
->
query
->
join
===
null
)
{
$element
->
query
->
join
=
$query
->
join
;
}
else
{
$element
->
query
->
join
=
array_merge
(
$element
->
query
->
join
,
$query
->
join
);
}
}
if
(
!
empty
(
$query
->
orderBy
))
{
$element
->
query
->
addOrderBy
(
$query
->
orderBy
);
}
if
(
!
empty
(
$query
->
groupBy
))
{
$element
->
query
->
addGroupBy
(
$query
->
groupBy
);
}
if
(
!
empty
(
$query
->
params
))
{
$element
->
query
->
addParams
(
$query
->
params
);
}
return
$joinTree
;
}
/**
/**
* @param JoinElement $parent
* @param JoinElement $parent
* @param array|string $with
* @param array|string $with
...
@@ -297,7 +204,7 @@ class ActiveFinder extends \yii\base\Object
...
@@ -297,7 +204,7 @@ class ActiveFinder extends \yii\base\Object
/**
/**
* @param JoinElement $element
* @param JoinElement $element
*/
*/
protected
function
buildTableAlias
(
$element
)
protected
function
initJoinTree
(
$element
)
{
{
if
(
$element
->
query
->
tableAlias
!==
null
)
{
if
(
$element
->
query
->
tableAlias
!==
null
)
{
$alias
=
$element
->
query
->
tableAlias
;
$alias
=
$element
->
query
->
tableAlias
;
...
@@ -313,58 +220,95 @@ class ActiveFinder extends \yii\base\Object
...
@@ -313,58 +220,95 @@ class ActiveFinder extends \yii\base\Object
$this
->
_tableAliases
[
$alias
]
=
true
;
$this
->
_tableAliases
[
$alias
]
=
true
;
$element
->
query
->
tableAlias
=
$alias
;
$element
->
query
->
tableAlias
=
$alias
;
$this
->
applyScopes
(
$element
->
query
);
foreach
(
$element
->
children
as
$child
)
{
foreach
(
$element
->
children
as
$child
)
{
$this
->
buildTableAlias
(
$child
,
$count
);
$this
->
initJoinTree
(
$child
,
$count
);
}
}
}
}
/**
/**
* @param JoinElement $element
* @param JoinElement $element
* @param Query $query
* @param
\yii\db\dao\
Query $query
*/
*/
protected
function
buildJoinQuery
(
$element
,
$query
)
protected
function
buildJoinQuery
(
$element
,
$query
)
{
{
$prefixes
=
array
(
if
(
$element
->
parent
)
{
'@.'
=>
$element
->
query
->
tableAlias
.
'.'
,
$prefixes
=
array
(
'?.'
=>
$element
->
parent
->
query
->
tableAlias
.
'.'
,
'@.'
=>
$element
->
query
->
tableAlias
.
'.'
,
);
'?.'
=>
$element
->
parent
->
query
->
tableAlias
.
'.'
,
$quotedPrefixes
=
array
(
);
'@.'
=>
$this
->
connection
->
quoteTableName
(
$element
->
query
->
tableAlias
,
true
)
.
'.'
,
$quotedPrefixes
=
array
(
'?.'
=>
$this
->
connection
->
quoteTableName
(
$element
->
parent
->
query
->
tableAlias
,
true
)
.
'.'
,
'@.'
=>
$this
->
connection
->
quoteTableName
(
$element
->
query
->
tableAlias
,
true
)
.
'.'
,
);
'?.'
=>
$this
->
connection
->
quoteTableName
(
$element
->
parent
->
query
->
tableAlias
,
true
)
.
'.'
,
);
}
else
{
$prefixes
=
array
(
'@.'
=>
$element
->
query
->
tableAlias
.
'.'
,
);
$quotedPrefixes
=
array
(
'@.'
=>
$this
->
connection
->
quoteTableName
(
$element
->
query
->
tableAlias
,
true
)
.
'.'
,
);
}
$qb
=
$this
->
connection
->
getQueryBuilder
();
foreach
(
$this
->
buildSelect
(
$element
,
$element
->
query
->
select
)
as
$column
)
{
foreach
(
$this
->
buildSelect
(
$element
,
$element
->
query
->
select
)
as
$column
)
{
$query
->
select
[]
=
strtr
(
$column
,
$prefixes
);
$query
->
select
[]
=
strtr
(
$column
,
$prefixes
);
}
}
if
(
$element
->
query
->
where
!==
null
)
{
if
(
$element
->
query
instanceof
ActiveQuery
)
{
$query
->
where
[]
=
strtr
(
$element
->
query
->
where
,
$quotedPrefixes
);
if
(
$element
->
query
->
from
===
null
)
{
$modelClass
=
$element
->
query
->
modelClass
;
$tableName
=
$modelClass
::
tableName
();
if
(
$element
->
query
->
tableAlias
!==
null
)
{
$tableName
.=
' '
.
$element
->
query
->
tableAlias
;
}
$query
->
from
=
array
(
$tableName
);
}
else
{
$query
->
from
=
$element
->
query
->
from
;
}
}
}
if
(
$element
->
query
->
having
!==
null
)
{
if
(
(
$where
=
$qb
->
buildCondition
(
$element
->
query
->
where
))
!==
''
)
{
$query
->
having
[]
=
strtr
(
$element
->
query
->
having
,
$quotedPrefixes
);
$query
->
andWhere
(
strtr
(
$where
,
$quotedPrefixes
)
);
}
}
if
(
$element
->
query
->
via
!==
null
)
{
if
(
(
$having
=
$qb
->
buildCondition
(
$element
->
query
->
having
))
!==
''
)
{
$query
->
join
[]
=
strtr
(
$element
->
query
->
via
,
$quotedPrefixes
);
$query
->
andHaving
(
strtr
(
$having
,
$quotedPrefixes
)
);
}
}
if
(
$element
->
query
->
joinType
===
null
)
{
if
(
$element
->
query
instanceof
ActiveRelation
)
{
$joinType
=
$element
->
query
->
select
===
false
?
'INNER JOIN'
:
'LEFT JOIN'
;
if
(
$element
->
query
->
via
!==
null
)
{
}
else
{
$query
->
join
[]
=
strtr
(
$element
->
query
->
via
,
$quotedPrefixes
);
$joinType
=
$element
->
query
->
joinType
;
}
}
$modelClass
=
$element
->
query
->
modelClass
;
if
(
$element
->
query
->
joinType
===
null
)
{
$tableName
=
$this
->
connection
->
quoteTableName
(
$modelClass
::
tableName
());
$joinType
=
$element
->
query
->
select
===
false
?
'INNER JOIN'
:
'LEFT JOIN'
;
$tableAlias
=
$this
->
connection
->
quoteTableName
(
$element
->
query
->
tableAlias
);
}
else
{
$join
=
"
$joinType
$tableName
$tableAlias
"
;
$joinType
=
$element
->
query
->
joinType
;
if
(
$element
->
query
->
on
!==
null
)
{
}
$join
.=
' ON '
.
strtr
(
$element
->
query
->
on
,
$quotedPrefixes
);
$modelClass
=
$element
->
query
->
modelClass
;
$tableName
=
$this
->
connection
->
quoteTableName
(
$modelClass
::
tableName
());
$tableAlias
=
$this
->
connection
->
quoteTableName
(
$element
->
query
->
tableAlias
);
$join
=
"
$joinType
$tableName
$tableAlias
"
;
if
(
$element
->
query
->
on
!==
null
)
{
$join
.=
' ON '
.
strtr
(
$qb
->
buildCondition
(
$element
->
query
->
on
),
$quotedPrefixes
);
}
$query
->
join
[]
=
$join
;
}
}
$query
->
join
[]
=
$join
;
if
(
$element
->
query
->
join
!==
null
)
{
if
(
$element
->
query
->
join
!==
null
)
{
$query
->
join
[]
=
strtr
(
$element
->
query
->
join
,
$quotedPrefixes
);
if
(
is_array
(
$element
->
query
->
join
))
{
foreach
(
$element
->
query
->
join
as
$join
)
{
if
(
is_array
(
$join
)
&&
isset
(
$join
[
2
]))
{
$join
[
2
]
=
strtr
(
$join
[
2
],
$quotedPrefixes
);
}
$query
->
join
[]
=
$join
;
}
}
else
{
$query
->
join
[]
=
strtr
(
$element
->
query
->
join
,
$quotedPrefixes
);
}
}
}
if
(
$element
->
query
->
orderBy
!==
null
)
{
if
(
$element
->
query
->
orderBy
!==
null
)
{
...
@@ -390,7 +334,7 @@ class ActiveFinder extends \yii\base\Object
...
@@ -390,7 +334,7 @@ class ActiveFinder extends \yii\base\Object
}
}
foreach
(
$element
->
children
as
$child
)
{
foreach
(
$element
->
children
as
$child
)
{
$this
->
buildQuery
(
$child
,
$query
);
$this
->
build
Join
Query
(
$child
,
$query
);
}
}
}
}
...
@@ -406,7 +350,7 @@ class ActiveFinder extends \yii\base\Object
...
@@ -406,7 +350,7 @@ class ActiveFinder extends \yii\base\Object
$prefix
=
$element
->
query
->
tableAlias
;
$prefix
=
$element
->
query
->
tableAlias
;
if
(
empty
(
$select
)
||
$select
===
'*'
)
{
if
(
empty
(
$select
)
||
$select
===
'*'
)
{
foreach
(
$table
->
columns
as
$column
)
{
foreach
(
$table
->
columns
as
$column
)
{
$alias
=
"
t
{
$element
->
id
}
c
"
.
(
$columnCount
++
);
$alias
=
"
c
{
$element
->
id
}
_
"
.
(
$columnCount
++
);
$columns
[]
=
"
$prefix
.
{
$column
->
name
}
AS
$alias
"
;
$columns
[]
=
"
$prefix
.
{
$column
->
name
}
AS
$alias
"
;
$element
->
columnAliases
[
$alias
]
=
$column
->
name
;
$element
->
columnAliases
[
$alias
]
=
$column
->
name
;
if
(
$column
->
isPrimaryKey
)
{
if
(
$column
->
isPrimaryKey
)
{
...
@@ -418,7 +362,7 @@ class ActiveFinder extends \yii\base\Object
...
@@ -418,7 +362,7 @@ class ActiveFinder extends \yii\base\Object
$select
=
explode
(
','
,
$select
);
$select
=
explode
(
','
,
$select
);
}
}
foreach
(
$table
->
primaryKey
as
$column
)
{
foreach
(
$table
->
primaryKey
as
$column
)
{
$alias
=
"
t
{
$element
->
id
}
c
"
.
(
$columnCount
++
);
$alias
=
"
c
{
$element
->
id
}
_
"
.
(
$columnCount
++
);
$columns
[]
=
"
$prefix
.
$column
AS
$alias
"
;
$columns
[]
=
"
$prefix
.
$column
AS
$alias
"
;
$element
->
pkAlias
[
$column
]
=
$alias
;
$element
->
pkAlias
[
$column
]
=
$alias
;
}
}
...
@@ -429,7 +373,7 @@ class ActiveFinder extends \yii\base\Object
...
@@ -429,7 +373,7 @@ class ActiveFinder extends \yii\base\Object
$element
->
columnAliases
[
$matches
[
2
]]
=
$matches
[
2
];
$element
->
columnAliases
[
$matches
[
2
]]
=
$matches
[
2
];
$columns
[]
=
$column
;
$columns
[]
=
$column
;
}
elseif
(
!
isset
(
$element
->
pkAlias
[
$column
]))
{
}
elseif
(
!
isset
(
$element
->
pkAlias
[
$column
]))
{
$alias
=
"
t
{
$element
->
id
}
c
"
.
(
$columnCount
++
);
$alias
=
"
c
{
$element
->
id
}
_
"
.
(
$columnCount
++
);
$columns
[]
=
"
$prefix
.
$column
AS
$alias
"
;
$columns
[]
=
"
$prefix
.
$column
AS
$alias
"
;
$element
->
columnAliases
[
$alias
]
=
$column
;
$element
->
columnAliases
[
$alias
]
=
$column
;
}
}
...
@@ -438,4 +382,4 @@ class ActiveFinder extends \yii\base\Object
...
@@ -438,4 +382,4 @@ class ActiveFinder extends \yii\base\Object
return
$columns
;
return
$columns
;
}
}
}
}
\ No newline at end of file
framework/db/ar/ActiveQuery.php
View file @
d794a813
...
@@ -243,10 +243,6 @@ class ActiveQuery extends BaseActiveQuery implements \IteratorAggregate, \ArrayA
...
@@ -243,10 +243,6 @@ class ActiveQuery extends BaseActiveQuery implements \IteratorAggregate, \ArrayA
protected
function
findRecords
()
protected
function
findRecords
()
{
{
$finder
=
new
ActiveFinder
(
$this
->
getDbConnection
());
$finder
=
new
ActiveFinder
(
$this
->
getDbConnection
());
if
(
!
empty
(
$this
->
with
))
{
return
$finder
->
findRecords
(
$this
);
return
$finder
->
findRecordsWithRelations
(
$this
);
}
else
{
return
$finder
->
findRecords
(
$this
);
}
}
}
}
}
framework/db/ar/JoinElement.php
View file @
d794a813
...
@@ -49,9 +49,10 @@ class JoinElement extends \yii\base\Object
...
@@ -49,9 +49,10 @@ class JoinElement extends \yii\base\Object
public
$relatedRecords
;
public
$relatedRecords
;
/**
/**
* @param integer $id
* @param ActiveRelation|ActiveQuery $query
* @param ActiveRelation|ActiveQuery $query
* @param JoinElement $parent
* @param
null|
JoinElement $parent
* @param JoinElement $container
* @param
null|
JoinElement $container
*/
*/
public
function
__construct
(
$id
,
$query
,
$parent
,
$container
)
public
function
__construct
(
$id
,
$query
,
$parent
,
$container
)
{
{
...
@@ -70,15 +71,24 @@ class JoinElement extends \yii\base\Object
...
@@ -70,15 +71,24 @@ class JoinElement extends \yii\base\Object
*/
*/
public
function
createRecord
(
$row
)
public
function
createRecord
(
$row
)
{
{
$pk
=
array
();
if
(
$this
->
query
->
indexBy
===
null
)
{
foreach
(
$this
->
pkAlias
as
$alias
)
{
$pk
=
array
();
if
(
isset
(
$row
[
$alias
]))
{
foreach
(
$this
->
pkAlias
as
$alias
)
{
$pk
[]
=
$row
[
$alias
];
if
(
isset
(
$row
[
$alias
]))
{
$pk
[]
=
$row
[
$alias
];
}
else
{
return
null
;
}
}
$pk
=
count
(
$pk
)
===
1
?
$pk
[
0
]
:
serialize
(
$pk
);
}
else
{
$pk
=
array_search
(
$this
->
query
->
indexBy
,
$this
->
columnAliases
);
if
(
$pk
!==
false
)
{
$pk
=
$row
[
$pk
];
}
else
{
}
else
{
return
null
;
throw
new
Exception
(
"Invalid indexBy:
{
$this
->
query
->
modelClass
}
has no attribute named '
{
$this
->
query
->
indexBy
}
'."
)
;
}
}
}
}
$pk
=
count
(
$pk
)
===
1
?
$pk
[
0
]
:
serialize
(
$pk
);
// create record
// create record
if
(
isset
(
$this
->
records
[
$pk
]))
{
if
(
isset
(
$this
->
records
[
$pk
]))
{
...
@@ -125,111 +135,4 @@ class JoinElement extends \yii\base\Object
...
@@ -125,111 +135,4 @@ class JoinElement extends \yii\base\Object
return
$record
;
return
$record
;
}
}
public
function
buildQuery
(
$query
)
{
$prefixes
=
array
(
'@.'
=>
$this
->
query
->
tableAlias
.
'.'
,
'?.'
=>
$this
->
parent
->
query
->
tableAlias
.
'.'
,
);
$quotedPrefixes
=
''
;
foreach
(
$this
->
buildSelect
(
$this
->
query
->
select
)
as
$column
)
{
$query
->
select
[]
=
strtr
(
$column
,
$prefixes
);
}
if
(
$this
->
query
->
where
!==
null
)
{
$query
->
where
[]
=
strtr
(
$this
->
query
->
where
,
$prefixes
);
}
if
(
$this
->
query
->
having
!==
null
)
{
$query
->
having
[]
=
strtr
(
$this
->
query
->
having
,
$prefixes
);
}
if
(
$this
->
query
->
via
!==
null
)
{
$query
->
join
[]
=
$this
->
query
->
via
;
}
$modelClass
=
$this
->
query
->
modelClass
;
$tableName
=
$modelClass
::
tableName
();
$joinType
=
$this
->
query
->
joinType
===
null
?
'LEFT JOIN'
:
$this
->
query
->
joinType
;
$join
=
"
$joinType
$tableName
{
$this
->
query
->
tableAlias
}
"
;
if
(
$this
->
query
->
on
!==
null
)
{
$join
.=
' ON '
.
strtr
(
$this
->
query
->
on
,
$prefixes
);
}
$query
->
join
[]
=
$join
;
if
(
$this
->
query
->
join
!==
null
)
{
$query
->
join
[]
=
strtr
(
$this
->
query
->
join
,
$prefixes
);
}
// todo: convert orderBy to array first
if
(
$this
->
query
->
orderBy
!==
null
)
{
$query
->
orderBy
[]
=
strtr
(
$this
->
query
->
orderBy
,
$prefixes
);
}
// todo: convert groupBy to array first
if
(
$this
->
query
->
groupBy
!==
null
)
{
$query
->
groupBy
[]
=
strtr
(
$this
->
query
->
groupBy
,
$prefixes
);
}
if
(
$this
->
query
->
params
!==
null
)
{
foreach
(
$this
->
query
->
params
as
$name
=>
$value
)
{
if
(
is_integer
(
$name
))
{
$query
->
params
[]
=
$value
;
}
else
{
$query
->
params
[
$name
]
=
$value
;
}
}
}
foreach
(
$this
->
children
as
$child
)
{
$child
->
buildQuery
(
$query
);
}
}
public
function
buildSelect
(
$select
)
{
if
(
$select
===
false
)
{
return
array
();
}
$modelClass
=
$this
->
query
->
modelClass
;
$table
=
$modelClass
::
getMetaData
()
->
table
;
$columns
=
array
();
$columnCount
=
0
;
$prefix
=
$this
->
query
->
tableAlias
;
if
(
empty
(
$select
)
||
$select
===
'*'
)
{
foreach
(
$table
->
columns
as
$column
)
{
$alias
=
"t
{
$this
->
id
}
c"
.
(
$columnCount
++
);
$columns
[]
=
"
$prefix
.
{
$column
->
name
}
AS
$alias
"
;
$this
->
columnAliases
[
$alias
]
=
$column
->
name
;
if
(
$column
->
isPrimaryKey
)
{
$this
->
pkAlias
[
$column
->
name
]
=
$alias
;
}
}
}
else
{
if
(
is_string
(
$select
))
{
$select
=
explode
(
','
,
$select
);
}
foreach
(
$table
->
primaryKey
as
$column
)
{
$alias
=
"t
{
$this
->
id
}
c"
.
(
$columnCount
++
);
$columns
[]
=
"
$prefix
.
$column
AS
$alias
"
;
$this
->
pkAlias
[
$column
]
=
$alias
;
}
foreach
(
$select
as
$column
)
{
$column
=
trim
(
$column
);
if
(
preg_match
(
'/^(.*?)\s+AS\s+(\w+)$/im'
,
$column
,
$matches
))
{
// if the column is already aliased
$this
->
columnAliases
[
$matches
[
2
]]
=
$matches
[
2
];
$columns
[]
=
$column
;
}
elseif
(
!
isset
(
$this
->
pkAlias
[
$column
]))
{
$alias
=
"t
{
$this
->
id
}
c"
.
(
$columnCount
++
);
$columns
[]
=
"
$prefix
.
$column
AS
$alias
"
;
$this
->
columnAliases
[
$alias
]
=
$column
;
}
}
}
return
$columns
;
}
}
}
\ No newline at end of file
framework/db/dao/Command.php
View file @
d794a813
...
@@ -355,7 +355,7 @@ class Command extends \yii\base\Component
...
@@ -355,7 +355,7 @@ class Command extends \yii\base\Component
}
}
\Yii
::
trace
(
"Querying SQL:
{
$sql
}{
$paramLog
}
"
,
__CLASS__
);
\Yii
::
trace
(
"Querying SQL:
{
$sql
}{
$paramLog
}
"
,
__CLASS__
);
echo
$sql
.
"
\n\n
"
;
if
(
$db
->
queryCachingCount
>
0
&&
$db
->
queryCachingDuration
>=
0
&&
$method
!==
''
)
{
if
(
$db
->
queryCachingCount
>
0
&&
$db
->
queryCachingDuration
>=
0
&&
$method
!==
''
)
{
$cache
=
\Yii
::
$application
->
getComponent
(
$db
->
queryCacheID
);
$cache
=
\Yii
::
$application
->
getComponent
(
$db
->
queryCacheID
);
}
}
...
...
framework/db/dao/QueryBuilder.php
View file @
d794a813
...
@@ -43,7 +43,7 @@ class QueryBuilder extends \yii\base\Object
...
@@ -43,7 +43,7 @@ class QueryBuilder extends \yii\base\Object
*/
*/
public
$typeMap
=
array
();
public
$typeMap
=
array
();
/**
/**
* @var Query the Query object that is currently processed by the query builder to generate a SQL statement.
* @var Query the Query object that is currently
being
processed by the query builder to generate a SQL statement.
*/
*/
public
$query
;
public
$query
;
...
@@ -63,17 +63,16 @@ class QueryBuilder extends \yii\base\Object
...
@@ -63,17 +63,16 @@ class QueryBuilder extends \yii\base\Object
*/
*/
public
function
build
(
$query
)
public
function
build
(
$query
)
{
{
$this
->
query
=
$query
;
$clauses
=
array
(
$clauses
=
array
(
$this
->
buildSelect
(),
$this
->
buildSelect
(
$query
->
select
,
$query
->
distinct
,
$query
->
selectOption
),
$this
->
buildFrom
(),
$this
->
buildFrom
(
$query
->
from
),
$this
->
buildJoin
(),
$this
->
buildJoin
(
$query
->
join
),
$this
->
buildWhere
(),
$this
->
buildWhere
(
$query
->
where
),
$this
->
buildGroupBy
(),
$this
->
buildGroupBy
(
$query
->
groupBy
),
$this
->
buildHaving
(),
$this
->
buildHaving
(
$query
->
having
),
$this
->
buildUnion
(),
$this
->
buildUnion
(
$query
->
union
),
$this
->
buildOrderBy
(),
$this
->
buildOrderBy
(
$query
->
orderBy
),
$this
->
buildLimit
(),
$this
->
buildLimit
(
$query
->
limit
,
$query
->
offset
),
);
);
return
implode
(
$this
->
separator
,
array_filter
(
$clauses
));
return
implode
(
$this
->
separator
,
array_filter
(
$clauses
));
}
}
...
@@ -161,7 +160,7 @@ class QueryBuilder extends \yii\base\Object
...
@@ -161,7 +160,7 @@ class QueryBuilder extends \yii\base\Object
$this
->
query
->
addParams
(
$params
);
$this
->
query
->
addParams
(
$params
);
}
}
$sql
=
'UPDATE '
.
$this
->
quoteTableName
(
$table
)
.
' SET '
.
implode
(
', '
,
$lines
);
$sql
=
'UPDATE '
.
$this
->
quoteTableName
(
$table
)
.
' SET '
.
implode
(
', '
,
$lines
);
if
((
$where
=
$this
->
buildCondition
(
$condition
))
!=
''
)
{
if
((
$where
=
$this
->
buildCondition
(
$condition
))
!=
=
''
)
{
$sql
.=
' WHERE '
.
$where
;
$sql
.=
' WHERE '
.
$where
;
}
}
...
@@ -185,7 +184,7 @@ class QueryBuilder extends \yii\base\Object
...
@@ -185,7 +184,7 @@ class QueryBuilder extends \yii\base\Object
public
function
delete
(
$table
,
$condition
=
''
,
$params
=
array
())
public
function
delete
(
$table
,
$condition
=
''
,
$params
=
array
())
{
{
$sql
=
'DELETE FROM '
.
$this
->
quoteTableName
(
$table
);
$sql
=
'DELETE FROM '
.
$this
->
quoteTableName
(
$table
);
if
((
$where
=
$this
->
buildCondition
(
$condition
))
!=
''
)
{
if
((
$where
=
$this
->
buildCondition
(
$condition
))
!=
=
''
)
{
$sql
.=
' WHERE '
.
$where
;
$sql
.=
' WHERE '
.
$where
;
}
}
if
(
$params
!==
array
()
&&
$this
->
query
instanceof
BaseQuery
)
{
if
(
$params
!==
array
()
&&
$this
->
query
instanceof
BaseQuery
)
{
...
@@ -620,16 +619,18 @@ class QueryBuilder extends \yii\base\Object
...
@@ -620,16 +619,18 @@ class QueryBuilder extends \yii\base\Object
}
}
/**
/**
* @param string|array $columns
* @param boolean $distinct
* @param string $selectOption
* @return string the SELECT clause built from [[query]].
* @return string the SELECT clause built from [[query]].
*/
*/
p
rotected
function
buildSelect
(
)
p
ublic
function
buildSelect
(
$columns
,
$distinct
=
false
,
$selectOption
=
null
)
{
{
$select
=
$
this
->
query
->
distinct
?
'SELECT DISTINCT'
:
'SELECT'
;
$select
=
$distinct
?
'SELECT DISTINCT'
:
'SELECT'
;
if
(
$
this
->
query
->
selectOption
!==
null
)
{
if
(
$selectOption
!==
null
)
{
$select
.=
' '
.
$
this
->
query
->
selectOption
;
$select
.=
' '
.
$selectOption
;
}
}
$columns
=
$this
->
query
->
select
;
if
(
empty
(
$columns
))
{
if
(
empty
(
$columns
))
{
return
$select
.
' *'
;
return
$select
.
' *'
;
}
}
...
@@ -664,16 +665,15 @@ class QueryBuilder extends \yii\base\Object
...
@@ -664,16 +665,15 @@ class QueryBuilder extends \yii\base\Object
}
}
/**
/**
* @param string|array $tables
* @return string the FROM clause built from [[query]].
* @return string the FROM clause built from [[query]].
*/
*/
p
rotected
function
buildFrom
(
)
p
ublic
function
buildFrom
(
$tables
)
{
{
if
(
empty
(
$t
his
->
query
->
from
))
{
if
(
empty
(
$t
ables
))
{
return
''
;
return
''
;
}
}
$tables
=
$this
->
query
->
from
;
if
(
$this
->
autoQuote
)
{
if
(
$this
->
autoQuote
)
{
$driver
=
$this
->
connection
->
driver
;
$driver
=
$this
->
connection
->
driver
;
if
(
!
is_array
(
$tables
))
{
if
(
!
is_array
(
$tables
))
{
...
@@ -702,11 +702,11 @@ class QueryBuilder extends \yii\base\Object
...
@@ -702,11 +702,11 @@ class QueryBuilder extends \yii\base\Object
}
}
/**
/**
* @param string|array $joins
* @return string the JOIN clause built from [[query]].
* @return string the JOIN clause built from [[query]].
*/
*/
p
rotected
function
buildJoin
(
)
p
ublic
function
buildJoin
(
$joins
)
{
{
$joins
=
$this
->
query
->
join
;
if
(
empty
(
$joins
))
{
if
(
empty
(
$joins
))
{
return
''
;
return
''
;
}
}
...
@@ -715,7 +715,7 @@ class QueryBuilder extends \yii\base\Object
...
@@ -715,7 +715,7 @@ class QueryBuilder extends \yii\base\Object
}
}
foreach
(
$joins
as
$i
=>
$join
)
{
foreach
(
$joins
as
$i
=>
$join
)
{
if
(
is_array
(
$join
))
{
//
join type, table name,
on-condition
if
(
is_array
(
$join
))
{
//
0:join type, 1:table name, 2:
on-condition
if
(
isset
(
$join
[
0
],
$join
[
1
]))
{
if
(
isset
(
$join
[
0
],
$join
[
1
]))
{
$table
=
$join
[
1
];
$table
=
$join
[
1
];
if
(
$this
->
autoQuote
&&
strpos
(
$table
,
'('
)
===
false
)
{
if
(
$this
->
autoQuote
&&
strpos
(
$table
,
'('
)
===
false
)
{
...
@@ -743,44 +743,47 @@ class QueryBuilder extends \yii\base\Object
...
@@ -743,44 +743,47 @@ class QueryBuilder extends \yii\base\Object
}
}
/**
/**
* @param string|array $condition
* @return string the WHERE clause built from [[query]].
* @return string the WHERE clause built from [[query]].
*/
*/
p
rotected
function
buildWhere
(
)
p
ublic
function
buildWhere
(
$condition
)
{
{
$where
=
$this
->
buildCondition
(
$
this
->
query
->
where
);
$where
=
$this
->
buildCondition
(
$
condition
);
return
empty
(
$where
)
?
''
:
'WHERE '
.
$where
;
return
$where
===
''
?
''
:
'WHERE '
.
$where
;
}
}
/**
/**
* @return string the GROUP BY clause built from [[query]].
* @param string|array $columns
* @return string the GROUP BY clause
*/
*/
p
rotected
function
buildGroupBy
(
)
p
ublic
function
buildGroupBy
(
$columns
)
{
{
if
(
empty
(
$
this
->
query
->
groupBy
))
{
if
(
empty
(
$
columns
))
{
return
''
;
return
''
;
}
else
{
}
else
{
return
'GROUP BY '
.
$this
->
buildColumns
(
$
this
->
query
->
groupBy
);
return
'GROUP BY '
.
$this
->
buildColumns
(
$
columns
);
}
}
}
}
/**
/**
* @param string|array $condition
* @return string the HAVING clause built from [[query]].
* @return string the HAVING clause built from [[query]].
*/
*/
p
rotected
function
buildHaving
(
)
p
ublic
function
buildHaving
(
$condition
)
{
{
$having
=
$this
->
buildCondition
(
$
this
->
query
->
having
);
$having
=
$this
->
buildCondition
(
$
condition
);
return
empty
(
$having
)
?
''
:
'HAVING '
.
$having
;
return
$having
===
''
?
''
:
'HAVING '
.
$having
;
}
}
/**
/**
* @param string|array $columns
* @return string the ORDER BY clause built from [[query]].
* @return string the ORDER BY clause built from [[query]].
*/
*/
p
rotected
function
buildOrderBy
(
)
p
ublic
function
buildOrderBy
(
$columns
)
{
{
if
(
empty
(
$
this
->
query
->
orderBy
))
{
if
(
empty
(
$
columns
))
{
return
''
;
return
''
;
}
}
$columns
=
$this
->
query
->
orderBy
;
if
(
$this
->
autoQuote
)
{
if
(
$this
->
autoQuote
)
{
$driver
=
$this
->
connection
->
driver
;
$driver
=
$this
->
connection
->
driver
;
if
(
!
is_array
(
$columns
))
{
if
(
!
is_array
(
$columns
))
{
...
@@ -809,26 +812,28 @@ class QueryBuilder extends \yii\base\Object
...
@@ -809,26 +812,28 @@ class QueryBuilder extends \yii\base\Object
}
}
/**
/**
* @param integer $limit
* @param integer $offset
* @return string the LIMIT and OFFSET clauses built from [[query]].
* @return string the LIMIT and OFFSET clauses built from [[query]].
*/
*/
p
rotected
function
buildLimit
(
)
p
ublic
function
buildLimit
(
$limit
,
$offset
)
{
{
$sql
=
''
;
$sql
=
''
;
if
(
$
this
->
query
->
limit
!==
null
&&
$this
->
query
->
limit
>=
0
)
{
if
(
$
limit
!==
null
&&
$
limit
>=
0
)
{
$sql
=
'LIMIT '
.
(
int
)
$
this
->
query
->
limit
;
$sql
=
'LIMIT '
.
(
int
)
$limit
;
}
}
if
(
$
this
->
query
->
offset
>
0
)
{
if
(
$offset
>
0
)
{
$sql
.=
' OFFSET '
.
(
int
)
$
this
->
query
->
offset
;
$sql
.=
' OFFSET '
.
(
int
)
$offset
;
}
}
return
ltrim
(
$sql
);
return
ltrim
(
$sql
);
}
}
/**
/**
* @param string|array $unions
* @return string the UNION clause built from [[query]].
* @return string the UNION clause built from [[query]].
*/
*/
p
rotected
function
buildUnion
(
)
p
ublic
function
buildUnion
(
$unions
)
{
{
$unions
=
$this
->
query
->
union
;
if
(
empty
(
$unions
))
{
if
(
empty
(
$unions
))
{
return
''
;
return
''
;
}
}
...
@@ -836,8 +841,8 @@ class QueryBuilder extends \yii\base\Object
...
@@ -836,8 +841,8 @@ class QueryBuilder extends \yii\base\Object
$unions
=
array
(
$unions
);
$unions
=
array
(
$unions
);
}
}
foreach
(
$unions
as
$i
=>
$union
)
{
foreach
(
$unions
as
$i
=>
$union
)
{
if
(
$union
instanceof
Query
)
{
if
(
$union
instanceof
Base
Query
)
{
$unions
[
$i
]
=
$
union
->
getSql
(
$this
->
connect
ion
);
$unions
[
$i
]
=
$
this
->
build
(
$un
ion
);
}
}
}
}
return
"UNION (
\n
"
.
implode
(
"
\n
) UNION (
\n
"
,
$unions
)
.
"
\n
)"
;
return
"UNION (
\n
"
.
implode
(
"
\n
) UNION (
\n
"
,
$unions
)
.
"
\n
)"
;
...
...
tests/unit/framework/db/ar/ActiveRecordTest.php
View file @
d794a813
...
@@ -219,17 +219,18 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
...
@@ -219,17 +219,18 @@ class ActiveRecordTest extends \yiiunit\MysqlTestCase
// indexBy
// indexBy
$customers
=
Customer
::
find
()
->
orderBy
(
'id'
)
->
indexBy
(
'name'
)
->
all
();
$customers
=
Customer
::
find
()
->
orderBy
(
'id'
)
->
indexBy
(
'name'
)
->
all
();
$this
->
assertEquals
(
2
,
$customers
[
'user2'
][
'id'
]);
}
}
public
function
testEagerLoading
()
public
function
testEagerLoading
()
{
{
$customers
=
Customer
::
find
()
->
with
(
'orders'
)
->
orderBy
(
'
t0
.id'
)
->
all
();
$customers
=
Customer
::
find
()
->
with
(
'orders'
)
->
orderBy
(
'
@
.id'
)
->
all
();
$this
->
assertEquals
(
3
,
count
(
$customers
));
$this
->
assertEquals
(
3
,
count
(
$customers
));
$this
->
assertEquals
(
1
,
count
(
$customers
[
0
]
->
orders
));
$this
->
assertEquals
(
1
,
count
(
$customers
[
0
]
->
orders
));
$this
->
assertEquals
(
2
,
count
(
$customers
[
1
]
->
orders
));
$this
->
assertEquals
(
2
,
count
(
$customers
[
1
]
->
orders
));
$this
->
assertEquals
(
0
,
count
(
$customers
[
2
]
->
orders
));
$this
->
assertEquals
(
0
,
count
(
$customers
[
2
]
->
orders
));
$customers
=
Customer
::
find
()
->
with
(
'orders.customer'
)
->
orderBy
(
'
t0
.id'
)
->
all
();
$customers
=
Customer
::
find
()
->
with
(
'orders.customer'
)
->
orderBy
(
'
@
.id'
)
->
all
();
}
}
/*
/*
...
...
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