Skip to content

Commit

Permalink
Add random() order support (#16964)
Browse files Browse the repository at this point in the history
Co-authored-by: Hisham Bin Ateya <hishamco_2007@yahoo.com>
  • Loading branch information
sebastienros and hishamco authored Nov 7, 2024
1 parent b3640be commit 949a550
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public SqlGrammar() : base(false)

// Create Index.
orderList.Rule = MakePlusRule(orderList, comma, orderMember);
orderMember.Rule = Id + orderDirOptional;
orderMember.Rule = Id + (orderDirOptional | "(" + functionArguments + ")");
orderDirOptional.Rule = Empty | "ASC" | "DESC";

// Select stmt.
Expand Down
27 changes: 22 additions & 5 deletions src/OrchardCore.Modules/OrchardCore.Queries/Sql/SqlParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,20 +246,37 @@ private void EvaluateOrderClause(ParseTreeNode parseTreeNode)
var idList = parseTreeNode.ChildNodes[2];

_modes.Push(FormattingModes.SelectClause);

for (var i = 0; i < idList.ChildNodes.Count; i++)
{
var id = idList.ChildNodes[i].ChildNodes[0];

if (i > 0)
{
_builder.Append(", ");
}

var id = idList.ChildNodes[i].ChildNodes[0];

// RANDOM() is a special case where we need to use the dialect's random function.
if (id.ChildNodes[0].Token != null && id.ChildNodes[0].Token.ValueString.Equals("RANDOM", StringComparison.OrdinalIgnoreCase))
{
var funArgs = idList.ChildNodes[i].ChildNodes[1].ChildNodes[0];

// "RANDOM" + {funArgs} + no arguments?
if (funArgs.Term.Name == "funArgs" && funArgs.ChildNodes.Count == 0)
{
_builder.Append(_dialect.RandomOrderByClause);

continue;
}
}

EvaluateId(id);

if (idList.ChildNodes[i].ChildNodes[1].ChildNodes.Count > 0)
var orderDirOpt = idList.ChildNodes[i].ChildNodes[1].ChildNodes[0];

if (orderDirOpt.Term.Name == "orderDirOpt" && orderDirOpt.ChildNodes.Count > 0)
{
_builder.Append(' ').Append(idList.ChildNodes[i].ChildNodes[1].ChildNodes[0].Term.Name);
_builder.Append(' ').Append(orderDirOpt.ChildNodes[0].Term.Name);
}
}

Expand Down Expand Up @@ -805,7 +822,7 @@ private void EvaluateOverClauseOptional(ParseTreeNode overClauseOpt)
var orderMember = orderList.ChildNodes[i];
var id = orderMember.ChildNodes[0];
EvaluateSelectId(id);
var orderDirOpt = orderMember.ChildNodes[1];
var orderDirOpt = orderMember.ChildNodes[1].ChildNodes[0];
if (orderDirOpt.ChildNodes.Count > 0)
{
_builder.Append(' ').Append(orderDirOpt.ChildNodes[0].Term.Name);
Expand Down
6 changes: 6 additions & 0 deletions src/docs/reference/modules/Queries/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,12 @@ The SQL parser is also able to convert some specific functions to the intended d
| `year(_date_)` | Returns the years part of a date. |
| `now()` | Returns current date time (utc). |

Order By clauses can also use the `random()` function (case insensitive) to order results randomly, e.g.,

```
SELECT * FROM ContentItemIndex ORDER BY random()
```

## Scripting

The following JavaScript functions are available with this module.
Expand Down
15 changes: 15 additions & 0 deletions test/OrchardCore.Tests/Orchard.Queries/SqlParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,4 +243,19 @@ public void ShouldParseSubquery(string sql, string expectedSql)
Assert.True(result);
Assert.Equal(expectedSql, FormatSql(rawQuery));
}

[Theory]
[InlineData("select a order by RANDOM()", "SELECT [a] ORDER BY newid();")]
[InlineData("select a order by random()", "SELECT [a] ORDER BY newid();")]
[InlineData("select a order by RANDOM", "SELECT [a] ORDER BY [RANDOM];")]
[InlineData("select a order by random", "SELECT [a] ORDER BY [random];")]
public void ShouldOrderByRandom(string sql, string expectedSql)
{
// Arrange & Act
var result = SqlParser.TryParse(sql, _schema, _defaultDialect, _defaultTablePrefix, null, out var rawQuery, out var errors);

// Assert
Assert.True(result);
Assert.Equal(expectedSql, FormatSql(rawQuery));
}
}

0 comments on commit 949a550

Please sign in to comment.