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
ba4f1555
Commit
ba4f1555
authored
Dec 15, 2015
by
Bill Schaller
Committed by
Steve Müller
Dec 15, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Resolved @todo to allow ORDER BY in TOP N subquery with SQL Server 2008 doModifyLimitQuery
parent
ccc2287e
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
54 additions
and
4 deletions
+54
-4
SQLServerPlatform.php
lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php
+54
-4
No files found.
lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php
View file @
ba4f1555
...
@@ -1183,7 +1183,7 @@ class SQLServerPlatform extends AbstractPlatform
...
@@ -1183,7 +1183,7 @@ class SQLServerPlatform extends AbstractPlatform
$start
=
$offset
+
1
;
$start
=
$offset
+
1
;
$end
=
$offset
+
$limit
;
$end
=
$offset
+
$limit
;
// We'll find a SELECT or SELECT distinct and
ap
pend TOP n to it
// We'll find a SELECT or SELECT distinct and
pre
pend TOP n to it
// Even if the TOP n is very large, the use of a CTE will
// Even if the TOP n is very large, the use of a CTE will
// allow the SQL Server query planner to optimize it so it doesn't
// allow the SQL Server query planner to optimize it so it doesn't
// actually scan the entire range covered by the TOP clause.
// actually scan the entire range covered by the TOP clause.
...
@@ -1193,7 +1193,7 @@ class SQLServerPlatform extends AbstractPlatform
...
@@ -1193,7 +1193,7 @@ class SQLServerPlatform extends AbstractPlatform
if
(
stristr
(
$query
,
"ORDER BY"
))
{
if
(
stristr
(
$query
,
"ORDER BY"
))
{
// Inner order by is not valid in SQL Server for our purposes
// Inner order by is not valid in SQL Server for our purposes
//
TODO throw DBALException here?
//
unless it's in a TOP N subquery.
$query
=
$this
->
scrubInnerOrderBy
(
$query
);
$query
=
$this
->
scrubInnerOrderBy
(
$query
);
}
}
...
@@ -1212,19 +1212,21 @@ class SQLServerPlatform extends AbstractPlatform
...
@@ -1212,19 +1212,21 @@ class SQLServerPlatform extends AbstractPlatform
/**
/**
* Remove ORDER BY clauses in subqueries - they're not supported by SQL Server.
* Remove ORDER BY clauses in subqueries - they're not supported by SQL Server.
* Caveat: will leave ORDER BY in TOP N subqueries.
*
*
* @param $query
* @param $query
* @return string
* @return string
*
*
* @todo allow ORDER BY clauses in subqueries that have TOP n, as that is ok.
*/
*/
private
function
scrubInnerOrderBy
(
$query
)
{
private
function
scrubInnerOrderBy
(
$query
)
{
$count
=
substr_count
(
strtoupper
(
$query
),
"ORDER BY"
);
$count
=
substr_count
(
strtoupper
(
$query
),
"ORDER BY"
);
$offset
=
0
;
while
(
$count
--
>
0
)
{
while
(
$count
--
>
0
)
{
$qLen
=
strlen
(
$query
);
$qLen
=
strlen
(
$query
);
$orderByPos
=
stripos
(
$query
,
" ORDER BY"
);
$orderByPos
=
stripos
(
$query
,
" ORDER BY"
,
$offset
);
$parenCount
=
0
;
$parenCount
=
0
;
$currentPosition
=
$orderByPos
;
$currentPosition
=
$orderByPos
;
while
(
$parenCount
>=
0
&&
$currentPosition
<
$qLen
)
{
while
(
$parenCount
>=
0
&&
$currentPosition
<
$qLen
)
{
if
(
$query
[
$currentPosition
]
==
'('
)
{
if
(
$query
[
$currentPosition
]
==
'('
)
{
$parenCount
++
;
$parenCount
++
;
...
@@ -1234,13 +1236,61 @@ class SQLServerPlatform extends AbstractPlatform
...
@@ -1234,13 +1236,61 @@ class SQLServerPlatform extends AbstractPlatform
$currentPosition
++
;
$currentPosition
++
;
}
}
if
(
$this
->
isOrderByInTopNSubquery
(
$query
,
$orderByPos
))
{
// If the order by clause is in a TOP N subquery, do not remove
// it and continue iteration from the current position.
$offset
=
$currentPosition
;
continue
;
}
if
(
$currentPosition
<
$qLen
-
1
)
{
if
(
$currentPosition
<
$qLen
-
1
)
{
$query
=
substr
(
$query
,
0
,
$orderByPos
)
.
substr
(
$query
,
$currentPosition
-
1
);
$query
=
substr
(
$query
,
0
,
$orderByPos
)
.
substr
(
$query
,
$currentPosition
-
1
);
$offset
=
$orderByPos
;
}
}
}
}
return
$query
;
return
$query
;
}
}
/**
* Check an ORDER BY clause to see if it is in a TOP N query or subquery.
*
* @param string $query The query
* @param int $currentPosition Start position of ORDER BY clause
* @return bool true if ORDER BY is in a TOP N query, false otherwise
*/
private
function
isOrderByInTopNSubquery
(
$query
,
$currentPosition
)
{
// Grab query text on the same nesting level as the ORDER BY clause we're examining.
$subQueryBuffer
=
''
;
$parenCount
=
0
;
// If $parentCount goes negative, we've exited the subquery we're examining.
// If $currentPosition goes negative, we've reached the beginning of the query.
while
(
$parenCount
>=
0
&&
$currentPosition
>=
0
)
{
if
(
$query
[
$currentPosition
]
==
'('
)
{
$parenCount
--
;
}
if
(
$query
[
$currentPosition
]
==
')'
)
{
$parenCount
++
;
}
if
(
$parenCount
===
0
)
{
// Only yank query text on the same nesting level as the ORDER BY clause.
$subQueryBuffer
=
$query
[
$currentPosition
]
.
$subQueryBuffer
;
}
else
{
$subQueryBuffer
=
" "
.
$subQueryBuffer
;
}
$currentPosition
--
;
}
if
(
preg_match
(
'/SELECT\s+TOP\s/'
,
$subQueryBuffer
))
{
return
true
;
}
return
false
;
}
/**
/**
* {@inheritDoc}
* {@inheritDoc}
*/
*/
...
...
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