Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5990625
UnionQueryBuilder.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
UnionQueryBuilder.php
View Options
<?php
namespace
Wikimedia\Rdbms
;
use
Wikimedia\Rdbms\Platform\ISQLPlatform
;
/**
* A query builder for UNION queries takes SelectQueryBuilder objects
*
* Any particular query builder object should only be used for a single database query,
* and not be reused afterwards.
*
* @since 1.41
* @ingroup Database
*/
class
UnionQueryBuilder
{
/** sort the results in ascending order */
public
const
SORT_ASC
=
'ASC'
;
/** sort the results in descending order */
public
const
SORT_DESC
=
'DESC'
;
/**
* @var SelectQueryBuilder[]
*/
private
$sqbs
=
[];
/** @var IDatabase */
private
$db
;
/** @var bool */
private
$all
=
IReadableDatabase
::
UNION_DISTINCT
;
/** @var array */
private
$options
=
[];
/**
* @var string The caller (function name) to be passed to IDatabase::query()
*/
private
$caller
=
__CLASS__
;
/**
* To create a UnionQueryBuilder instance, use `$db->newUnionQueryBuilder()` instead.
*
* @param IDatabase $db
*/
public
function
__construct
(
IDatabase
$db
)
{
$this
->
db
=
$db
;
}
/**
* Add a select query builder object to the list of union
*
* @return $this
*/
public
function
add
(
SelectQueryBuilder
$selectQueryBuilder
)
{
$this
->
sqbs
[]
=
$selectQueryBuilder
;
return
$this
;
}
/**
* Enable UNION_ALL option, the default is UNION_DISTINCT
*
* @return $this
*/
public
function
all
()
{
$this
->
all
=
$this
->
db
::
UNION_ALL
;
return
$this
;
}
/**
* Set the query limit. Return at most this many rows. The rows are sorted
* and then the first rows are taken until the limit is reached. Limit
* is applied to a result set after offset.
*
* If the query builder already has a limit, the old limit will be discarded.
* This would be also ignored if the DB does not support limit in union queries.
*
* @param int $limit
* @return $this
*/
public
function
limit
(
$limit
)
{
if
(
!
$this
->
db
->
unionSupportsOrderAndLimit
()
)
{
return
$this
;
}
$this
->
options
[
'LIMIT'
]
=
$limit
;
return
$this
;
}
/**
* Set the offset. Skip this many rows at the start of the result set. Offset
* with limit() can theoretically be used for paging through a result set,
* but this is discouraged for performance reasons.
*
* If the query builder already has an offset, the old offset will be discarded.
* This would be also ignored if the DB does not support offset in union queries.
*
* @param int $offset
* @return $this
*/
public
function
offset
(
$offset
)
{
if
(
!
$this
->
db
->
unionSupportsOrderAndLimit
()
)
{
return
$this
;
}
$this
->
options
[
'OFFSET'
]
=
$offset
;
return
$this
;
}
/**
* Set the ORDER BY clause. If it has already been set, append the
* additional fields to it.
*
* This would be ignored if the DB does not support order by in union queries.
*
* @param string[]|string $fields The field or list of fields to order by.
* @param-taint $fields exec_sql
* @param string|null $direction self::SORT_ASC or self::SORT_DESC.
* If this is null then $fields is assumed to optionally contain ASC or DESC
* after each field name.
* @param-taint $direction exec_sql
* @return $this
*/
public
function
orderBy
(
$fields
,
$direction
=
null
)
{
if
(
!
$this
->
db
->
unionSupportsOrderAndLimit
()
)
{
return
$this
;
}
if
(
$direction
===
null
)
{
$this
->
mergeOption
(
'ORDER BY'
,
$fields
);
}
elseif
(
is_array
(
$fields
)
)
{
$fieldsWithDirection
=
[];
foreach
(
$fields
as
$field
)
{
$fieldsWithDirection
[]
=
"$field $direction"
;
}
$this
->
mergeOption
(
'ORDER BY'
,
$fieldsWithDirection
);
}
else
{
$this
->
mergeOption
(
'ORDER BY'
,
"$fields $direction"
);
}
return
$this
;
}
/**
* Add a value to an option which may be not set or a string or array.
*
* @param string $name
* @param string|string[] $newArrayOrValue
*/
private
function
mergeOption
(
$name
,
$newArrayOrValue
)
{
$value
=
isset
(
$this
->
options
[
$name
]
)
?
(
array
)
$this
->
options
[
$name
]
:
[];
if
(
is_array
(
$newArrayOrValue
)
)
{
$value
=
array_merge
(
$value
,
$newArrayOrValue
);
}
else
{
$value
[]
=
$newArrayOrValue
;
}
$this
->
options
[
$name
]
=
$value
;
}
/**
* Set the method name to be included in an SQL comment.
*
* @param string $fname
* @param-taint $fname exec_sql
* @return $this
*/
public
function
caller
(
$fname
)
{
$this
->
caller
=
$fname
;
return
$this
;
}
/**
* Run the constructed UNION query and return all results.
*
* @return IResultWrapper
*/
public
function
fetchResultSet
()
{
$query
=
new
Query
(
$this
->
getSQL
(),
ISQLPlatform
::
QUERY_CHANGE_NONE
,
'SELECT'
);
return
$this
->
db
->
query
(
$query
,
$this
->
caller
);
}
/**
* Run the constructed UNION query, and return a single field extracted
* from the first result row. If there were no result rows, false is
* returned. This may only be called when only one field has been added to
* the constituent queries.
*
* @since 1.42
* @return mixed
* @return-taint tainted
*/
public
function
fetchField
()
{
$this
->
limit
(
1
);
foreach
(
$this
->
fetchResultSet
()
as
$row
)
{
$row
=
(
array
)
$row
;
if
(
count
(
$row
)
!==
1
)
{
throw
new
\UnexpectedValueException
(
__METHOD__
.
' expects the query to have only one field'
);
}
return
$row
[
array_key_first
(
$row
)
];
}
return
false
;
}
/**
* Run the constructed UNION query, and extract a single field from each
* result row, returning an array containing all the values. This may only
* be called when only one field has been added to the constituent queries.
*
* @since 1.42
* @return array
* @return-taint tainted
*/
public
function
fetchFieldValues
()
{
$values
=
[];
foreach
(
$this
->
fetchResultSet
()
as
$row
)
{
$row
=
(
array
)
$row
;
if
(
count
(
$row
)
!==
1
)
{
throw
new
\UnexpectedValueException
(
__METHOD__
.
' expects the query to have only one field'
);
}
$values
[]
=
$row
[
array_key_first
(
$row
)
];
}
return
$values
;
}
/**
* Run the constructed UNION query, and return the first result row. If
* there were no results, return false.
*
* @since 1.42
* @return \stdClass|false
* @return-taint tainted
*/
public
function
fetchRow
()
{
$this
->
limit
(
1
);
foreach
(
$this
->
fetchResultSet
()
as
$row
)
{
return
$row
;
}
return
false
;
}
/**
* Get the SQL query string which would be used by fetchResultSet().
*
* @since 1.42
* @return string
*/
public
function
getSQL
()
{
$sqls
=
[];
foreach
(
$this
->
sqbs
as
$sqb
)
{
$sqls
[]
=
$sqb
->
getSQL
();
}
return
$this
->
db
->
unionQueries
(
$sqls
,
$this
->
all
,
$this
->
options
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sun, Oct 4, 01:35 (3 w, 5 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
a8/e7/a410e78df729c1e2eb6cfd7a6ffa
Default Alt Text
UnionQueryBuilder.php (6 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment