Skip to content

Commit 4ebca81

Browse files
Copilotmathiasrw
andauthored
Improve test coverage for scalar subqueries to close #1967 (#2397)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: mathiasrw <[email protected]> Co-authored-by: M. Wulff <[email protected]>
1 parent 8aa97be commit 4ebca81

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

test/test1967.js

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
if (typeof exports === 'object') {
2+
var assert = require('assert');
3+
var alasql = require('..');
4+
}
5+
6+
describe('Test - Scalar Subquery Support', function () {
7+
const test = 'scalarsubquery';
8+
9+
before(function () {
10+
alasql('create database test' + test);
11+
alasql('use test' + test);
12+
});
13+
14+
after(function () {
15+
alasql('drop database test' + test);
16+
});
17+
18+
it('A) Scalar subquery in SELECT clause - basic', function () {
19+
alasql('CREATE TABLE products (id INT, name STRING, price INT)');
20+
alasql(
21+
'INSERT INTO products VALUES (1, "Widget", 10), (2, "Gadget", 20), (3, "Doohickey", 30)'
22+
);
23+
24+
var res = alasql(
25+
'SELECT id, name, price, (SELECT MAX(price) FROM products) as max_price FROM products'
26+
);
27+
28+
assert.deepEqual(res, [
29+
{id: 1, name: 'Widget', price: 10, max_price: 30},
30+
{id: 2, name: 'Gadget', price: 20, max_price: 30},
31+
{id: 3, name: 'Doohickey', price: 30, max_price: 30},
32+
]);
33+
});
34+
35+
it('B) Scalar subquery in SELECT clause - with aggregate functions', function () {
36+
var res = alasql(
37+
'SELECT id, name, price, (SELECT AVG(price) FROM products) as avg_price, (SELECT MIN(price) FROM products) as min_price FROM products'
38+
);
39+
40+
assert.deepEqual(res, [
41+
{id: 1, name: 'Widget', price: 10, avg_price: 20, min_price: 10},
42+
{id: 2, name: 'Gadget', price: 20, avg_price: 20, min_price: 10},
43+
{id: 3, name: 'Doohickey', price: 30, avg_price: 20, min_price: 10},
44+
]);
45+
});
46+
47+
it('C) Scalar subquery in WHERE clause', function () {
48+
var res = alasql('SELECT * FROM products WHERE price > (SELECT AVG(price) FROM products)');
49+
50+
assert.deepEqual(res, [{id: 3, name: 'Doohickey', price: 30}]);
51+
});
52+
53+
it('D) Scalar subquery in WHERE clause - with comparison operators', function () {
54+
var res = alasql('SELECT * FROM products WHERE price = (SELECT MAX(price) FROM products)');
55+
56+
assert.deepEqual(res, [{id: 3, name: 'Doohickey', price: 30}]);
57+
});
58+
59+
it('E) Correlated scalar subquery - SUM aggregate', function () {
60+
alasql('CREATE TABLE customers (id INT, name STRING, income INT)');
61+
alasql(
62+
'INSERT INTO customers VALUES (1, "Alice", 50000), (2, "Bob", 60000), (3, "Charlie", 70000)'
63+
);
64+
alasql('CREATE TABLE orders (customer_id INT, amount INT)');
65+
alasql('INSERT INTO orders VALUES (1, 100), (1, 200), (2, 150), (2, 250), (3, 300), (3, 400)');
66+
67+
var res = alasql(
68+
'SELECT c.id, c.name, (SELECT SUM(amount) FROM orders o WHERE o.customer_id = c.id) as total_orders FROM customers c'
69+
);
70+
71+
assert.deepEqual(res, [
72+
{id: 1, name: 'Alice', total_orders: 300},
73+
{id: 2, name: 'Bob', total_orders: 400},
74+
{id: 3, name: 'Charlie', total_orders: 700},
75+
]);
76+
});
77+
78+
it('F) Correlated scalar subquery - COUNT aggregate', function () {
79+
var res = alasql(
80+
'SELECT c.id, c.name, (SELECT COUNT(*) FROM orders o WHERE o.customer_id = c.id) as order_count FROM customers c'
81+
);
82+
83+
assert.deepEqual(res, [
84+
{id: 1, name: 'Alice', order_count: 2},
85+
{id: 2, name: 'Bob', order_count: 2},
86+
{id: 3, name: 'Charlie', order_count: 2},
87+
]);
88+
});
89+
90+
it('G) Correlated scalar subquery - AVG aggregate', function () {
91+
var res = alasql(
92+
'SELECT c.id, c.name, (SELECT AVG(amount) FROM orders o WHERE o.customer_id = c.id) as avg_order FROM customers c'
93+
);
94+
95+
assert.deepEqual(res, [
96+
{id: 1, name: 'Alice', avg_order: 150},
97+
{id: 2, name: 'Bob', avg_order: 200},
98+
{id: 3, name: 'Charlie', avg_order: 350},
99+
]);
100+
});
101+
102+
it('H) Multiple scalar subqueries in SELECT clause', function () {
103+
var res = alasql(`
104+
SELECT c.id, c.name,
105+
(SELECT SUM(amount) FROM orders o WHERE o.customer_id = c.id) as sum_amt,
106+
(SELECT AVG(amount) FROM orders o WHERE o.customer_id = c.id) as avg_amt,
107+
(SELECT COUNT(*) FROM orders o WHERE o.customer_id = c.id) as cnt
108+
FROM customers c
109+
WHERE c.id = 1
110+
`);
111+
112+
assert.deepEqual(res, [{id: 1, name: 'Alice', sum_amt: 300, avg_amt: 150, cnt: 2}]);
113+
});
114+
115+
it('I) Scalar subquery with WHERE condition in subquery', function () {
116+
var res = alasql(
117+
'SELECT * FROM customers WHERE income > (SELECT AVG(income) FROM customers WHERE id > 1)'
118+
);
119+
120+
assert.deepEqual(res, [{id: 3, name: 'Charlie', income: 70000}]);
121+
});
122+
123+
it('J) Scalar subquery in complex WHERE condition', function () {
124+
alasql('CREATE TABLE stats (category STRING, avg_val INT)');
125+
alasql('INSERT INTO stats VALUES ("high", 65000), ("low", 55000)');
126+
127+
var res = alasql(
128+
'SELECT * FROM customers WHERE income > (SELECT avg_val FROM stats WHERE category = "high")'
129+
);
130+
131+
assert.deepEqual(res, [{id: 3, name: 'Charlie', income: 70000}]);
132+
});
133+
134+
it('K) Scalar subquery returns 0 for SUM when no rows match', function () {
135+
var res = alasql(
136+
'SELECT c.id, c.name, (SELECT SUM(amount) FROM orders o WHERE o.customer_id = 999) as no_orders FROM customers c WHERE c.id = 1'
137+
);
138+
139+
// Note: In AlaSQL, SUM returns 0 when no rows match.
140+
// This differs from standard SQL where SUM typically returns NULL for empty result sets.
141+
assert.deepEqual(res, [{id: 1, name: 'Alice', no_orders: 0}]);
142+
});
143+
144+
it('L) Scalar subquery in arithmetic expression', function () {
145+
var res = alasql(
146+
'SELECT id, name, price, price - (SELECT AVG(price) FROM products) as price_diff FROM products WHERE id = 1'
147+
);
148+
149+
assert.deepEqual(res, [{id: 1, name: 'Widget', price: 10, price_diff: -10}]);
150+
});
151+
});

0 commit comments

Comments
 (0)