Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
d4a597fd
Commit
d4a597fd
authored
Sep 11, 2009
by
webchick
Browse files
#561104
by Crell: Added support for random ordering in dynamic select queries.
parent
f24f709e
Changes
3
Hide whitespace changes
Inline
Side-by-side
includes/database/pgsql/query.inc
View file @
d4a597fd
...
...
@@ -173,3 +173,13 @@ public function execute() {
return
$stmt
->
rowCount
();
}
}
class
SelectQuery_pgsql
extends
SelectQuery
{
public
function
orderRandom
()
{
$alias
=
$this
->
addExpression
(
'RANDOM()'
,
'random_field'
);
$this
->
orderBy
(
$alias
);
return
$this
;
}
}
includes/database/select.inc
View file @
d4a597fd
...
...
@@ -347,6 +347,28 @@ public function addJoin($type, $table, $alias = NULL, $condition = NULL, $argume
*/
public
function
orderBy
(
$field
,
$direction
=
'ASC'
);
/**
* Orders the result set by a random value.
*
* This may be stacked with other orderBy() calls. If so, the query will order
* by each specified field, including this one, in the order called. Although
* this method may be called multiple times on the same query, doing so
* is not particularly useful.
*
* Note: The method used by most drivers may not scale to very large result
* sets. If you need to work with extremely large data sets, you may create
* your own database driver by subclassing off of an existing driver and
* implementing your own randomization mechanism. See
*
* http://jan.kneschke.de/projects/mysql/order-by-rand/
*
* for an example of such an alternate sorting mechanism.
*
* @return
* The called object
*/
public
function
orderRandom
();
/**
* Restricts a query to a given range in the result set.
*
...
...
@@ -643,6 +665,11 @@ public function orderBy($field, $direction = 'ASC') {
return
$this
;
}
public
function
orderRandom
()
{
$this
->
query
->
orderRandom
();
return
$this
;
}
public
function
range
(
$start
=
NULL
,
$length
=
NULL
)
{
$this
->
query
->
range
(
$start
,
$length
);
return
$this
;
...
...
@@ -1182,6 +1209,12 @@ public function orderBy($field, $direction = 'ASC') {
return
$this
;
}
public
function
orderRandom
()
{
$alias
=
$this
->
addExpression
(
'RAND()'
,
'random_field'
);
$this
->
orderBy
(
$alias
);
return
$this
;
}
public
function
range
(
$start
=
NULL
,
$length
=
NULL
)
{
$this
->
range
=
func_num_args
()
?
array
(
'start'
=>
$start
,
'length'
=>
$length
)
:
array
();
return
$this
;
...
...
modules/simpletest/tests/database_test.test
View file @
d4a597fd
...
...
@@ -1400,6 +1400,55 @@ class DatabaseSelectTestCase extends DatabaseTestCase {
$this
->
assertEqual
(
$names
[
1
],
'Ringo'
,
t
(
'Second query returned correct second name.'
));
$this
->
assertEqual
(
$names
[
2
],
'Ringo'
,
t
(
'Third query returned correct name.'
));
}
/**
* Test that random ordering of queries works.
*
* This is a non-deterministic query. That is, it is not guaranteed to pass
* 100% of the time. Random numbers are like that. Instead, we take two sets
* of random selects. By the laws of probability, the average of each set
* should be roughly the average of the data set being selected from and
* roughly the same each time through, provided that the original data set
* is evenly distributed. Because we know that ours is, this test should pass
* correctly 99% of the time. It is not possible to unit test for that other
* 1% successfully, so that will have to do.
*/
function
testRandomOrder
()
{
$sets
=
2
;
$runs
=
50
;
$ids
=
array
();
$ids
=
array
();
$max
=
db_query
(
"SELECT MAX(id) FROM
{
test
}
"
)
->
fetchField
();
$min
=
db_query
(
"SELECT MIN(id) FROM
{
test
}
"
)
->
fetchField
();
$ideal_average
=
(
$min
+
$max
)
/
2
;
$allowed_deviation
=
(
$max
-
$min
)
/
4
;
for
(
$i
=
0
;
$i
<
$sets
;
++
$i
)
{
for
(
$j
=
0
;
$j
<
$runs
;
++
$j
)
{
$ids
[
$i
][]
=
db_select
(
'test'
,
't'
)
->
fields
(
't'
,
array
(
'id'
))
->
range
(
0
,
1
)
->
orderRandom
()
->
orderBy
(
'id'
)
->
execute
()
->
fetchField
();
}
}
for
(
$i
=
0
;
$i
<
$sets
;
++
$i
)
{
$found_average
[
$i
]
=
array_sum
(
$ids
[
$i
])
/
count
(
$ids
[
$i
]);
$deviation
=
abs
(
$found_average
[
$i
]
-
$ideal_average
);
$this
->
assertTrue
(
$deviation
<=
$allowed_deviation
,
t
(
'Random ids are within allowed deviation.'
));
}
for
(
$i
=
1
;
$i
<
$sets
;
++
$i
)
{
$deviation
=
abs
(
$found_average
[
$i
]
-
$found_average
[
$i
-
1
]);
$this
->
assertTrue
(
$deviation
<=
$allowed_deviation
,
t
(
'Random ids are within allowed deviation from each other.'
));
}
}
}
/**
...
...
@@ -2897,7 +2946,7 @@ class DatabaseExtraTypesTestCase extends DrupalWebTestCase {
'description'
=>
t
(
'Test Time field'
),
'type'
=>
'time'
,
'not null'
=>
FALSE
,
),
),
),
);
$ret
=
array
();
...
...
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