Skip to content

Commit

Permalink
Merge pull request #43427 from poorna2152/order_by_arr
Browse files Browse the repository at this point in the history
Fix hanging of query when the key in order is an array
  • Loading branch information
gimantha authored Oct 2, 2024
2 parents 1869673 + 35407ff commit fe0509b
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 33 deletions.
1 change: 1 addition & 0 deletions langlib/lang.query/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dependencies {
distributionBala project(path: ':ballerina-lang:table', configuration: 'distributionBala')
distributionBala project(path: ':ballerina-lang:stream', configuration: 'distributionBala')
distributionBala project(path: ':ballerina-lang:error', configuration: 'distributionBala')
distributionBala project(path: ':ballerina-lang:function', configuration: 'distributionBala')
distributionBala project(path: ':ballerina-lang:jballerina.java', configuration: 'distributionBala')
distributionBala project(path: ':ballerina-lang:object', configuration: 'distributionBala')

Expand Down
36 changes: 6 additions & 30 deletions langlib/lang.query/src/main/ballerina/types.bal
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import ballerina/lang.'xml as lang_xml;
import ballerina/lang.'stream as lang_stream;
import ballerina/lang.'table as lang_table;
import ballerina/lang.'object as lang_object;
import ballerina/lang.'function;

# A type parameter that is a subtype of `any|error`.
# Has the special semantic that when used in a declaration
Expand Down Expand Up @@ -1053,39 +1054,14 @@ class _OrderTreeNode {
return orderedFrames;
}

# sorting is not supported for any[], therefore have to resolve runtime type and sort it.
# sorting is not supported for any[], thus use the `function:call` method call the sort operation.
# + return - ordered array.
function getSortedArray(any[] arr) returns any[] {
if (arr.length() > 0) {
int i = 0;
while (i < arr.length()) {
if (arr[i] is ()) {
i += 1;
continue;
} else if (arr[i] is boolean) {
boolean?[] res = [];
self.copyArray(arr, res);
return res.sort(self.nodesDirection, (v) => v);
} else if (arr[i] is int) {
int?[] res = [];
self.copyArray(arr, res);
return res.sort(self.nodesDirection, (v) => v);
} else if (arr[i] is float) {
float?[] res = [];
self.copyArray(arr, res);
return res.sort(self.nodesDirection, (v) => v);
} else if (arr[i] is decimal) {
decimal?[] res = [];
self.copyArray(arr, res);
return res.sort(self.nodesDirection, (v) => v);
} else if (arr[i] is string) {
string?[] res = [];
self.copyArray(arr, res);
return res.sort(self.nodesDirection, (v) => v);
}
}
any|error res = function:call(lang_array:sort, arr, self.nodesDirection);
if res is any[] {
return res;
}
return arr;
panic error(string `Error while sorting the arr: ${arr.toBalString()}`);
}

# copy every element of source array into empty target array.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,17 +233,28 @@ public void testQueryExprWithOrderByClauseReturnXML() {

@Test(description = "Test negative scenarios for query expr with order by clause")
public void testNegativeScenarios() {
Assert.assertEquals(negativeResult.getErrorCount(), 3);
int index = 0;

validateError(negativeResult, index++, "order by not supported for complex type fields, " +
"order key should belong to a basic type",
35, 18);
validateError(negativeResult, index++, "undefined symbol 'address'",
35, 18);
validateError(negativeResult, index, "order by not supported for complex type fields, " +
"order key should belong to a basic type",
validateError(negativeResult, index++,
"order by not supported for complex type fields, order key should belong to a basic type",
47, 18);
validateError(negativeResult, index++,
"order by not supported for complex type fields, order key should belong to a basic type",
55, 18);
validateError(negativeResult, index++,
"order by not supported for complex type fields, order key should belong to a basic type",
61, 18);
Assert.assertEquals(negativeResult.getErrorCount(), index);
}

@Test
public void testQueryExprWithOrderByClauseWithArrayKey() {
BRunUtil.invoke(result, "testQueryExprWithOrderByClauseWithArrayKey");
}

@AfterClass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,17 @@ function testOrderByClauseWithComplexTypeFieldInOrderBy() {
order by customer.address
select customer;
}

function testOrderByClauseWithArrayTypeFieldInOrderBy() {
record {|(int|boolean)[] t; string s;|}[] data1 = [];

_ = from var rec in data1
order by rec.t descending
select rec.s;

record {|int k; [decimal|float, int] arr;|}[] data2 = [];

_ = from var rec in data2
order by rec.arr
select rec.k;
}
Original file line number Diff line number Diff line change
Expand Up @@ -502,3 +502,117 @@ function incrementCount(int i) returns int {
int count = i + 2;
return count;
}

enum Color {
RED,
GREEN,
BLUE
}

function testQueryExprWithOrderByClauseWithArrayKey() {
record {|int[] t; string s;|}[] data1 = [
{s: "s5", t: [5, 2]},
{s: "s1", t: [1, 1, 3, 4]},
{s: "s0", t: [0]},
{s: "s4", t: [4]}
];

string[] q1 = from var rec in data1
order by rec.t descending
select rec.s;
assertEquality(["s5", "s4", "s1", "s0"], q1);

record {|int k; [decimal, int] arr;|}[] data2 = [
{k: 1, arr: [3.2, 1]},
{k: 2, arr: [212.21, 3]},
{k: 3, arr: [0.2, 4]},
{k: 4, arr: [-1.2, 10]}
];

int[] q2 = from var rec in data2
order by rec.arr descending
select rec.k;
assertEquality([2, 1, 3, 4], q2);

record {|int k; [boolean, string, int] arr;|}[] data3 = [
{k: 1, arr: [true, "abcd", 1]},
{k: 2, arr: [false, "efgh", 9]},
{k: 3, arr: [false, "abcd", 10]},
{k: 4, arr: [true, "ijkl", -5]}
];

int[] q3 = from var rec in data3
order by rec.arr
select rec.k;
assertEquality([3, 2, 1, 4], q3);

record {|int k; [float...] arr;|}[] data4 = [
{k: 1, arr: [1.2, 3.1, 5.6, 9.2]},
{k: 2, arr: []},
{k: 3, arr: [-0.7, 0.8, 1.45]},
{k: 4, arr: [1, 2]}
];

int[] q4 = from var rec in data4
order by rec.arr
select rec.k;
assertEquality([2, 3, 4, 1], q4);

record {|int k; [float...] arr1; [string, string...] arr2;|}[] data5 = [
{k: 1, arr1: [1.2, 3.1, 5.6, 9.2], arr2: ["s1", "s2"]},
{k: 2, arr1: [], arr2: ["s10", "s9"]},
{k: 3, arr1: [], arr2: ["s1", "s2"]},
{k: 4, arr1: [], arr2: ["s1", "s2"]},
{k: 5, arr1: [1, 2], arr2: ["s24", "s2"]}
];

int[] q5 = from var rec in data5
order by rec.arr1 descending, rec.arr2 ascending
select rec.k;
assertEquality([1, 5, 3, 4, 2], q5);

record {|int k; float?[]? arr1;|}[] data6 = [
{k: 1, arr1: [1.2, 3.1, 5.6, 9.2]},
{k: 2, arr1: [1.2, 3.1, 5.6, ()]},
{k: 3, arr1: [(), (), ()]},
{k: 4, arr1: ()},
{k: 5, arr1: [1, 2]}
];

int[] q6 = from var rec in data6
order by rec.arr1 descending
select rec.k;
assertEquality([1, 2, 5, 3, 4], q6);

record {|int k; [int?, string?, decimal?...] arr1;|}[] data7 = [
{k: 1, arr1: [1, "a", 9.2]},
{k: 2, arr1: [1, (), ()]},
{k: 3, arr1: [(), (), 4.2]},
{k: 4, arr1: [2, "b"]},
{k: 5, arr1: [2, (), 2.3]}
];

int[] q7 = from var rec in data7
order by rec.arr1 descending
select rec.k;
assertEquality([4, 5, 1, 2, 3], q7);

record {|int k; Color[] arr1;|}[] data8 = [
{k: 1, arr1: [RED]},
{k: 2, arr1: [RED, GREEN]},
{k: 3, arr1: [GREEN, BLUE, RED]},
{k: 4, arr1: [BLUE, RED]},
{k: 5, arr1: [BLUE, BLUE]}
];

int[] q8 = from var rec in data8
order by rec.arr1 descending
select rec.k;
assertEquality([2, 1, 3, 4, 5], q8);
}

function assertEquality(anydata expected, anydata actual) {
if expected != actual {
panic error(string `Expected ${expected.toBalString()}, found ${actual.toBalString()}`);
}
}

0 comments on commit fe0509b

Please sign in to comment.