Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
doctrine-dbal
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
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
Tomáš Trávníček
doctrine-dbal
Commits
7359ee0e
Commit
7359ee0e
authored
Sep 12, 2007
by
zYne
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
DQL expression handling rewrite
parent
5fba56bb
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
178 additions
and
96 deletions
+178
-96
Query.php
lib/Doctrine/Query.php
+178
-96
No files found.
lib/Doctrine/Query.php
View file @
7359ee0e
...
@@ -54,18 +54,18 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
...
@@ -54,18 +54,18 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
protected
$isLimitSubqueryUsed
=
false
;
protected
$isLimitSubqueryUsed
=
false
;
/**
/**
* @var array $_neededTable
Aliases
an array containing the needed table aliases
* @var array $_neededTable
s
an array containing the needed table aliases
*/
*/
protected
$_neededTables
=
array
();
protected
$_neededTables
=
array
();
/**
* @var array $pendingFields
*/
protected
$pendingFields
=
array
();
/**
/**
* @var array $pendingSubqueries SELECT part subqueries, these are called pending subqueries since
* @var array $pendingSubqueries SELECT part subqueries, these are called pending subqueries since
* they cannot be parsed directly (some queries might be correlated)
* they cannot be parsed directly (some queries might be correlated)
*/
*/
protected
$pendingSubqueries
=
array
();
protected
$pendingSubqueries
=
array
();
/**
* @var array $pendingFields
*/
protected
$pendingFields
=
array
();
/**
/**
* @var array $_parsers an array of parser objects, each DQL query part has its own parser
* @var array $_parsers an array of parser objects, each DQL query part has its own parser
*/
*/
...
@@ -79,9 +79,9 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
...
@@ -79,9 +79,9 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
* @var array $_dqlParts an array containing all DQL query parts
* @var array $_dqlParts an array containing all DQL query parts
*/
*/
protected
$_dqlParts
=
array
(
protected
$_dqlParts
=
array
(
'from'
=>
array
(),
'select'
=>
array
(),
'select'
=>
array
(),
'forUpdate'
=>
false
,
'forUpdate'
=>
false
,
'from'
=>
array
(),
'set'
=>
array
(),
'set'
=>
array
(),
'join'
=>
array
(),
'join'
=>
array
(),
'where'
=>
array
(),
'where'
=>
array
(),
...
@@ -372,22 +372,91 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
...
@@ -372,22 +372,91 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
if
(
in_array
(
'*'
,
$fields
))
{
if
(
in_array
(
'*'
,
$fields
))
{
$fields
=
$table
->
getColumnNames
();
$fields
=
$table
->
getColumnNames
();
}
else
{
}
else
{
// only auto-add the primary key fields if this query object is not
// only auto-add the primary key fields if this query object is not
// a subquery of another query object
// a subquery of another query object
if
(
!
$this
->
isSubquery
)
{
if
(
!
$this
->
isSubquery
)
{
$fields
=
array_unique
(
array_merge
(
$table
->
getPrimaryKeys
(),
$fields
));
$fields
=
array_unique
(
array_merge
(
$table
->
getPrimaryKeys
(),
$fields
));
}
}
}
}
}
$sql
=
array
();
foreach
(
$fields
as
$name
)
{
foreach
(
$fields
as
$name
)
{
$name
=
$table
->
getColumnName
(
$name
);
$name
=
$table
->
getColumnName
(
$name
);
$sql
[]
=
$this
->
_conn
->
quoteIdentifier
(
$tableAlias
.
'.'
.
$name
)
.
' AS '
.
$this
->
_conn
->
quoteIdentifier
(
$tableAlias
.
'__'
.
$name
);
}
$this
->
_neededTables
[]
=
$tableAlias
;
$this
->
parts
[
'select'
][]
=
$this
->
_conn
->
quoteIdentifier
(
$tableAlias
.
'.'
.
$name
)
return
implode
(
', '
,
$sql
);
.
' AS '
.
$this
->
_conn
->
quoteIdentifier
(
$tableAlias
.
'__'
.
$name
);
}
}
}
/**
* parseSelectField
*
* @throws Doctrine_Query_Exception if unknown component alias has been given
* @return void
*/
public
function
parseSelectField
(
$field
)
{
$terms
=
explode
(
'.'
,
$field
);
$this
->
neededTables
[]
=
$tableAlias
;
if
(
isset
(
$terms
[
1
]))
{
$componentAlias
=
$terms
[
0
];
$field
=
$terms
[
1
];
}
else
{
reset
(
$this
->
_aliasMap
);
$componentAlias
=
key
(
$this
->
_aliasMap
);
$fields
=
$terms
[
0
];
}
$tableAlias
=
$this
->
getTableAlias
(
$componentAlias
);
$table
=
$this
->
_aliasMap
[
$componentAlias
][
'table'
];
// check for wildcards
if
(
$field
===
'*'
)
{
$sql
=
array
();
foreach
(
$table
->
getColumnNames
()
as
$field
)
{
$sql
[]
=
$this
->
parseSelectField
(
$componentAlias
.
'.'
.
$field
);
}
return
implode
(
', '
,
$sql
);
}
else
{
}
$name
=
$table
->
getColumnName
(
$field
);
$this
->
_neededTables
[]
=
$tableAlias
;
return
$this
->
_conn
->
quoteIdentifier
(
$tableAlias
.
'.'
.
$name
)
.
' AS '
.
$this
->
_conn
->
quoteIdentifier
(
$tableAlias
.
'__'
.
$name
);
}
/**
* getExpressionOwner
* returns the component alias for owner of given expression
*
* @param string $expr expression from which to get to owner from
* @return string the component alias
*/
public
function
getExpressionOwner
(
$expr
)
{
if
(
strtoupper
(
substr
(
trim
(
$expr
,
'( '
),
0
,
6
))
!==
'SELECT'
)
{
preg_match_all
(
"/[a-z0-9_]+\.[a-z0-9_]+[\.[a-z0-9]+]*/i"
,
$expr
,
$matches
);
$match
=
current
(
$matches
);
if
(
isset
(
$match
[
0
]))
{
$terms
=
explode
(
'.'
,
$match
[
0
]);
return
$terms
[
0
];
}
}
return
$this
->
getRootAlias
();
}
}
/**
/**
...
@@ -399,62 +468,71 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
...
@@ -399,62 +468,71 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
*/
*/
public
function
parseSelect
(
$dql
)
public
function
parseSelect
(
$dql
)
{
{
$refs
=
Doctrine_Tokenizer
::
bracket
Explode
(
$dql
,
','
);
$refs
=
Doctrine_Tokenizer
::
sql
Explode
(
$dql
,
','
);
$pos
=
strpos
(
trim
(
$refs
[
0
]),
' '
);
$pos
=
strpos
(
trim
(
$refs
[
0
]),
' '
);
$first
=
substr
(
$refs
[
0
],
0
,
$pos
);
$first
=
substr
(
$refs
[
0
],
0
,
$pos
);
// check for DISTINCT keyword
if
(
$first
===
'DISTINCT'
)
{
if
(
$first
===
'DISTINCT'
)
{
$this
->
parts
[
'distinct'
]
=
true
;
$this
->
parts
[
'distinct'
]
=
true
;
$refs
[
0
]
=
substr
(
$refs
[
0
],
++
$pos
);
$refs
[
0
]
=
substr
(
$refs
[
0
],
++
$pos
);
}
}
$parsedComponents
=
array
();
foreach
(
$refs
as
$reference
)
{
foreach
(
$refs
as
$reference
)
{
$reference
=
trim
(
$reference
);
$reference
=
trim
(
$reference
);
if
(
strpos
(
$reference
,
'('
)
!==
false
)
{
if
(
substr
(
$reference
,
0
,
1
)
===
'('
)
{
if
(
empty
(
$reference
))
{
// subselect found in SELECT part
continue
;
$this
->
parseSubselect
(
$reference
);
}
}
else
{
$this
->
parseAggregateFunction
(
$reference
);
$terms
=
Doctrine_Tokenizer
::
sqlExplode
(
$reference
,
' '
);
$pos
=
strpos
(
$terms
[
0
],
'('
);
if
(
count
(
$terms
)
>
1
||
$pos
!==
false
)
{
$expression
=
array_shift
(
$terms
);
$alias
=
array_pop
(
$terms
);
if
(
!
$alias
)
{
$alias
=
substr
(
$expression
,
0
,
$pos
);
}
}
}
else
{
$componentAlias
=
$this
->
getExpressionOwner
(
$expression
);
$expression
=
$this
->
parseClause
(
$expression
);
$tableAlias
=
$this
->
getTableAlias
(
$componentAlias
);
$index
=
count
(
$this
->
aggregateMap
);
$sqlAlias
=
$this
->
_conn
->
quoteIdentifier
(
$tableAlias
.
'__'
.
$index
);
$this
->
parts
[
'select'
][]
=
$expression
.
' AS '
.
$sqlAlias
;
$this
->
aggregateMap
[
$alias
]
=
$sqlAlias
;
$this
->
_expressionMap
[
$alias
][
0
]
=
$expression
;
$this
->
_aliasMap
[
$componentAlias
][
'agg'
][
$index
]
=
$alias
;
$e
=
explode
(
'.'
,
$reference
);
$this
->
_neededTables
[]
=
$tableAlias
;
if
(
count
(
$e
)
>
2
)
{
}
else
{
$this
->
pendingFields
[]
=
$reference
;
$e
=
explode
(
'.'
,
$terms
[
0
]);
if
(
isset
(
$e
[
1
]))
{
$componentAlias
=
$e
[
0
];
$field
=
$e
[
1
];
}
else
{
}
else
{
$this
->
pendingFields
[
$e
[
0
]][]
=
$e
[
1
];
reset
(
$this
->
_aliasMap
);
$componentAlias
=
key
(
$this
->
_aliasMap
);
$field
=
$e
[
0
];
}
}
}
}
}
/**
* parseSubselect
*
* parses the subquery found in DQL SELECT part and adds the
* parsed form into $pendingSubqueries stack
*
* @param string $reference
* @return void
*/
public
function
parseSubselect
(
$reference
)
{
$e
=
Doctrine_Tokenizer
::
bracketExplode
(
$reference
,
' '
);
$alias
=
$e
[
1
];
if
(
count
(
$e
)
>
2
)
{
$this
->
pendingFields
[
$componentAlias
][]
=
$field
;
if
(
strtoupper
(
$e
[
1
])
!==
'AS'
)
{
throw
new
Doctrine_Query_Exception
(
'Syntax error near: '
.
$reference
);
}
}
$alias
=
$e
[
2
];
}
}
$subquery
=
substr
(
$e
[
0
],
1
,
-
1
);
$this
->
pendingSubqueries
[]
=
array
(
$subquery
,
$alias
);
}
}
/**
/**
* parseClause
* parseClause
...
@@ -494,7 +572,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
...
@@ -494,7 +572,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
try
{
try
{
$expr
=
call_user_func_array
(
array
(
$this
->
_conn
->
expression
,
$name
),
$args
);
$expr
=
call_user_func_array
(
array
(
$this
->
_conn
->
expression
,
$name
),
$args
);
}
catch
(
Doctrine_Expression_Exception
$e
)
{
}
catch
(
Doctrine_Expression_Exception
$e
)
{
throw
new
Doctrine_Query_Exception
(
'Unknown function '
.
$
func
.
'.'
);
throw
new
Doctrine_Query_Exception
(
'Unknown function '
.
$
expr
.
'.'
);
}
}
$term
[
0
]
=
$expr
;
$term
[
0
]
=
$expr
;
}
else
{
}
else
{
...
@@ -706,7 +784,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
...
@@ -706,7 +784,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
$this
->
_aliasMap
[
$componentAlias
][
'agg'
][
$index
]
=
$alias
;
$this
->
_aliasMap
[
$componentAlias
][
'agg'
][
$index
]
=
$alias
;
$this
->
neededTables
[]
=
$tableAlias
;
$this
->
_
neededTables
[]
=
$tableAlias
;
}
}
// reset the state
// reset the state
$this
->
pendingAggregates
=
array
();
$this
->
pendingAggregates
=
array
();
...
@@ -755,7 +833,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
...
@@ -755,7 +833,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
$e
=
explode
(
' '
,
$part
);
$e
=
explode
(
' '
,
$part
);
$aliases
=
array_merge
(
$this
->
subqueryAliases
,
$aliases
=
array_merge
(
$this
->
subqueryAliases
,
array_keys
(
$this
->
neededTables
));
array_keys
(
$this
->
_
neededTables
));
if
(
!
in_array
(
$e
[
3
],
$aliases
)
&&
if
(
!
in_array
(
$e
[
3
],
$aliases
)
&&
!
in_array
(
$e
[
2
],
$aliases
)
&&
!
in_array
(
$e
[
2
],
$aliases
)
&&
...
@@ -810,6 +888,37 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
...
@@ -810,6 +888,37 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
public
function
postQuery
()
public
function
postQuery
()
{
{
}
/**
* processQueryPart
* parses given query part
*
* @param string $queryPartName the name of the query part
* @param array $queryParts an array containing the query part data
* @return Doctrine_Query this object
*/
public
function
processQueryPart
(
$queryPartName
,
$queryParts
)
{
$this
->
removeQueryPart
(
$queryPartName
);
if
(
is_array
(
$queryParts
)
&&
!
empty
(
$queryParts
))
{
foreach
(
$queryParts
as
$queryPart
)
{
$parser
=
$this
->
getParser
(
$queryPartName
);
$sql
=
$parser
->
parse
(
$queryPart
);
if
(
isset
(
$sql
))
{
if
(
$queryPartName
==
'limit'
||
$queryPartName
==
'offset'
)
{
$this
->
setQueryPart
(
$queryPartName
,
$sql
);
}
else
{
$this
->
addQueryPart
(
$queryPartName
,
$sql
);
}
}
}
}
}
}
/**
/**
* builds the sql query from the given parameters and applies things such as
* builds the sql query from the given parameters and applies things such as
...
@@ -837,28 +946,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
...
@@ -837,28 +946,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
// parse the DQL parts
// parse the DQL parts
foreach
(
$this
->
_dqlParts
as
$queryPartName
=>
$queryParts
)
{
foreach
(
$this
->
_dqlParts
as
$queryPartName
=>
$queryParts
)
{
$this
->
processQueryPart
(
$queryPartName
,
$queryParts
);
$this
->
removeQueryPart
(
$queryPartName
);
if
(
is_array
(
$queryParts
)
&&
!
empty
(
$queryParts
))
{
foreach
(
$queryParts
as
$queryPart
)
{
$parser
=
$this
->
getParser
(
$queryPartName
);
$sql
=
$parser
->
parse
(
$queryPart
);
if
(
isset
(
$sql
))
{
if
(
$queryPartName
==
'limit'
||
$queryPartName
==
'offset'
)
{
$this
->
setQueryPart
(
$queryPartName
,
$sql
);
}
else
{
$this
->
addQueryPart
(
$queryPartName
,
$sql
);
}
}
}
}
}
}
$params
=
$this
->
convertEnums
(
$params
);
$params
=
$this
->
convertEnums
(
$params
);
...
@@ -885,12 +973,20 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
...
@@ -885,12 +973,20 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
$needsSubQuery
=
true
;
$needsSubQuery
=
true
;
}
}
// process all pending SELECT part subqueries
$sql
=
array
();
$this
->
processPendingSubqueries
();
foreach
(
$this
->
_aliasMap
as
$alias
=>
$map
)
{
$this
->
processPendingAggregates
();
$fieldSql
=
$this
->
processPendingFields
(
$alias
);
if
(
!
empty
(
$fieldSql
))
{
$sql
[]
=
$fieldSql
;
}
}
if
(
!
empty
(
$sql
))
{
array_unshift
(
$this
->
parts
[
'select'
],
implode
(
', '
,
$sql
));
}
$this
->
pendingFields
=
array
();
// build the basic query
// build the basic query
$q
=
$this
->
getQueryBase
();
$q
=
$this
->
getQueryBase
();
$q
.=
$this
->
buildFromPart
();
$q
.=
$this
->
buildFromPart
();
...
@@ -1395,22 +1491,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
...
@@ -1395,22 +1491,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
$restoreState
=
false
;
$restoreState
=
false
;
// load fields if necessary
// load fields if necessary
if
(
$loadFields
&&
empty
(
$this
->
pendingFields
)
if
(
$loadFields
&&
empty
(
$this
->
_dqlParts
[
'select'
]))
{
&&
empty
(
$this
->
pendingAggregates
)
&&
empty
(
$this
->
pendingSubqueries
))
{
$this
->
pendingFields
[
$componentAlias
]
=
array
(
'*'
);
$this
->
pendingFields
[
$componentAlias
]
=
array
(
'*'
);
$restoreState
=
true
;
}
if
(
isset
(
$this
->
pendingFields
[
$componentAlias
]))
{
$this
->
processPendingFields
(
$componentAlias
);
}
if
(
$restoreState
)
{
$this
->
pendingFields
=
array
();
$this
->
pendingAggregates
=
array
();
}
}
}
}
$parent
=
$prevPath
;
$parent
=
$prevPath
;
...
...
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