Files
2025-02-15 00:52:14 +01:00

632 lines
16 KiB
TypeScript

import {
query
} from './solution';
import {
expect
} from "chai";
describe("SQL tests", function() {
it("Basic SELECT tests", () => {
var numbers = [1, 2, 3];
expect(query().select().from(numbers).execute()).to.deep.equal(numbers);
expect(query().select().execute()).to.deep.equal([], 'No FROM clause produces empty array');
expect(query().from(numbers).execute()).to.deep.equal(numbers, 'SELECT can be omited');
expect(query().execute()).to.deep.equal([]);
expect(query().from(numbers).select().execute()).to.deep.equal(numbers, 'The order does not matter');
});
it("Basic SELECT and WHERE over objects", () => {
var persons = [{
name: 'Peter',
profession: 'teacher',
age: 20,
maritalStatus: 'married'
},
{
name: 'Michael',
profession: 'teacher',
age: 50,
maritalStatus: 'single'
},
{
name: 'Peter',
profession: 'teacher',
age: 20,
maritalStatus: 'married'
},
{
name: 'Anna',
profession: 'scientific',
age: 20,
maritalStatus: 'married'
},
{
name: 'Rose',
profession: 'scientific',
age: 50,
maritalStatus: 'married'
},
{
name: 'Anna',
profession: 'scientific',
age: 20,
maritalStatus: 'single'
},
{
name: 'Anna',
profession: 'politician',
age: 50,
maritalStatus: 'married'
}
];
expect(query().select().from(persons).execute()).to.deep.equal(persons);
function profession(person: any) {
return person.profession;
}
// SELECT profession FROM persons
expect(query().select(profession).from(persons).execute()).to.deep.equal(["teacher", "teacher", "teacher", "scientific", "scientific", "scientific", "politician"]);
expect(query().select(profession).execute()).to.deep.equal([], 'No FROM clause produces empty array');
function isTeacher(person: any) {
return person.profession === 'teacher';
}
// SELECT profession FROM persons WHERE profession="teacher"
expect(query().select(profession).from(persons).where(isTeacher).execute()).to.deep.equal(["teacher", "teacher", "teacher"]);
// SELECT * FROM persons WHERE profession="teacher"
expect(query().from(persons).where(isTeacher).execute()).to.deep.equal(persons.slice(0, 3));
function name(person: any) {
return person.name;
}
// SELECT name FROM persons WHERE profession="teacher"
expect(query().select(name).from(persons).where(isTeacher).execute()).to.deep.equal(["Peter", "Michael", "Peter"]);
expect(query().where(isTeacher).from(persons).select(name).execute()).to.deep.equal(["Peter", "Michael", "Peter"]);
});
it("GROUP BY tests", () => {
var persons = [{
name: 'Peter',
profession: 'teacher',
age: 20,
maritalStatus: 'married'
},
{
name: 'Michael',
profession: 'teacher',
age: 50,
maritalStatus: 'single'
},
{
name: 'Peter',
profession: 'teacher',
age: 20,
maritalStatus: 'married'
},
{
name: 'Anna',
profession: 'scientific',
age: 20,
maritalStatus: 'married'
},
{
name: 'Rose',
profession: 'scientific',
age: 50,
maritalStatus: 'married'
},
{
name: 'Anna',
profession: 'scientific',
age: 20,
maritalStatus: 'single'
},
{
name: 'Anna',
profession: 'politician',
age: 50,
maritalStatus: 'married'
}
];
function profession(person: any) {
return person.profession;
}
// SELECT * FROM persons GROUPBY profession <- Bad in SQL but possible in JavaScript
expect(query().select().from(persons).groupBy(profession).execute()).to.deep.equal([
["teacher", [{
"name": "Peter",
"profession": "teacher",
"age": 20,
"maritalStatus": "married"
}, {
"name": "Michael",
"profession": "teacher",
"age": 50,
"maritalStatus": "single"
}, {
"name": "Peter",
"profession": "teacher",
"age": 20,
"maritalStatus": "married"
}]],
["scientific", [{
"name": "Anna",
"profession": "scientific",
"age": 20,
"maritalStatus": "married"
}, {
"name": "Rose",
"profession": "scientific",
"age": 50,
"maritalStatus": "married"
}, {
"name": "Anna",
"profession": "scientific",
"age": 20,
"maritalStatus": "single"
}]],
["politician", [{
"name": "Anna",
"profession": "politician",
"age": 50,
"maritalStatus": "married"
}]]
]);
function isTeacher(person: any) {
return person.profession === 'teacher';
}
// SELECT * FROM persons WHERE profession='teacher' GROUPBY profession
expect(query().select().from(persons).where(isTeacher).groupBy(profession).execute()).to.deep.equal([
["teacher", [{
"name": "Peter",
"profession": "teacher",
"age": 20,
"maritalStatus": "married"
}, {
"name": "Michael",
"profession": "teacher",
"age": 50,
"maritalStatus": "single"
}, {
"name": "Peter",
"profession": "teacher",
"age": 20,
"maritalStatus": "married"
}]]
]);
function professionGroup(group: any) {
return group[0];
}
// SELECT profession FROM persons GROUPBY profession
expect(query().select(professionGroup).from(persons).groupBy(profession).execute()).to.deep.equal(["teacher", "scientific", "politician"]);
function name(person: any) {
return person.name;
}
// SELECT * FROM persons WHERE profession='teacher' GROUPBY profession, name
expect(query().select().from(persons).groupBy(profession, name).execute()).to.deep.equal([
["teacher", [
["Peter", [{
"name": "Peter",
"profession": "teacher",
"age": 20,
"maritalStatus": "married"
}, {
"name": "Peter",
"profession": "teacher",
"age": 20,
"maritalStatus": "married"
}]],
["Michael", [{
"name": "Michael",
"profession": "teacher",
"age": 50,
"maritalStatus": "single"
}]]
]],
["scientific", [
["Anna", [{
"name": "Anna",
"profession": "scientific",
"age": 20,
"maritalStatus": "married"
}, {
"name": "Anna",
"profession": "scientific",
"age": 20,
"maritalStatus": "single"
}]],
["Rose", [{
"name": "Rose",
"profession": "scientific",
"age": 50,
"maritalStatus": "married"
}]]
]],
["politician", [
["Anna", [{
"name": "Anna",
"profession": "politician",
"age": 50,
"maritalStatus": "married"
}]]
]]
]);
function age(person: any) {
return person.age;
}
function maritalStatus(person: any) {
return person.maritalStatus;
}
// SELECT * FROM persons WHERE profession='teacher' GROUPBY profession, name, age
expect(query().select().from(persons).groupBy(profession, name, age, maritalStatus).execute()).to.deep.equal([
["teacher", [
["Peter", [
[20, [
["married", [{
"name": "Peter",
"profession": "teacher",
"age": 20,
"maritalStatus": "married"
}, {
"name": "Peter",
"profession": "teacher",
"age": 20,
"maritalStatus": "married"
}]]
]]
]],
["Michael", [
[50, [
["single", [{
"name": "Michael",
"profession": "teacher",
"age": 50,
"maritalStatus": "single"
}]]
]]
]]
]],
["scientific", [
["Anna", [
[20, [
["married", [{
"name": "Anna",
"profession": "scientific",
"age": 20,
"maritalStatus": "married"
}]],
["single", [{
"name": "Anna",
"profession": "scientific",
"age": 20,
"maritalStatus": "single"
}]]
]]
]],
["Rose", [
[50, [
["married", [{
"name": "Rose",
"profession": "scientific",
"age": 50,
"maritalStatus": "married"
}]]
]]
]]
]],
["politician", [
["Anna", [
[50, [
["married", [{
"name": "Anna",
"profession": "politician",
"age": 50,
"maritalStatus": "married"
}]]
]]
]]
]]
]);
function professionCount(group: any) {
return [group[0], group[1].length];
}
// SELECT profession, count(profession) FROM persons GROUPBY profession
expect(query().select(professionCount).from(persons).groupBy(profession).execute()).to.deep.equal([
["teacher", 3],
["scientific", 3],
["politician", 1]
]);
function naturalCompare(value1: any, value2: any) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
// SELECT profession, count(profession) FROM persons GROUPBY profession ORDER BY profession
expect(query().select(professionCount).from(persons).groupBy(profession).orderBy(naturalCompare).execute()).to.deep.equal([
["politician", 1],
["scientific", 3],
["teacher", 3]
]);
});
it("Number tests", () => {
function isEven(number: number) {
return number % 2 === 0;
}
function parity(number: number) {
return isEven(number) ? 'even' : 'odd';
}
function isPrime(number: number) {
if (number < 2) {
return false;
}
var divisor = 2;
for (; number % divisor !== 0; divisor++);
return divisor === number;
}
function prime(number: number) {
return isPrime(number) ? 'prime' : 'divisible';
}
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// SELECT * FROM numbers
expect(query().select().from(numbers).execute()).to.deep.equal(numbers);
// SELECT * FROM numbers GROUP BY parity
expect(query().select().from(numbers).groupBy(parity).execute()).to.deep.equal([
["odd", [1, 3, 5, 7, 9]],
["even", [2, 4, 6, 8]]
]);
// SELECT * FROM numbers GROUP BY parity, isPrime
expect(query().select().from(numbers).groupBy(parity, prime).execute()).to.deep.equal([
["odd", [
["divisible", [1, 9]],
["prime", [3, 5, 7]]
]],
["even", [
["prime", [2]],
["divisible", [4, 6, 8]]
]]
]);
function odd(group: any) {
return group[0] === 'odd';
}
// SELECT * FROM numbers GROUP BY parity HAVING
expect(query().select().from(numbers).groupBy(parity).having(odd).execute()).to.deep.equal([
["odd", [1, 3, 5, 7, 9]]
]);
function descendentCompare(number1: number, number2: number) {
return number2 - number1;
}
// SELECT * FROM numbers ORDER BY value DESC
expect(query().select().from(numbers).orderBy(descendentCompare).execute()).to.deep.equal([9, 8, 7, 6, 5, 4, 3, 2, 1]);
function lessThan3(number: number) {
return number < 3;
}
function greaterThan4(number: number) {
return number > 4;
}
// SELECT * FROM number WHERE number < 3 OR number > 4
expect(query().select().from(numbers).where(lessThan3, greaterThan4).execute()).to.deep.equal([1, 2, 5, 6, 7, 8, 9]);
});
it("Frequency tests", () => {
var persons = [
['Peter', 3],
['Anna', 4],
['Peter', 7],
['Michael', 10]
];
function nameGrouping(person: any) {
return person[0];
}
function sumValues(value: any) {
return [value[0], value[1].reduce(function(result: any, person: any) {
return result + person[1];
}, 0)];
}
function naturalCompare(value1: any, value2: any) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
// SELECT name, sum(value) FROM persons ORDER BY naturalCompare GROUP BY nameGrouping
expect(query().select(sumValues).from(persons).orderBy(naturalCompare).groupBy(nameGrouping).execute()).to.deep.equal([
["Anna", 4],
["Michael", 10],
["Peter", 10]
]);
var numbers = [1, 2, 1, 3, 5, 6, 1, 2, 5, 6];
function id(value: any) {
return value;
}
function frequency(group: any) {
return {
value: group[0],
frequency: group[1].length
};
}
// SELECT number, count(number) FROM numbers GROUP BY number
expect(query().select(frequency).from(numbers).groupBy(id).execute()).to.deep.equal([{
"value": 1,
"frequency": 3
}, {
"value": 2,
"frequency": 2
}, {
"value": 3,
"frequency": 1
}, {
"value": 5,
"frequency": 2
}, {
"value": 6,
"frequency": 2
}]);
function greatThan1(group: any) {
return group[1].length > 1;
}
function isPair(group: any) {
return group[0] % 2 === 0;
}
// SELECT number, count(number) FROM numbers GROUP BY number HAVING count(number) > 1 AND isPair(number)
expect(query().select(frequency).from(numbers).groupBy(id).having(greatThan1).having(isPair).execute()).to.deep.equal([{
"value": 2,
"frequency": 2
}, {
"value": 6,
"frequency": 2
}]);
});
it("Join tests", () => {
var teachers = [{
teacherId: '1',
teacherName: 'Peter'
},
{
teacherId: '2',
teacherName: 'Anna'
}
];
var students = [{
studentName: 'Michael',
tutor: '1'
},
{
studentName: 'Rose',
tutor: '2'
}
];
function teacherJoin(join: any) {
return join[0].teacherId === join[1].tutor;
}
function student(join: any) {
return {
studentName: join[1].studentName,
teacherName: join[0].teacherName
};
}
// SELECT studentName, teacherName FROM teachers, students WHERE teachers.teacherId = students.tutor
expect(query().select(student).from(teachers, students).where(teacherJoin).execute()).to.deep.equal([{
"studentName": "Michael",
"teacherName": "Peter"
}, {
"studentName": "Rose",
"teacherName": "Anna"
}]);
var numbers1 = [1, 2];
var numbers2 = [4, 5];
expect(query().select().from(numbers1, numbers2).execute()).to.deep.equal([
[1, 4],
[1, 5],
[2, 4],
[2, 5]
]);
function tutor1(join: any) {
return join[1].tutor === "1";
}
// SELECT studentName, teacherName FROM teachers, students WHERE teachers.teacherId = students.tutor AND tutor = 1
expect(query().select(student).from(teachers, students).where(teacherJoin).where(tutor1).execute()).to.deep.equal([{
"studentName": "Michael",
"teacherName": "Peter"
}]);
expect(query().where(teacherJoin).select(student).where(tutor1).from(teachers, students).execute()).to.deep.equal([{
"studentName": "Michael",
"teacherName": "Peter"
}]);
});
it("Duplication exception tests", () => {
function checkError(fn: any, duplicate: any) {
try {
fn();
expect(false).to.equal(false, 'An error should be throw');
} catch (e) {
expect(e instanceof Error).to.equal(true);
expect((e as Error).message).to.equal('Duplicate ' + duplicate);
}
}
function id(value: any) {
return value;
}
checkError(function() {
query().select().select().execute();
}, 'SELECT');
checkError(function() {
query().select().from([]).select().execute();
}, 'SELECT');
checkError(function() {
query().select().from([]).from([]).execute();
}, 'FROM');
checkError(function() {
query().select().from([]).orderBy(id).orderBy(id).execute();
}, 'ORDERBY');
checkError(function() {
query().select().groupBy(id).from([]).groupBy(id).execute();
}, 'GROUPBY');
});
});