Commit 57ca9e10 authored by François Ferry's avatar François Ferry
Browse files

feat(order): add support for order by NULLS LAST and NULLS FIRST

related: #301
parent 1790ec0af1a4
......@@ -895,7 +895,7 @@ class SQLGenerator(object):
for sortterm in sorts:
_term = self._sortterm_sql(sortterm, selectidx)
if _term is not None:
sqlsortterms.append(_term)
sqlsortterms.append((_term, sortterm.asc, sortterm.nulls_sort))
if sqlsortterms:
sql = self.dbhelper.sql_add_order_by(
sql, sqlsortterms, origselection, fneedwrap,
......@@ -982,10 +982,7 @@ class SQLGenerator(object):
sqlterm = term.accept(self)
if sqlterm is None:
return None
if sortterm.asc:
return str(sqlterm)
else:
return '%s DESC' % sqlterm
return str(sqlterm)
def visit_and(self, et):
"""generate SQL for a AND subtree"""
......
......@@ -1440,6 +1440,26 @@ FROM cw_CWUser AS _X
WHERE _X.cw_login ~ [0-9].*
''')
def test_order_by_nulls_first_and_last(self):
for rql, sql in [
(
'Any N ORDERBY 1 NULLSFIRST WHERE X name N, X is State',
'''
SELECT _X.cw_name
FROM cw_State AS _X
ORDER BY 1 NULLS FIRST'''
),
(
'Any N ORDERBY 1 NULLSLAST WHERE X name N, X is State',
'''
SELECT _X.cw_name
FROM cw_State AS _X
ORDER BY 1 NULLS LAST'''
),
]:
with self.subTest(rql=rql):
self._check(rql, sql)
def test_aggregate_in_orderby(self):
self._check("Any X GROUPBY X ORDERBY ABS(COUNT(Y)) WHERE"
"X is CWGROUP, Y is CWUSER, Y in_group X",
......@@ -1862,6 +1882,26 @@ FROM cw_CWUser AS _X
WHERE _X.cw_login REGEXP [0-9].*
''')
def test_order_by_nulls_first_and_last(self):
for rql, sql in [
(
'Any N ORDERBY 1 NULLSFIRST WHERE X name N, X is State',
'''
SELECT _X.cw_name
FROM cw_State AS _X
ORDER BY 1 is NULL DESC, 1'''
),
(
'Any N ORDERBY 1 NULLSLAST WHERE X name N, X is State',
'''
SELECT _X.cw_name
FROM cw_State AS _X
ORDER BY 1 is NULL, 1'''
),
]:
with self.subTest(rql=rql):
self._check(rql, sql)
def test_union(self):
for rql, sql in [
('(Any N ORDERBY 1 WHERE X name N, X is State)'
......
......@@ -13,8 +13,8 @@ Reserved keywords
::
AND, ASC, BEING, DELETE, DESC, DISTINCT, EXISTS, FALSE, GROUPBY,
HAVING, ILIKE, INSERT, LIKE, LIMIT, NOT, NOW, NULL, OFFSET,
OR, ORDERBY, SET, TODAY, TRUE, UNION, WHERE, WITH
HAVING, ILIKE, INSERT, LIKE, LIMIT, NOT, NOW, NULL, NULLSFIRST, NULLSLAST,
OFFSET, OR, ORDERBY, SET, TODAY, TRUE, UNION, WHERE, WITH
The keywords are not case sensitive. You should not use them when defining your
schema, or as RQL variable names.
......@@ -288,6 +288,18 @@ order: variable or column number followed by sorting method (``ASC``,
``DESC``), ``ASC`` being the default. If the sorting method is not
specified, then the sorting is ascendant (`ASC`).
It is also possible to precise a specific ordering for `NULL` values.
The NULLSFIRST and NULLSLAST options can be used to determine whether
nulls appear before or after non-null values in the sort ordering.
By default, null values sort as if larger than any non-null value;
that is, NULLSFIRST is the default for DESC order, and NULLSLAST otherwise.
These options are written after the sorting method when it is specified.
For instance, this request will return all projects ordered by creation date
in descending order, with projects with no date in last position.
.. sourcecode:: sql
Any X ORDERBY Y DESC NULLSLAST WHERE X creation_date Y
Pagination
``````````
......
......@@ -4,4 +4,4 @@ hg+https://forge.extranet.logilab.fr/open-source/logilab-constraint/
hg+https://forge.extranet.logilab.fr/open-source/logilab-mtconverter/
hg+https://forge.extranet.logilab.fr/open-source/yams/
hg+https://forge.extranet.logilab.fr/CubicWeb/RQL/
https://github.com/logilab/yapps/tarball/master#egg=yapps
https://github.com/logilab/yapps/tarball/master#egg=yapps2
......@@ -65,10 +65,10 @@ setup(
install_requires=[
'logilab-common >= 1.8.0',
'logilab-mtconverter >= 0.9.2',
'rql >= 0.36.1',
'rql >= 0.37.0, < 1.0.0',
'yams >= 0.45.3',
'lxml',
'logilab-database >= 1.17.2',
'logilab-database >= 1.18.0, < 2.0.0',
'passlib >= 1.7',
'pytz',
'Markdown',
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment