• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

demmings / gsSQL / 19082797250

04 Nov 2025 09:05PM UTC coverage: 95.319% (+0.08%) from 95.236%
19082797250

push

github

demmings
Self Join && Join ON not equal

#65, #66 Issues.
The explicit self JOIN ON syntax is supported - however, the self join syntax where the JOIN ON is not explicitly stated is NOT supported at this time.

Previously only JOIN ON equality was supported ("="), I have changed to add support for other conditions as well as calculated fields.

1588 of 1682 branches covered (94.41%)

Branch coverage included in aggregate %.

375 of 376 new or added lines in 5 files covered. (99.73%)

13093 of 13720 relevant lines covered (95.43%)

281.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.09
/src/SqlTest.js
1
/*  *** DEBUG START ***  
1✔
2
//  Remove comments for testing in NODE
1✔
3
import { Sql, GasSql, gsSQL } from './Sql.js';
1✔
4
import { Table } from './Table.js';
1✔
5
import { TableData } from './TableData.js';
1✔
6
import { Logger, Utilities } from '../GasMocks.js';
1✔
7
import { Select2Object } from './Select2Object.js';
1✔
8
import { SelectTables } from './Views.js';
1✔
9
export { Range };
1✔
10
export { SqlTester };
1✔
11
export { TestSql };
1✔
12
export { SpreadsheetApp };
1✔
13

1✔
14
//  GAS Mock Ups.
1✔
15

1✔
16
class SpreadsheetApp {
1✔
17
    static getActiveSpreadsheet() {
1✔
18
        return new SpreadsheetApp();
8✔
19
    }
8✔
20

1✔
21
    getRangeByName(tableNamedRange) {
1✔
22
        const dataRange = new Range(tableNamedRange);
6✔
23
        return dataRange.getMockData() === null ? null : dataRange;
6✔
24
    }
6✔
25

1✔
26
    getSheetByName(sheetTabName) {
1✔
27
        let sheetObj = new Sheet(sheetTabName);
2✔
28
        if (sheetObj.getSheetValues(1, 1, 1, 1) === null)
2✔
29
            return null;
2!
30
        return sheetObj;
2✔
31
    }
2✔
32

1✔
33
    static getUi() {
1✔
34
        return new Ui();
×
35
    }
×
36
}
1✔
37

1✔
38
class Ui {
1✔
39
    createMenu(name) {
1✔
40
        return this;
×
41
    }
×
42

1✔
43
    addItem(dest, func) {
1✔
44
        return this;
×
45
    }
×
46

1✔
47
    addToUi() {
1✔
48
        return this;
×
49
    }
×
50
}
1✔
51

1✔
52
class Sheet {
1✔
53
    constructor(sheetName) {
1✔
54
        this.sheetName = sheetName;
2✔
55
    }
2✔
56

1✔
57
    getLastColumn() {
1✔
58
        let data = this.getSheetValues(-1, -1, -1, -1);
1✔
59
        if (data !== null && data.length > 0)
1✔
60
            return data[0].length;
1✔
61

×
62
        return -1
×
63
    }
1✔
64

1✔
65
    getLastRow() {
1✔
66
        let data = this.getSheetValues(-1, -1, -1, -1);
1✔
67
        if (data !== null && data.length > 0)
1✔
68
            return data.length;
1✔
69

×
70
        return -1;
×
71
    }
1✔
72

1✔
73
    getSheetValues(startRow, startCol, lastRow, lastColumn) {
1✔
74
        let tester = new SqlTester();
5✔
75

5✔
76
        switch (this.sheetName.toUpperCase()) {
5✔
77
            case "MASTER TRANSACTIONS":
5✔
78
                return tester.masterTransactionsTable();
5✔
79
            default:
5!
80
                return null;
×
81
        }
5✔
82
    }
5✔
83

1✔
84

1✔
85
    getRange(row, col, numRows, numCols) {
1✔
86
        return new Range();
×
87
    }
×
88
}
1✔
89

1✔
90
class Range {
1✔
91
    constructor(tableNameRange = "") {
1✔
92
        this.tableNameRange = tableNameRange;
6✔
93
    }
6✔
94

1✔
95
    getValues() {
1✔
96
        return this.getMockData();
3✔
97
    }
3✔
98

1✔
99
    getValue() {
1✔
100
        return this.getMockData()
2✔
101
    }
2✔
102

1✔
103
    clearContent() {
1✔
104
        return this;
×
105
    }
×
106

1✔
107
    clearFormat() {
1✔
108
        return this;
×
109
    }
×
110

1✔
111
    clear() {
1✔
112
        return this;
×
113
    }
×
114

1✔
115
    setValues(values) {
1✔
116
        return this;
×
117
    }
×
118

1✔
119
    setFontWeight(font) {
1✔
120
        return this;
×
121
    }
×
122

1✔
123
    setFormula(formula) {
1✔
124
        return this;
×
125
    }
×
126

1✔
127
    setBackground(background) {
1✔
128
        return this;
×
129
    }
×
130

1✔
131
    setFormulas(formulas) {
1✔
132
        return this;
×
133
    }
×
134

1✔
135
    //  Set data to be returned for any named range tested.
1✔
136
    getMockData() {
1✔
137
        let tester = new SqlTester();
11✔
138

11✔
139
        switch (this.tableNameRange.toUpperCase()) {
11✔
140
            case 'STARTINCOMEDATE':
11✔
141
                return '6/7/2019';
2✔
142
            case 'ENDINCOMEDATE':
11✔
143
                return '6/20/2019';
2✔
144
            case "MASTER_TRANSACTIONS":
11!
145
            case "MASTER TRANSACTIONS!$A$1:$I":
11✔
146
            case "MASTER TRANSACTIONS!$A$1:$I30":
11✔
147
                return tester.masterTransactionsTable();
6✔
148
            case 'ACCOUNTNAMESDATA':
11!
149
                return tester.bookTable();
×
150
            default:
11✔
151
                return null;
1✔
152
        }
11✔
153
    }
11✔
154
}
1✔
155

1✔
156
//  *** DEBUG END ***/
1✔
157

1✔
158
/**
1✔
159
 * Runs all tests and reports back the result of the tests.
1✔
160
 * @customfunction
1✔
161
 */
1✔
162
function SQLselfTest() {
×
163
    const success = testerSql() ? "Success" : "Failed";
×
164

×
165
    return [[success]];
×
166
}
×
167

1✔
168
function SqlLiveDataTest() {
×
169
    let tester = new SqlTester();
×
170

×
171
    tester.liveTest1();
×
172
    tester.liveTest2();
×
173
}
×
174

1✔
175
/**
1✔
176
 * Function should be commented out when NOT running in a TEST SHEET.
1✔
177
 * It will create a menu option that allows you to create a gsSQL() 
1✔
178
 * statement for every test SQL in TestSQL().
1✔
179
 */
1✔
180
function onOpen() {
×
181
    if (SpreadsheetApp.getActiveSpreadsheet().getSheetByName("gsSqlTest") === null) {
×
182
        //  Only create menu option on test sheet.
×
183
        return true;
×
184
    }
×
185

×
186
    // This line calls the SpreadsheetApp and gets its UI   
×
187
    // Or DocumentApp or FormApp.
×
188
    const ui = SpreadsheetApp.getUi();
×
189

×
190
    //These lines create the menu items and 
×
191
    // tie them to functions we will write in Apps Script
×
192

×
193
    ui.createMenu('gsSQL Options')
×
194
        .addItem('Generate Tests on TDD SHEET !!!', 'customMenuGenerateTests')
×
195
        .addToUi();
×
196
}
×
197

1✔
198
/**
1✔
199
 * @type {TestedStatements[]}
1✔
200
 */
1✔
201
let sqlTestCases = [];
1✔
202

1✔
203
/**
1✔
204
 * Expected to be run as a menu item.
1✔
205
 * Runs all internal tests, collects the SQL from each test and generates
1✔
206
 * a =gsSQL() string and writes it to the current active screen.
1✔
207
 * Each customfunction is written in column A, starting two rows below the
1✔
208
 * last row in the current sheet.  Room is left after the expected results
1✔
209
 * and the subsequent gsSQL() will be updated 3 rows after.
1✔
210
 */
1✔
211
function customMenuGenerateTests() {
×
212
    sqlTestCases = [];      //  Reset collected test case array.
×
213
    testerSql();
×
214
    TestSql.generateTestCustomFunctions();
×
215
}
×
216

1✔
217
/**
1✔
218
 * Needed by Google Sheets Testing app.
1✔
219
 * @param {String} functionName 
1✔
220
 * @param {any[][]} array1 
1✔
221
 * @param {any[][]} array2 
1✔
222
 * @returns {String[][]}
1✔
223
 * @customfunction
1✔
224
 */
1✔
225
function isEqual(functionName, array1, array2) {
×
226
    const test = new SqlTester();
×
227
    const status = test.isEqual(functionName, array1, array2) ? "Equal" : "Not Equal";
×
228

×
229
    const results = [];
×
230
    results.push([functionName]);
×
231
    results.push([status]);
×
232

×
233
    return results;
×
234
}
×
235

1✔
236
class TestedStatements {
1✔
237
    /**
1✔
238
     * 
1✔
239
     * @param {String} statement 
1✔
240
     * @param {any[]} bindVariables 
1✔
241
     * @param {any[][]} data 
1✔
242
     * @param {Map<String,Table>} tables
1✔
243
     * @param {Boolean} generateColumnTitles
1✔
244
     */
1✔
245
    constructor(statement, bindVariables, data, tables, generateColumnTitles) {
1✔
246
        this.statement = statement;
174✔
247
        this.bindVariables = bindVariables;
174✔
248
        this.expectedOutputlines = data.length;
174✔
249
        this.data = data;
174✔
250
        this.tables = tables;
174✔
251
        this.generateColumnTitles = generateColumnTitles;
174✔
252
        this.generateTableDefinition = false;
174✔
253

174✔
254
        // @ts-ignore
174✔
255
        for (let tableInfo of this.tables.values()) {
174✔
256
            if (!tableInfo.hasColumnTitle)
284✔
257
                this.generateTableDefinition = true;
284✔
258
        }
284✔
259
    }
174✔
260

1✔
261
    /**
1✔
262
     * 
1✔
263
     * @returns {String}
1✔
264
     */
1✔
265
    getTableDefinitionString() {
1✔
266
        let definition = "{";
×
267
        let tabDef = "";
×
268

×
269
        // @ts-ignore
×
270
        for (let table of this.tables.values()) {
×
271
            let rangeName = table.tableName;
×
272
            if (table.tableData.length > 0) {
×
273
                rangeName += "!A2:" + Table.numberToSheetColumnLetter(table.tableData[0].length)
×
274
            }
×
275

×
276
            if (tabDef !== "") {
×
277
                tabDef += ";";
×
278
            }
×
279

×
280
            tabDef += "{";
×
281

×
282
            tabDef += '"' + table.tableName + '",';
×
283
            tabDef += '"' + rangeName + '",';
×
284
            tabDef += "60, " + table.hasColumnTitle.toString();
×
285

×
286
            tabDef += "}";
×
287
        }
×
288

×
289
        definition += tabDef + "}";
×
290
        return definition;
×
291
    }
×
292
}
1✔
293

1✔
294
class TestSql extends Sql {
1✔
295
    constructor() {
1✔
296
        super();
204✔
297
    }
204✔
298

1✔
299
    /**
1✔
300
     * 
1✔
301
     * @param {String} stmt 
1✔
302
     * @returns {any[][]}
1✔
303
     */
1✔
304
    execute(stmt) {
1✔
305
        let bindings = [...super.getBindData()];
204✔
306
        let tables = super.getTables();
204✔
307
        let generateColumnTitles = super.areColumnTitlesOutput();
204✔
308

204✔
309
        const data = super.execute(stmt);
204✔
310

204✔
311
        let test = new TestedStatements(stmt, bindings, data, tables, generateColumnTitles);
204✔
312

204✔
313
        sqlTestCases.push(test);
204✔
314

204✔
315
        return data;
204✔
316
    }
204✔
317

1✔
318
    static generateTestCustomFunctions() {
1✔
319
        let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TDD");
×
320

×
321
        if (sheet === null) {
×
322
            Logger.log("Invalid SHEET.  'TDD' not found.");
×
323
            return;
×
324
        }
×
325

×
326
        const SUMMARY_ITEMS_PER_ROW = 10;
×
327
        const SHEET_HEADER_ROWS = 6;
×
328

×
329
        //  Clear out old tests.
×
330
        sheet.getRange(SHEET_HEADER_ROWS, 1, sheet.getLastRow(), sheet.getLastColumn()).clearContent().clearFormat().clear();
×
331

×
332
        const rowsForSummary = Math.ceil(sqlTestCases.length / SUMMARY_ITEMS_PER_ROW) * 3;
×
333
        const summaryTestResults = [];
×
334
        let summaryTestResultRow = [];
×
335
        let blankRow = [];
×
336

×
337
        let testCount = 1;
×
338

×
339
        let lastRow = sheet.getLastRow() + 3 + rowsForSummary;
×
340

×
341
        for (const testCase of sqlTestCases) {
×
342
            let descriptionRange = sheet.getRange(lastRow - 1, 1, 1, 2);
×
343
            let testNumber = "Test  #" + testCount;
×
344

×
345
            let descriptionRow = [[testNumber, testCase.statement]];
×
346
            descriptionRange.setValues(descriptionRow);
×
347
            descriptionRange.setFontWeight("bold");
×
348

×
349
            let formula = TestSql.makeCustomFormulaString(testCase);
×
350

×
351
            let formulaRange = sheet.getRange(lastRow, 1);
×
352
            formulaRange.setFormula(formula);
×
353

×
354
            //  Write out expected results.
×
355
            if (testCase.data.length > 0) {
×
356
                let expectedRange = sheet.getRange(lastRow, 3 + testCase.data[0].length, testCase.data.length, testCase.data[0].length);
×
357
                // expectedRange.setNumberFormat("@");
×
358
                expectedRange.setValues(testCase.data);
×
359
                expectedRange.setFontWeight("bold").setBackground("yellow");
×
360

×
361
                let resultsRange = sheet.getRange(lastRow, 1, testCase.data.length, testCase.data[0].length);
×
362
                resultsRange.setBackground("cyan");
×
363
                let resultFormula = TestSql.makeTestResultFormulaString(testCount, resultsRange, expectedRange);
×
364
                summaryTestResultRow.push(resultFormula);
×
365
                blankRow.push("");
×
366
                if (summaryTestResultRow.length >= SUMMARY_ITEMS_PER_ROW) {
×
367
                    summaryTestResults.push(summaryTestResultRow);
×
368
                    summaryTestResults.push(blankRow);
×
369
                    summaryTestResults.push(blankRow);
×
370
                    summaryTestResultRow = [];
×
371
                    blankRow = [];
×
372
                }
×
373
            }
×
374

×
375
            lastRow = lastRow + testCase.expectedOutputlines + 3;
×
376
            testCount++;
×
377
        }
×
378

×
379
        if (summaryTestResultRow.length > 0) {
×
380
            while (summaryTestResultRow.length < SUMMARY_ITEMS_PER_ROW) {
×
381
                summaryTestResultRow.push("");
×
382
            }
×
383
            summaryTestResults.push(summaryTestResultRow);
×
384
        }
×
385

×
386
        if (summaryTestResults.length > 0) {
×
387
            Logger.log(`Items=${summaryTestResults.length}. Cols=${summaryTestResults[0].length}`);
×
388
            let summaryRange = sheet.getRange(SHEET_HEADER_ROWS, 1, summaryTestResults.length, summaryTestResults[0].length);
×
389
            summaryRange.setFormulas(summaryTestResults);
×
390
        }
×
391
    }
×
392

1✔
393
    /**
1✔
394
     * 
1✔
395
     * @param {TestedStatements} testCase 
1✔
396
     * @returns {String}
1✔
397
     */
1✔
398
    static makeCustomFormulaString(testCase) {
1✔
399
        let tableDefinitionString = "";
×
400
        if (testCase.generateTableDefinition) {
×
401
            tableDefinitionString = testCase.getTableDefinitionString();
×
402
        }
×
403

×
404
        let formula = '=gsSQL("' + testCase.statement + '"';
×
405

×
406
        if (testCase.bindVariables.length > 0 || !testCase.generateColumnTitles) {
×
407
            formula += "," + tableDefinitionString + ", " + testCase.generateColumnTitles.toString();
×
408
            for (const bindData of testCase.bindVariables) {
×
409
                formula += ", ";
×
410
                if (typeof bindData === 'string') {
×
411
                    formula += '"' + bindData + '"';
×
412
                }
×
413
                else if (bindData instanceof Date) {
×
414
                    formula += '"' + Utilities.formatDate(bindData, "GMT+1", "MM/dd/yyyy") + '"';
×
415
                }
×
416
                else {
×
417
                    formula += bindData;
×
418
                }
×
419
            }
×
420
        }
×
421
        else if (tableDefinitionString !== "") {
×
422
            formula += "," + tableDefinitionString + ", true";
×
423
        }
×
424

×
425
        formula += ')';
×
426

×
427
        return formula;
×
428
    }
×
429

1✔
430
    static makeTestResultFormulaString(testNumber, rangeResults, rangeExpected) {
1✔
431
        let formula = '=isEqual("Test #' + testNumber.toString() + '"';
×
432

×
433
        formula += "," + rangeResults.getA1Notation();
×
434
        formula += "," + rangeExpected.getA1Notation();
×
435
        formula += ")";
×
436

×
437
        return formula;
×
438
    }
×
439
}
1✔
440

1✔
441
class SqlTester {
1✔
442
    /*
1✔
443
    LOAD DATA INFILE '/home/cdemmings/Projects/Sheets/CanadianRetirementPlanner/SQL/csv/books.csv'
1✔
444
    INTO TABLE books
1✔
445
    FIELDS 
1✔
446
        TERMINATED BY ', '
1✔
447
        ENCLOSED BY '\"'
1✔
448
        ESCAPED BY ''
1✔
449
    LINES TERMINATED BY '\n'
1✔
450
    IGNORE 1 ROWS;
1✔
451
    */
1✔
452

1✔
453
    /* CREATE TABLE books (id CHAR(6), title VARCHAR(200),
1✔
454
        type VARCHAR(20), author_id CHAR(6), editor_id CHAR(6), translator_id CHAR(6));
1✔
455
    */
1✔
456
    bookTable(extraRecords = 0) {
1✔
457
        let recs = [
49✔
458
            ["id", "title", "type", "author id", "editor id", "translator id"],
49✔
459
            ["1", "Time to Grow Up!", "original", "11", "21", ""],
49✔
460
            ["2", "Your Trip", "translated", "15", "22", "32"],
49✔
461
            ["3", "Lovely Love", "original", "14", "24", ""],
49✔
462
            ["4", "Dream Your Life", "original", "11", "24", ""],
49✔
463
            ["5", "Oranges", "translated", "12", "25", "31"],
49✔
464
            ["6", "Your Happy Life", "translated", "15", "22", "33"],
49✔
465
            ["7", "Applied AI", "translated", "13", "23", "34"],
49✔
466
            ["9", "Book with Mysterious Author", "translated", "1", "23", "34"],
49✔
467
            ["8", "My Last Book", "original", "11", "28", ""]
49✔
468
        ];
49✔
469

49✔
470
        for (let i = 0; i < extraRecords; i++) {
49!
471
            let newRecord = [];
×
472

×
473
            newRecord.push((10 + i).toString());
×
474
            newRecord.push("Great Boook volume " + (1 + i).toString());
×
475
            newRecord.push(i % 2 === 0 ? "original" : "translated");
×
476
            newRecord.push((11 + i).toString());
×
477
            newRecord.push((12 + i).toString());
×
478
            newRecord.push((13 + i).toString());
×
479

×
480
            recs.push(newRecord);
×
481
        }
×
482

49✔
483
        return recs;
49✔
484
    }
49✔
485

1✔
486
    /*
1✔
487
    LOAD DATA INFILE '/home/cdemmings/Projects/Sheets/CanadianRetirementPlanner/SQL/csv/booksales.csv'
1✔
488
    INTO TABLE booksales
1✔
489
    FIELDS 
1✔
490
        TERMINATED BY ', '
1✔
491
        ENCLOSED BY '\"'
1✔
492
        ESCAPED BY ''
1✔
493
    LINES TERMINATED BY '\n'
1✔
494
    IGNORE 1 ROWS;
1✔
495
    */
1✔
496

1✔
497
    /* CREATE TABLE booksales (invoice CHAR(6), book_id CHAR(6),
1✔
498
        customer_id CHAR(6), quantity integer, price double, date date);
1✔
499
    */
1✔
500
    bookSalesTable(extraRecords = 0) {
1✔
501
        let recs = [
117✔
502
            ["Invoice", "Book Id", "Customer ID", "Quantity", "Price", "Date"],
117✔
503
            ["I7200", "9", "C1", 10, 34.95, "05/01/2022"],
117✔
504
            ["I7201", "8", "C2", 3, 29.95, "05/01/2022"],
117✔
505
            ["I7201", "7", "C2", 5, 18.99, "05/01/2022"],
117✔
506
            ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
117✔
507
            ["I7203", "1", "", 1, 90, "05/02/2022"],
117✔
508
            ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
117✔
509
            ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
117✔
510
            ["I7204", "4", "C4", 50, 19.99, "05/03/2022"],
117✔
511
            ["I7205", "7", "C1", 1, 33.97, "05/04/2022"],
117✔
512
            ["I7206", "7", "C2", 100, 17.99, "05/04/2022"]
117✔
513
        ];
117✔
514

117✔
515
        for (let i = 0; i < extraRecords; i++) {
117!
516
            let newRecord = [];
×
517

×
518
            newRecord.push("I" + (707 + i).toString());
×
519
            newRecord.push((10 + i).toString());
×
520
            newRecord.push("C" + (5 + i).toString());
×
521
            newRecord.push(i % 100);
×
522
            newRecord.push(i % 100 + 1 / (i % 99 === 0 ? 99 : i % 99));
×
523
            newRecord.push((1 + i % 12).toString() + "/" + (i % 28).toString() + "/" + (2022 + i % 50).toString());
×
524

×
525
            recs.push(newRecord);
×
526
        }
×
527

117✔
528
        return recs;
117✔
529
    }
117✔
530

1✔
531
    /*
1✔
532
    LOAD DATA INFILE '/home/cdemmings/Projects/Sheets/CanadianRetirementPlanner/SQL/csv/bookreturns.csv'
1✔
533
    INTO TABLE bookreturns
1✔
534
    FIELDS 
1✔
535
        TERMINATED BY ', '
1✔
536
        ENCLOSED BY '\"'
1✔
537
        ESCAPED BY ''
1✔
538
    LINES TERMINATED BY '\n'
1✔
539
    IGNORE 1 ROWS;
1✔
540
    */
1✔
541

1✔
542
    /* CREATE TABLE bookreturns (rma CHAR(7), book_id CHAR(6),
1✔
543
        customer_id CHAR(6), quantity integer, price double, date date);
1✔
544
    */
1✔
545
    bookReturnsTable() {
1✔
546
        return [
10✔
547
            ["RMA", "Book Id", "Customer ID", "Quantity", "Price", "Date"],
10✔
548
            ["Rma001", "9", "c1", 10, 34.95, "05/01/2022"],
10✔
549
            ["rma020", "8", "c2", 3, 29.95, "05/01/2022"],
10✔
550
            ["rmA030", "7", "c2", 5, 18.99, "05/01/2022"],
10✔
551
            ["RMA040", "9", "c3", 1, 59.99, "05/02/2022"],
10✔
552
            ["rma005", "1", "c1", 1, 90, "05/02/2022"],
10✔
553
            ["RMA600", "2", "c4", 100, 65.49, "05/03/2022"],
10✔
554
            ["Rma701", "3", "c4", 150, 24.95, "05/03/2022"],
10✔
555
            ["RmA800", "4", "c4", 50, 19.99, "05/03/2022"],
10✔
556
            ["RMA900", "7", "c1", 1, 33.97, "05/04/2022"],
10✔
557
            ["rma1010", "7", "c2", 100, 17.99, "05/04/2022"]
10✔
558
        ];
10✔
559

10✔
560
    }
10✔
561

1✔
562
    /*
1✔
563
    LOAD DATA INFILE '/home/cdemmings/Projects/Sheets/CanadianRetirementPlanner/SQL/csv/customers.csv'
1✔
564
    INTO TABLE customers
1✔
565
    FIELDS 
1✔
566
        TERMINATED BY ', '
1✔
567
        ENCLOSED BY '\"'
1✔
568
        ESCAPED BY ''
1✔
569
    LINES TERMINATED BY '\n'
1✔
570
    IGNORE 1 ROWS;
1✔
571
    */
1✔
572

1✔
573
    /* CREATE TABLE customers (id CHAR(6), name VARCHAR(100),
1✔
574
        address VARCHAR(200), city VARCHAR(50), phone CHAR(20), email VARCHAR(200));
1✔
575
    */
1✔
576
    customerTable() {
1✔
577
        return [
38✔
578
            ["ID", "Name", "Address", "City", "Phone", "eMail"],
38✔
579
            ["C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
38✔
580
            ["C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"],
38✔
581
            ["C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
38✔
582
            ["C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"],
38✔
583
            ["C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
38✔
584
            ["C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
38✔
585
            ["C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "]
38✔
586
        ];
38✔
587

38✔
588
    }
38✔
589

1✔
590
    /*
1✔
591
    LOAD DATA INFILE '/home/cdemmings/Projects/Sheets/CanadianRetirementPlanner/SQL/csv/authors.csv'
1✔
592
    INTO TABLE authors
1✔
593
    FIELDS 
1✔
594
        TERMINATED BY ', '
1✔
595
        ENCLOSED BY '\"'
1✔
596
        ESCAPED BY ''
1✔
597
    LINES TERMINATED BY '\n'
1✔
598
    IGNORE 1 ROWS;
1✔
599
    */
1✔
600

1✔
601
    /* CREATE TABLE authors (id CHAR(6), first_name VARCHAR(100),
1✔
602
        last_name VARCHAR(200));
1✔
603
    */
1✔
604
    authorsTable() {
1✔
605
        return [
46✔
606
            ["id", "first_name", "last_name"],
46✔
607
            ["11", "Ellen", "Writer"],
46✔
608
            ["12", "Olga", "Savelieva"],
46✔
609
            ["13", "Jack", "Smart"],
46✔
610
            ["14", "Donald", "Brain"],
46✔
611
            ["15", "Yao", "Dou"]
46✔
612
        ];
46✔
613
    }
46✔
614

1✔
615
    /*
1✔
616
    LOAD DATA INFILE '/home/cdemmings/Projects/Sheets/CanadianRetirementPlanner/SQL/csv/editors.csv'
1✔
617
    INTO TABLE editors
1✔
618
    FIELDS 
1✔
619
        TERMINATED BY ', '
1✔
620
        ENCLOSED BY '\"'
1✔
621
        ESCAPED BY ''
1✔
622
    LINES TERMINATED BY '\n'
1✔
623
    IGNORE 1 ROWS;
1✔
624
    */
1✔
625

1✔
626
    /* CREATE TABLE editors (id CHAR(6), first_name VARCHAR(100),
1✔
627
        last_name VARCHAR(200));
1✔
628
    */
1✔
629
    editorsTable() {
1✔
630
        return [
32✔
631
            ["id", "first name", "last name"],
32✔
632
            ["13", "Jack", "Smart"],
32✔
633
            ["21", "Daniel", "Brown"],
32✔
634
            ["22", "Mark", "Johnson"],
32✔
635
            ["23", "Maria", "Evans"],
32✔
636
            ["24", "Cathrine", "Roberts"],
32✔
637
            ["25", "Sebastian", "Wright"],
32✔
638
            ["26", "Barbara", "Jones"],
32✔
639
            ["27", "Matthew", "Smith"],
32✔
640
            ["50", "Jack", "Dumb"],
32✔
641
            ["51", "Daniel", "Smart"]
32✔
642
        ];
32✔
643
    }
32✔
644

1✔
645

1✔
646
    /*
1✔
647
    LOAD DATA INFILE '/home/cdemmings/Projects/Sheets/CanadianRetirementPlanner/SQL/csv/translators.csv'
1✔
648
    INTO TABLE translators
1✔
649
    FIELDS 
1✔
650
        TERMINATED BY ', '
1✔
651
        ENCLOSED BY '\"'
1✔
652
        ESCAPED BY ''
1✔
653
    LINES TERMINATED BY '\n'
1✔
654
    IGNORE 1 ROWS;
1✔
655
    */
1✔
656

1✔
657
    /* CREATE TABLE translators (id CHAR(6), first_name VARCHAR(100),
1✔
658
        last_name VARCHAR(200));
1✔
659
    */
1✔
660
    translatorsTable() {
1✔
661
        return [
15✔
662
            ["id", "first_name", "last_name"],
15✔
663
            ["31", "Ira", "Davies"],
15✔
664
            ["32", "Ling", "Weng"],
15✔
665
            ["33", "Kristian", "Green"],
15✔
666
            ["34", "Roman", "Edwards"]
15✔
667
        ];
15✔
668

15✔
669
    }
15✔
670

1✔
671
    masterTransactionsTable() {
1✔
672
        return [
15✔
673
            ["Name of Institution", "Transaction Date", "Description 1", "Description 2", "Amount", "Expense Category", "Account", "Gross", "Balance"],
15✔
674
            ["Royal Bank of Canada", new Date("6/7/2019"), "Interac purchase - 3707 NADIM'S NO FRIL", "", -47.85, "Food & Dining - Groceries", "", "", ""],
15✔
675
            ["Royal Bank of Canada", new Date("6/7/2019"), "Interac purchase - 2357 FRESHCO 3826", "", -130.36, "Food & Dining - Groceries", "", "", ""],
15✔
676
            ["Royal Bank of Canada", new Date("6/7/2019"), "Payroll Deposit WEST UNIFIED CO", "", 2343.48, "Income - Paycheck", "", "", ""],
15✔
677
            ["Royal Bank of Canada", new Date("6/7/2019"), "MBNA-MASTERCARD", "", -500, "Transfer - CC", "", "", ""],
15✔
678
            ["Royal Bank of Canada", new Date("6/7/2019"), "e-Transfer sent S.E", "", -575, "Utilities - Rent", "", "", ""],
15✔
679
            ["Royal Bank of Canada", new Date("6/11/2019"), "Insurance ADMIN.BY GWL", "", 122.4, "Health & Fitness - Health Insurance", "", "", ""],
15✔
680
            ["Royal Bank of Canada", new Date("6/13/2019"), "Misc Payment GOODLIFE CLUBS", "", -24.85, "Health & Fitness - Gym", "", "", ""],
15✔
681
            ["Royal Bank of Canada", new Date("6/13/2019"), "WHITBY TAXES", "", -100, "Taxes - Property Tax", "", "", ""],
15✔
682
            ["Royal Bank of Canada", new Date("6/13/2019"), "Online Transfer to Deposit Account-***9", "", -15, "Transfer - Savings acct", "", "", ""],
15✔
683
            ["Royal Bank of Canada", new Date("6/14/2019"), "Interac purchase - 8727 NADIM'S NO FRIL", "", -86.73, "Food & Dining - Groceries", "", "", ""],
15✔
684
            ["Royal Bank of Canada", new Date("6/14/2019"), "Insurance ADMIN.BY GWL", "", 300, "Health & Fitness - Dentist", "", "", ""],
15✔
685
            ["Royal Bank of Canada", new Date("6/17/2019"), "Interac purchase - 0238 BAMIYAN KABOB", "", -12.98, "Food & Dining - Restaurants", "", "", ""],
15✔
686
            ["Royal Bank of Canada", new Date("6/17/2019"), "Interac purchase - 1236 NADIM'S NO FRIL", "", -33.32, "Food & Dining - Groceries", "", "", ""],
15✔
687
            ["Royal Bank of Canada", new Date("6/17/2019"), "Deposit ONLINE TRANSFER", "", 12000, "Transfer - Savings acct", "", "", ""],
15✔
688
            ["Royal Bank of Canada", new Date("6/18/2019"), "MBNA-MASTERCARD", "", -1100, "Transfer - CC", "", "", ""],
15✔
689
            ["MBNA Mastercard", new Date("6/19/2019"), "PAYMENT", "", 1100, "Transfer - Savings acct", "", "", ""],
15✔
690
            ["Royal Bank of Canada", new Date("6/19/2019"), "Utility Bill Pmt Enbridge Gas", "", -108, "Utilities - Heating (Gas)", "", "", ""],
15✔
691
            ["MBNA Mastercard", new Date("6/20/2019"), "JOE'S NO FRILLS 3141 WHITBY ON", "", -41.77, "Food & Dining - Groceries", "", "", ""],
15✔
692
            ["MBNA Mastercard", new Date("6/20/2019"), "PIONEER STN#200 WHITBY ON", "", -28.17, "Auto - Fuel", "", "", ""],
15✔
693
            ["MBNA Mastercard", new Date("6/20/2019"), "AVIVA GENERAL INSURANC MARKHAM ON", "", -137.93, "Utilities - Insurance", "", "", ""],
15✔
694
            ["MBNA Mastercard", new Date("6/20/2019"), "AVIVA GENERAL INSURANC MARKHAM ON", "", -307.73, "Auto - Insurance", "", "", ""],
15✔
695
            ["Royal Bank of Canada", new Date("6/20/2019"), "Misc Payment Archdiocese TO", "", -22, "Gifts & Donations - Donations", "", "", ""],
15✔
696
            ["Royal Bank of Canada", new Date("6/20/2019"), "ELEXICON-WHITBY", "", -95, "Utilities - Electricity", "", "", ""],
15✔
697
            ["Royal Bank of Canada", new Date("6/20/2019"), "WHITBY TAXES", "", -100, "Taxes - Property Tax", "", "", ""]
15✔
698
        ];
15✔
699
    }
15✔
700

1✔
701
    yearlySalesTable() {
1✔
702
        return [
1✔
703
            ["Name", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
1✔
704
            ["Chris", 50, "", "", "", 60, "", "", "", "", "", "", ""],
1✔
705
            ["Fred", "", "", "", "", "", "", 20, 30, "", "", "", ""],
1✔
706
            ["Dan", "", "", "", "", "", 10, 20, 31, "", "", "", ""],
1✔
707
            ["Kev", "", 10, 20, "", 60, "", "", "", "", "", "", ""],
1✔
708
            ["Dori", "", "", "", "", "", "", "", "", "", "", "", 50],
1✔
709
            ["Gab", 50, "", "", "", 60, "", "", 10, "20", "", "", ""]
1✔
710
        ]
1✔
711
    }
1✔
712

1✔
713
    selectAll1() {
1✔
714
        return this.selectAllAuthors("selectAll1", "select * from authors");
1✔
715
    }
1✔
716

1✔
717
    selectAllCase1() {
1✔
718
        return this.selectAllAuthors("selectAllCase1", "Select * from authors");
1✔
719
    }
1✔
720

1✔
721
    selectIsNotNull1() {
1✔
722
        return this.selectAllAuthors("selectIsNotNull1", "select * from authors where id is not null");
1✔
723
    }
1✔
724

1✔
725
    selectAllAuthors(functionName, stmt) {
1✔
726
        let data = new TestSql()
3✔
727
            .addTableData("authors", this.authorsTable())
3✔
728
            .enableColumnTitle(true)
3✔
729
            .execute(stmt);
3✔
730

3✔
731
        let expected = [["AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME"],
3✔
732
        ["11", "Ellen", "Writer"],
3✔
733
        ["12", "Olga", "Savelieva"],
3✔
734
        ["13", "Jack", "Smart"],
3✔
735
        ["14", "Donald", "Brain"],
3✔
736
        ["15", "Yao", "Dou"]];
3✔
737

3✔
738
        return this.isEqual(functionName, data, expected);
3✔
739
    }
3✔
740

1✔
741
    selectAllAuthorsToObject(functionName) {
1✔
742
        let stmt = "select * from authors";
1✔
743

1✔
744
        let data = new Select2Object()
1✔
745
            .addTableData("authors", this.authorsTable())
1✔
746
            .execute(stmt);
1✔
747

1✔
748
        let expected = [{ "id": "11", "first_name": "Ellen", "last_name": "Writer" },
1✔
749
        { "id": "12", "first_name": "Olga", "last_name": "Savelieva" },
1✔
750
        { "id": "13", "first_name": "Jack", "last_name": "Smart" },
1✔
751
        { "id": "14", "first_name": "Donald", "last_name": "Brain" },
1✔
752
        { "id": "15", "first_name": "Yao", "last_name": "Dou" }];
1✔
753

1✔
754
        return this.isEqual("selectAllAuthorsToObject", data, expected);
1✔
755
    }
1✔
756

1✔
757
    selectAnAuthorsToObject(functionName) {
1✔
758
        let stmt = "select * from authors where first_name = ?1";
1✔
759

1✔
760
        let data = new Select2Object()
1✔
761
            .addTableData("authors", this.authorsTable())
1✔
762
            .addBindVariable("Jack")
1✔
763
            .execute(stmt);
1✔
764

1✔
765
        let expected = [{ "id": "13", "first_name": "Jack", "last_name": "Smart" }];
1✔
766

1✔
767
        return this.isEqual("selectAnAuthorsToObject", data, expected);
1✔
768
    }
1✔
769

1✔
770
    selectIsNull1() {
1✔
771
        let stmt = "select * from authors where id is null";
1✔
772

1✔
773
        let data = new TestSql()
1✔
774
            .addTableData("authors", this.authorsTable())
1✔
775
            .enableColumnTitle(true)
1✔
776
            .execute(stmt);
1✔
777

1✔
778
        let expected = [["AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME"]];
1✔
779

1✔
780
        return this.isEqual("selectIsNull1", data, expected);
1✔
781
    }
1✔
782

1✔
783

1✔
784
    innerJoin1a() {
1✔
785
        let stmt = "SELECT books.id, books.title, authors.first_name, authors.last_name " +
1✔
786
            "FROM books " +
1✔
787
            "INNER JOIN authors " +
1✔
788
            "ON books.author_id = authors.id " +
1✔
789
            "ORDER BY books.id";
1✔
790

1✔
791
        return this.innerJoin1(stmt, "innerJoin1a");
1✔
792
    }
1✔
793

1✔
794
    innerJoin1case() {
1✔
795
        let stmt = "SELECT books.id, books.title, authors.first_name, authors.last_name " +
1✔
796
            "FROM books " +
1✔
797
            "Inner Join authors " +
1✔
798
            "ON books.author_id = authors.id " +
1✔
799
            "ORDER BY books.id";
1✔
800

1✔
801
        return this.innerJoin1(stmt, "innerJoin1case");
1✔
802
    }
1✔
803

1✔
804
    innerJoin1(stmt, funcName) {
1✔
805
        let data = new TestSql()
2✔
806
            .addTableData("books", this.bookTable())
2✔
807
            .addTableData("authors", this.authorsTable())
2✔
808
            .enableColumnTitle(true)
2✔
809
            .execute(stmt);
2✔
810

2✔
811
        let expected = [["books.id", "books.title", "authors.first_name", "authors.last_name"],
2✔
812
        ["1", "Time to Grow Up!", "Ellen", "Writer"],
2✔
813
        ["2", "Your Trip", "Yao", "Dou"],
2✔
814
        ["3", "Lovely Love", "Donald", "Brain"],
2✔
815
        ["4", "Dream Your Life", "Ellen", "Writer"],
2✔
816
        ["5", "Oranges", "Olga", "Savelieva"],
2✔
817
        ["6", "Your Happy Life", "Yao", "Dou"],
2✔
818
        ["7", "Applied AI", "Jack", "Smart"],
2✔
819
        ["8", "My Last Book", "Ellen", "Writer"]];
2✔
820

2✔
821
        return this.isEqual(funcName, data, expected);
2✔
822
    }
2✔
823

1✔
824
    innerJoin2() {
1✔
825
        let stmt = "SELECT books.id, books.title, books.type, authors.last_name, " +
1✔
826
            "translators.last_name " +
1✔
827
            "FROM books " +
1✔
828
            "INNER JOIN authors " +
1✔
829
            "ON books.author_id = authors.id " +
1✔
830
            "INNER JOIN translators " +
1✔
831
            "ON books.translator_id = translators.id " +
1✔
832
            "ORDER BY books.id";
1✔
833

1✔
834
        let data = new TestSql()
1✔
835
            .addTableData("books", this.bookTable())
1✔
836
            .addTableData("translators", this.translatorsTable())
1✔
837
            .addTableData("authors", this.authorsTable())
1✔
838
            .enableColumnTitle(true)
1✔
839
            .execute(stmt);
1✔
840

1✔
841
        let expected = [["books.id", "books.title", "books.type", "authors.last_name", "translators.last_name"],
1✔
842
        ["2", "Your Trip", "translated", "Dou", "Weng"],
1✔
843
        ["5", "Oranges", "translated", "Savelieva", "Davies"],
1✔
844
        ["6", "Your Happy Life", "translated", "Dou", "Green"],
1✔
845
        ["7", "Applied AI", "translated", "Smart", "Edwards"]];
1✔
846

1✔
847
        return this.isEqual("innerJoin2", data, expected);
1✔
848
    }
1✔
849

1✔
850
    innerJoin2ToObject() {
1✔
851
        let stmt = "SELECT books.id, books.title, books.type, authors.last_name, " +
1✔
852
            "translators.last_name " +
1✔
853
            "FROM books " +
1✔
854
            "INNER JOIN authors " +
1✔
855
            "ON books.author_id = authors.id " +
1✔
856
            "INNER JOIN translators " +
1✔
857
            "ON books.translator_id = translators.id " +
1✔
858
            "ORDER BY books.id";
1✔
859

1✔
860

1✔
861
        let data = new Select2Object()
1✔
862
            .addTableData("books", this.bookTable())
1✔
863
            .addTableData("translators", this.translatorsTable())
1✔
864
            .addTableData("authors", this.authorsTable())
1✔
865
            .execute(stmt);
1✔
866

1✔
867
        let expected = [{ "books.id": "2", "books.title": "Your Trip", "books.type": "translated", "authors.last_name": "Dou", "translators.last_name": "Weng" },
1✔
868
        { "books.id": "5", "books.title": "Oranges", "books.type": "translated", "authors.last_name": "Savelieva", "translators.last_name": "Davies" },
1✔
869
        { "books.id": "6", "books.title": "Your Happy Life", "books.type": "translated", "authors.last_name": "Dou", "translators.last_name": "Green" },
1✔
870
        { "books.id": "7", "books.title": "Applied AI", "books.type": "translated", "authors.last_name": "Smart", "translators.last_name": "Edwards" }];
1✔
871

1✔
872
        let test1 = this.isEqual("innerJoin2ToObject(a)", data, expected);
1✔
873

1✔
874
        data = data.filter(v => v["authors.last_name"] === "Smart");
1✔
875
        expected = [{ "books.id": "7", "books.title": "Applied AI", "books.type": "translated", "authors.last_name": "Smart", "translators.last_name": "Edwards" }];
1✔
876
        let test2 = this.isEqual("innerJoin2ToObject(b)", data, expected);;
1✔
877

1✔
878
        return test1 && test2;
1✔
879
    }
1✔
880

1✔
881
    innerJoinAlias1() {
1✔
882
        let stmt = "SELECT b.id, b.title, a.first_name, a.last_name " +
1✔
883
            "FROM books as b " +
1✔
884
            "INNER JOIN authors as a " +
1✔
885
            "ON b.author_id = a.id " +
1✔
886
            "ORDER BY books.id";
1✔
887

1✔
888
        let data = new TestSql()
1✔
889
            .addTableData("books", this.bookTable())
1✔
890
            .addTableData("authors", this.authorsTable())
1✔
891
            .enableColumnTitle(true)
1✔
892
            .execute(stmt);
1✔
893

1✔
894
        let expected = [["b.id", "b.title", "a.first_name", "a.last_name"],
1✔
895
        ["1", "Time to Grow Up!", "Ellen", "Writer"],
1✔
896
        ["2", "Your Trip", "Yao", "Dou"],
1✔
897
        ["3", "Lovely Love", "Donald", "Brain"],
1✔
898
        ["4", "Dream Your Life", "Ellen", "Writer"],
1✔
899
        ["5", "Oranges", "Olga", "Savelieva"],
1✔
900
        ["6", "Your Happy Life", "Yao", "Dou"],
1✔
901
        ["7", "Applied AI", "Jack", "Smart"],
1✔
902
        ["8", "My Last Book", "Ellen", "Writer"]];
1✔
903

1✔
904
        return this.isEqual("innerJoinAlias1", data, expected);
1✔
905
    }
1✔
906

1✔
907
    innerJoinAlias2() {
1✔
908
        let stmt = "SELECT b.id, b.title, a.first_name, a.last_name " +
1✔
909
            "FROM books as b " +
1✔
910
            "INNER JOIN authors as a " +
1✔
911
            "ON b.author_id = a.id " +
1✔
912
            "ORDER BY books.id";
1✔
913

1✔
914
        let testSQL = new TestSql()
1✔
915
            .addTableData("books", this.bookTable())
1✔
916
            .addTableData("authors", this.authorsTable())
1✔
917
            .enableColumnTitle(true);
1✔
918

1✔
919
        let data = testSQL.execute(stmt);
1✔
920

1✔
921
        let expected = [["b.id", "b.title", "a.first_name", "a.last_name"],
1✔
922
        ["1", "Time to Grow Up!", "Ellen", "Writer"],
1✔
923
        ["2", "Your Trip", "Yao", "Dou"],
1✔
924
        ["3", "Lovely Love", "Donald", "Brain"],
1✔
925
        ["4", "Dream Your Life", "Ellen", "Writer"],
1✔
926
        ["5", "Oranges", "Olga", "Savelieva"],
1✔
927
        ["6", "Your Happy Life", "Yao", "Dou"],
1✔
928
        ["7", "Applied AI", "Jack", "Smart"],
1✔
929
        ["8", "My Last Book", "Ellen", "Writer"]];
1✔
930

1✔
931
        this.isEqual("innerJoinAlias2a", data, expected);
1✔
932

1✔
933
        stmt = "SELECT b1.id, b1.title, a2.first_name, a2.last_name " +
1✔
934
            "FROM books as b1 " +
1✔
935
            "INNER JOIN authors as a2 " +
1✔
936
            "ON b1.author_id = a2.id " +
1✔
937
            "ORDER BY books.id";
1✔
938
        data = testSQL.execute(stmt);
1✔
939

1✔
940
        expected = [["b1.id", "b1.title", "a2.first_name", "a2.last_name"],
1✔
941
        ["1", "Time to Grow Up!", "Ellen", "Writer"],
1✔
942
        ["2", "Your Trip", "Yao", "Dou"],
1✔
943
        ["3", "Lovely Love", "Donald", "Brain"],
1✔
944
        ["4", "Dream Your Life", "Ellen", "Writer"],
1✔
945
        ["5", "Oranges", "Olga", "Savelieva"],
1✔
946
        ["6", "Your Happy Life", "Yao", "Dou"],
1✔
947
        ["7", "Applied AI", "Jack", "Smart"],
1✔
948
        ["8", "My Last Book", "Ellen", "Writer"]];
1✔
949

1✔
950
        return this.isEqual("innerJoinAlias2b", data, expected);
1✔
951
    }
1✔
952

1✔
953
    join2a() {
1✔
954
        let stmt = "SELECT books.id, books.title, books.type, translators.last_name  " +
1✔
955
            "FROM books " +
1✔
956
            "JOIN translators " +
1✔
957
            "ON books.translator_id = translators.id " +
1✔
958
            "ORDER BY books.id";
1✔
959

1✔
960
        return this.join2(stmt, "join2a");
1✔
961
    }
1✔
962
    join2b() {
1✔
963
        let stmt = "sElEcT books.id, books.title, books.type, translators.last_name  " +
1✔
964
            "froM books " +
1✔
965
            "Join translators " +
1✔
966
            "On books.translator_id = translators.id " +
1✔
967
            "ORDEr  By books.id";
1✔
968

1✔
969
        return this.join2(stmt, "join2b");
1✔
970
    }
1✔
971

1✔
972
    join2(stmt, funcName) {
1✔
973

2✔
974
        let data = new TestSql()
2✔
975
            .addTableData("books", this.bookTable())
2✔
976
            .addTableData("translators", this.translatorsTable())
2✔
977
            .enableColumnTitle(true)
2✔
978
            .execute(stmt)
2✔
979

2✔
980
        let expected = [["books.id", "books.title", "books.type", "translators.last_name"],
2✔
981
        ["2", "Your Trip", "translated", "Weng"],
2✔
982
        ["5", "Oranges", "translated", "Davies"],
2✔
983
        ["6", "Your Happy Life", "translated", "Green"],
2✔
984
        ["7", "Applied AI", "translated", "Edwards"],
2✔
985
        ["9", "Book with Mysterious Author", "translated", "Edwards"]];
2✔
986

2✔
987
        return this.isEqual(funcName, data, expected);
2✔
988
    }
2✔
989

1✔
990
    join3() {
1✔
991
        let stmt = "SELECT books.id, books.title, editors.last_name " +
1✔
992
            "FROM books " +
1✔
993
            "LEFT JOIN editors " +
1✔
994
            "ON books.editor_id = editors.id " +
1✔
995
            "ORDER BY books.id";
1✔
996

1✔
997
        let data = new TestSql()
1✔
998
            .addTableData("books", this.bookTable())
1✔
999
            .addTableData("editors", this.editorsTable())
1✔
1000
            .enableColumnTitle(true)
1✔
1001
            .execute(stmt);
1✔
1002

1✔
1003
        let expected = [["books.id", "books.title", "editors.last_name"],
1✔
1004
        ["1", "Time to Grow Up!", "Brown"],
1✔
1005
        ["2", "Your Trip", "Johnson"],
1✔
1006
        ["3", "Lovely Love", "Roberts"],
1✔
1007
        ["4", "Dream Your Life", "Roberts"],
1✔
1008
        ["5", "Oranges", "Wright"],
1✔
1009
        ["6", "Your Happy Life", "Johnson"],
1✔
1010
        ["7", "Applied AI", "Evans"],
1✔
1011
        ["8", "My Last Book", null],
1✔
1012
        ["9", "Book with Mysterious Author", "Evans"]];
1✔
1013

1✔
1014
        return this.isEqual("join3", data, expected);
1✔
1015
    }
1✔
1016

1✔
1017
    joinLimit1() {
1✔
1018
        let stmt = "SELECT books.id, books.title, editors.last_name " +
1✔
1019
            "FROM books " +
1✔
1020
            "LEFT JOIN editors " +
1✔
1021
            "ON books.editor_id = editors.id " +
1✔
1022
            "ORDER BY books.id " +
1✔
1023
            "LIMIT 5";
1✔
1024

1✔
1025
        let data = new TestSql()
1✔
1026
            .addTableData("books", this.bookTable())
1✔
1027
            .addTableData("editors", this.editorsTable())
1✔
1028
            .enableColumnTitle(true)
1✔
1029
            .execute(stmt);
1✔
1030

1✔
1031
        let expected = [["books.id", "books.title", "editors.last_name"],
1✔
1032
        ["1", "Time to Grow Up!", "Brown"],
1✔
1033
        ["2", "Your Trip", "Johnson"],
1✔
1034
        ["3", "Lovely Love", "Roberts"],
1✔
1035
        ["4", "Dream Your Life", "Roberts"],
1✔
1036
        ["5", "Oranges", "Wright"]];
1✔
1037

1✔
1038
        return this.isEqual("joinLimit1", data, expected);
1✔
1039
    }
1✔
1040

1✔
1041
    leftJoin1() {
1✔
1042
        let stmt = "SELECT books.id, books.title, books.type, authors.last_name, " +
1✔
1043
            "translators.last_name " +
1✔
1044
            "FROM books " +
1✔
1045
            "LEFT JOIN authors " +
1✔
1046
            "ON books.author_id = authors.id " +
1✔
1047
            "LEFT JOIN translators " +
1✔
1048
            "ON books.translator_id = translators.id " +
1✔
1049
            "ORDER BY books.id";
1✔
1050

1✔
1051
        let data = new TestSql()
1✔
1052
            .addTableData("books", this.bookTable())
1✔
1053
            .addTableData("translators", this.translatorsTable())
1✔
1054
            .addTableData("authors", this.authorsTable())
1✔
1055
            .enableColumnTitle(true)
1✔
1056
            .execute(stmt);
1✔
1057

1✔
1058
        let expected = [["books.id", "books.title", "books.type", "authors.last_name", "translators.last_name"],
1✔
1059
        ["1", "Time to Grow Up!", "original", "Writer", null],
1✔
1060
        ["2", "Your Trip", "translated", "Dou", "Weng"],
1✔
1061
        ["3", "Lovely Love", "original", "Brain", null],
1✔
1062
        ["4", "Dream Your Life", "original", "Writer", null],
1✔
1063
        ["5", "Oranges", "translated", "Savelieva", "Davies"],
1✔
1064
        ["6", "Your Happy Life", "translated", "Dou", "Green"],
1✔
1065
        ["7", "Applied AI", "translated", "Smart", "Edwards"],
1✔
1066
        ["8", "My Last Book", "original", "Writer", null],
1✔
1067
        ["9", "Book with Mysterious Author", "translated", null, "Edwards"]];
1✔
1068

1✔
1069
        return this.isEqual("leftJoin1", data, expected);
1✔
1070
    }
1✔
1071

1✔
1072
    rightJoin1() {
1✔
1073
        let stmt = "SELECT books.id, books.title, editors.last_name, editors.id  " +
1✔
1074
            "FROM books " +
1✔
1075
            "RIGHT JOIN editors " +
1✔
1076
            "ON books.editor_id = editors.id " +
1✔
1077
            "ORDER BY books.id";
1✔
1078

1✔
1079
        let data = new TestSql()
1✔
1080
            .addTableData("books", this.bookTable())
1✔
1081
            .addTableData("editors", this.editorsTable())
1✔
1082
            .enableColumnTitle(true)
1✔
1083
            .execute(stmt);
1✔
1084

1✔
1085
        let expected = [["books.id", "books.title", "editors.last_name", "editors.id"],
1✔
1086
        [null, null, "Smart", "13"],
1✔
1087
        [null, null, "Jones", "26"],
1✔
1088
        [null, null, "Smith", "27"],
1✔
1089
        [null, null, "Dumb", "50"],
1✔
1090
        [null, null, "Smart", "51"],
1✔
1091
        ["1", "Time to Grow Up!", "Brown", "21"],
1✔
1092
        ["2", "Your Trip", "Johnson", "22"],
1✔
1093
        ["3", "Lovely Love", "Roberts", "24"],
1✔
1094
        ["4", "Dream Your Life", "Roberts", "24"],
1✔
1095
        ["5", "Oranges", "Wright", "25"],
1✔
1096
        ["6", "Your Happy Life", "Johnson", "22"],
1✔
1097
        ["7", "Applied AI", "Evans", "23"],
1✔
1098
        ["9", "Book with Mysterious Author", "Evans", "23"]];
1✔
1099

1✔
1100
        return this.isEqual("rightJoin1", data, expected);
1✔
1101
    }
1✔
1102

1✔
1103
    rightJoin1a() {
1✔
1104
        let stmt = "SELECT books.id, books.title, editors.last_name, editors.id  " +
1✔
1105
            "FROM books " +
1✔
1106
            "right join editors on  editors.id = books.editor_id " +
1✔
1107
            "ORDER BY books.id";
1✔
1108

1✔
1109
        let data = new TestSql()
1✔
1110
            .addTableData("books", this.bookTable())
1✔
1111
            .addTableData("editors", this.editorsTable())
1✔
1112
            .enableColumnTitle(true)
1✔
1113
            .execute(stmt);
1✔
1114

1✔
1115
        let expected = [["books.id", "books.title", "editors.last_name", "editors.id"],
1✔
1116
        [null, null, "Smart", "13"],
1✔
1117
        [null, null, "Jones", "26"],
1✔
1118
        [null, null, "Smith", "27"],
1✔
1119
        [null, null, "Dumb", "50"],
1✔
1120
        [null, null, "Smart", "51"],
1✔
1121
        ["1", "Time to Grow Up!", "Brown", "21"],
1✔
1122
        ["2", "Your Trip", "Johnson", "22"],
1✔
1123
        ["3", "Lovely Love", "Roberts", "24"],
1✔
1124
        ["4", "Dream Your Life", "Roberts", "24"],
1✔
1125
        ["5", "Oranges", "Wright", "25"],
1✔
1126
        ["6", "Your Happy Life", "Johnson", "22"],
1✔
1127
        ["7", "Applied AI", "Evans", "23"],
1✔
1128
        ["9", "Book with Mysterious Author", "Evans", "23"]];
1✔
1129

1✔
1130
        return this.isEqual("rightJoin1a", data, expected);
1✔
1131
    }
1✔
1132

1✔
1133
    rightJoin2() {
1✔
1134
        let stmt = "SELECT books.id, books.title, books.translator_id, " +
1✔
1135
            "editors.last_name, editors.id,  " +
1✔
1136
            "translators.last_name " +
1✔
1137
            "FROM books " +
1✔
1138
            "RIGHT JOIN editors " +
1✔
1139
            "ON books.editor_id = editors.id " +
1✔
1140
            "RIGHT JOIN translators " +
1✔
1141
            "ON books.translator_id = translators.id " +
1✔
1142
            "ORDER BY books.id";
1✔
1143

1✔
1144
        let data = new TestSql()
1✔
1145
            .addTableData("books", this.bookTable())
1✔
1146
            .addTableData("translators", this.translatorsTable())
1✔
1147
            .addTableData("editors", this.editorsTable())
1✔
1148
            .enableColumnTitle(true)
1✔
1149
            .execute(stmt);
1✔
1150

1✔
1151
        let expected = [["books.id", "books.title", "books.translator_id", "editors.last_name", "editors.id", "translators.last_name"],
1✔
1152
        ["2", "Your Trip", "32", "Johnson", "22", "Weng"],
1✔
1153
        ["5", "Oranges", "31", "Wright", "25", "Davies"],
1✔
1154
        ["6", "Your Happy Life", "33", "Johnson", "22", "Green"],
1✔
1155
        ["7", "Applied AI", "34", "Evans", "23", "Edwards"],
1✔
1156
        ["9", "Book with Mysterious Author", "34", "Evans", "23", "Edwards"]];
1✔
1157

1✔
1158
        return this.isEqual("rightJoin2", data, expected);
1✔
1159
    }
1✔
1160

1✔
1161
    fullJoin1() {
1✔
1162
        let stmt = "SELECT authors.id, authors.last_name, editors.id, editors.last_name " +
1✔
1163
            "FROM authors " +
1✔
1164
            "FULL JOIN editors " +
1✔
1165
            "ON authors.id = editors.id ";
1✔
1166

1✔
1167
        let data = new TestSql()
1✔
1168
            .addTableData("authors", this.authorsTable())
1✔
1169
            .addTableData("editors", this.editorsTable())
1✔
1170
            .enableColumnTitle(true)
1✔
1171
            .execute(stmt);
1✔
1172

1✔
1173
        let expected = [["authors.id", "authors.last_name", "editors.id", "editors.last_name"],
1✔
1174
        ["11", "Writer", null, null],
1✔
1175
        ["12", "Savelieva", null, null],
1✔
1176
        ["13", "Smart", "13", "Smart"],
1✔
1177
        ["14", "Brain", null, null],
1✔
1178
        ["15", "Dou", null, null],
1✔
1179
        [null, null, "21", "Brown"],
1✔
1180
        [null, null, "22", "Johnson"],
1✔
1181
        [null, null, "23", "Evans"],
1✔
1182
        [null, null, "24", "Roberts"],
1✔
1183
        [null, null, "25", "Wright"],
1✔
1184
        [null, null, "26", "Jones"],
1✔
1185
        [null, null, "27", "Smith"],
1✔
1186
        [null, null, "50", "Dumb"],
1✔
1187
        [null, null, "51", "Smart"]];
1✔
1188

1✔
1189
        return this.isEqual("fullJoin1", data, expected);
1✔
1190
    }
1✔
1191

1✔
1192
    //  FULL JOIN not supported in mySQL - so no comparison is possible.
1✔
1193
    fullJoin2() {
1✔
1194
        let stmt = "SELECT *, customers.address, customers.id, customers.name " +
1✔
1195
            "FROM booksales " +
1✔
1196
            "FULL JOIN customers " +
1✔
1197
            "ON customer_id = customers.id ";
1✔
1198

1✔
1199
        let data = new TestSql()
1✔
1200
            .addTableData("booksales", this.bookSalesTable())
1✔
1201
            .addTableData("customers", this.customerTable())
1✔
1202
            .enableColumnTitle(true)
1✔
1203
            .execute(stmt);
1✔
1204

1✔
1205
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "CUSTOMERS.ID", "CUSTOMERS.NAME", "CUSTOMERS.ADDRESS", "CUSTOMERS.CITY", "CUSTOMERS.PHONE", "CUSTOMERS.EMAIL", "customers.address", "customers.id", "customers.name"],
1✔
1206
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com", "101 One Way", "C1", "Numereo Uno"],
1✔
1207
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com", "202 Second St.", "C2", "Dewy Tuesdays"],
1✔
1208
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com", "202 Second St.", "C2", "Dewy Tuesdays"],
1✔
1209
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com", "3 Way St", "C3", "Tres Buon Goods"],
1✔
1210
        ["I7203", "1", "", 1, 90, "05/02/2022", null, null, null, null, null, null, null, null, null],
1✔
1211
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "40 Four St", "C4", "ForMe Resellers"],
1✔
1212
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "40 Four St", "C4", "ForMe Resellers"],
1✔
1213
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "40 Four St", "C4", "ForMe Resellers"],
1✔
1214
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com", "101 One Way", "C1", "Numereo Uno"],
1✔
1215
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com", "202 Second St.", "C2", "Dewy Tuesdays"],
1✔
1216
        [null, null, null, null, null, null, "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com", "5 ohFive St.", "C5", "Fe Fi Fo Giant Tiger"],
1✔
1217
        [null, null, null, null, null, null, "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   ", "6 Seventh St", "C6", "Sx in Cars"],
1✔
1218
        [null, null, null, null, null, null, "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com ", "7 Eight Crt.", "C7", "7th Heaven"]];
1✔
1219

1✔
1220
        return this.isEqual("fullJoin2", data, expected);
1✔
1221
    }
1✔
1222

1✔
1223
    fullJoin3() {
1✔
1224
        let stmt = "SELECT * " +
1✔
1225
            "FROM booksales " +
1✔
1226
            "FULL JOIN customers " +
1✔
1227
            "ON booksales.customer_id = customers.id " +
1✔
1228
            "FULL JOIN books " +
1✔
1229
            "ON booksales.Book_Id = books.id";
1✔
1230

1✔
1231
        let data = new TestSql()
1✔
1232
            .addTableData("booksales", this.bookSalesTable())
1✔
1233
            .addTableData("customers", this.customerTable())
1✔
1234
            .addTableData("books", this.bookTable())
1✔
1235
            .enableColumnTitle(true)
1✔
1236
            .execute(stmt);
1✔
1237

1✔
1238
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "CUSTOMERS.ID", "CUSTOMERS.NAME", "CUSTOMERS.ADDRESS", "CUSTOMERS.CITY", "CUSTOMERS.PHONE", "CUSTOMERS.EMAIL", "BOOKS.ID", "BOOKS.TITLE", "BOOKS.TYPE", "BOOKS.AUTHOR_ID", "BOOKS.EDITOR_ID", "BOOKS.TRANSLATOR_ID"],
1✔
1239
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com", "9", "Book with Mysterious Author", "translated", "1", "23", "34"],
1✔
1240
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com", "8", "My Last Book", "original", "11", "28", ""],
1✔
1241
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com", "7", "Applied AI", "translated", "13", "23", "34"],
1✔
1242
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com", "9", "Book with Mysterious Author", "translated", "1", "23", "34"],
1✔
1243
        ["I7203", "1", "", 1, 90, "05/02/2022", null, null, null, null, null, null, "1", "Time to Grow Up!", "original", "11", "21", ""],
1✔
1244
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "2", "Your Trip", "translated", "15", "22", "32"],
1✔
1245
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "3", "Lovely Love", "original", "14", "24", ""],
1✔
1246
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "4", "Dream Your Life", "original", "11", "24", ""],
1✔
1247
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com", "7", "Applied AI", "translated", "13", "23", "34"],
1✔
1248
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com", "7", "Applied AI", "translated", "13", "23", "34"],
1✔
1249
        [null, null, null, null, null, null, "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com", null, null, null, null, null, null],
1✔
1250
        [null, null, null, null, null, null, "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   ", null, null, null, null, null, null],
1✔
1251
        [null, null, null, null, null, null, "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com ", null, null, null, null, null, null],
1✔
1252
        [null, null, null, null, null, null, null, null, null, null, null, null, "5", "Oranges", "translated", "12", "25", "31"],
1✔
1253
        [null, null, null, null, null, null, null, null, null, null, null, null, "6", "Your Happy Life", "translated", "15", "22", "33"]];
1✔
1254

1✔
1255
        return this.isEqual("fullJoin3", data, expected);
1✔
1256
    }
1✔
1257

1✔
1258
    whereIn1() {
1✔
1259
        let stmt = "SELECT books.id, books.title, books.author_id " +
1✔
1260
            "FROM books " +
1✔
1261
            "WHERE books.author_id IN (SELECT id from authors)" +
1✔
1262
            "ORDER BY books.title";
1✔
1263

1✔
1264
        let data = new TestSql()
1✔
1265
            .addTableData("books", this.bookTable())
1✔
1266
            .addTableData("authors", this.authorsTable())
1✔
1267
            .enableColumnTitle(true)
1✔
1268
            .execute(stmt);
1✔
1269

1✔
1270
        let expected = [["books.id", "books.title", "books.author_id"],
1✔
1271
        ["7", "Applied AI", "13"],
1✔
1272
        ["4", "Dream Your Life", "11"],
1✔
1273
        ["3", "Lovely Love", "14"],
1✔
1274
        ["8", "My Last Book", "11"],
1✔
1275
        ["5", "Oranges", "12"],
1✔
1276
        ["1", "Time to Grow Up!", "11"],
1✔
1277
        ["6", "Your Happy Life", "15"],
1✔
1278
        ["2", "Your Trip", "15"]];
1✔
1279

1✔
1280
        return this.isEqual("whereIn1", data, expected);
1✔
1281
    }
1✔
1282

1✔
1283
    whereIn2() {
1✔
1284
        let stmt = "SELECT books.id, books.title, books.author_id " +
1✔
1285
            "FROM books " +
1✔
1286
            "WHERE books.author_id IN ('11',   '12') " +
1✔
1287
            "ORDER BY books.title";
1✔
1288

1✔
1289
        let data = new TestSql()
1✔
1290
            .addTableData("books", this.bookTable())
1✔
1291
            .enableColumnTitle(true)
1✔
1292
            .execute(stmt);
1✔
1293

1✔
1294
        let expected = [["books.id", "books.title", "books.author_id"],
1✔
1295
        ["4", "Dream Your Life", "11"],
1✔
1296
        ["8", "My Last Book", "11"],
1✔
1297
        ["5", "Oranges", "12"],
1✔
1298
        ["1", "Time to Grow Up!", "11"]];
1✔
1299

1✔
1300
        return this.isEqual("whereIn2", data, expected);
1✔
1301
    }
1✔
1302

1✔
1303
    whereIn3() {
1✔
1304
        let stmt = "SELECT id, title, author_id " +
1✔
1305
            "FROM books " +
1✔
1306
            "WHERE author_id IN (select id from authors where first_name like '%ald') " +
1✔
1307
            "ORDER BY title";
1✔
1308

1✔
1309
        let data = new TestSql()
1✔
1310
            .addTableData("books", this.bookTable())
1✔
1311
            .addTableData("authors", this.authorsTable())
1✔
1312
            .enableColumnTitle(true)
1✔
1313
            .execute(stmt);
1✔
1314

1✔
1315
        let expected = [["id", "title", "author_id"],
1✔
1316
        ["3", "Lovely Love", "14"]];
1✔
1317

1✔
1318
        return this.isEqual("whereIn3", data, expected);
1✔
1319
    }
1✔
1320

1✔
1321
    whereIn4() {
1✔
1322
        let stmt = "SELECT * " +
1✔
1323
            "FROM books " +
1✔
1324
            "WHERE author_id IN (select id from authors where first_name = ?1) " +
1✔
1325
            "or editor_id in (select id from editors where last_name = ?2) " +
1✔
1326
            "or title = ?3 " +
1✔
1327
            "ORDER BY title";
1✔
1328

1✔
1329
        let data = new TestSql()
1✔
1330
            .addTableData("books", this.bookTable())
1✔
1331
            .addTableData("authors", this.authorsTable())
1✔
1332
            .addTableData("editors", this.editorsTable())
1✔
1333
            .enableColumnTitle(true)
1✔
1334
            .addBindParameter('Donald')
1✔
1335
            .addBindParameter('Roberts')
1✔
1336
            .addBindParameter('Oranges')
1✔
1337
            .execute(stmt);
1✔
1338

1✔
1339
        let expected = [["BOOKS.ID", "BOOKS.TITLE", "BOOKS.TYPE", "BOOKS.AUTHOR_ID", "BOOKS.EDITOR_ID", "BOOKS.TRANSLATOR_ID"],
1✔
1340
        ["4", "Dream Your Life", "original", "11", "24", ""],
1✔
1341
        ["3", "Lovely Love", "original", "14", "24", ""],
1✔
1342
        ["5", "Oranges", "translated", "12", "25", "31"]];
1✔
1343

1✔
1344
        return this.isEqual("whereIn4", data, expected);
1✔
1345
    }
1✔
1346

1✔
1347
    whereIn5() {
1✔
1348
        let stmt = "SELECT * " +
1✔
1349
            "FROM books " +
1✔
1350
            "WHERE author_id IN (select a.id from authors as a where first_name = ?1) " +
1✔
1351
            "or editor_id in (select e.id from editors as e where last_name = ?2) " +
1✔
1352
            "or title = ?3 " +
1✔
1353
            "ORDER BY title";
1✔
1354

1✔
1355
        let data = new TestSql()
1✔
1356
            .addTableData("books", this.bookTable())
1✔
1357
            .addTableData("authors", this.authorsTable())
1✔
1358
            .addTableData("editors", this.editorsTable())
1✔
1359
            .enableColumnTitle(true)
1✔
1360
            .addBindParameter('Donald')
1✔
1361
            .addBindParameter('Roberts')
1✔
1362
            .addBindParameter('Oranges')
1✔
1363
            .execute(stmt);
1✔
1364

1✔
1365
        let expected = [["BOOKS.ID", "BOOKS.TITLE", "BOOKS.TYPE", "BOOKS.AUTHOR_ID", "BOOKS.EDITOR_ID", "BOOKS.TRANSLATOR_ID"],
1✔
1366
        ["4", "Dream Your Life", "original", "11", "24", ""],
1✔
1367
        ["3", "Lovely Love", "original", "14", "24", ""],
1✔
1368
        ["5", "Oranges", "translated", "12", "25", "31"]];
1✔
1369

1✔
1370
        return this.isEqual("whereIn5", data, expected);
1✔
1371
    }
1✔
1372

1✔
1373
    whereIn6() {
1✔
1374
        let stmt = "SELECT * FROM editors WHERE first_name IN (' Mark ', 'Maria    ', 'CATHRINE  ',  'Jack')";
1✔
1375

1✔
1376
        let data = new TestSql()
1✔
1377
            .addTableData("editors", this.editorsTable())
1✔
1378
            .enableColumnTitle(true)
1✔
1379
            .execute(stmt);
1✔
1380

1✔
1381
        let expected = [["EDITORS.ID", "EDITORS.FIRST_NAME", "EDITORS.LAST_NAME"],
1✔
1382
        ["13", "Jack", "Smart"],
1✔
1383
        ["50", "Jack", "Dumb"]];
1✔
1384

1✔
1385
        return this.isEqual("whereIn6", data, expected);
1✔
1386
    }
1✔
1387

1✔
1388

1✔
1389
    whereIn7() {
1✔
1390
        let stmt = "select * from booksales where quantity in (select quantity from booksales where price < 30)";
1✔
1391

1✔
1392
        let data = new TestSql()
1✔
1393
            .addTableData("booksales", this.bookSalesTable())
1✔
1394
            .enableColumnTitle(true)
1✔
1395
            .execute(stmt);
1✔
1396

1✔
1397
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
1398
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022"],
1✔
1399
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022"],
1✔
1400
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
1✔
1401
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
1✔
1402
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"],
1✔
1403
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022"]];
1✔
1404

1✔
1405
        return this.isEqual("whereIn7", data, expected);
1✔
1406
    }
1✔
1407

1✔
1408
    whereNotIn1() {
1✔
1409
        let stmt = "SELECT books.id, books.title, books.author_id " +
1✔
1410
            "FROM books " +
1✔
1411
            "WHERE books.author_id NOT IN (SELECT id from authors)" +
1✔
1412
            "ORDER BY books.title";
1✔
1413

1✔
1414
        let data = new TestSql()
1✔
1415
            .addTableData("books", this.bookTable())
1✔
1416
            .addTableData("authors", this.authorsTable())
1✔
1417
            .enableColumnTitle(true)
1✔
1418
            .execute(stmt);
1✔
1419

1✔
1420
        let expected = [["books.id", "books.title", "books.author_id"],
1✔
1421
        ["9", "Book with Mysterious Author", "1"]];
1✔
1422

1✔
1423
        return this.isEqual("whereNotIn1", data, expected);
1✔
1424
    }
1✔
1425

1✔
1426
    whereNotIn2() {
1✔
1427
        let stmt = "SELECT * FROM editors  WHERE first_name NOT IN ('Jack', 'Daniel', 'Mark')";
1✔
1428

1✔
1429
        let data = new TestSql()
1✔
1430
            .addTableData("editors", this.editorsTable())
1✔
1431
            .enableColumnTitle(true)
1✔
1432
            .execute(stmt);
1✔
1433

1✔
1434
        let expected = [["EDITORS.ID", "EDITORS.FIRST_NAME", "EDITORS.LAST_NAME"],
1✔
1435
        ["23", "Maria", "Evans"],
1✔
1436
        ["24", "Cathrine", "Roberts"],
1✔
1437
        ["25", "Sebastian", "Wright"],
1✔
1438
        ["26", "Barbara", "Jones"],
1✔
1439
        ["27", "Matthew", "Smith"]];
1✔
1440

1✔
1441
        return this.isEqual("whereNotIn2", data, expected);
1✔
1442
    }
1✔
1443

1✔
1444
    whereNotIn3() {
1✔
1445
        let stmt = "SELECT * FROM editors  WHERE first_name NOT IN ('JacK')";
1✔
1446

1✔
1447
        let data = new TestSql()
1✔
1448
            .addTableData("editors", this.editorsTable())
1✔
1449
            .enableColumnTitle(true)
1✔
1450
            .execute(stmt);
1✔
1451

1✔
1452
        //  Depending on how your SQL is configured, the comparison is either
1✔
1453
        //  case or case insensitive.  For gsSQL() it is case senstive.
1✔
1454
        let expected = [["EDITORS.ID", "EDITORS.FIRST_NAME", "EDITORS.LAST_NAME"],
1✔
1455
        ["21", "Daniel", "Brown"],
1✔
1456
        ["22", "Mark", "Johnson"],
1✔
1457
        ["23", "Maria", "Evans"],
1✔
1458
        ["24", "Cathrine", "Roberts"],
1✔
1459
        ["25", "Sebastian", "Wright"],
1✔
1460
        ["26", "Barbara", "Jones"],
1✔
1461
        ["27", "Matthew", "Smith"],
1✔
1462
        ["51", "Daniel", "Smart"]];
1✔
1463

1✔
1464
        return this.isEqual("whereNotIn3", data, expected);
1✔
1465
    }
1✔
1466

1✔
1467
    whereNotIn4() {
1✔
1468
        let stmt = "SELECT * FROM editors  WHERE first_name NOT IN ('Jack')";
1✔
1469

1✔
1470
        let data = new TestSql()
1✔
1471
            .addTableData("editors", this.editorsTable())
1✔
1472
            .enableColumnTitle(true)
1✔
1473
            .execute(stmt);
1✔
1474

1✔
1475
        let expected = [["EDITORS.ID", "EDITORS.FIRST_NAME", "EDITORS.LAST_NAME"],
1✔
1476
        ["21", "Daniel", "Brown"],
1✔
1477
        ["22", "Mark", "Johnson"],
1✔
1478
        ["23", "Maria", "Evans"],
1✔
1479
        ["24", "Cathrine", "Roberts"],
1✔
1480
        ["25", "Sebastian", "Wright"],
1✔
1481
        ["26", "Barbara", "Jones"],
1✔
1482
        ["27", "Matthew", "Smith"],
1✔
1483
        ["51", "Daniel", "Smart"]];
1✔
1484

1✔
1485
        return this.isEqual("whereNotIn4", data, expected);
1✔
1486
    }
1✔
1487

1✔
1488
    whereAndOr1() {
1✔
1489
        let stmt = "select * from bookSales where date > '05/01/2022' AND date < '05/04/2022' OR book_id = '9'";
1✔
1490

1✔
1491
        let data = new TestSql()
1✔
1492
            .addTableData("bookSales", this.bookSalesTable())
1✔
1493
            .enableColumnTitle(true)
1✔
1494
            .execute(stmt);
1✔
1495

1✔
1496
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
1497
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
1✔
1498
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
1499
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
1✔
1500
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
1✔
1501
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"],
1✔
1502
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022"]];
1✔
1503

1✔
1504
        return this.isEqual("whereAndOr1", data, expected);
1✔
1505
    }
1✔
1506

1✔
1507
    whereAndOr2() {
1✔
1508
        let stmt = "select * from bookSales where date > ?1 AND date < ?2 OR book_id = ?3";
1✔
1509

1✔
1510
        let data = new TestSql()
1✔
1511
            .addTableData("bookSales", this.bookSalesTable())
1✔
1512
            .enableColumnTitle(true)
1✔
1513
            .addBindParameter('05/01/2022')
1✔
1514
            .addBindParameter('05/04/2022')
1✔
1515
            .addBindParameter('9')
1✔
1516
            .execute(stmt);
1✔
1517

1✔
1518
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
1519
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
1✔
1520
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
1521
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
1✔
1522
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
1✔
1523
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"],
1✔
1524
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022"]];
1✔
1525

1✔
1526
        return this.isEqual("whereAndOr2", data, expected);
1✔
1527
    }
1✔
1528

1✔
1529
    whereAndOr3() {
1✔
1530
        let stmt = "select * from bookSales where date > ?1 AND date < ?2 OR book_id = ?3";
1✔
1531

1✔
1532
        let startDate = new Date();
1✔
1533
        startDate.setDate(1);
1✔
1534
        startDate.setMonth(4);
1✔
1535
        startDate.setFullYear(2022);
1✔
1536

1✔
1537
        let data = new TestSql()
1✔
1538
            .addTableData("bookSales", this.bookSalesTable())
1✔
1539
            .enableColumnTitle(true)
1✔
1540
            .addBindParameter(startDate)
1✔
1541
            .addBindParameter('05/04/2022')
1✔
1542
            .addBindParameter('9')
1✔
1543
            .execute(stmt);
1✔
1544

1✔
1545
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
1546
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
1✔
1547
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
1548
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
1✔
1549
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
1✔
1550
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"],
1✔
1551
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022"]];
1✔
1552

1✔
1553
        return this.isEqual("whereAndOr3", data, expected);
1✔
1554
    }
1✔
1555

1✔
1556
    whereAndNotEqual2() {
1✔
1557
        let stmt = "select * from bookSales where date >= ?1 AND date <= ?2 And book_id <> ?3";
1✔
1558
        let func = "whereAndNotEqual2";
1✔
1559
        return this.whereAndNotEqual2base(stmt, func);
1✔
1560
    }
1✔
1561

1✔
1562
    whereAndNotEqual3() {
1✔
1563
        let stmt = "select * from bookSales where date>=?1 AND date<=?2 And book_id<>?3";
1✔
1564
        let func = "whereAndNotEqual3";
1✔
1565
        return this.whereAndNotEqual2base(stmt, func);
1✔
1566
    }
1✔
1567
    whereAndNotEqual2base(stmt, func) {
1✔
1568

2✔
1569
        let data = new TestSql()
2✔
1570
            .addTableData("bookSales", this.bookSalesTable())
2✔
1571
            .enableColumnTitle(true)
2✔
1572
            .addBindParameter('05/01/2022')
2✔
1573
            .addBindParameter('05/04/2022')
2✔
1574
            .addBindParameter('9')
2✔
1575
            .execute(stmt);
2✔
1576

2✔
1577
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
2✔
1578
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022"],
2✔
1579
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022"],
2✔
1580
        ["I7203", "1", "", 1, 90, "05/02/2022"],
2✔
1581
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
2✔
1582
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
2✔
1583
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"],
2✔
1584
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022"],
2✔
1585
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022"]];
2✔
1586

2✔
1587
        return this.isEqual(func, data, expected);
2✔
1588
    }
2✔
1589

1✔
1590
    selectAgainNewBinds1() {
1✔
1591
        let stmt = "select * from bookSales where date > ?1 AND date < ?2 OR book_id = ?3";
1✔
1592

1✔
1593
        let sqlObj = new TestSql()
1✔
1594
            .addTableData("bookSales", this.bookSalesTable())
1✔
1595
            .enableColumnTitle(true)
1✔
1596
            .addBindParameter('05/01/2022')
1✔
1597
            .addBindParameter('05/04/2022')
1✔
1598
            .addBindParameter('9');
1✔
1599

1✔
1600
        let data = sqlObj.execute(stmt);
1✔
1601

1✔
1602
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
1603
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
1✔
1604
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
1605
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
1✔
1606
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
1✔
1607
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"],
1✔
1608
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022"]];
1✔
1609

1✔
1610
        let result = this.isEqual("selectAgainNewBinds1a", data, expected);
1✔
1611

1✔
1612
        data = sqlObj.clearBindParameters()
1✔
1613
            .addBindParameter('05/02/2022')
1✔
1614
            .addBindParameter('05/04/2022')
1✔
1615
            .addBindParameter('9')
1✔
1616
            .execute(stmt);
1✔
1617

1✔
1618
        expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
1619
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
1✔
1620
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
1✔
1621
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"],
1✔
1622
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022"],
1✔
1623
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"]];
1✔
1624

1✔
1625
        return result && this.isEqual("selectAgainNewBinds1b", data, expected);
1✔
1626
    }
1✔
1627

1✔
1628
    groupBy1() {
1✔
1629
        let stmt = "select bookSales.book_id, SUM(bookSales.Quantity) from bookSales group by book_id";
1✔
1630

1✔
1631
        let data = new TestSql()
1✔
1632
            .addTableData("bookSales", this.bookSalesTable())
1✔
1633
            .enableColumnTitle(true)
1✔
1634
            .execute(stmt);
1✔
1635

1✔
1636
        let expected = [["bookSales.book_id", "SUM(bookSales.Quantity)"],
1✔
1637
        ["1", 1],
1✔
1638
        ["2", 100],
1✔
1639
        ["3", 150],
1✔
1640
        ["4", 50],
1✔
1641
        ["7", 106],
1✔
1642
        ["8", 3],
1✔
1643
        ["9", 11]];
1✔
1644

1✔
1645
        return this.isEqual("groupBy1", data, expected);
1✔
1646
    }
1✔
1647

1✔
1648
    groupBy2() {
1✔
1649
        let stmt =
1✔
1650
            "select bookSales.customer_id, SUM(bookSales.quantity) FROM booksales " +
1✔
1651
            "GROUP BY booksales.customer_id HAVING SUM(bookSales.quantity) > 11";
1✔
1652

1✔
1653
        let data = new TestSql()
1✔
1654
            .addTableData("bookSales", this.bookSalesTable())
1✔
1655
            .enableColumnTitle(true)
1✔
1656
            .execute(stmt);
1✔
1657

1✔
1658
        let expected = [["bookSales.customer_id", "SUM(bookSales.quantity)"],
1✔
1659
        ["C2", 108],
1✔
1660
        ["C4", 300]];
1✔
1661

1✔
1662
        return this.isEqual("groupBy2", data, expected);
1✔
1663
    }
1✔
1664

1✔
1665
    groupBy3() {
1✔
1666
        let stmt =
1✔
1667
            "select bookSales.customer_id, date, SUM(bookSales.quantity) FROM booksales " +
1✔
1668
            "GROUP BY customer_id, date";
1✔
1669

1✔
1670
        let data = new TestSql()
1✔
1671
            .addTableData("bookSales", this.bookSalesTable())
1✔
1672
            .enableColumnTitle(true)
1✔
1673
            .execute(stmt);
1✔
1674

1✔
1675
        let expected = [["bookSales.customer_id", "date", "SUM(bookSales.quantity)"],
1✔
1676
        ["", "05/02/2022", 1],
1✔
1677
        ["C1", "05/01/2022", 10],
1✔
1678
        ["C1", "05/04/2022", 1],
1✔
1679
        ["C2", "05/01/2022", 8],
1✔
1680
        ["C2", "05/04/2022", 100],
1✔
1681
        ["C3", "05/02/2022", 1],
1✔
1682
        ["C4", "05/03/2022", 300]];
1✔
1683

1✔
1684
        return this.isEqual("groupBy3", data, expected);
1✔
1685
    }
1✔
1686

1✔
1687
    groupBy4() {
1✔
1688
        let stmt =
1✔
1689
            "select bookSales.customer_id, date, count(customer_id), count(date) FROM booksales " +
1✔
1690
            "GROUP BY customer_id, date";
1✔
1691

1✔
1692
        let data = new TestSql()
1✔
1693
            .addTableData("bookSales", this.bookSalesTable())
1✔
1694
            .enableColumnTitle(true)
1✔
1695
            .execute(stmt);
1✔
1696

1✔
1697
        let expected = [["bookSales.customer_id", "date", "count(customer_id)", "count(date)"],
1✔
1698
        ["", "05/02/2022", 1, 1],
1✔
1699
        ["C1", "05/01/2022", 1, 1],
1✔
1700
        ["C1", "05/04/2022", 1, 1],
1✔
1701
        ["C2", "05/01/2022", 2, 2],
1✔
1702
        ["C2", "05/04/2022", 1, 1],
1✔
1703
        ["C3", "05/02/2022", 1, 1],
1✔
1704
        ["C4", "05/03/2022", 3, 3]];
1✔
1705

1✔
1706
        return this.isEqual("groupBy4", data, expected);
1✔
1707
    }
1✔
1708

1✔
1709

1✔
1710
    groupBy5() {
1✔
1711
        let stmt = "select id,  first_name, last_name, count(*) from (select id, first_name, last_name from editors union all select id, first_name, last_name from authors union all select id, first_name, last_name from translators) as test group by id, first_name, last_name";
1✔
1712

1✔
1713
        let data = new TestSql()
1✔
1714
            .addTableData("editors", this.editorsTable())
1✔
1715
            .addTableData("authors", this.authorsTable())
1✔
1716
            .addTableData("translators", this.translatorsTable())
1✔
1717
            .enableColumnTitle(true)
1✔
1718
            .execute(stmt);
1✔
1719

1✔
1720
        let expected = [["id", "first_name", "last_name", "count(*)"],
1✔
1721
        ["11", "Ellen", "Writer", 1],
1✔
1722
        ["12", "Olga", "Savelieva", 1],
1✔
1723
        ["13", "Jack", "Smart", 2],
1✔
1724
        ["14", "Donald", "Brain", 1],
1✔
1725
        ["15", "Yao", "Dou", 1],
1✔
1726
        ["21", "Daniel", "Brown", 1],
1✔
1727
        ["22", "Mark", "Johnson", 1],
1✔
1728
        ["23", "Maria", "Evans", 1],
1✔
1729
        ["24", "Cathrine", "Roberts", 1],
1✔
1730
        ["25", "Sebastian", "Wright", 1],
1✔
1731
        ["26", "Barbara", "Jones", 1],
1✔
1732
        ["27", "Matthew", "Smith", 1],
1✔
1733
        ["31", "Ira", "Davies", 1],
1✔
1734
        ["32", "Ling", "Weng", 1],
1✔
1735
        ["33", "Kristian", "Green", 1],
1✔
1736
        ["34", "Roman", "Edwards", 1],
1✔
1737
        ["50", "Jack", "Dumb", 1],
1✔
1738
        ["51", "Daniel", "Smart", 1]];
1✔
1739

1✔
1740
        return this.isEqual("groupBy5", data, expected);
1✔
1741
    }
1✔
1742

1✔
1743
    avgSelect1() {
1✔
1744
        let stmt = "select AVG(quantity) from booksales";
1✔
1745

1✔
1746
        let data = new TestSql()
1✔
1747
            .addTableData("bookSales", this.bookSalesTable())
1✔
1748
            .enableColumnTitle(true)
1✔
1749
            .execute(stmt);
1✔
1750

1✔
1751
        let expected = [["AVG(quantity)"], [42.1]];
1✔
1752

1✔
1753
        return this.isEqual("avgSelect1", data, expected);
1✔
1754
    }
1✔
1755

1✔
1756
    funcsSelect2() {
1✔
1757
        let stmt = "select AVG(quantity), MIN(quantity), MAX(quantity), SUM(quantity), COUNT(quantity) from booksales";
1✔
1758

1✔
1759
        let data = new TestSql()
1✔
1760
            .addTableData("bookSales", this.bookSalesTable())
1✔
1761
            .enableColumnTitle(true)
1✔
1762
            .execute(stmt);
1✔
1763

1✔
1764
        let expected = [["AVG(quantity)", "MIN(quantity)", "MAX(quantity)", "SUM(quantity)", "COUNT(quantity)"],
1✔
1765
        [42.1, 1, 150, 421, 10]];
1✔
1766

1✔
1767
        return this.isEqual("funcsSelect2", data, expected);
1✔
1768
    }
1✔
1769

1✔
1770
    innerSelect1() {
1✔
1771
        let stmt = "SELECT *, customers.name FROM bookSales " +
1✔
1772
            "LEFT JOIN customers ON bookSales.customer_ID = customers.ID " +
1✔
1773
            "WHERE bookSales.quantity > (select AVG(quantity) from booksales)";
1✔
1774

1✔
1775
        let data = new TestSql()
1✔
1776
            .addTableData("bookSales", this.bookSalesTable())
1✔
1777
            .addTableData("customers", this.customerTable())
1✔
1778
            .enableColumnTitle(true)
1✔
1779
            .execute(stmt);
1✔
1780

1✔
1781
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "CUSTOMERS.ID", "CUSTOMERS.NAME", "CUSTOMERS.ADDRESS", "CUSTOMERS.CITY", "CUSTOMERS.PHONE", "CUSTOMERS.EMAIL", "customers.name"],
1✔
1782
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "ForMe Resellers"],
1✔
1783
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "ForMe Resellers"],
1✔
1784
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "ForMe Resellers"],
1✔
1785
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com", "Dewy Tuesdays"]];
1✔
1786

1✔
1787
        return this.isEqual("innerSelect1", data, expected);
1✔
1788
    }
1✔
1789

1✔
1790
    whereLike1() {
1✔
1791
        let stmt = "select * from bookSales " +
1✔
1792
            "LEFT JOIN books ON booksales.book_id = books.id " +
1✔
1793
            "LEFT JOIN authors on books.author_id = authors.id " +
1✔
1794
            "LEFT JOIN editors on books.editor_id = editors.id " +
1✔
1795
            "LEFT JOIN customers on bookSales.customer_id = customers.id " +
1✔
1796
            "WHERE customers.email LIKE '%gmail.com'";
1✔
1797

1✔
1798
        let data = new TestSql()
1✔
1799
            .addTableData("bookSales", this.bookSalesTable())
1✔
1800
            .addTableData("customers", this.customerTable())
1✔
1801
            .addTableData("books", this.bookTable())
1✔
1802
            .addTableData("editors", this.editorsTable())
1✔
1803
            .addTableData("authors", this.authorsTable())
1✔
1804
            .enableColumnTitle(true)
1✔
1805
            .execute(stmt);
1✔
1806

1✔
1807
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "BOOKS.ID", "BOOKS.TITLE", "BOOKS.TYPE", "BOOKS.AUTHOR_ID", "BOOKS.EDITOR_ID", "BOOKS.TRANSLATOR_ID", "AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME", "EDITORS.ID", "EDITORS.FIRST_NAME", "EDITORS.LAST_NAME", "CUSTOMERS.ID", "CUSTOMERS.NAME", "CUSTOMERS.ADDRESS", "CUSTOMERS.CITY", "CUSTOMERS.PHONE", "CUSTOMERS.EMAIL"],
1✔
1808
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "9", "Book with Mysterious Author", "translated", "1", "23", "34", null, null, null, "23", "Maria", "Evans", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
1✔
1809
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022", "8", "My Last Book", "original", "11", "28", "", "11", "Ellen", "Writer", null, null, null, "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"],
1✔
1810
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "7", "Applied AI", "translated", "13", "23", "34", "13", "Jack", "Smart", "23", "Maria", "Evans", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"],
1✔
1811
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "7", "Applied AI", "translated", "13", "23", "34", "13", "Jack", "Smart", "23", "Maria", "Evans", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
1✔
1812
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "7", "Applied AI", "translated", "13", "23", "34", "13", "Jack", "Smart", "23", "Maria", "Evans", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"]];
1✔
1813

1✔
1814
        return this.isEqual("whereLike1", data, expected);
1✔
1815
    }
1✔
1816

1✔
1817
    whereLike2() {
1✔
1818
        let stmt = "select books.title as Title, auth.first_name as [First Name], editors.first_name, customers.name, customers.email, booksales.quantity from bookSales as sale" +
1✔
1819
            "LEFT JOIN books as bk ON sale.book_id = bk.id " +
1✔
1820
            "LEFT JOIN authors as auth on books.author_id = authors.id " +
1✔
1821
            "LEFT JOIN editors as ed on books.editor_id = ed.id " +
1✔
1822
            "LEFT JOIN customers on bookSales.customer_id = customers.id " +
1✔
1823
            "WHERE customers.email LIKE '%gmail.com'";
1✔
1824

1✔
1825
        let data = new TestSql()
1✔
1826
            .addTableData("bookSales", this.bookSalesTable())
1✔
1827
            .addTableData("customers", this.customerTable())
1✔
1828
            .addTableData("books", this.bookTable())
1✔
1829
            .addTableData("editors", this.editorsTable())
1✔
1830
            .addTableData("authors", this.authorsTable())
1✔
1831
            .enableColumnTitle(true)
1✔
1832
            .execute(stmt);
1✔
1833

1✔
1834
        let expected = [["Title", "First Name", "editors.first_name", "customers.name", "customers.email", "booksales.quantity"],
1✔
1835
        ["Book with Mysterious Author", null, "Maria", "Numereo Uno", "bigOne@gmail.com", 10],
1✔
1836
        ["My Last Book", "Ellen", null, "Dewy Tuesdays", "twoguys@gmail.com", 3],
1✔
1837
        ["Applied AI", "Jack", "Maria", "Dewy Tuesdays", "twoguys@gmail.com", 5],
1✔
1838
        ["Applied AI", "Jack", "Maria", "Numereo Uno", "bigOne@gmail.com", 1],
1✔
1839
        ["Applied AI", "Jack", "Maria", "Dewy Tuesdays", "twoguys@gmail.com", 100]];
1✔
1840

1✔
1841
        return this.isEqual("whereLike2", data, expected);
1✔
1842
    }
1✔
1843

1✔
1844
    whereNotLike1() {
1✔
1845
        let stmt = "select * from bookSales " +
1✔
1846
            "LEFT JOIN books ON booksales.book_id = books.id " +
1✔
1847
            "LEFT JOIN authors on books.author_id = authors.id " +
1✔
1848
            "LEFT JOIN editors on books.editor_id = editors.id " +
1✔
1849
            "LEFT JOIN customers on bookSales.customer_id = customers.id " +
1✔
1850
            "WHERE customers.email NOT LIKE '%gmail.com'";
1✔
1851

1✔
1852
        let data = new TestSql()
1✔
1853
            .addTableData("bookSales", this.bookSalesTable())
1✔
1854
            .addTableData("customers", this.customerTable())
1✔
1855
            .addTableData("books", this.bookTable())
1✔
1856
            .addTableData("editors", this.editorsTable())
1✔
1857
            .addTableData("authors", this.authorsTable())
1✔
1858
            .enableColumnTitle(true)
1✔
1859
            .execute(stmt);
1✔
1860

1✔
1861
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "BOOKS.ID", "BOOKS.TITLE", "BOOKS.TYPE", "BOOKS.AUTHOR_ID", "BOOKS.EDITOR_ID", "BOOKS.TRANSLATOR_ID", "AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME", "EDITORS.ID", "EDITORS.FIRST_NAME", "EDITORS.LAST_NAME", "CUSTOMERS.ID", "CUSTOMERS.NAME", "CUSTOMERS.ADDRESS", "CUSTOMERS.CITY", "CUSTOMERS.PHONE", "CUSTOMERS.EMAIL"],
1✔
1862
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "9", "Book with Mysterious Author", "translated", "1", "23", "34", null, null, null, "23", "Maria", "Evans", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
1✔
1863
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "2", "Your Trip", "translated", "15", "22", "32", "15", "Yao", "Dou", "22", "Mark", "Johnson", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"],
1✔
1864
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "3", "Lovely Love", "original", "14", "24", "", "14", "Donald", "Brain", "24", "Cathrine", "Roberts", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"],
1✔
1865
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "4", "Dream Your Life", "original", "11", "24", "", "11", "Ellen", "Writer", "24", "Cathrine", "Roberts", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"]];
1✔
1866

1✔
1867
        return this.isEqual("whereNotLike1", data, expected);
1✔
1868
    }
1✔
1869

1✔
1870
    union1() {
1✔
1871
        let stmt = "select * from authors UNION select * from editors";
1✔
1872

1✔
1873
        let data = new TestSql()
1✔
1874
            .addTableData("authors", this.authorsTable())
1✔
1875
            .addTableData("editors", this.editorsTable())
1✔
1876
            .enableColumnTitle(true)
1✔
1877
            .execute(stmt);
1✔
1878

1✔
1879
        let expected = [["AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME"],
1✔
1880
        ["11", "Ellen", "Writer"],
1✔
1881
        ["12", "Olga", "Savelieva"],
1✔
1882
        ["13", "Jack", "Smart"],
1✔
1883
        ["14", "Donald", "Brain"],
1✔
1884
        ["15", "Yao", "Dou"],
1✔
1885
        ["21", "Daniel", "Brown"],
1✔
1886
        ["22", "Mark", "Johnson"],
1✔
1887
        ["23", "Maria", "Evans"],
1✔
1888
        ["24", "Cathrine", "Roberts"],
1✔
1889
        ["25", "Sebastian", "Wright"],
1✔
1890
        ["26", "Barbara", "Jones"],
1✔
1891
        ["27", "Matthew", "Smith"],
1✔
1892
        ["50", "Jack", "Dumb"],
1✔
1893
        ["51", "Daniel", "Smart"]];
1✔
1894

1✔
1895
        return this.isEqual("union1", data, expected);
1✔
1896
    }
1✔
1897

1✔
1898
    unionAlias1() {
1✔
1899
        let stmt = "select a.id, a.first_name, a.last_name from authors as a UNION select e.id, e.first_name, e.last_name from editors as e";
1✔
1900

1✔
1901
        let data = new TestSql()
1✔
1902
            .addTableData("authors", this.authorsTable())
1✔
1903
            .addTableData("editors", this.editorsTable())
1✔
1904
            .enableColumnTitle(true)
1✔
1905
            .execute(stmt);
1✔
1906

1✔
1907
        let expected = [["a.id", "a.first_name", "a.last_name"],
1✔
1908
        ["11", "Ellen", "Writer"],
1✔
1909
        ["12", "Olga", "Savelieva"],
1✔
1910
        ["13", "Jack", "Smart"],
1✔
1911
        ["14", "Donald", "Brain"],
1✔
1912
        ["15", "Yao", "Dou"],
1✔
1913
        ["21", "Daniel", "Brown"],
1✔
1914
        ["22", "Mark", "Johnson"],
1✔
1915
        ["23", "Maria", "Evans"],
1✔
1916
        ["24", "Cathrine", "Roberts"],
1✔
1917
        ["25", "Sebastian", "Wright"],
1✔
1918
        ["26", "Barbara", "Jones"],
1✔
1919
        ["27", "Matthew", "Smith"],
1✔
1920
        ["50", "Jack", "Dumb"],
1✔
1921
        ["51", "Daniel", "Smart"]];
1✔
1922

1✔
1923
        return this.isEqual("unionAlias1", data, expected);
1✔
1924
    }
1✔
1925

1✔
1926
    unionBind1() {
1✔
1927
        let stmt = "select * from authors where id = ?1 UNION Select * From editors Where id = ?2 UNION select * from translators where id = ?3";
1✔
1928
        let data = new TestSql()
1✔
1929
            .addTableData("authors", this.authorsTable())
1✔
1930
            .addTableData("editors", this.editorsTable())
1✔
1931
            .addTableData("translators", this.translatorsTable())
1✔
1932
            .enableColumnTitle(true)
1✔
1933
            .addBindParameter('15')
1✔
1934
            .addBindParameter('51')
1✔
1935
            .addBindParameter('31')
1✔
1936
            .execute(stmt);
1✔
1937

1✔
1938
        let expected = [["AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME"],
1✔
1939
        ["15", "Yao", "Dou"],
1✔
1940
        ["51", "Daniel", "Smart"],
1✔
1941
        ["31", "Ira", "Davies"]];
1✔
1942

1✔
1943
        return this.isEqual("unionBind1", data, expected);
1✔
1944
    }
1✔
1945

1✔
1946
    unionAll1() {
1✔
1947
        let stmt = "select * from authors UNION ALL select * from editors";
1✔
1948

1✔
1949
        let data = new TestSql()
1✔
1950
            .addTableData("authors", this.authorsTable())
1✔
1951
            .addTableData("editors", this.editorsTable())
1✔
1952
            .enableColumnTitle(true)
1✔
1953
            .execute(stmt);
1✔
1954

1✔
1955
        let expected = [["AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME"],
1✔
1956
        ["11", "Ellen", "Writer"],
1✔
1957
        ["12", "Olga", "Savelieva"],
1✔
1958
        ["13", "Jack", "Smart"],
1✔
1959
        ["14", "Donald", "Brain"],
1✔
1960
        ["15", "Yao", "Dou"],
1✔
1961
        ["13", "Jack", "Smart"],
1✔
1962
        ["21", "Daniel", "Brown"],
1✔
1963
        ["22", "Mark", "Johnson"],
1✔
1964
        ["23", "Maria", "Evans"],
1✔
1965
        ["24", "Cathrine", "Roberts"],
1✔
1966
        ["25", "Sebastian", "Wright"],
1✔
1967
        ["26", "Barbara", "Jones"],
1✔
1968
        ["27", "Matthew", "Smith"],
1✔
1969
        ["50", "Jack", "Dumb"],
1✔
1970
        ["51", "Daniel", "Smart"]];
1✔
1971

1✔
1972
        return this.isEqual("unionAll1", data, expected);
1✔
1973
    }
1✔
1974

1✔
1975
    unionAll2() {
1✔
1976
        let stmt = "select * from authors UNION ALL select * from editors UNION ALL select * from translators";
1✔
1977

1✔
1978
        let data = new TestSql()
1✔
1979
            .addTableData("authors", this.authorsTable())
1✔
1980
            .addTableData("editors", this.editorsTable())
1✔
1981
            .addTableData("translators", this.translatorsTable())
1✔
1982
            .enableColumnTitle(true)
1✔
1983
            .execute(stmt);
1✔
1984

1✔
1985
        let expected = [["AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME"],
1✔
1986
        ["11", "Ellen", "Writer"],
1✔
1987
        ["12", "Olga", "Savelieva"],
1✔
1988
        ["13", "Jack", "Smart"],
1✔
1989
        ["14", "Donald", "Brain"],
1✔
1990
        ["15", "Yao", "Dou"],
1✔
1991
        ["13", "Jack", "Smart"],
1✔
1992
        ["21", "Daniel", "Brown"],
1✔
1993
        ["22", "Mark", "Johnson"],
1✔
1994
        ["23", "Maria", "Evans"],
1✔
1995
        ["24", "Cathrine", "Roberts"],
1✔
1996
        ["25", "Sebastian", "Wright"],
1✔
1997
        ["26", "Barbara", "Jones"],
1✔
1998
        ["27", "Matthew", "Smith"],
1✔
1999
        ["50", "Jack", "Dumb"],
1✔
2000
        ["51", "Daniel", "Smart"],
1✔
2001
        ["31", "Ira", "Davies"],
1✔
2002
        ["32", "Ling", "Weng"],
1✔
2003
        ["33", "Kristian", "Green"],
1✔
2004
        ["34", "Roman", "Edwards"]];
1✔
2005

1✔
2006
        return this.isEqual("unionAll2", data, expected);
1✔
2007
    }
1✔
2008

1✔
2009
    unionAll3() {
1✔
2010
        let stmt = "select * from authors UNION ALL select * from editors UNION select * from translators";
1✔
2011

1✔
2012
        let data = new TestSql()
1✔
2013
            .addTableData("authors", this.authorsTable())
1✔
2014
            .addTableData("editors", this.editorsTable())
1✔
2015
            .addTableData("translators", this.translatorsTable())
1✔
2016
            .enableColumnTitle(true)
1✔
2017
            .execute(stmt);
1✔
2018

1✔
2019
        let expected = [["AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME"],
1✔
2020
        ["11", "Ellen", "Writer"],
1✔
2021
        ["12", "Olga", "Savelieva"],
1✔
2022
        ["13", "Jack", "Smart"],
1✔
2023
        ["14", "Donald", "Brain"],
1✔
2024
        ["15", "Yao", "Dou"],
1✔
2025
        ["21", "Daniel", "Brown"],
1✔
2026
        ["22", "Mark", "Johnson"],
1✔
2027
        ["23", "Maria", "Evans"],
1✔
2028
        ["24", "Cathrine", "Roberts"],
1✔
2029
        ["25", "Sebastian", "Wright"],
1✔
2030
        ["26", "Barbara", "Jones"],
1✔
2031
        ["27", "Matthew", "Smith"],
1✔
2032
        ["50", "Jack", "Dumb"],
1✔
2033
        ["51", "Daniel", "Smart"],
1✔
2034
        ["31", "Ira", "Davies"],
1✔
2035
        ["32", "Ling", "Weng"],
1✔
2036
        ["33", "Kristian", "Green"],
1✔
2037
        ["34", "Roman", "Edwards"]];
1✔
2038

1✔
2039
        return this.isEqual("unionAll3", data, expected);
1✔
2040
    }
1✔
2041

1✔
2042
    unionAll4() {
1✔
2043
        let stmt = "select * from authors UNION ALL select * from editors UNION select * from translators EXCEPT select * from editors where first_name like 'M%'";
1✔
2044

1✔
2045
        let data = new TestSql()
1✔
2046
            .addTableData("authors", this.authorsTable())
1✔
2047
            .addTableData("editors", this.editorsTable())
1✔
2048
            .addTableData("translators", this.translatorsTable())
1✔
2049
            .enableColumnTitle(false)
1✔
2050
            .execute(stmt);
1✔
2051

1✔
2052
        let expected = [["11", "Ellen", "Writer"],
1✔
2053
        ["12", "Olga", "Savelieva"],
1✔
2054
        ["13", "Jack", "Smart"],
1✔
2055
        ["14", "Donald", "Brain"],
1✔
2056
        ["15", "Yao", "Dou"],
1✔
2057
        ["21", "Daniel", "Brown"],
1✔
2058
        ["24", "Cathrine", "Roberts"],
1✔
2059
        ["25", "Sebastian", "Wright"],
1✔
2060
        ["26", "Barbara", "Jones"],
1✔
2061
        ["50", "Jack", "Dumb"],
1✔
2062
        ["51", "Daniel", "Smart"],
1✔
2063
        ["31", "Ira", "Davies"],
1✔
2064
        ["32", "Ling", "Weng"],
1✔
2065
        ["33", "Kristian", "Green"],
1✔
2066
        ["34", "Roman", "Edwards"]];
1✔
2067

1✔
2068
        return this.isEqual("unionAll4", data, expected);
1✔
2069
    }
1✔
2070

1✔
2071
    unionJoin1() {
1✔
2072
        let stmt = "select booksales.invoice as 'Invoice', booksales.quantity as 'Quantity', booksales.price as 'Price', booksales.quantity * booksales.price as 'Sales', booksales.date, books.title, customers.name, authors.first_name + ' ' + authors.last_name as 'Author', translators.first_name + ' ' + translators.last_name as 'Translator', editors.first_name + ' ' + editors.last_name as 'Editor' " +
1✔
2073
            "from booksales left join books on booksales.book_id = books.id " +
1✔
2074
            "left join customers on booksales.customer_id = customers.id " +
1✔
2075
            "left join authors on books.author_id = authors.id " +
1✔
2076
            "left join translators on books.translator_id = translators.id " +
1✔
2077
            "left join editors on books.editor_id = editors.id " +
1✔
2078
            "where booksales.date >= ?1 and booksales.date <= ?2 " +
1✔
2079
            "union all select 'Total', SUM(booksales.quantity), avg(booksales.price), SUM(booksales.price * booksales.quantity), '' ,'', '', '', '', '' from booksales " +
1✔
2080
            "where booksales.date >= ?3 and booksales.date <= ?4 ";
1✔
2081

1✔
2082
        let data = new TestSql()
1✔
2083
            .addTableData("authors", this.authorsTable())
1✔
2084
            .addTableData("editors", this.editorsTable())
1✔
2085
            .addTableData("translators", this.translatorsTable())
1✔
2086
            .addTableData("booksales", this.bookSalesTable())
1✔
2087
            .addTableData("customers", this.customerTable())
1✔
2088
            .addTableData("editors", this.editorsTable())
1✔
2089
            .addTableData("books", this.bookTable())
1✔
2090
            .addBindParameter("05/01/2022")
1✔
2091
            .addBindParameter("05/02/2022")
1✔
2092
            .addBindParameter("05/01/2022")
1✔
2093
            .addBindParameter("05/02/2022")
1✔
2094
            .enableColumnTitle(true)
1✔
2095
            .execute(stmt);
1✔
2096

1✔
2097
        let expected = [["Invoice", "Quantity", "Price", "Sales", "booksales.date", "books.title", "customers.name", "Author", "Translator", "Editor"],
1✔
2098
        ["I7200", 10, 34.95, 349.5, "05/01/2022", "Book with Mysterious Author", "Numereo Uno", "null null", "Roman Edwards", "Maria Evans"],
1✔
2099
        ["I7201", 3, 29.95, 89.85, "05/01/2022", "My Last Book", "Dewy Tuesdays", "Ellen Writer", "null null", "null null"],
1✔
2100
        ["I7201", 5, 18.99, 94.94999999999999, "05/01/2022", "Applied AI", "Dewy Tuesdays", "Jack Smart", "Roman Edwards", "Maria Evans"],
1✔
2101
        ["I7202", 1, 59.99, 59.99, "05/02/2022", "Book with Mysterious Author", "Tres Buon Goods", "null null", "Roman Edwards", "Maria Evans"],
1✔
2102
        ["I7203", 1, 90, 90, "05/02/2022", "Time to Grow Up!", null, "Ellen Writer", "null null", "Daniel Brown"],
1✔
2103
        ["Total", 20, 46.775999999999996, 684.29, "", "", "", "", "", ""]];
1✔
2104

1✔
2105
        return this.isEqual("unionJoin1", data, expected);
1✔
2106

1✔
2107
    }
1✔
2108

1✔
2109
    except1() {
1✔
2110
        let stmt = "select * from authors EXCEPT select * from authors where last_name like 'S%'";
1✔
2111

1✔
2112
        let data = new TestSql()
1✔
2113
            .addTableData("authors", this.authorsTable())
1✔
2114
            .addTableData("editors", this.editorsTable())
1✔
2115
            .enableColumnTitle(true)
1✔
2116
            .execute(stmt);
1✔
2117

1✔
2118
        let expected = [["AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME"],
1✔
2119
        ["11", "Ellen", "Writer"],
1✔
2120
        ["14", "Donald", "Brain"],
1✔
2121
        ["15", "Yao", "Dou"]];
1✔
2122

1✔
2123
        return this.isEqual("except1", data, expected);
1✔
2124
    }
1✔
2125

1✔
2126
    intersect1() {
1✔
2127
        let stmt = "select * from editors INTERSECT select * from authors";
1✔
2128

1✔
2129
        let data = new TestSql()
1✔
2130
            .addTableData("authors", this.authorsTable())
1✔
2131
            .addTableData("editors", this.editorsTable())
1✔
2132
            .enableColumnTitle(true)
1✔
2133
            .execute(stmt);
1✔
2134

1✔
2135
        let expected = [["EDITORS.ID", "EDITORS.FIRST_NAME", "EDITORS.LAST_NAME"],
1✔
2136
        ["13", "Jack", "Smart"]];
1✔
2137

1✔
2138
        return this.isEqual("intersect1", data, expected);
1✔
2139
    }
1✔
2140

1✔
2141
    orderByDesc1() {
1✔
2142
        let stmt = "select * from bookSales order by DATE DESC";
1✔
2143

1✔
2144
        let data = new TestSql()
1✔
2145
            .addTableData("bookSales", this.bookSalesTable())
1✔
2146
            .enableColumnTitle(true)
1✔
2147
            .execute(stmt);
1✔
2148

1✔
2149
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
2150
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022"],
1✔
2151
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022"],
1✔
2152
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
1✔
2153
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
1✔
2154
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"],
1✔
2155
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
1✔
2156
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
2157
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022"],
1✔
2158
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022"],
1✔
2159
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022"]];
1✔
2160

1✔
2161
        return this.isEqual("orderByDesc1", data, expected);
1✔
2162
    }
1✔
2163

1✔
2164
    orderByDesc2() {
1✔
2165
        let stmt = "select * from bookSales order by DATE DESC, PRICE ASC";
1✔
2166

1✔
2167
        let data = new TestSql()
1✔
2168
            .addTableData("bookSales", this.bookSalesTable())
1✔
2169
            .enableColumnTitle(true)
1✔
2170
            .execute(stmt);
1✔
2171

1✔
2172
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
2173
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022"],
1✔
2174
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022"],
1✔
2175
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"],
1✔
2176
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
1✔
2177
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
1✔
2178
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
1✔
2179
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
2180
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022"],
1✔
2181
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022"],
1✔
2182
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022"]];
1✔
2183

1✔
2184
        return this.isEqual("orderByDesc2", data, expected);
1✔
2185
    }
1✔
2186

1✔
2187
    orderByDesc3() {
1✔
2188
        let stmt = "select * from customers where lower(city) like '%city%' order by email desc";
1✔
2189

1✔
2190
        let data = new TestSql()
1✔
2191
            .addTableData("customers", this.customerTable())
1✔
2192
            .enableColumnTitle(true)
1✔
2193
            .execute(stmt);
1✔
2194

1✔
2195
        let expected = [["CUSTOMERS.ID", "CUSTOMERS.NAME", "CUSTOMERS.ADDRESS", "CUSTOMERS.CITY", "CUSTOMERS.PHONE", "CUSTOMERS.EMAIL"],
1✔
2196
        ["C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"],
1✔
2197
        ["C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
1✔
2198
        ["C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
2199
        ["C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"],
1✔
2200
        ["C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
1✔
2201
        ["C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "]];
1✔
2202

1✔
2203
        return this.isEqual("orderByDesc3", data, expected);
1✔
2204
    }
1✔
2205

1✔
2206
    distinct1() {
1✔
2207
        let stmt = "select distinct last_name from editors";
1✔
2208

1✔
2209
        let data = new TestSql()
1✔
2210
            .addTableData("editors", this.editorsTable())
1✔
2211
            .enableColumnTitle(true)
1✔
2212
            .execute(stmt);
1✔
2213

1✔
2214
        let expected = [["LAST_NAME"],
1✔
2215
        ["Brown"],
1✔
2216
        ["Dumb"],
1✔
2217
        ["Evans"],
1✔
2218
        ["Johnson"],
1✔
2219
        ["Jones"],
1✔
2220
        ["Roberts"],
1✔
2221
        ["Smart"],
1✔
2222
        ["Smith"],
1✔
2223
        ["Wright"]];
1✔
2224

1✔
2225
        return this.isEqual("distinct1", data, expected);
1✔
2226
    }
1✔
2227

1✔
2228
    selectMath1() {
1✔
2229
        let stmt = "select book_id, -(quantity), price, Quantity * Price, booksales.quantity * booksales.price * 0.13, quantity % 2, ((quantity + 1) * price)/100  from bookSales";
1✔
2230

1✔
2231
        let data = new TestSql()
1✔
2232
            .addTableData("bookSales", this.bookSalesTable())
1✔
2233
            .enableColumnTitle(true)
1✔
2234
            .execute(stmt);
1✔
2235

1✔
2236
        let expected = [["book_id", "-(quantity)", "price", "Quantity * Price", "booksales.quantity * booksales.price * 0.13", "quantity % 2", "((quantity + 1) * price)/100"],
1✔
2237
        ["9", -10, 34.95, 349.5, 45.435, 0, 3.8445000000000005],
1✔
2238
        ["8", -3, 29.95, 89.85, 11.6805, 1, 1.198],
1✔
2239
        ["7", -5, 18.99, 94.94999999999999, 12.343499999999999, 1, 1.1394],
1✔
2240
        ["9", -1, 59.99, 59.99, 7.7987, 1, 1.1998],
1✔
2241
        ["1", -1, 90, 90, 11.700000000000001, 1, 1.8],
1✔
2242
        ["2", -100, 65.49, 6548.999999999999, 851.3699999999999, 0, 66.14489999999999],
1✔
2243
        ["3", -150, 24.95, 3742.5, 486.52500000000003, 0, 37.674499999999995],
1✔
2244
        ["4", -50, 19.99, 999.4999999999999, 129.935, 0, 10.194899999999999],
1✔
2245
        ["7", -1, 33.97, 33.97, 4.4161, 1, 0.6794],
1✔
2246
        ["7", -100, 17.99, 1798.9999999999998, 233.86999999999998, 0, 18.1699]];
1✔
2247

1✔
2248
        return this.isEqual("selectMath1", data, expected);
1✔
2249
    }
1✔
2250

1✔
2251
    selectMathFunc1() {
1✔
2252
        let stmt = "select book_id, quantity, price, round(((quantity + 1) * price)/100), LEFT(invoice,3), RIGHT(invoice,4)  from bookSales";
1✔
2253

1✔
2254
        let data = new TestSql()
1✔
2255
            .addTableData("bookSales", this.bookSalesTable())
1✔
2256
            .enableColumnTitle(true)
1✔
2257
            .execute(stmt);
1✔
2258

1✔
2259
        let expected = [["book_id", "quantity", "price", "round(((quantity + 1) * price)/100)", "LEFT(invoice,3)", "RIGHT(invoice,4)"],
1✔
2260
        ["9", 10, 34.95, 4, "I72", "7200"],
1✔
2261
        ["8", 3, 29.95, 1, "I72", "7201"],
1✔
2262
        ["7", 5, 18.99, 1, "I72", "7201"],
1✔
2263
        ["9", 1, 59.99, 1, "I72", "7202"],
1✔
2264
        ["1", 1, 90, 2, "I72", "7203"],
1✔
2265
        ["2", 100, 65.49, 66, "I72", "7204"],
1✔
2266
        ["3", 150, 24.95, 38, "I72", "7204"],
1✔
2267
        ["4", 50, 19.99, 10, "I72", "7204"],
1✔
2268
        ["7", 1, 33.97, 1, "I72", "7205"],
1✔
2269
        ["7", 100, 17.99, 18, "I72", "7206"]];
1✔
2270

1✔
2271
        return this.isEqual("selectMathFunc1", data, expected);
1✔
2272
    }
1✔
2273

1✔
2274
    selectMathFunc2() {
1✔
2275
        let stmt = "select book_id, quantity, price, ABS(quantity-10), CEILING(price), floor(price), log(quantity), log10(quantity), power(quantity, 2), sqrt(quantity)  from bookSales";
1✔
2276

1✔
2277
        let data = new TestSql()
1✔
2278
            .addTableData("bookSales", this.bookSalesTable())
1✔
2279
            .enableColumnTitle(true)
1✔
2280
            .execute(stmt);
1✔
2281

1✔
2282
        let expected = [["book_id", "quantity", "price", "ABS(quantity-10)", "CEILING(price)", "floor(price)", "log(quantity)", "log10(quantity)", "power(quantity, 2)", "sqrt(quantity)"],
1✔
2283
        ["9", 10, 34.95, 0, 35, 34, 3.321928094887362, 1, 100, 3.1622776601683795],
1✔
2284
        ["8", 3, 29.95, 7, 30, 29, 1.584962500721156, 0.47712125471966244, 9, 1.7320508075688772],
1✔
2285
        ["7", 5, 18.99, 5, 19, 18, 2.321928094887362, 0.6989700043360189, 25, 2.23606797749979],
1✔
2286
        ["9", 1, 59.99, 9, 60, 59, 0, 0, 1, 1],
1✔
2287
        ["1", 1, 90, 9, 90, 90, 0, 0, 1, 1],
1✔
2288
        ["2", 100, 65.49, 90, 66, 65, 6.643856189774724, 2, 10000, 10],
1✔
2289
        ["3", 150, 24.95, 140, 25, 24, 7.22881869049588, 2.1760912590556813, 22500, 12.24744871391589],
1✔
2290
        ["4", 50, 19.99, 40, 20, 19, 5.643856189774724, 1.6989700043360187, 2500, 7.0710678118654755],
1✔
2291
        ["7", 1, 33.97, 9, 34, 33, 0, 0, 1, 1], ["7", 100, 17.99, 90, 18, 17, 6.643856189774724, 2, 10000, 10]];
1✔
2292

1✔
2293
        return this.isEqual("selectMathFunc2", data, expected);
1✔
2294
    }
1✔
2295

1✔
2296
    selectFuncs2() {
1✔
2297
        let stmt = "select name, address, LEN(name), LENGTH(address), lower(name), upper(address), trim(email), ltrim(email), rtrim(email) from customers";
1✔
2298

1✔
2299
        let data = new TestSql()
1✔
2300
            .addTableData("customers", this.customerTable())
1✔
2301
            .enableColumnTitle(true)
1✔
2302
            .execute(stmt);
1✔
2303

1✔
2304
        let expected = [["name", "address", "LEN(name)", "LENGTH(address)", "lower(name)", "upper(address)", "trim(email)", "ltrim(email)", "rtrim(email)"],
1✔
2305
        ["Numereo Uno", "101 One Way", 11, 11, "numereo uno", "101 ONE WAY", "bigOne@gmail.com", "bigOne@gmail.com", "bigOne@gmail.com"],
1✔
2306
        ["Dewy Tuesdays", "202 Second St.", 13, 14, "dewy tuesdays", "202 SECOND ST.", "twoguys@gmail.com", "twoguys@gmail.com", "twoguys@gmail.com"],
1✔
2307
        ["Tres Buon Goods", "3 Way St", 15, 8, "tres buon goods", "3 WAY ST", "thrice@hotmail.com", "thrice@hotmail.com", "thrice@hotmail.com"],
1✔
2308
        ["ForMe Resellers", "40 Four St", 15, 10, "forme resellers", "40 FOUR ST", "fourtimes@hotmail.com", "fourtimes@hotmail.com", "fourtimes@hotmail.com"],
1✔
2309
        ["Fe Fi Fo Giant Tiger", "5 ohFive St.", 20, 12, "fe fi fo giant tiger", "5 OHFIVE ST.", "fiver@gmail.com", "fiver@gmail.com", "   fiver@gmail.com"],
1✔
2310
        ["Sx in Cars", "6 Seventh St", 10, 12, "sx in cars", "6 SEVENTH ST", "gotyourSix@hotmail.com", "gotyourSix@hotmail.com   ", "gotyourSix@hotmail.com"],
1✔
2311
        ["7th Heaven", "7 Eight Crt.", 10, 12, "7th heaven", "7 EIGHT CRT.", "timesAcharm@gmail.com", "timesAcharm@gmail.com ", " timesAcharm@gmail.com"]];
1✔
2312

1✔
2313
        return this.isEqual("selectFuncs2", data, expected);
1✔
2314
    }
1✔
2315

1✔
2316
    selectFuncs3() {
1✔
2317
        let stmt = "select name + ' = ' + upper(email), reverse(name), replicate(name,2) from customers";
1✔
2318

1✔
2319
        let data = new TestSql()
1✔
2320
            .addTableData("customers", this.customerTable())
1✔
2321
            .enableColumnTitle(true)
1✔
2322
            .execute(stmt);
1✔
2323

1✔
2324
        let expected = [["name + ' = ' + upper(email)", "reverse(name)", "replicate(name,2)"],
1✔
2325
        ["Numereo Uno = BIGONE@GMAIL.COM", "onU oeremuN", "Numereo UnoNumereo Uno"],
1✔
2326
        ["Dewy Tuesdays = TWOGUYS@GMAIL.COM", "syadseuT yweD", "Dewy TuesdaysDewy Tuesdays"],
1✔
2327
        ["Tres Buon Goods = THRICE@HOTMAIL.COM", "sdooG nouB serT", "Tres Buon GoodsTres Buon Goods"],
1✔
2328
        ["ForMe Resellers = FOURTIMES@HOTMAIL.COM", "srelleseR eMroF", "ForMe ResellersForMe Resellers"],
1✔
2329
        ["Fe Fi Fo Giant Tiger =    FIVER@GMAIL.COM", "regiT tnaiG oF iF eF", "Fe Fi Fo Giant TigerFe Fi Fo Giant Tiger"],
1✔
2330
        ["Sx in Cars = GOTYOURSIX@HOTMAIL.COM   ", "sraC ni xS", "Sx in CarsSx in Cars"],
1✔
2331
        ["7th Heaven =  TIMESACHARM@GMAIL.COM ", "nevaeH ht7", "7th Heaven7th Heaven"]];
1✔
2332

1✔
2333
        return this.isEqual("selectFuncs3", data, expected);
1✔
2334
    }
1✔
2335

1✔
2336
    selectFuncs4() {
1✔
2337
        let stmt = "select space(5), email, stuff(email, 2, 3, 'CJD'), substring(email, 5, 5) from customers";
1✔
2338

1✔
2339
        let data = new TestSql()
1✔
2340
            .addTableData("customers", this.customerTable())
1✔
2341
            .enableColumnTitle(true)
1✔
2342
            .execute(stmt);
1✔
2343

1✔
2344
        let expected = [["space(5)", "email", "stuff(email, 2, 3, 'CJD')", "substring(email, 5, 5)"],
1✔
2345
        ["     ", "bigOne@gmail.com", "bCJDne@gmail.com", "ne@gm"],
1✔
2346
        ["     ", "twoguys@gmail.com", "tCJDuys@gmail.com", "uys@g"],
1✔
2347
        ["     ", "thrice@hotmail.com", "tCJDce@hotmail.com", "ce@ho"],
1✔
2348
        ["     ", "fourtimes@hotmail.com", "fCJDtimes@hotmail.com", "times"],
1✔
2349
        ["     ", "   fiver@gmail.com", " CJDiver@gmail.com", "iver@"],
1✔
2350
        ["     ", "gotyourSix@hotmail.com   ", "gCJDourSix@hotmail.com   ", "ourSi"],
1✔
2351
        ["     ", " timesAcharm@gmail.com ", " CJDesAcharm@gmail.com ", "esAch"]];
1✔
2352

1✔
2353
        return this.isEqual("selectFuncs4", data, expected);
1✔
2354
    }
1✔
2355

1✔
2356
    selectFuncs5() {
1✔
2357
        let stmt = "select now(), email, stuff(email, 2, 3, 'CJD'), substring(email, 5, 5) from customers limit 1";
1✔
2358

1✔
2359
        let testSQL = new TestSql()
1✔
2360
            .addTableData("customers", this.customerTable())
1✔
2361
            .enableColumnTitle(true);
1✔
2362

1✔
2363
        Logger.log("NOTE:  selectFuncs5(), Test is attempted multiple times on failure (matching current time).")
1✔
2364
        //  NOW() is always changing, so try our test a few times.
1✔
2365
        let attempts = 0;
1✔
2366
        let success = false;
1✔
2367
        while (attempts < 5 && !success) {
1✔
2368
            let data = testSQL.execute(stmt);
1✔
2369

1✔
2370
            let expected = [["now()", "email", "stuff(email, 2, 3, 'CJD')", "substring(email, 5, 5)"],
1✔
2371
            ["%1", "bigOne@gmail.com", "bCJDne@gmail.com", "ne@gm"]];
1✔
2372

1✔
2373
            for (let row of expected) {
1✔
2374
                let nowPos = row.indexOf("%1");
2✔
2375
                if (nowPos != -1)
2✔
2376
                    row[nowPos] = new Date().toLocaleString();
2✔
2377
            }
2✔
2378

1✔
2379
            success = this.isEqual("selectFuncs5", data, expected);
1✔
2380
            attempts++;
1✔
2381
        }
1✔
2382

1✔
2383
        return success;
1✔
2384
    }
1✔
2385

1✔
2386
    selectFuncs6() {
1✔
2387
        let stmt = "select date, year(date), month(date), day(date) from booksales";
1✔
2388

1✔
2389
        let data = new TestSql()
1✔
2390
            .addTableData("booksales", this.bookSalesTable())
1✔
2391
            .enableColumnTitle(true)
1✔
2392
            .execute(stmt);
1✔
2393

1✔
2394
        let expected = [["date", "year(date)", "month(date)", "day(date)"],
1✔
2395
        ["05/01/2022", 2022, 5, 1],
1✔
2396
        ["05/01/2022", 2022, 5, 1],
1✔
2397
        ["05/01/2022", 2022, 5, 1],
1✔
2398
        ["05/02/2022", 2022, 5, 2],
1✔
2399
        ["05/02/2022", 2022, 5, 2],
1✔
2400
        ["05/03/2022", 2022, 5, 3],
1✔
2401
        ["05/03/2022", 2022, 5, 3],
1✔
2402
        ["05/03/2022", 2022, 5, 3],
1✔
2403
        ["05/04/2022", 2022, 5, 4],
1✔
2404
        ["05/04/2022", 2022, 5, 4]];
1✔
2405

1✔
2406
        return this.isEqual("selectFuncs6", data, expected);
1✔
2407
    }
1✔
2408

1✔
2409
    selectFuncs7() {
1✔
2410
        let stmt = "select name, charindex(' ', name, 2), charindex(' ', name, 4), charindex(' ', name, 6) from customers";
1✔
2411

1✔
2412
        let data = new TestSql()
1✔
2413
            .addTableData("customers", this.customerTable())
1✔
2414
            .enableColumnTitle(true)
1✔
2415
            .execute(stmt);
1✔
2416

1✔
2417
        let expected = [["name", "charindex(' ', name, 2)", "charindex(' ', name, 4)", "charindex(' ', name, 6)"],
1✔
2418
        ["Numereo Uno", 8, 8, 8],
1✔
2419
        ["Dewy Tuesdays", 5, 5, 0],
1✔
2420
        ["Tres Buon Goods", 5, 5, 10],
1✔
2421
        ["ForMe Resellers", 6, 6, 6],
1✔
2422
        ["Fe Fi Fo Giant Tiger", 3, 6, 6],
1✔
2423
        ["Sx in Cars", 3, 6, 6],
1✔
2424
        ["7th Heaven", 4, 4, 0]];
1✔
2425

1✔
2426
        return this.isEqual("selectFuncs7", data, expected);
1✔
2427
    }
1✔
2428

1✔
2429
    selectFuncInFunc1() {
1✔
2430
        let stmt = "select email, upper(substring(email, 5, 5)), trim(upper(email)) from customers";
1✔
2431

1✔
2432
        let data = new TestSql()
1✔
2433
            .addTableData("customers", this.customerTable())
1✔
2434
            .enableColumnTitle(true)
1✔
2435
            .execute(stmt);
1✔
2436

1✔
2437
        let expected = [["email", "upper(substring(email, 5, 5))", "trim(upper(email))"],
1✔
2438
        ["bigOne@gmail.com", "NE@GM", "BIGONE@GMAIL.COM"],
1✔
2439
        ["twoguys@gmail.com", "UYS@G", "TWOGUYS@GMAIL.COM"],
1✔
2440
        ["thrice@hotmail.com", "CE@HO", "THRICE@HOTMAIL.COM"],
1✔
2441
        ["fourtimes@hotmail.com", "TIMES", "FOURTIMES@HOTMAIL.COM"],
1✔
2442
        ["   fiver@gmail.com", "IVER@", "FIVER@GMAIL.COM"],
1✔
2443
        ["gotyourSix@hotmail.com   ", "OURSI", "GOTYOURSIX@HOTMAIL.COM"],
1✔
2444
        [" timesAcharm@gmail.com ", "ESACH", "TIMESACHARM@GMAIL.COM"]];
1✔
2445

1✔
2446
        return this.isEqual("selectFuncInFunc1", data, expected);
1✔
2447
    }
1✔
2448

1✔
2449
    selectFuncInFunc2() {
1✔
2450
        let stmt = "select email,charindex('@', email), if(charindex('@', email) > 0, trim(substring(email, 1, charindex('@', email) - 1)), email) from customers";
1✔
2451

1✔
2452
        let data = new TestSql()
1✔
2453
            .addTableData("customers", this.customerTable())
1✔
2454
            .enableColumnTitle(true)
1✔
2455
            .execute(stmt);
1✔
2456

1✔
2457
        let expected = [["email", "charindex('@', email)", "if(charindex('@', email) > 0, trim(substring(email, 1, charindex('@', email) - 1)), email)"],
1✔
2458
        ["bigOne@gmail.com", 7, "bigOne"],
1✔
2459
        ["twoguys@gmail.com", 8, "twoguys"],
1✔
2460
        ["thrice@hotmail.com", 7, "thrice"],
1✔
2461
        ["fourtimes@hotmail.com", 10, "fourtimes"],
1✔
2462
        ["   fiver@gmail.com", 9, "fiver"],
1✔
2463
        ["gotyourSix@hotmail.com   ", 11, "gotyourSix"],
1✔
2464
        [" timesAcharm@gmail.com ", 13, "timesAcharm"]];
1✔
2465

1✔
2466
        return this.isEqual("selectFuncInFunc2", data, expected);
1✔
2467
    }
1✔
2468

1✔
2469
    selectIF1() {
1✔
2470
        let stmt = "SELECT IF(authors.id = '', 'MISSING AUTHOR', authors.id), authors.last_name, IF(editors.id = '', 'MISSING EDITOR', editors.id), editors.last_name " +
1✔
2471
            "FROM authors " +
1✔
2472
            "FULL JOIN editors " +
1✔
2473
            "ON authors.id = editors.id ";
1✔
2474

1✔
2475
        let data = new TestSql()
1✔
2476
            .addTableData("authors", this.authorsTable())
1✔
2477
            .addTableData("editors", this.editorsTable())
1✔
2478
            .enableColumnTitle(true)
1✔
2479
            .execute(stmt);
1✔
2480

1✔
2481
        let expected = [["IF(authors.id = '', 'MISSING AUTHOR', authors.id)", "authors.last_name", "IF(editors.id = '', 'MISSING EDITOR', editors.id)", "editors.last_name"],
1✔
2482
        ["11", "Writer", null, null],
1✔
2483
        ["12", "Savelieva", null, null],
1✔
2484
        ["13", "Smart", "13", "Smart"],
1✔
2485
        ["14", "Brain", null, null],
1✔
2486
        ["15", "Dou", null, null],
1✔
2487
        [null, null, "21", "Brown"],
1✔
2488
        [null, null, "22", "Johnson"],
1✔
2489
        [null, null, "23", "Evans"],
1✔
2490
        [null, null, "24", "Roberts"],
1✔
2491
        [null, null, "25", "Wright"],
1✔
2492
        [null, null, "26", "Jones"],
1✔
2493
        [null, null, "27", "Smith"],
1✔
2494
        [null, null, "50", "Dumb"],
1✔
2495
        [null, null, "51", "Smart"]]
1✔
2496
            ;
1✔
2497

1✔
2498
        return this.isEqual("selectIF1", data, expected);
1✔
2499
    }
1✔
2500

1✔
2501
    selectIF2() {
1✔
2502
        let stmt = "SELECT quantity, price, if(price > 25, 'OVER $25', 'UNDER $25') " +
1✔
2503
            "FROM booksales ";
1✔
2504

1✔
2505
        let data = new TestSql()
1✔
2506
            .addTableData("bookSales", this.bookSalesTable())
1✔
2507
            .enableColumnTitle(true)
1✔
2508
            .execute(stmt);
1✔
2509

1✔
2510
        let expected = [["quantity", "price", "if(price > 25, 'OVER $25', 'UNDER $25')"],
1✔
2511
        [10, 34.95, "OVER $25"],
1✔
2512
        [3, 29.95, "OVER $25"],
1✔
2513
        [5, 18.99, "UNDER $25"],
1✔
2514
        [1, 59.99, "OVER $25"],
1✔
2515
        [1, 90, "OVER $25"],
1✔
2516
        [100, 65.49, "OVER $25"],
1✔
2517
        [150, 24.95, "UNDER $25"],
1✔
2518
        [50, 19.99, "UNDER $25"],
1✔
2519
        [1, 33.97, "OVER $25"],
1✔
2520
        [100, 17.99, "UNDER $25"]];
1✔
2521

1✔
2522
        return this.isEqual("selectIF2", data, expected);
1✔
2523
    }
1✔
2524

1✔
2525
    selectIF3() {
1✔
2526
        let stmt = "SELECT quantity, price, if(quantity + price > 100, 'OVER $100', 'UNDER $100') " +
1✔
2527
            "FROM booksales ";
1✔
2528

1✔
2529
        let data = new TestSql()
1✔
2530
            .addTableData("bookSales", this.bookSalesTable())
1✔
2531
            .enableColumnTitle(true)
1✔
2532
            .execute(stmt);
1✔
2533

1✔
2534
        let expected = [["quantity", "price", "if(quantity + price > 100, 'OVER $100', 'UNDER $100')"],
1✔
2535
        [10, 34.95, "UNDER $100"],
1✔
2536
        [3, 29.95, "UNDER $100"],
1✔
2537
        [5, 18.99, "UNDER $100"],
1✔
2538
        [1, 59.99, "UNDER $100"],
1✔
2539
        [1, 90, "UNDER $100"],
1✔
2540
        [100, 65.49, "OVER $100"],
1✔
2541
        [150, 24.95, "OVER $100"],
1✔
2542
        [50, 19.99, "UNDER $100"],
1✔
2543
        [1, 33.97, "UNDER $100"]
1✔
2544
            , [100, 17.99, "OVER $100"]];
1✔
2545

1✔
2546
        return this.isEqual("selectIF3", data, expected);
1✔
2547
    }
1✔
2548

1✔
2549
    selectIF4() {
1✔
2550
        let stmt = "SELECT quantity, price, if(quantity * price > 100, 'OVER $100', 'UNDER $100') " +
1✔
2551
            "FROM booksales ";
1✔
2552

1✔
2553
        let data = new TestSql()
1✔
2554
            .addTableData("bookSales", this.bookSalesTable())
1✔
2555
            .enableColumnTitle(true)
1✔
2556
            .execute(stmt);
1✔
2557

1✔
2558
        let expected = [["quantity", "price", "if(quantity * price > 100, 'OVER $100', 'UNDER $100')"],
1✔
2559
        [10, 34.95, "OVER $100"],
1✔
2560
        [3, 29.95, "UNDER $100"],
1✔
2561
        [5, 18.99, "UNDER $100"],
1✔
2562
        [1, 59.99, "UNDER $100"],
1✔
2563
        [1, 90, "UNDER $100"],
1✔
2564
        [100, 65.49, "OVER $100"],
1✔
2565
        [150, 24.95, "OVER $100"],
1✔
2566
        [50, 19.99, "OVER $100"],
1✔
2567
        [1, 33.97, "UNDER $100"],
1✔
2568
        [100, 17.99, "OVER $100"]];
1✔
2569

1✔
2570
        return this.isEqual("selectIF4", data, expected);
1✔
2571
    }
1✔
2572

1✔
2573
    selectWhereCalc1() {
1✔
2574
        let stmt = "SELECT quantity, price, price + quantity from booksales where (price + quantity > 100)";
1✔
2575

1✔
2576
        let data = new TestSql()
1✔
2577
            .addTableData("bookSales", this.bookSalesTable())
1✔
2578
            .enableColumnTitle(true)
1✔
2579
            .execute(stmt);
1✔
2580

1✔
2581
        let expected = [["quantity", "price", "price + quantity"],
1✔
2582
        [100, 65.49, 165.49],
1✔
2583
        [150, 24.95, 174.95],
1✔
2584
        [100, 17.99, 117.99]];
1✔
2585

1✔
2586
        return this.isEqual("selectWhereCalc1", data, expected);
1✔
2587
    }
1✔
2588

1✔
2589
    selectWhereCalc2() {
1✔
2590
        let stmt = "SELECT quantity, price, quantity * price from booksales where price * quantity > 100";
1✔
2591

1✔
2592
        let data = new TestSql()
1✔
2593
            .addTableData("bookSales", this.bookSalesTable())
1✔
2594
            .enableColumnTitle(true)
1✔
2595
            .execute(stmt);
1✔
2596

1✔
2597
        let expected = [["quantity", "price", "quantity * price"],
1✔
2598
        [10, 34.95, 349.5],
1✔
2599
        [100, 65.49, 6548.999999999999],
1✔
2600
        [150, 24.95, 3742.5],
1✔
2601
        [50, 19.99, 999.4999999999999],
1✔
2602
        [100, 17.99, 1798.9999999999998]];
1✔
2603

1✔
2604
        return this.isEqual("selectWhereCalc2", data, expected);
1✔
2605
    }
1✔
2606

1✔
2607
    selectCase1() {
1✔
2608
        let stmt = "SELECT quantity, price, " +
1✔
2609
            "CASE " +
1✔
2610
            "WHEN quantity = 1 THEN 'One Sold' " +
1✔
2611
            "WHEN quantity = 2 THEN 'Two Sold' " +
1✔
2612
            "WHEN quantity = 3 THEN 'Three Sold' " +
1✔
2613
            "WHEN quantity < 100 THEN 'Up to 100 Sold' " +
1✔
2614
            "ELSE quantity + ' items sold' " +
1✔
2615
            "END " +
1✔
2616
            "from booksales";
1✔
2617

1✔
2618
        let data = new TestSql()
1✔
2619
            .addTableData("bookSales", this.bookSalesTable())
1✔
2620
            .enableColumnTitle(true)
1✔
2621
            .execute(stmt);
1✔
2622

1✔
2623
        let expected = [["quantity", "price", "CASE WHEN quantity = 1 THEN 'One Sold' WHEN quantity = 2 THEN 'Two Sold' WHEN quantity = 3 THEN 'Three Sold' WHEN quantity < 100 THEN 'Up to 100 Sold' ELSE quantity + ' items sold' END"],
1✔
2624
        [10, 34.95, "Up to 100 Sold"],
1✔
2625
        [3, 29.95, "Three Sold"],
1✔
2626
        [5, 18.99, "Up to 100 Sold"],
1✔
2627
        [1, 59.99, "One Sold"],
1✔
2628
        [1, 90, "One Sold"],
1✔
2629
        [100, 65.49, "100 items sold"],
1✔
2630
        [150, 24.95, "150 items sold"],
1✔
2631
        [50, 19.99, "Up to 100 Sold"],
1✔
2632
        [1, 33.97, "One Sold"],
1✔
2633
        [100, 17.99, "100 items sold"]];
1✔
2634

1✔
2635
        return this.isEqual("selectCase1", data, expected);
1✔
2636
    }
1✔
2637

1✔
2638
    selectCase2() {
1✔
2639
        let stmt = "SELECT quantity, price, " +
1✔
2640
            "'Invoice=' + substring(invoice,2,4) + ' ' + " +
1✔
2641
            "CASE " +
1✔
2642
            "WHEN quantity > 1 and quantity <= 5 THEN 'Low Volume ' + quantity * price " +
1✔
2643
            "WHEN quantity > 5 and quantity < 10 THEN 'Moderate Volume' + quantity " +
1✔
2644
            "WHEN quantity = 100 or quantity = 150 THEN '100 or 150' " +
1✔
2645
            "WHEN quantity * price = 90 THEN '$90, ka ching.'   " +
1✔
2646
            "ELSE quantity + ' items sold. ID=' + lower(customer_id) " +
1✔
2647
            "END as summary" +
1✔
2648
            "from booksales";
1✔
2649

1✔
2650
        let data = new TestSql()
1✔
2651
            .addTableData("bookSales", this.bookSalesTable())
1✔
2652
            .enableColumnTitle(true)
1✔
2653
            .execute(stmt);
1✔
2654

1✔
2655
        let expected = [["quantity", "price", "summary"],
1✔
2656
        [10, 34.95, "Invoice=7200 10 items sold. ID=c1"],
1✔
2657
        [3, 29.95, "Invoice=7201 Low Volume 89.85"],
1✔
2658
        [5, 18.99, "Invoice=7201 Low Volume 94.94999999999999"],
1✔
2659
        [1, 59.99, "Invoice=7202 1 items sold. ID=c3"],
1✔
2660
        [1, 90, "Invoice=7203 $90, ka ching."],
1✔
2661
        [100, 65.49, "Invoice=7204 100 or 150"],
1✔
2662
        [150, 24.95, "Invoice=7204 100 or 150"],
1✔
2663
        [50, 19.99, "Invoice=7204 50 items sold. ID=c4"],
1✔
2664
        [1, 33.97, "Invoice=7205 1 items sold. ID=c1"],
1✔
2665
        [100, 17.99, "Invoice=7206 100 or 150"]];
1✔
2666

1✔
2667
        return this.isEqual("selectCase2", data, expected);
1✔
2668
    }
1✔
2669

1✔
2670
    selectAlias1() {
1✔
2671
        let stmt = "SELECT quantity as QTY, price as Pricing,  round(quantity * price) as Money from booksales where price * quantity > 100";
1✔
2672

1✔
2673
        let data = new TestSql()
1✔
2674
            .addTableData("bookSales", this.bookSalesTable())
1✔
2675
            .enableColumnTitle(true)
1✔
2676
            .execute(stmt);
1✔
2677

1✔
2678
        let expected = [["QTY", "Pricing", "Money"],
1✔
2679
        [10, 34.95, 350],
1✔
2680
        [100, 65.49, 6549],
1✔
2681
        [150, 24.95, 3743],
1✔
2682
        [50, 19.99, 999],
1✔
2683
        [100, 17.99, 1799]];
1✔
2684

1✔
2685
        return this.isEqual("selectAlias1", data, expected);
1✔
2686
    }
1✔
2687

1✔
2688
    liveTest1() {
1✔
2689
        let stmt = "select mastertransactions.transaction_date, sum(mastertransactions.gross), sum(mastertransactions.amount) from mastertransactions inner join budgetCategories on mastertransactions.Expense_Category = budgetCategories.Income where mastertransactions.transaction_date >=  '01/01/2022' and mastertransactions.transaction_date <= '05/19/2022' group by mastertransactions.transaction_date pivot mastertransactions.account";
×
2690

×
2691
        let data = new TestSql()
×
2692
            .addTableData('mastertransactions', 'Master Transactions!$A$1:$I')
×
2693
            .addTableData('budgetCategories', 'budgetIncomeCategories')
×
2694
            .enableColumnTitle(true)
×
2695
            .execute(stmt);
×
2696

×
2697
        let expected = [["QTY", "Pricing", "Money"],
×
2698
        [10, 34.95, 350],
×
2699
        [100, 65.49, 6549],
×
2700
        [150, 24.95, 3743],
×
2701
        [50, 19.99, 999],
×
2702
        [100, 17.99, 1799]];
×
2703

×
2704
        return this.isEqual("liveTest1", data, expected);
×
2705

×
2706
    }
×
2707

1✔
2708
    liveTest2() {
1✔
2709
        let stmt = "select name_of_institution, transaction_date, balance from 'master transactions' where name_of_institution in (select account_name from accounts where type = 'Bank') and balance is not null and transaction_date >= ? and transaction_date <= ?";
×
2710

×
2711
        let data = gsSQL(stmt, [], false, 'startBankingDate', 'endBankingDate');
×
2712

×
2713
        let expected = [["QTY", "Pricing", "Money"],
×
2714
        [10, 34.95, 350],
×
2715
        [100, 65.49, 6549],
×
2716
        [150, 24.95, 3743],
×
2717
        [50, 19.99, 999],
×
2718
        [100, 17.99, 1799]];
×
2719

×
2720
        return this.isEqual("liveTest2", data, expected);
×
2721

×
2722
    }
×
2723

1✔
2724
    groupPivot1() {
1✔
2725
        let stmt = "select bookSales.date, SUM(bookSales.Quantity) from bookSales where customer_id != '' group by date pivot customer_id";
1✔
2726

1✔
2727
        let data = new TestSql()
1✔
2728
            .addTableData("bookSales", this.bookSalesTable())
1✔
2729
            .enableColumnTitle(true)
1✔
2730
            .execute(stmt);
1✔
2731

1✔
2732
        let expected = [["bookSales.date", "C1 SUM(bookSales.Quantity)", "C2 SUM(bookSales.Quantity)", "C3 SUM(bookSales.Quantity)", "C4 SUM(bookSales.Quantity)"],
1✔
2733
        ["05/01/2022", 10, 8, 0, 0],
1✔
2734
        ["05/02/2022", 0, 0, 1, 0],
1✔
2735
        ["05/03/2022", 0, 0, 0, 300],
1✔
2736
        ["05/04/2022", 1, 100, 0, 0]];
1✔
2737

1✔
2738
        return this.isEqual("groupPivot1", data, expected);
1✔
2739
    }
1✔
2740

1✔
2741
    groupPivot2() {
1✔
2742
        let stmt = "select date, sum(quantity) from bookReturns group by date pivot customer_id";
1✔
2743

1✔
2744
        let data = new TestSql()
1✔
2745
            .addTableData("bookReturns", this.bookReturnsTable())
1✔
2746
            .enableColumnTitle(true)
1✔
2747
            .execute(stmt);
1✔
2748

1✔
2749
        let expected = [["date", "c1 sum(quantity)", "c2 sum(quantity)", "c3 sum(quantity)", "c4 sum(quantity)"],
1✔
2750
        ["05/01/2022", 10, 8, 0, 0],
1✔
2751
        ["05/02/2022", 1, 0, 1, 0],
1✔
2752
        ["05/03/2022", 0, 0, 0, 300],
1✔
2753
        ["05/04/2022", 1, 100, 0, 0]];
1✔
2754

1✔
2755
        return this.isEqual("groupPivot2", data, expected);
1✔
2756
    }
1✔
2757

1✔
2758
    groupPivot3() {
1✔
2759
        let stmt = "select date, sum(quantity) from bookReturns where date >= ?1 and date <= ?2 group by date pivot customer_id";
1✔
2760

1✔
2761
        let data = new TestSql()
1✔
2762
            .addTableData("bookReturns", this.bookReturnsTable())
1✔
2763
            .enableColumnTitle(true)
1✔
2764
            .addBindParameter("05/01/2022")
1✔
2765
            .addBindParameter("05/04/2022")
1✔
2766
            .execute(stmt);
1✔
2767

1✔
2768
        let expected = [["date", "c1 sum(quantity)", "c2 sum(quantity)", "c3 sum(quantity)", "c4 sum(quantity)"],
1✔
2769
        ["05/01/2022", 10, 8, 0, 0],
1✔
2770
        ["05/02/2022", 1, 0, 1, 0],
1✔
2771
        ["05/03/2022", 0, 0, 0, 300],
1✔
2772
        ["05/04/2022", 1, 100, 0, 0]];
1✔
2773

1✔
2774
        return this.isEqual("groupPivot3", data, expected);
1✔
2775
    }
1✔
2776

1✔
2777

1✔
2778
    groupFunc1() {
1✔
2779
        let stmt = "select bookSales.date, SUM(if(customer_id = 'C1', bookSales.Quantity,0)), SUM(if(customer_id = 'C2', bookSales.Quantity,0)) from bookSales where customer_id != '' group by date";
1✔
2780

1✔
2781
        let data = new TestSql()
1✔
2782
            .addTableData("bookSales", this.bookSalesTable())
1✔
2783
            .enableColumnTitle(true)
1✔
2784
            .execute(stmt);
1✔
2785

1✔
2786
        let expected = [["bookSales.date", "SUM(if(customer_id = 'C1', bookSales.Quantity,0))", "SUM(if(customer_id = 'C2', bookSales.Quantity,0))"],
1✔
2787
        ["05/01/2022", 10, 8],
1✔
2788
        ["05/02/2022", 0, 0],
1✔
2789
        ["05/03/2022", 0, 0],
1✔
2790
        ["05/04/2022", 1, 100]];
1✔
2791

1✔
2792
        return this.isEqual("groupFunc1", data, expected);
1✔
2793
    }
1✔
2794

1✔
2795
    groupFunc2() {
1✔
2796
        let stmt = "select bookSales.date, SUM(if(customer_id = 'C1', bookSales.Quantity,0)), SUM(if(customer_id = 'C2', bookSales.Quantity,0)) from bookSales where customer_id = '1010' group by date";
1✔
2797

1✔
2798
        let data = new TestSql()
1✔
2799
            .addTableData("bookSales", this.bookSalesTable())
1✔
2800
            .enableColumnTitle(false)
1✔
2801
            .execute(stmt);
1✔
2802

1✔
2803
        let expected = [['']];
1✔
2804

1✔
2805
        return this.isEqual("groupFunc2", data, expected);
1✔
2806
    }
1✔
2807

1✔
2808
    selectInGroupByPivot1() {
1✔
2809
        let stmt = "select bookSales.date, SUM(bookSales.Quantity) from bookSales where customer_id in (select id from customers)  group by date pivot customer_id";
1✔
2810

1✔
2811
        let data = new TestSql()
1✔
2812
            .addTableData("bookSales", this.bookSalesTable())
1✔
2813
            .addTableData("customers", this.customerTable())
1✔
2814
            .enableColumnTitle(true)
1✔
2815
            .execute(stmt);
1✔
2816

1✔
2817
        let expected = [["bookSales.date", "C1 SUM(bookSales.Quantity)", "C2 SUM(bookSales.Quantity)", "C3 SUM(bookSales.Quantity)", "C4 SUM(bookSales.Quantity)"],
1✔
2818
        ["05/01/2022", 10, 8, 0, 0],
1✔
2819
        ["05/02/2022", 0, 0, 1, 0],
1✔
2820
        ["05/03/2022", 0, 0, 0, 300],
1✔
2821
        ["05/04/2022", 1, 100, 0, 0]];
1✔
2822

1✔
2823
        return this.isEqual("selectInGroupByPivot1", data, expected);
1✔
2824
    }
1✔
2825

1✔
2826
    selectInGroupByPivot2() {
1✔
2827
        let stmt = "select bookSales.date as 'Transaction Date', SUM(bookSales.Quantity) as [ as Much Quantity], Max(price) as Maximum from bookSales where customer_id in (select id from customers)  group by date pivot customer_id";
1✔
2828

1✔
2829
        let data = new TestSql()
1✔
2830
            .addTableData("bookSales", this.bookSalesTable())
1✔
2831
            .addTableData("customers", this.customerTable())
1✔
2832
            .enableColumnTitle(true)
1✔
2833
            .execute(stmt);
1✔
2834

1✔
2835
        let expected = [["Transaction Date", "C1  as Much Quantity", "C2  as Much Quantity", "C3  as Much Quantity", "C4  as Much Quantity", "C1 Maximum", "C2 Maximum", "C3 Maximum", "C4 Maximum"],
1✔
2836
        ["05/01/2022", 10, 8, 0, 0, 34.95, 29.95, 0, 0],
1✔
2837
        ["05/02/2022", 0, 0, 1, 0, 0, 0, 59.99, 0],
1✔
2838
        ["05/03/2022", 0, 0, 0, 300, 0, 0, 0, 65.49],
1✔
2839
        ["05/04/2022", 1, 100, 0, 0, 33.97, 17.99, 0, 0]];
1✔
2840

1✔
2841
        return this.isEqual("selectInGroupByPivot2", data, expected);
1✔
2842
    }
1✔
2843

1✔
2844
    selectInGroupByPivot3() {
1✔
2845
        let stmt = "select bookSales.date as 'Date', SUM(bookSales.Quantity) as [Quantity], Max(price) as Maximum, min(price) as Min, avg(price) as avg, count(date) from bookSales where customer_id in (select id from customers)  group by date pivot customer_id";
1✔
2846

1✔
2847
        let data = new TestSql()
1✔
2848
            .addTableData("bookSales", this.bookSalesTable())
1✔
2849
            .addTableData("customers", this.customerTable())
1✔
2850
            .enableColumnTitle(true)
1✔
2851
            .execute(stmt);
1✔
2852

1✔
2853
        let expected = [["Date", "C1 Quantity", "C2 Quantity", "C3 Quantity", "C4 Quantity", "C1 Maximum", "C2 Maximum", "C3 Maximum", "C4 Maximum", "C1 Min", "C2 Min", "C3 Min", "C4 Min", "C1 avg", "C2 avg", "C3 avg", "C4 avg", "C1 count(date)", "C2 count(date)", "C3 count(date)", "C4 count(date)"],
1✔
2854
        ["05/01/2022", 10, 8, 0, 0, 34.95, 29.95, 0, 0, 34.95, 18.99, 0, 0, 34.95, 24.47, null, null, 1, 2, 0, 0],
1✔
2855
        ["05/02/2022", 0, 0, 1, 0, 0, 0, 59.99, 0, 0, 0, 59.99, 0, null, null, 59.99, null, 0, 0, 1, 0],
1✔
2856
        ["05/03/2022", 0, 0, 0, 300, 0, 0, 0, 65.49, 0, 0, 0, 19.99, null, null, null, 36.809999999999995, 0, 0, 0, 3],
1✔
2857
        ["05/04/2022", 1, 100, 0, 0, 33.97, 17.99, 0, 0, 33.97, 17.99, 0, 0, 33.97, 17.99, null, null, 1, 1, 0, 0]];
1✔
2858

1✔
2859
        return this.isEqual("selectInGroupByPivot3", data, expected);
1✔
2860
    }
1✔
2861

1✔
2862
    selectCount1() {
1✔
2863
        let stmt = "select count(*) from booksales";
1✔
2864

1✔
2865
        let data = new TestSql()
1✔
2866
            .addTableData("bookSales", this.bookSalesTable())
1✔
2867
            .enableColumnTitle(true)
1✔
2868
            .execute(stmt);
1✔
2869

1✔
2870
        let expected = [["count(*)"],
1✔
2871
        [10]];
1✔
2872

1✔
2873
        return this.isEqual("selectCount1", data, expected);
1✔
2874
    }
1✔
2875

1✔
2876
    selectCount2() {
1✔
2877
        let stmt = "select customer_id, count(*) from booksales group by customer_id having count(*) > 1";
1✔
2878

1✔
2879
        let data = new TestSql()
1✔
2880
            .addTableData("bookSales", this.bookSalesTable())
1✔
2881
            .enableColumnTitle(true)
1✔
2882
            .execute(stmt);
1✔
2883

1✔
2884
        let expected = [["customer_id", "count(*)"],
1✔
2885
        ["C1", 2],
1✔
2886
        ["C2", 3],
1✔
2887
        ["C4", 3]];
1✔
2888

1✔
2889
        return this.isEqual("selectCount2", data, expected);
1✔
2890
    }
1✔
2891

1✔
2892
    selectCount3() {
1✔
2893
        let stmt = "select count(distinct customer_id), count(distinct invoice) from booksales where customer_id <> ''";
1✔
2894

1✔
2895
        let data = new TestSql()
1✔
2896
            .addTableData("bookSales", this.bookSalesTable())
1✔
2897
            .enableColumnTitle(true)
1✔
2898
            .execute(stmt);
1✔
2899

1✔
2900
        let expected = [["count(distinct customer_id)", "count(distinct invoice)"],
1✔
2901
        [4, 6]];
1✔
2902

1✔
2903
        return this.isEqual("selectCount3", data, expected);
1✔
2904
    }
1✔
2905

1✔
2906
    selectCount4() {
1✔
2907
        let stmt = "select count(distinct customer_id), count(distinct invoice) from booksales";
1✔
2908

1✔
2909
        let data = new TestSql()
1✔
2910
            .addTableData("bookSales", this.bookSalesTable())
1✔
2911
            .enableColumnTitle(true)
1✔
2912
            .execute(stmt);
1✔
2913

1✔
2914
        let expected = [["count(distinct customer_id)", "count(distinct invoice)"],
1✔
2915
        [5, 7]];
1✔
2916

1✔
2917
        return this.isEqual("selectCount4", data, expected);
1✔
2918
    }
1✔
2919

1✔
2920
    selectCount5() {
1✔
2921
        let stmt = "select count(all customer_id), count(all invoice) from booksales";
1✔
2922

1✔
2923
        let data = new TestSql()
1✔
2924
            .addTableData("bookSales", this.bookSalesTable())
1✔
2925
            .enableColumnTitle(true)
1✔
2926
            .execute(stmt);
1✔
2927

1✔
2928
        let expected = [["count(all customer_id)", "count(all invoice)"],
1✔
2929
        [10, 10]];
1✔
2930

1✔
2931
        return this.isEqual("selectCount5", data, expected);
1✔
2932
    }
1✔
2933

1✔
2934
    selectCount6() {
1✔
2935
        let stmt = "select avg(price), max(quantity), count(customer_id) from booksales group by customer_id";
1✔
2936

1✔
2937
        let data = new TestSql()
1✔
2938
            .addTableData("bookSales", this.bookSalesTable())
1✔
2939
            .enableColumnTitle(true)
1✔
2940
            .execute(stmt);
1✔
2941

1✔
2942
        let expected = [["avg(price)", "max(quantity)", "count(customer_id)"],
1✔
2943
        [90, 1, 1],
1✔
2944
        [34.46, 10, 2],
1✔
2945
        [22.31, 100, 3],
1✔
2946
        [59.99, 1, 1],
1✔
2947
        [36.809999999999995, 150, 3]];
1✔
2948

1✔
2949
        return this.isEqual("selectCount6", data, expected);
1✔
2950
    }
1✔
2951

1✔
2952
    selectGroupByNotInSelect() {
1✔
2953
        let stmt = "select avg(price), max(quantity)  from booksales group by customer_id";
1✔
2954

1✔
2955
        let data = new TestSql()
1✔
2956
            .addTableData("bookSales", this.bookSalesTable())
1✔
2957
            .enableColumnTitle(true)
1✔
2958
            .execute(stmt);
1✔
2959

1✔
2960
        let expected = [["avg(price)", "max(quantity)"],
1✔
2961
        [90, 1],
1✔
2962
        [34.46, 10],
1✔
2963
        [22.31, 100],
1✔
2964
        [59.99, 1],
1✔
2965
        [36.809999999999995, 150]];
1✔
2966

1✔
2967
        return this.isEqual("selectGroupByNotInSelect", data, expected);
1✔
2968
    }
1✔
2969

1✔
2970
    selectGroupByNotInSelect2() {
1✔
2971
        let stmt = "select avg(price), max(quantity)  from booksales group by customer_id, date";
1✔
2972

1✔
2973
        let data = new TestSql()
1✔
2974
            .addTableData("bookSales", this.bookSalesTable())
1✔
2975
            .enableColumnTitle(true)
1✔
2976
            .execute(stmt);
1✔
2977

1✔
2978
        let expected = [["avg(price)", "max(quantity)"],
1✔
2979
        [90, 1],
1✔
2980
        [34.95, 10],
1✔
2981
        [33.97, 1],
1✔
2982
        [24.47, 5],
1✔
2983
        [17.99, 100],
1✔
2984
        [59.99, 1],
1✔
2985
        [36.809999999999995, 150]];
1✔
2986

1✔
2987
        return this.isEqual("selectGroupByNotInSelect2", data, expected);
1✔
2988
    }
1✔
2989

1✔
2990
    selectOrderByNotInSelect() {
1✔
2991
        let stmt = "select price, quantity from booksales order by customer_id";
1✔
2992

1✔
2993
        let data = new TestSql()
1✔
2994
            .addTableData("bookSales", this.bookSalesTable())
1✔
2995
            .enableColumnTitle(true)
1✔
2996
            .execute(stmt);
1✔
2997

1✔
2998
        let expected = [["price", "quantity"],
1✔
2999
        [90, 1],
1✔
3000
        [34.95, 10],
1✔
3001
        [33.97, 1],
1✔
3002
        [29.95, 3],
1✔
3003
        [18.99, 5],
1✔
3004
        [17.99, 100],
1✔
3005
        [59.99, 1],
1✔
3006
        [65.49, 100],
1✔
3007
        [24.95, 150],
1✔
3008
        [19.99, 50]];
1✔
3009

1✔
3010
        return this.isEqual("selectOrderByNotInSelect", data, expected);
1✔
3011
    }
1✔
3012

1✔
3013
    selectCoalesce() {
1✔
3014
        let stmt = "select name, coalesce(dec, nov, oct, sep, aug, jul, jun, may, apr, mar, feb, jan) from yearlysales";
1✔
3015

1✔
3016
        let data = new TestSql()
1✔
3017
            .addTableData("yearlysales", this.yearlySalesTable())
1✔
3018
            .enableColumnTitle(true)
1✔
3019
            .execute(stmt);
1✔
3020

1✔
3021
        let expected = [["name", "coalesce(dec, nov, oct, sep, aug, jul, jun, may, apr, mar, feb, jan)"],
1✔
3022
        ["Chris", 60],
1✔
3023
        ["Fred", 30],
1✔
3024
        ["Dan", 31],
1✔
3025
        ["Kev", 60],
1✔
3026
        ["Dori", 50],
1✔
3027
        ["Gab", "20"]];
1✔
3028

1✔
3029
        return this.isEqual("selectCoalesce", data, expected);
1✔
3030
    }
1✔
3031

1✔
3032
    selectConcat_Ws() {
1✔
3033
        let stmt = "select concat_ws('-', *) as concatenated from customers " +
1✔
3034
            "where concat_ws('-', *) like '%Way%'";
1✔
3035

1✔
3036
        let data = new TestSql()
1✔
3037
            .addTableData("customers", this.customerTable())
1✔
3038
            .enableColumnTitle(true)
1✔
3039
            .execute(stmt);
1✔
3040

1✔
3041
        let expected = [["concatenated"],
1✔
3042
        ["C1-Numereo Uno-101 One Way-One Point City-9051112111-bigOne@gmail.com"],
1✔
3043
        ["C3-Tres Buon Goods-3 Way St-Tres City-5193133303-thrice@hotmail.com"]];
1✔
3044

1✔
3045
        return this.isEqual("selectConcat_Ws", data, expected);
1✔
3046
    }
1✔
3047

1✔
3048
    selectConcat_Ws2() {
1✔
3049
        let stmt = "select concat_ws('-', *) as concatenated from booksales " +
1✔
3050
            "left join customers on booksales.customer_id = customers.id " +
1✔
3051
            "where concat_ws('-', *) like '%Way%'";
1✔
3052

1✔
3053
        let data = new TestSql()
1✔
3054
            .addTableData("customers", this.customerTable())
1✔
3055
            .addTableData("booksales", this.bookSalesTable())
1✔
3056
            .enableColumnTitle(true)
1✔
3057
            .execute(stmt);
1✔
3058

1✔
3059
        let expected = [["concatenated"],
1✔
3060
        ["I7200-9-C1-10-34.95-05/01/2022-C1-Numereo Uno-101 One Way-One Point City-9051112111-bigOne@gmail.com"],
1✔
3061
        ["I7202-9-C3-1-59.99-05/02/2022-C3-Tres Buon Goods-3 Way St-Tres City-5193133303-thrice@hotmail.com"],
1✔
3062
        ["I7205-7-C1-1-33.97-05/04/2022-C1-Numereo Uno-101 One Way-One Point City-9051112111-bigOne@gmail.com"]];
1✔
3063

1✔
3064
        return this.isEqual("selectConcat_Ws2", data, expected);
1✔
3065
    }
1✔
3066

1✔
3067
    selectNoTitle1() {
1✔
3068
        let stmt = "SELECT booksales.A as 'Invoice', booksales.B as 'Book ID', CUST.A, CUST.B FROM booksales " +
1✔
3069
            "LEFT JOIN customers as CUST on booksales.C = customers.A ";
1✔
3070

1✔
3071
        let customers = this.customerTable();
1✔
3072
        let bookSales = this.bookSalesTable();
1✔
3073

1✔
3074
        //  Get rid of current column titles.
1✔
3075
        customers.shift();
1✔
3076
        bookSales.shift();
1✔
3077

1✔
3078
        let data = new TestSql()
1✔
3079
            .addTableData("customers", customers, 0, false)
1✔
3080
            .addTableData("booksales", bookSales, 0, false)
1✔
3081
            .enableColumnTitle(true)
1✔
3082
            .execute(stmt);
1✔
3083

1✔
3084
        let expected = [["Invoice", "Book ID", "CUST.A", "CUST.B"],
1✔
3085
        ["I7200", "9", "C1", "Numereo Uno"],
1✔
3086
        ["I7201", "8", "C2", "Dewy Tuesdays"],
1✔
3087
        ["I7201", "7", "C2", "Dewy Tuesdays"],
1✔
3088
        ["I7202", "9", "C3", "Tres Buon Goods"],
1✔
3089
        ["I7203", "1", null, null],
1✔
3090
        ["I7204", "2", "C4", "ForMe Resellers"],
1✔
3091
        ["I7204", "3", "C4", "ForMe Resellers"],
1✔
3092
        ["I7204", "4", "C4", "ForMe Resellers"],
1✔
3093
        ["I7205", "7", "C1", "Numereo Uno"],
1✔
3094
        ["I7206", "7", "C2", "Dewy Tuesdays"]];
1✔
3095

1✔
3096
        return this.isEqual("selectNoTitle1", data, expected);
1✔
3097
    }
1✔
3098

1✔
3099

1✔
3100
    selectNested() {
1✔
3101
        let stmt = "select * from books where id in (select book_id from booksales where price > (select avg(price) from booksales))";
1✔
3102

1✔
3103
        let data = new TestSql()
1✔
3104
            .addTableData("books", this.bookTable())
1✔
3105
            .addTableData("booksales", this.bookSalesTable())
1✔
3106
            .enableColumnTitle(true)
1✔
3107
            .execute(stmt);
1✔
3108

1✔
3109
        let expected = [["BOOKS.ID", "BOOKS.TITLE", "BOOKS.TYPE", "BOOKS.AUTHOR_ID", "BOOKS.EDITOR_ID", "BOOKS.TRANSLATOR_ID"],
1✔
3110
        ["1", "Time to Grow Up!", "original", "11", "21", ""],
1✔
3111
        ["2", "Your Trip", "translated", "15", "22", "32"],
1✔
3112
        ["9", "Book with Mysterious Author", "translated", "1", "23", "34"]];
1✔
3113

1✔
3114
        return this.isEqual("selectNested", data, expected);
1✔
3115
    }
1✔
3116

1✔
3117
    selectNested2() {
1✔
3118
        let stmt = "select last_name from authors where id in (select author_id from books where id in (select book_id from booksales where price > (select avg(price) from booksales)))";
1✔
3119

1✔
3120
        let data = new TestSql()
1✔
3121
            .addTableData("books", this.bookTable())
1✔
3122
            .addTableData("booksales", this.bookSalesTable())
1✔
3123
            .addTableData("authors", this.authorsTable())
1✔
3124
            .enableColumnTitle(true)
1✔
3125
            .execute(stmt);
1✔
3126

1✔
3127
        let expected = [["last_name"],
1✔
3128
        ["Writer"],
1✔
3129
        ["Dou"]];
1✔
3130

1✔
3131
        return this.isEqual("selectNested2", data, expected);
1✔
3132
    }
1✔
3133

1✔
3134
    selectCorrelatedSubQuery1() {
1✔
3135
        let stmt = "select id, title, (select count(*) from booksales where books.id = booksales.book_id) from books";
1✔
3136

1✔
3137
        let data = new TestSql()
1✔
3138
            .addTableData("books", this.bookTable())
1✔
3139
            .addTableData("booksales", this.bookSalesTable())
1✔
3140
            .enableColumnTitle(true)
1✔
3141
            .execute(stmt);
1✔
3142

1✔
3143
        let expected = [["id", "title", "(select count(*) from booksales where books.id = booksales.book_id)"],
1✔
3144
        ["1", "Time to Grow Up!", 1],
1✔
3145
        ["2", "Your Trip", 1],
1✔
3146
        ["3", "Lovely Love", 1],
1✔
3147
        ["4", "Dream Your Life", 1],
1✔
3148
        ["5", "Oranges", ""],
1✔
3149
        ["6", "Your Happy Life", ""],
1✔
3150
        ["7", "Applied AI", 3],
1✔
3151
        ["9", "Book with Mysterious Author", 2],
1✔
3152
        ["8", "My Last Book", 1]];
1✔
3153

1✔
3154
        return this.isEqual("selectCorrelatedSubQuery1", data, expected);
1✔
3155
    }
1✔
3156

1✔
3157
    selectCorrelatedSubQuery2() {
1✔
3158
        let stmt = "select id, title, (select count(*) from booksales where books.id = booksales.book_id) as 'Sold' from books where (select count(*)  from booksales where books.id = booksales.book_id) > 1";
1✔
3159

1✔
3160
        let data = new TestSql()
1✔
3161
            .addTableData("books", this.bookTable())
1✔
3162
            .addTableData("booksales", this.bookSalesTable())
1✔
3163
            .enableColumnTitle(true)
1✔
3164
            .execute(stmt);
1✔
3165

1✔
3166
        let expected = [["id", "title", "Sold"],
1✔
3167
        ["7", "Applied AI", 3],
1✔
3168
        ["9", "Book with Mysterious Author", 2]];
1✔
3169

1✔
3170
        return this.isEqual("selectCorrelatedSubQuery2", data, expected);
1✔
3171
    }
1✔
3172

1✔
3173

1✔
3174
    selectCorrelatedSubQuery3() {
1✔
3175
        let stmt = "select * from customers where exists (SELECT * FROM booksales WHERE booksales.customer_id = customers.id) and email like '%gmail.com' ";
1✔
3176

1✔
3177
        let data = new TestSql()
1✔
3178
            .addTableData("customers", this.customerTable())
1✔
3179
            .addTableData("booksales", this.bookSalesTable())
1✔
3180
            .enableColumnTitle(true)
1✔
3181
            .execute(stmt);
1✔
3182

1✔
3183
        let expected = [["CUSTOMERS.ID", "CUSTOMERS.NAME", "CUSTOMERS.ADDRESS", "CUSTOMERS.CITY", "CUSTOMERS.PHONE", "CUSTOMERS.EMAIL"],
1✔
3184
        ["C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
1✔
3185
        ["C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"]];
1✔
3186

1✔
3187
        return this.isEqual("selectCorrelatedSubQuery3", data, expected);
1✔
3188
    }
1✔
3189

1✔
3190
    selectCorrelatedSubQuery4() {
1✔
3191
        let stmt = "select * from customers where not exists (SELECT * FROM booksales WHERE booksales.customer_id = customers.id)";
1✔
3192

1✔
3193
        let data = new TestSql()
1✔
3194
            .addTableData("customers", this.customerTable())
1✔
3195
            .addTableData("booksales", this.bookSalesTable())
1✔
3196
            .enableColumnTitle(true)
1✔
3197
            .execute(stmt);
1✔
3198

1✔
3199
        let expected = [["CUSTOMERS.ID", "CUSTOMERS.NAME", "CUSTOMERS.ADDRESS", "CUSTOMERS.CITY", "CUSTOMERS.PHONE", "CUSTOMERS.EMAIL"],
1✔
3200
        ["C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
1✔
3201
        ["C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
3202
        ["C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "]];
1✔
3203

1✔
3204
        return this.isEqual("selectCorrelatedSubQuery4", data, expected);
1✔
3205
    }
1✔
3206

1✔
3207
    selectCorrelatedSubQuery5() {
1✔
3208
        let stmt = "SELECT * FROM booksales as b1 where price = (select max(booksales.price) from booksales where booksales.customer_id = b1.customer_id)";
1✔
3209

1✔
3210
        let data = new TestSql()
1✔
3211
            .addTableData("booksales", this.bookSalesTable())
1✔
3212
            .enableColumnTitle(true)
1✔
3213
            .execute(stmt);
1✔
3214

1✔
3215
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
3216
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022"],
1✔
3217
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022"],
1✔
3218
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
1✔
3219
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
3220
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"]];
1✔
3221

1✔
3222
        return this.isEqual("selectCorrelatedSubQuery5", data, expected);
1✔
3223
    }
1✔
3224

1✔
3225
    selectCorrelatedSubQuery6() {
1✔
3226
        let stmt = "select * from bookreturns as br where price < (select max(price) from bookreturns  where br.customer_id = customer_id) and price > (select min(price) from bookreturns  where br.customer_id = customer_id)";
1✔
3227

1✔
3228
        let data = new TestSql()
1✔
3229
            .addTableData("bookreturns", this.bookReturnsTable())
1✔
3230
            .enableColumnTitle(true)
1✔
3231
            .execute(stmt);
1✔
3232

1✔
3233
        let expected = [["BOOKRETURNS.RMA", "BOOKRETURNS.BOOK_ID", "BOOKRETURNS.CUSTOMER_ID", "BOOKRETURNS.QUANTITY", "BOOKRETURNS.PRICE", "BOOKRETURNS.DATE"],
1✔
3234
        ["Rma001", "9", "c1", 10, 34.95, "05/01/2022"],
1✔
3235
        ["rmA030", "7", "c2", 5, 18.99, "05/01/2022"],
1✔
3236
        ["Rma701", "3", "c4", 150, 24.95, "05/03/2022"]];
1✔
3237

1✔
3238
        return this.isEqual("selectCorrelatedSubQuery6", data, expected);
1✔
3239
    }
1✔
3240

1✔
3241
    selectCorrelatedSubQuery7() {
1✔
3242
        let stmt = "select * from bookreturns as br where price < (select max(sub.price) from bookreturns as sub where br.customer_id = sub.customer_id) and price > (select min(price) from bookreturns  where br.customer_id = customer_id)";
1✔
3243

1✔
3244
        let data = new TestSql()
1✔
3245
            .addTableData("bookreturns", this.bookReturnsTable())
1✔
3246
            .enableColumnTitle(true)
1✔
3247
            .execute(stmt);
1✔
3248

1✔
3249
        let expected = [["BOOKRETURNS.RMA", "BOOKRETURNS.BOOK_ID", "BOOKRETURNS.CUSTOMER_ID", "BOOKRETURNS.QUANTITY", "BOOKRETURNS.PRICE", "BOOKRETURNS.DATE"],
1✔
3250
        ["Rma001", "9", "c1", 10, 34.95, "05/01/2022"],
1✔
3251
        ["rmA030", "7", "c2", 5, 18.99, "05/01/2022"],
1✔
3252
        ["Rma701", "3", "c4", 150, 24.95, "05/03/2022"]];
1✔
3253

1✔
3254
        return this.isEqual("selectCorrelatedSubQuery7", data, expected);
1✔
3255
    }
1✔
3256

1✔
3257
    selectCorrelatedSubQuery8() {
1✔
3258
        let stmt = "select * from booksales as b1 where price in (select max(price) from booksales where b1.customer_id = customer_id)";
1✔
3259

1✔
3260
        let data = new TestSql()
1✔
3261
            .addTableData("booksales", this.bookSalesTable())
1✔
3262
            .enableColumnTitle(true)
1✔
3263
            .execute(stmt);
1✔
3264

1✔
3265
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
3266
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022"],
1✔
3267
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022"],
1✔
3268
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
1✔
3269
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
3270
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"]];
1✔
3271

1✔
3272
        return this.isEqual("selectCorrelatedSubQuery8", data, expected);
1✔
3273
    }
1✔
3274

1✔
3275
    selectCorrelatedSubQuery9() {
1✔
3276
        let stmt = "select id, name, (select max(quantity) from booksales where customers.id = booksales.customer_id) as 'max sold' from customers";
1✔
3277

1✔
3278
        let data = new TestSql()
1✔
3279
            .addTableData("booksales", this.bookSalesTable())
1✔
3280
            .addTableData("customers", this.customerTable())
1✔
3281
            .enableColumnTitle(true)
1✔
3282
            .execute(stmt);
1✔
3283

1✔
3284
        let expected = [["id", "name", "max sold"],
1✔
3285
        ["C1", "Numereo Uno", 10],
1✔
3286
        ["C2", "Dewy Tuesdays", 100],
1✔
3287
        ["C3", "Tres Buon Goods", 1],
1✔
3288
        ["C4", "ForMe Resellers", 150],
1✔
3289
        ["C5", "Fe Fi Fo Giant Tiger", ""],
1✔
3290
        ["C6", "Sx in Cars", ""],
1✔
3291
        ["C7", "7th Heaven", ""]];
1✔
3292

1✔
3293
        return this.isEqual("selectCorrelatedSubQuery9", data, expected);
1✔
3294
    }
1✔
3295

1✔
3296
    selectCorrelatedSubQuery10() {
1✔
3297
        let stmt = "select * from booksales as b1 where price in (select max(price) from booksales where b1.customer_id = customer_id and book_id <> '9')";
1✔
3298

1✔
3299
        let data = new TestSql()
1✔
3300
            .addTableData("booksales", this.bookSalesTable())
1✔
3301
            .enableColumnTitle(true)
1✔
3302
            .execute(stmt);
1✔
3303

1✔
3304
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
3305
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022"],
1✔
3306
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
3307
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
1✔
3308
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022"]];
1✔
3309

1✔
3310
        return this.isEqual("selectCorrelatedSubQuery10", data, expected);
1✔
3311
    }
1✔
3312

1✔
3313
    selectCorrelatedSubQuery11() {
1✔
3314
        let stmt = "select *, (select sum(quantity) from booksales where b1.customer_id = customer_id) as 'Total for Customer' from booksales as b1 where customer_id = ?1";
1✔
3315

1✔
3316
        let data = new TestSql()
1✔
3317
            .addTableData("booksales", this.bookSalesTable())
1✔
3318
            .enableColumnTitle(true)
1✔
3319
            .addBindParameter("C4")
1✔
3320
            .execute(stmt);
1✔
3321

1✔
3322
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "Total for Customer"],
1✔
3323
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", 300],
1✔
3324
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", 300],
1✔
3325
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", 300]];
1✔
3326

1✔
3327
        return this.isEqual("selectCorrelatedSubQuery11", data, expected);
1✔
3328
    }
1✔
3329

1✔
3330
    selectFromSubQuery1() {
1✔
3331
        let stmt = "select score.customer_id, score.wins, score.loss, (score.wins / (score.wins+score.loss)) as rate from (select customer_id, sum(case when quantity < 100 then 1 else 0 end) as wins, sum(case when quantity >= 100 then 1 else 0 end) as loss from booksales group by customer_id) as score";
1✔
3332

1✔
3333
        let data = new TestSql()
1✔
3334
            .addTableData("booksales", this.bookSalesTable())
1✔
3335
            .enableColumnTitle(true)
1✔
3336
            .execute(stmt);
1✔
3337

1✔
3338
        let expected = [["score.customer_id", "score.wins", "score.loss", "rate"],
1✔
3339
        ["", 1, 0, 1],
1✔
3340
        ["C1", 2, 0, 1],
1✔
3341
        ["C2", 2, 1, 0.6666666666666666],
1✔
3342
        ["C3", 1, 0, 1],
1✔
3343
        ["C4", 1, 2, 0.3333333333333333]];
1✔
3344

1✔
3345
        return this.isEqual("selectFromSubQuery1", data, expected);
1✔
3346
    }
1✔
3347

1✔
3348
    selectFromSubQuery2() {
1✔
3349
        let stmt = "select customer_id, wins, loss, (wins / (wins+loss)) as rate from (select customer_id, sum(case when quantity < 100 then 1 else 0 end) as wins, sum(case when quantity >= 100 then 1 else 0 end) as loss from booksales group by customer_id) as score";
1✔
3350

1✔
3351
        let data = new TestSql()
1✔
3352
            .addTableData("booksales", this.bookSalesTable())
1✔
3353
            .enableColumnTitle(true)
1✔
3354
            .execute(stmt);
1✔
3355

1✔
3356
        let expected = [["customer_id", "wins", "loss", "rate"],
1✔
3357
        ["", 1, 0, 1],
1✔
3358
        ["C1", 2, 0, 1],
1✔
3359
        ["C2", 2, 1, 0.6666666666666666],
1✔
3360
        ["C3", 1, 0, 1],
1✔
3361
        ["C4", 1, 2, 0.3333333333333333]];
1✔
3362

1✔
3363
        return this.isEqual("selectFromSubQuery2", data, expected);
1✔
3364
    }
1✔
3365

1✔
3366
    selectFromSubQuery3() {
1✔
3367
        let stmt = "select invoice from (select invoice from booksales where customer_id = 'C1') as mysales";
1✔
3368

1✔
3369
        let data = new TestSql()
1✔
3370
            .addTableData("booksales", this.bookSalesTable())
1✔
3371
            .enableColumnTitle(true)
1✔
3372
            .execute(stmt);
1✔
3373

1✔
3374
        let expected = [["invoice"],
1✔
3375
        ["I7200"],
1✔
3376
        ["I7205"]];
1✔
3377

1✔
3378
        return this.isEqual("selectFromSubQuery3", data, expected);
1✔
3379
    }
1✔
3380

1✔
3381
    selectFromSubQuery4() {
1✔
3382
        let stmt = "select table3.invoice from " +
1✔
3383
            "(select invoice, quantity from " +
1✔
3384
            "(select invoice, table1.QTY as quantity from " +
1✔
3385
            "(select invoice, quantity as QTY, customer_id from booksales where quantity <= 10) as table1 "
1✔
3386
            + "where customer_id = 'C1') as table2) "
1✔
3387
            + "as table3";
1✔
3388

1✔
3389
        let data = new TestSql()
1✔
3390
            .addTableData("booksales", this.bookSalesTable())
1✔
3391
            .enableColumnTitle(true)
1✔
3392
            .execute(stmt);
1✔
3393

1✔
3394
        let expected = [["table3.invoice"],
1✔
3395
        ["I7200"],
1✔
3396
        ["I7205"]];
1✔
3397

1✔
3398
        return this.isEqual("selectFromSubQuery4", data, expected);
1✔
3399
    }
1✔
3400

1✔
3401
    selectFromSubQuery5() {
1✔
3402
        let stmt = "select table3.invoice from " +
1✔
3403
            "(select * from " +
1✔
3404
            "(select invoice, table1.QTY as quantity from " +
1✔
3405
            "(select invoice, quantity as QTY, customer_id from booksales where quantity <= 10) as table1 "
1✔
3406
            + "where customer_id = 'C1') as table2) "
1✔
3407
            + "as table3";
1✔
3408

1✔
3409
        let data = new TestSql()
1✔
3410
            .addTableData("booksales", this.bookSalesTable())
1✔
3411
            .enableColumnTitle(true)
1✔
3412
            .execute(stmt);
1✔
3413

1✔
3414
        let expected = [["table3.invoice"],
1✔
3415
        ["I7200"],
1✔
3416
        ["I7205"]];
1✔
3417

1✔
3418
        return this.isEqual("selectFromSubQuery5", data, expected);
1✔
3419
    }
1✔
3420

1✔
3421
    selectFromSubQuery6() {
1✔
3422
        let stmt = "select table3.invoice, table3.name from (select * from (select invoice, table1.QTY as quantity, customers.name from (select invoice, quantity as QTY, customer_id from booksales where quantity <= 10) as table1 join customers on table1.customer_id = customers.id where customer_id = 'C1') as table2) as table3";
1✔
3423

1✔
3424
        let data = new TestSql()
1✔
3425
            .addTableData("booksales", this.bookSalesTable())
1✔
3426
            .addTableData("customers", this.customerTable())
1✔
3427
            .enableColumnTitle(true)
1✔
3428
            .execute(stmt);
1✔
3429

1✔
3430
        let expected = [["table3.invoice", "table3.name"],
1✔
3431
        ["I7200", "Numereo Uno"],
1✔
3432
        ["I7205", "Numereo Uno"]];
1✔
3433

1✔
3434
        return this.isEqual("selectFromSubQuery6", data, expected);
1✔
3435
    }
1✔
3436

1✔
3437

1✔
3438
    selectFromSubQuery7() {
1✔
3439
        let stmt = "select * from booksales join (select * from booksales where customer_id = 'C1') as subsales on booksales.book_id = subsales.book_id";
1✔
3440

1✔
3441
        let data = new TestSql()
1✔
3442
            .addTableData("booksales", this.bookSalesTable())
1✔
3443
            .enableColumnTitle(true)
1✔
3444
            .execute(stmt);
1✔
3445

1✔
3446
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "SUBSALES.INVOICE", "SUBSALES.BOOK_ID", "SUBSALES.CUSTOMER_ID", "SUBSALES.QUANTITY", "SUBSALES.PRICE", "SUBSALES.DATE"],
1✔
3447
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "I7200", "9", "C1", 10, 34.95, "05/01/2022"],
1✔
3448
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "I7205", "7", "C1", 1, 33.97, "05/04/2022"],
1✔
3449
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "I7200", "9", "C1", 10, 34.95, "05/01/2022"],
1✔
3450
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "I7205", "7", "C1", 1, 33.97, "05/04/2022"],
1✔
3451
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "I7205", "7", "C1", 1, 33.97, "05/04/2022"]];
1✔
3452

1✔
3453
        return this.isEqual("selectFromSubQuery7", data, expected);
1✔
3454
    }
1✔
3455

1✔
3456
    selectConvertFunction() {
1✔
3457
        let stmt = "select convert(address, signed), convert(address, char), convert(name, signed), convert(id, signed), convert(phone, char), convert(phone, decimal) from customers";
1✔
3458

1✔
3459
        let data = new TestSql()
1✔
3460
            .addTableData("customers", this.customerTable())
1✔
3461
            .enableColumnTitle(true)
1✔
3462
            .execute(stmt);
1✔
3463

1✔
3464
        let expected = [["convert(address, signed)", "convert(address, char)", "convert(name, signed)", "convert(id, signed)", "convert(phone, char)", "convert(phone, decimal)"],
1✔
3465
        [101, "101 One Way", 0, 0, "9051112111", 9051112111],
1✔
3466
        [202, "202 Second St.", 0, 0, "4162022222", 4162022222],
1✔
3467
        [3, "3 Way St", 0, 0, "5193133303", 5193133303],
1✔
3468
        [40, "40 Four St", 0, 0, "2894441234", 2894441234],
1✔
3469
        [5, "5 ohFive St.", 0, 0, "4165551234", 4165551234],
1✔
3470
        [6, "6 Seventh St", 0, 0, "6661116666", 6661116666],
1✔
3471
        [7, "7 Eight Crt.", 7, 0, "5551117777", 5551117777]];
1✔
3472

1✔
3473
        return this.isEqual("selectConvertFunction", data, expected);
1✔
3474
    }
1✔
3475

1✔
3476
    selectJoinMultipleConditions() {
1✔
3477
        let stmt = "select * from booksales join bookreturns on booksales.quantity = bookreturns.quantity and booksales.date = bookreturns.date or booksales.book_id = bookreturns.book_id";
1✔
3478

1✔
3479
        let data = new TestSql()
1✔
3480
            .addTableData("booksales", this.bookSalesTable())
1✔
3481
            .addTableData("bookreturns", this.bookReturnsTable())
1✔
3482
            .enableColumnTitle(true)
1✔
3483
            .execute(stmt);
1✔
3484

1✔
3485
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "BOOKRETURNS.RMA", "BOOKRETURNS.BOOK_ID", "BOOKRETURNS.CUSTOMER_ID", "BOOKRETURNS.QUANTITY", "BOOKRETURNS.PRICE", "BOOKRETURNS.DATE"],
1✔
3486
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "Rma001", "9", "c1", 10, 34.95, "05/01/2022"],
1✔
3487
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "RMA040", "9", "c3", 1, 59.99, "05/02/2022"],
1✔
3488
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022", "rma020", "8", "c2", 3, 29.95, "05/01/2022"],
1✔
3489
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "rmA030", "7", "c2", 5, 18.99, "05/01/2022"],
1✔
3490
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "RMA900", "7", "c1", 1, 33.97, "05/04/2022"],
1✔
3491
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "rma1010", "7", "c2", 100, 17.99, "05/04/2022"],
1✔
3492
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "RMA040", "9", "c3", 1, 59.99, "05/02/2022"],
1✔
3493
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "rma005", "1", "c1", 1, 90, "05/02/2022"],
1✔
3494
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "Rma001", "9", "c1", 10, 34.95, "05/01/2022"],
1✔
3495
        ["I7203", "1", "", 1, 90, "05/02/2022", "RMA040", "9", "c3", 1, 59.99, "05/02/2022"],
1✔
3496
        ["I7203", "1", "", 1, 90, "05/02/2022", "rma005", "1", "c1", 1, 90, "05/02/2022"],
1✔
3497
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "RMA600", "2", "c4", 100, 65.49, "05/03/2022"],
1✔
3498
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "Rma701", "3", "c4", 150, 24.95, "05/03/2022"],
1✔
3499
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "RmA800", "4", "c4", 50, 19.99, "05/03/2022"],
1✔
3500
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "RMA900", "7", "c1", 1, 33.97, "05/04/2022"],
1✔
3501
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "rmA030", "7", "c2", 5, 18.99, "05/01/2022"],
1✔
3502
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "rma1010", "7", "c2", 100, 17.99, "05/04/2022"],
1✔
3503
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "rma1010", "7", "c2", 100, 17.99, "05/04/2022"],
1✔
3504
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "rmA030", "7", "c2", 5, 18.99, "05/01/2022"],
1✔
3505
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "RMA900", "7", "c1", 1, 33.97, "05/04/2022"]];
1✔
3506

1✔
3507
        return this.isEqual("selectJoinMultipleConditions", data, expected);
1✔
3508
    }
1✔
3509

1✔
3510
    selectJoinOnExpression1() {
1✔
3511
        let stmt = "select invoice, name from booksales inner join customers on substr(booksales.customer_id, 2, 1) = substr(customers.id, 2, 1)";
1✔
3512

1✔
3513
        let data = new TestSql()
1✔
3514
            .addTableData("booksales", this.bookSalesTable())
1✔
3515
            .addTableData("customers", this.customerTable())
1✔
3516
            .enableColumnTitle(true)
1✔
3517
            .execute(stmt);
1✔
3518

1✔
3519
        let expected = [["invoice", "name"],
1✔
3520
        ["I7200", "Numereo Uno"],
1✔
3521
        ["I7201", "Dewy Tuesdays"],
1✔
3522
        ["I7201", "Dewy Tuesdays"],
1✔
3523
        ["I7202", "Tres Buon Goods"],
1✔
3524
        ["I7204", "ForMe Resellers"],
1✔
3525
        ["I7204", "ForMe Resellers"],
1✔
3526
        ["I7204", "ForMe Resellers"],
1✔
3527
        ["I7205", "Numereo Uno"],
1✔
3528
        ["I7206", "Dewy Tuesdays"]];
1✔
3529

1✔
3530
        return this.isEqual("selectJoinOnExpression1", data, expected);
1✔
3531
    }
1✔
3532

1✔
3533

1✔
3534
    selectJoinMultipleConditions2() {
1✔
3535
        let stmt = "select invoice, name, title from customers inner join booksales on booksales.customer_id = customers.id join books on books.id = booksales.book_id";
1✔
3536

1✔
3537
        let data = new TestSql()
1✔
3538
            .addTableData("booksales", this.bookSalesTable())
1✔
3539
            .addTableData("customers", this.customerTable())
1✔
3540
            .addTableData("books", this.bookTable())
1✔
3541
            .enableColumnTitle(true)
1✔
3542
            .execute(stmt);
1✔
3543

1✔
3544
        let expected = [["invoice", "name", "title"],
1✔
3545
        ["I7200", "Numereo Uno", "Book with Mysterious Author"],
1✔
3546
        ["I7205", "Numereo Uno", "Applied AI"],
1✔
3547
        ["I7201", "Dewy Tuesdays", "My Last Book"],
1✔
3548
        ["I7201", "Dewy Tuesdays", "Applied AI"],
1✔
3549
        ["I7206", "Dewy Tuesdays", "Applied AI"],
1✔
3550
        ["I7202", "Tres Buon Goods", "Book with Mysterious Author"],
1✔
3551
        ["I7204", "ForMe Resellers", "Your Trip"],
1✔
3552
        ["I7204", "ForMe Resellers", "Lovely Love"],
1✔
3553
        ["I7204", "ForMe Resellers", "Dream Your Life"]];
1✔
3554

1✔
3555
        return this.isEqual("selectJoinMultipleConditions2", data, expected);
1✔
3556
    }
1✔
3557

1✔
3558
    selectJoinOnExpression2() {
1✔
3559
        let stmt = "select invoice, name, title from customers inner join booksales on substr(booksales.customer_id, 2, 1) = substr(customers.id, 2, 1) join books on books.id = booksales.book_id";
1✔
3560

1✔
3561
        let data = new TestSql()
1✔
3562
            .addTableData("booksales", this.bookSalesTable())
1✔
3563
            .addTableData("customers", this.customerTable())
1✔
3564
            .addTableData("books", this.bookTable())
1✔
3565
            .enableColumnTitle(true)
1✔
3566
            .execute(stmt);
1✔
3567

1✔
3568
        let expected = [["invoice", "name", "title"],
1✔
3569
        ["I7200", "Numereo Uno", "Book with Mysterious Author"],
1✔
3570
        ["I7205", "Numereo Uno", "Applied AI"],
1✔
3571
        ["I7201", "Dewy Tuesdays", "My Last Book"],
1✔
3572
        ["I7201", "Dewy Tuesdays", "Applied AI"],
1✔
3573
        ["I7206", "Dewy Tuesdays", "Applied AI"],
1✔
3574
        ["I7202", "Tres Buon Goods", "Book with Mysterious Author"],
1✔
3575
        ["I7204", "ForMe Resellers", "Your Trip"],
1✔
3576
        ["I7204", "ForMe Resellers", "Lovely Love"],
1✔
3577
        ["I7204", "ForMe Resellers", "Dream Your Life"]];
1✔
3578

1✔
3579
        return this.isEqual("selectJoinOnExpression2", data, expected);
1✔
3580
    }
1✔
3581

1✔
3582

1✔
3583
    selectJoinOnExpression3() {
1✔
3584
        let stmt = "select invoice, name, title from customers inner join booksales on 'BB' + substr(booksales.customer_id, 2, 1) = 'BB' + substr(customers.id, 2, 1) join books on 'CC' + books.id = 'CC' + booksales.book_id";
1✔
3585

1✔
3586
        let data = new TestSql()
1✔
3587
            .addTableData("booksales", this.bookSalesTable())
1✔
3588
            .addTableData("customers", this.customerTable())
1✔
3589
            .addTableData("books", this.bookTable())
1✔
3590
            .enableColumnTitle(true)
1✔
3591
            .execute(stmt);
1✔
3592

1✔
3593
        let expected = [["invoice", "name", "title"],
1✔
3594
        ["I7200", "Numereo Uno", "Book with Mysterious Author"],
1✔
3595
        ["I7205", "Numereo Uno", "Applied AI"],
1✔
3596
        ["I7201", "Dewy Tuesdays", "My Last Book"],
1✔
3597
        ["I7201", "Dewy Tuesdays", "Applied AI"],
1✔
3598
        ["I7206", "Dewy Tuesdays", "Applied AI"],
1✔
3599
        ["I7202", "Tres Buon Goods", "Book with Mysterious Author"],
1✔
3600
        ["I7204", "ForMe Resellers", "Your Trip"],
1✔
3601
        ["I7204", "ForMe Resellers", "Lovely Love"],
1✔
3602
        ["I7204", "ForMe Resellers", "Dream Your Life"]];
1✔
3603

1✔
3604
        return this.isEqual("selectJoinOnExpression3", data, expected);
1✔
3605
    }
1✔
3606

1✔
3607
    selectJoinLeftRightSwitchedInCondition() {
1✔
3608
        let stmt = "select * from books left join authors on authors.id = books.author_id";
1✔
3609

1✔
3610
        let data = new TestSql()
1✔
3611
            .addTableData("books", this.bookTable())
1✔
3612
            .addTableData("authors", this.authorsTable())
1✔
3613
            .enableColumnTitle(true)
1✔
3614
            .execute(stmt);
1✔
3615

1✔
3616
        let expected = [["BOOKS.ID", "BOOKS.TITLE", "BOOKS.TYPE", "BOOKS.AUTHOR_ID", "BOOKS.EDITOR_ID", "BOOKS.TRANSLATOR_ID", "AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME"],
1✔
3617
        ["1", "Time to Grow Up!", "original", "11", "21", "", "11", "Ellen", "Writer"],
1✔
3618
        ["2", "Your Trip", "translated", "15", "22", "32", "15", "Yao", "Dou"],
1✔
3619
        ["3", "Lovely Love", "original", "14", "24", "", "14", "Donald", "Brain"],
1✔
3620
        ["4", "Dream Your Life", "original", "11", "24", "", "11", "Ellen", "Writer"],
1✔
3621
        ["5", "Oranges", "translated", "12", "25", "31", "12", "Olga", "Savelieva"],
1✔
3622
        ["6", "Your Happy Life", "translated", "15", "22", "33", "15", "Yao", "Dou"],
1✔
3623
        ["7", "Applied AI", "translated", "13", "23", "34", "13", "Jack", "Smart"],
1✔
3624
        ["9", "Book with Mysterious Author", "translated", "1", "23", "34", null, null, null],
1✔
3625
        ["8", "My Last Book", "original", "11", "28", "", "11", "Ellen", "Writer"]];
1✔
3626

1✔
3627
        return this.isEqual("selectJoinLeftRightSwitchedInCondition", data, expected);
1✔
3628
    }
1✔
3629

1✔
3630
    selectJoinMultipleConditions3() {
1✔
3631
        let stmt = "select * from booksales inner join bookreturns on booksales.book_id = bookreturns.book_id and booksales.invoice = bookreturns.rma";
1✔
3632

1✔
3633
        let data = new TestSql()
1✔
3634
            .addTableData("booksales", this.bookSalesTable())
1✔
3635
            .addTableData("bookreturns", this.bookReturnsTable())
1✔
3636
            .enableColumnTitle(true)
1✔
3637
            .execute(stmt);
1✔
3638

1✔
3639
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "BOOKRETURNS.RMA", "BOOKRETURNS.BOOK_ID", "BOOKRETURNS.CUSTOMER_ID", "BOOKRETURNS.QUANTITY", "BOOKRETURNS.PRICE", "BOOKRETURNS.DATE"]];
1✔
3640

1✔
3641
        return this.isEqual("selectJoinMultipleConditions3", data, expected);
1✔
3642
    }
1✔
3643

1✔
3644
    selectSingleQuoteDataWithCalculation() {
1✔
3645
        let stmt = "select sum(amount), avg(amount), max(transaction_date), min(transaction_date) from master";
1✔
3646

1✔
3647
        let data = new TestSql()
1✔
3648
            .addTableData("master", this.masterTransactionsTable())
1✔
3649
            .enableColumnTitle(true)
1✔
3650
            .execute(stmt);
1✔
3651

1✔
3652
        let expected = [["sum(amount)", "avg(amount)", "max(transaction_date)", "min(transaction_date)"],
1✔
3653
        [12399.19, 516.6329166666667, "2019-06-20T04:00:00.000Z", "2019-06-07T04:00:00.000Z"]];
1✔
3654

1✔
3655
        return this.isEqual("selectSingleQuoteDataWithCalculation", data, expected);
1✔
3656
    }
1✔
3657

1✔
3658
    selectWithBadDate() {
1✔
3659
        let stmt = "select AddDate(Transaction_Date,1), Last_day(transaction_date) from master where adddate(transaction_date,1) <> ?1";
1✔
3660

1✔
3661
        const myData = this.masterTransactionsTable();
1✔
3662
        myData.push(["Royal Bank of Canada", "Cancelled Appointment", "Chiropractor", "", -100, "Taxes - Property Tax", "", "", ""]);
1✔
3663

1✔
3664
        let data = new TestSql()
1✔
3665
            .addTableData("master", myData)
1✔
3666
            .enableColumnTitle(true)
1✔
3667
            .addBindParameter(new Date("06/14/2019"))
1✔
3668
            .execute(stmt);
1✔
3669

1✔
3670
        let expected = [["AddDate(Transaction_Date,1)", "Last_day(transaction_date)"],
1✔
3671
        ["2019-06-08T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3672
        ["2019-06-08T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3673
        ["2019-06-08T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3674
        ["2019-06-08T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3675
        ["2019-06-08T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3676
        ["2019-06-12T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3677
        ["2019-06-15T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3678
        ["2019-06-15T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3679
        ["2019-06-18T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3680
        ["2019-06-18T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3681
        ["2019-06-18T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3682
        ["2019-06-19T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3683
        ["2019-06-20T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3684
        ["2019-06-20T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3685
        ["2019-06-21T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3686
        ["2019-06-21T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3687
        ["2019-06-21T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3688
        ["2019-06-21T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3689
        ["2019-06-21T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3690
        ["2019-06-21T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3691
        ["2019-06-21T04:00:00.000Z", "2019-06-30T04:00:00.000Z"],
1✔
3692
        [null, null]];
1✔
3693

1✔
3694
        return this.isEqual("selectWithBadDate", data, expected);
1✔
3695
    }
1✔
3696

1✔
3697
    selectWhereBadDate() {
1✔
3698
        let stmt = "select * from master where transaction_date < ?1";
1✔
3699

1✔
3700
        const myData = this.masterTransactionsTable();
1✔
3701
        myData.push(["Royal Bank of Canada", "Cancelled Appointment", "Chiropractor", "", -100, "Taxes - Property Tax", "", "", ""]);
1✔
3702

1✔
3703
        let data = new TestSql()
1✔
3704
            .addTableData("master", myData)
1✔
3705
            .enableColumnTitle(true)
1✔
3706
            .addBindParameter(new Date("06/14/2019"))
1✔
3707
            .execute(stmt);
1✔
3708

1✔
3709
        let expected = [["MASTER.NAME_OF_INSTITUTION", "MASTER.TRANSACTION_DATE", "MASTER.DESCRIPTION_1", "MASTER.DESCRIPTION_2", "MASTER.AMOUNT", "MASTER.EXPENSE_CATEGORY", "MASTER.ACCOUNT", "MASTER.GROSS", "MASTER.BALANCE"],
1✔
3710
        ["Royal Bank of Canada", "2019-06-07T04:00:00.000Z", "Interac purchase - 3707 NADIM'S NO FRIL", "", -47.85, "Food & Dining - Groceries", "", "", ""],
1✔
3711
        ["Royal Bank of Canada", "2019-06-07T04:00:00.000Z", "Interac purchase - 2357 FRESHCO 3826", "", -130.36, "Food & Dining - Groceries", "", "", ""],
1✔
3712
        ["Royal Bank of Canada", "2019-06-07T04:00:00.000Z", "Payroll Deposit WEST UNIFIED CO", "", 2343.48, "Income - Paycheck", "", "", ""],
1✔
3713
        ["Royal Bank of Canada", "2019-06-07T04:00:00.000Z", "MBNA-MASTERCARD", "", -500, "Transfer - CC", "", "", ""],
1✔
3714
        ["Royal Bank of Canada", "2019-06-07T04:00:00.000Z", "e-Transfer sent S.E", "", -575, "Utilities - Rent", "", "", ""],
1✔
3715
        ["Royal Bank of Canada", "2019-06-11T04:00:00.000Z", "Insurance ADMIN.BY GWL", "", 122.4, "Health & Fitness - Health Insurance", "", "", ""],
1✔
3716
        ["Royal Bank of Canada", "2019-06-13T04:00:00.000Z", "Misc Payment GOODLIFE CLUBS", "", -24.85, "Health & Fitness - Gym", "", "", ""],
1✔
3717
        ["Royal Bank of Canada", "2019-06-13T04:00:00.000Z", "WHITBY TAXES", "", -100, "Taxes - Property Tax", "", "", ""],
1✔
3718
        ["Royal Bank of Canada", "2019-06-13T04:00:00.000Z", "Online Transfer to Deposit Account-***9", "", -15, "Transfer - Savings acct", "", "", ""]];
1✔
3719

1✔
3720
        return this.isEqual("selectWhereBadDate", data, expected);
1✔
3721
    }
1✔
3722

1✔
3723
    selectGroupByCalculatedField() {
1✔
3724
        let stmt = "select convert(day(date), char) + convert(year(date), char),  count(*) from booksales group by convert(day(date), char) + convert(year(date), char)";
1✔
3725

1✔
3726
        let data = new TestSql()
1✔
3727
            .addTableData("booksales", this.bookSalesTable())
1✔
3728
            .enableColumnTitle(true)
1✔
3729
            .execute(stmt);
1✔
3730

1✔
3731
        let expected = [["convert(day(date), char) + convert(year(date), char)", "count(*)"],
1✔
3732
        ["12022", 3],
1✔
3733
        ["22022", 2],
1✔
3734
        ["32022", 3],
1✔
3735
        ["42022", 2]];
1✔
3736

1✔
3737
        return this.isEqual("selectGroupByCalculatedField", data, expected);
1✔
3738
    }
1✔
3739

1✔
3740
    selectGroupByCalculatedFieldNotInSelectFieldList() {
1✔
3741
        let stmt = "select count(*) from booksales group by convert(day(date), char) + convert(year(date), char)";
1✔
3742

1✔
3743
        let data = new TestSql()
1✔
3744
            .addTableData("booksales", this.bookSalesTable())
1✔
3745
            .enableColumnTitle(true)
1✔
3746
            .execute(stmt);
1✔
3747

1✔
3748
        let expected = [["count(*)"],
1✔
3749
        [3],
1✔
3750
        [2],
1✔
3751
        [3],
1✔
3752
        [2]];
1✔
3753

1✔
3754
        return this.isEqual("selectGroupByCalculatedFieldNotInSelectFieldList", data, expected);
1✔
3755
    }
1✔
3756

1✔
3757
    selectGroupByCalculatedField2() {
1✔
3758
        let stmt = "select concat(convert(substr(customers.phone,1,3),char), booksales.date), count(*)from booksales join customers on booksales.customer_id = customers.id group by concat(convert(substr(customers.phone,1,3),char), booksales.date)";
1✔
3759

1✔
3760
        let data = new TestSql()
1✔
3761
            .addTableData("booksales", this.bookSalesTable())
1✔
3762
            .addTableData("customers", this.customerTable())
1✔
3763
            .enableColumnTitle(true)
1✔
3764
            .execute(stmt);
1✔
3765

1✔
3766
        let expected = [["concat(convert(substr(customers.phone,1,3),char), booksales.date)", "count(*)"],
1✔
3767
        ["28905/03/2022", 3],
1✔
3768
        ["41605/01/2022", 2],
1✔
3769
        ["41605/04/2022", 1],
1✔
3770
        ["51905/02/2022", 1],
1✔
3771
        ["90505/01/2022", 1],
1✔
3772
        ["90505/04/2022", 1]];
1✔
3773

1✔
3774
        return this.isEqual("selectGroupByCalculatedField2", data, expected);
1✔
3775
    }
1✔
3776

1✔
3777
    selectOrderByCalculated() {
1✔
3778
        let stmt = "select * from booksales order by customer_id asc, convert(day(date), char) + convert(year(date), char) desc";
1✔
3779

1✔
3780
        let data = new TestSql()
1✔
3781
            .addTableData("booksales", this.bookSalesTable())
1✔
3782
            .enableColumnTitle(true)
1✔
3783
            .execute(stmt);
1✔
3784

1✔
3785
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
3786
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
3787
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022"],
1✔
3788
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022"],
1✔
3789
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022"],
1✔
3790
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022"],
1✔
3791
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022"],
1✔
3792
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
1✔
3793
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
1✔
3794
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
1✔
3795
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"]];
1✔
3796

1✔
3797
        return this.isEqual("selectOrderByCalculated", data, expected);
1✔
3798
    }
1✔
3799

1✔
3800
    selectOrderByCalculated2() {
1✔
3801
        let stmt = "select *, quantity*price from booksales order by convert(day(date), char) + convert(year(date), char) desc, quantity*price asc";
1✔
3802

1✔
3803
        let data = new TestSql()
1✔
3804
            .addTableData("booksales", this.bookSalesTable())
1✔
3805
            .enableColumnTitle(true)
1✔
3806
            .execute(stmt);
1✔
3807

1✔
3808
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "quantity*price"],
1✔
3809
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", 33.97],
1✔
3810
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", 1798.9999999999998],
1✔
3811
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", 999.4999999999999],
1✔
3812
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", 3742.5],
1✔
3813
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", 6548.999999999999],
1✔
3814
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", 59.99],
1✔
3815
        ["I7203", "1", "", 1, 90, "05/02/2022", 90],
1✔
3816
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022", 89.85],
1✔
3817
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", 94.94999999999999],
1✔
3818
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", 349.5]];
1✔
3819

1✔
3820
        return this.isEqual("selectOrderByCalculated2", data, expected);
1✔
3821
    }
1✔
3822

1✔
3823

1✔
3824
    joinBigTables1() {
1✔
3825
        let recCount = 100000;
×
3826
        let stmt = "select * from booksales join books on booksales.book_id = books.id order by booksales.invoice desc";
×
3827

×
3828
        const bigBookSalesTable = this.bookSalesTable(recCount);
×
3829
        const bigBookTable = this.bookTable(recCount);
×
3830

×
3831
        const startTime = performance.now();
×
3832
        let data = new TestSql()
×
3833
            .addTableData("booksales", bigBookSalesTable)
×
3834
            .addTableData("books", bigBookTable)
×
3835
            .enableColumnTitle(true)
×
3836
            .execute(stmt);
×
3837
        const endtime = performance.now();
×
3838
        Logger.log(`Big Table Join.  ms=${(endtime - startTime).toString()}`);
×
3839

×
3840
        let expected = recCount + 11;
×
3841

×
3842
        return this.isEqual("joinBigTables1", data.length, expected);
×
3843
    }
×
3844

1✔
3845
    selectWhereLike3() {
1✔
3846
        let stmt = "select id, title, author_id from books where title like 'Your%'";
1✔
3847

1✔
3848
        let data = new TestSql()
1✔
3849
            .addTableData("books", this.bookTable())
1✔
3850
            .enableColumnTitle(true)
1✔
3851
            .execute(stmt);
1✔
3852

1✔
3853
        let expected = [["id", "title", "author_id"],
1✔
3854
        ["2", "Your Trip", "15"],
1✔
3855
        ["6", "Your Happy Life", "15"]];
1✔
3856

1✔
3857
        return this.isEqual("selectWhereLike3", data, expected);
1✔
3858
    }
1✔
3859

1✔
3860
    selectWhereLike4() {
1✔
3861
        let stmt = "select id, title, author_id from books where title like '%Your%'";
1✔
3862

1✔
3863
        let data = new TestSql()
1✔
3864
            .addTableData("books", this.bookTable())
1✔
3865
            .enableColumnTitle(true)
1✔
3866
            .execute(stmt);
1✔
3867

1✔
3868
        let expected = [["id", "title", "author_id"],
1✔
3869
        ["2", "Your Trip", "15"],
1✔
3870
        ["4", "Dream Your Life", "11"],
1✔
3871
        ["6", "Your Happy Life", "15"]];
1✔
3872

1✔
3873
        return this.isEqual("selectWhereLike4", data, expected);
1✔
3874
    }
1✔
3875

1✔
3876
    selectFromSubQuery8() {
1✔
3877
        let stmt = "Select * from (select * from books where title like 'Your%') as mybooks";
1✔
3878

1✔
3879
        let data = new TestSql()
1✔
3880
            .addTableData("books", this.bookTable())
1✔
3881
            .enableColumnTitle(true)
1✔
3882
            .execute(stmt);
1✔
3883

1✔
3884
        let expected = [["MYBOOKS.ID", "MYBOOKS.TITLE", "MYBOOKS.TYPE", "MYBOOKS.AUTHOR_ID", "MYBOOKS.EDITOR_ID", "MYBOOKS.TRANSLATOR_ID"],
1✔
3885
        ["2", "Your Trip", "translated", "15", "22", "32"],
1✔
3886
        ["6", "Your Happy Life", "translated", "15", "22", "33"]];
1✔
3887

1✔
3888
        return this.isEqual("selectFromSubQuery8", data, expected);
1✔
3889
    }
1✔
3890

1✔
3891
    selectFromSubQuery9() {
1✔
3892
        let stmt = "Select * from (select * from books where title = 'Your Happy Life') as mybooks";
1✔
3893

1✔
3894
        let data = new TestSql()
1✔
3895
            .addTableData("books", this.bookTable())
1✔
3896
            .enableColumnTitle(true)
1✔
3897
            .execute(stmt);
1✔
3898

1✔
3899
        let expected = [["MYBOOKS.ID", "MYBOOKS.TITLE", "MYBOOKS.TYPE", "MYBOOKS.AUTHOR_ID", "MYBOOKS.EDITOR_ID", "MYBOOKS.TRANSLATOR_ID"],
1✔
3900
        ["6", "Your Happy Life", "translated", "15", "22", "33"]];
1✔
3901

1✔
3902
        return this.isEqual("selectFromSubQuery9", data, expected);
1✔
3903
    }
1✔
3904

1✔
3905
    selectConcat1() {
1✔
3906
        let stmt = "Select concat(invoice, ', ', price) from  booksales";
1✔
3907

1✔
3908
        let data = new TestSql()
1✔
3909
            .addTableData("booksales", this.bookSalesTable())
1✔
3910
            .enableColumnTitle(true)
1✔
3911
            .execute(stmt);
1✔
3912

1✔
3913
        let expected = [["concat(invoice, ', ', price)"],
1✔
3914
        ["I7200, 34.95"],
1✔
3915
        ["I7201, 29.95"],
1✔
3916
        ["I7201, 18.99"],
1✔
3917
        ["I7202, 59.99"],
1✔
3918
        ["I7203, 90"],
1✔
3919
        ["I7204, 65.49"],
1✔
3920
        ["I7204, 24.95"],
1✔
3921
        ["I7204, 19.99"],
1✔
3922
        ["I7205, 33.97"],
1✔
3923
        ["I7206, 17.99"]];
1✔
3924

1✔
3925
        return this.isEqual("selectConcat1", data, expected);
1✔
3926
    }
1✔
3927

1✔
3928
    selectBadHavingButStillWork() {
1✔
3929
        //  Should be a GROUP BY, but this does work in mySQL
1✔
3930
        let stmt = "select id from books having id < 5";
1✔
3931

1✔
3932
        let data = new TestSql()
1✔
3933
            .addTableData("books", this.bookTable())
1✔
3934
            .enableColumnTitle(true)
1✔
3935
            .execute(stmt);
1✔
3936

1✔
3937
        let expected = [["id"],
1✔
3938
        ["1"],
1✔
3939
        ["2"],
1✔
3940
        ["3"],
1✔
3941
        ["4"]];
1✔
3942

1✔
3943
        return this.isEqual("selectBadHavingButStillWork", data, expected);
1✔
3944
    }
1✔
3945

1✔
3946
    selectDateDiff() {
1✔
3947
        //  This will never test.
×
3948
        let stmt = "select date as 'Invoice Date', adddate(date, 30) as '30 Days Overdue', datediff(adddate(curDate(),7), now()) from booksales where date <= adddate('05/01/2022',1)";
×
3949

×
3950
        let data = new TestSql()
×
3951
            .addTableData("BookSales", this.bookSalesTable())
×
3952
            .enableColumnTitle(true)
×
3953
            .execute(stmt);
×
3954

×
3955
        let expected = [["Invoice Date", "30 Days Overdue", "datediff(adddate(curDate(),7), now())"],
×
3956
        ["05/01/2022", "2022-05-31T04:00:00.000Z", 7],
×
3957
        ["05/01/2022", "2022-05-31T04:00:00.000Z", 7],
×
3958
        ["05/01/2022", "2022-05-31T04:00:00.000Z", 7],
×
3959
        ["05/02/2022", "2022-06-01T04:00:00.000Z", 7],
×
3960
        ["05/02/2022", "2022-06-01T04:00:00.000Z", 7]];
×
3961

×
3962
        return this.isEqual("selectDateDiff", data, expected);
×
3963
    }
×
3964

1✔
3965
    selectDateDiff2() {
1✔
3966
        //  This will never test.
1✔
3967
        let stmt = "select date as 'Invoice Date', adddate(date, 30) as 'Overdue', datediff(adddate(date, 30), date) from booksales where date <= adddate('05/01/2022',1)";
1✔
3968

1✔
3969
        let data = new TestSql()
1✔
3970
            .addTableData("BookSales", this.bookSalesTable())
1✔
3971
            .enableColumnTitle(true)
1✔
3972
            .execute(stmt);
1✔
3973

1✔
3974
        let expected = [["Invoice Date", "Overdue", "datediff(adddate(date, 30), date)"],
1✔
3975
        ["05/01/2022", "2022-05-31T04:00:00.000Z", 30],
1✔
3976
        ["05/01/2022", "2022-05-31T04:00:00.000Z", 30],
1✔
3977
        ["05/01/2022", "2022-05-31T04:00:00.000Z", 30],
1✔
3978
        ["05/02/2022", "2022-06-01T04:00:00.000Z", 30],
1✔
3979
        ["05/02/2022", "2022-06-01T04:00:00.000Z", 30]];
1✔
3980

1✔
3981
        return this.isEqual("selectDateDiff2", data, expected);
1✔
3982
    }
1✔
3983

1✔
3984

1✔
3985
    selectNotLikeInMiddle1() {
1✔
3986
        let stmt = "select * from books where title not like 'Your%'";
1✔
3987

1✔
3988
        let data = new TestSql()
1✔
3989
            .addTableData("books", this.bookTable())
1✔
3990
            .enableColumnTitle(true)
1✔
3991
            .execute(stmt);
1✔
3992

1✔
3993
        let expected = [["BOOKS.ID", "BOOKS.TITLE", "BOOKS.TYPE", "BOOKS.AUTHOR_ID", "BOOKS.EDITOR_ID", "BOOKS.TRANSLATOR_ID"],
1✔
3994
        ["1", "Time to Grow Up!", "original", "11", "21", ""],
1✔
3995
        ["3", "Lovely Love", "original", "14", "24", ""],
1✔
3996
        ["4", "Dream Your Life", "original", "11", "24", ""],
1✔
3997
        ["5", "Oranges", "translated", "12", "25", "31"],
1✔
3998
        ["7", "Applied AI", "translated", "13", "23", "34"],
1✔
3999
        ["9", "Book with Mysterious Author", "translated", "1", "23", "34"],
1✔
4000
        ["8", "My Last Book", "original", "11", "28", ""]];
1✔
4001

1✔
4002
        return this.isEqual("selectNotLikeInMiddle1", data, expected);
1✔
4003
    }
1✔
4004

1✔
4005
    selectGroupConcat() {
1✔
4006
        let stmt = "select group_concat(name) as concatenated from customers ";
1✔
4007

1✔
4008
        let data = new TestSql()
1✔
4009
            .addTableData("customers", this.customerTable())
1✔
4010
            .enableColumnTitle(true)
1✔
4011
            .execute(stmt);
1✔
4012

1✔
4013
        let expected = [["concatenated"],
1✔
4014
        ["7th Heaven,Dewy Tuesdays,Fe Fi Fo Giant Tiger,ForMe Resellers,Numereo Uno,Sx in Cars,Tres Buon Goods"]];
1✔
4015

1✔
4016
        return this.isEqual("selectGroupConcat", data, expected);
1✔
4017

1✔
4018
    }
1✔
4019

1✔
4020
    selectGroupConcat2() {
1✔
4021
        let stmt = "select customer_id, group_concat(distinct(book_id)) as Books from booksales group by customer_id ";
1✔
4022

1✔
4023
        let data = new TestSql()
1✔
4024
            .addTableData("booksales", this.bookSalesTable())
1✔
4025
            .enableColumnTitle(true)
1✔
4026
            .execute(stmt);
1✔
4027

1✔
4028
        let expected = [["customer_id", "Books"],
1✔
4029
        ["", "1"], ["C1", "7,9"], ["C2", "7,8"], ["C3", "9"], ["C4", "2,3,4"]];
1✔
4030

1✔
4031
        return this.isEqual("selectGroupConcat2", data, expected);
1✔
4032

1✔
4033
    }
1✔
4034

1✔
4035
    selectBetween1() {
1✔
4036
        let stmt = "select * from booksales where price between 10 and 24.95 order by quantity";
1✔
4037

1✔
4038
        let data = new TestSql()
1✔
4039
            .addTableData("bookSales", this.bookSalesTable())
1✔
4040
            .enableColumnTitle(true)
1✔
4041
            .execute(stmt);
1✔
4042

1✔
4043
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
4044
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022"],
1✔
4045
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"],
1✔
4046
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022"],
1✔
4047
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"]];
1✔
4048

1✔
4049
        return this.isEqual("selectBetween1", data, expected);
1✔
4050
    }
1✔
4051

1✔
4052
    selectNotBetween1() {
1✔
4053
        let stmt = "select * from booksales where price not between 10 and 24.95 order by quantity";
1✔
4054

1✔
4055
        let data = new TestSql()
1✔
4056
            .addTableData("bookSales", this.bookSalesTable())
1✔
4057
            .enableColumnTitle(true)
1✔
4058
            .execute(stmt);
1✔
4059

1✔
4060
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
4061
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
1✔
4062
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
4063
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022"],
1✔
4064
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022"],
1✔
4065
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022"],
1✔
4066
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"]];
1✔
4067

1✔
4068
        return this.isEqual("selectNotBetween1", data, expected);
1✔
4069
    }
1✔
4070

1✔
4071
    selectNotBetweenAndIN() {
1✔
4072
        let stmt = "select * from booksales where price not between 10 and 24.95 and invoice in ('I7202', 'I7201')";
1✔
4073

1✔
4074
        let data = new TestSql()
1✔
4075
            .addTableData("bookSales", this.bookSalesTable())
1✔
4076
            .enableColumnTitle(true)
1✔
4077
            .execute(stmt);
1✔
4078

1✔
4079
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
4080
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022"],
1✔
4081
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"]];
1✔
4082

1✔
4083
        return this.isEqual("selectNotBetweenAndIN", data, expected);
1✔
4084
    }
1✔
4085

1✔
4086
    selectBetweenFromFunction() {
1✔
4087
        let stmt = "select * from booksales where day(date) between 2 and 3";
1✔
4088

1✔
4089
        let data = new TestSql()
1✔
4090
            .addTableData("bookSales", this.bookSalesTable())
1✔
4091
            .enableColumnTitle(true)
1✔
4092
            .execute(stmt);
1✔
4093

1✔
4094
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE"],
1✔
4095
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022"],
1✔
4096
        ["I7203", "1", "", 1, 90, "05/02/2022"],
1✔
4097
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022"],
1✔
4098
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022"],
1✔
4099
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022"]];
1✔
4100

1✔
4101
        return this.isEqual("selectBetweenFromFunction", data, expected);
1✔
4102
    }
1✔
4103

1✔
4104
    selectCountWithNullOnJoin() {
1✔
4105
        let stmt = "select author_id, count(translators.id) from books left join translators on books.translator_id = translators.id group by  author_id";
1✔
4106

1✔
4107
        let data = new TestSql()
1✔
4108
            .addTableData("books", this.bookTable())
1✔
4109
            .addTableData("translators", this.translatorsTable())
1✔
4110
            .enableColumnTitle(true)
1✔
4111
            .execute(stmt);
1✔
4112

1✔
4113
        let expected = [["author_id", "count(translators.id)"],
1✔
4114
        ["1", 1],
1✔
4115
        ["11", 0],
1✔
4116
        ["12", 1],
1✔
4117
        ["13", 1],
1✔
4118
        ["14", 0],
1✔
4119
        ["15", 2]];
1✔
4120

1✔
4121
        return this.isEqual("selectCountWithNullOnJoin", data, expected);
1✔
4122
    }
1✔
4123

1✔
4124
    selectCalculatedFieldWitinGroupBY() {
1✔
4125
        let stmt = "select author_id as Fred, Count( translators.id) as Tom, min(editor_id), group_concat(editor_id), (COUNT( translators.id) * 5 + min (editor_id ) - COUNT(translators.id)) as test from books left join translators on books.translator_id = translators.id group by  author_id";
1✔
4126

1✔
4127
        let data = new TestSql()
1✔
4128
            .addTableData("books", this.bookTable())
1✔
4129
            .addTableData("translators", this.translatorsTable())
1✔
4130
            .enableColumnTitle(true)
1✔
4131
            .execute(stmt);
1✔
4132

1✔
4133
        let expected = [["Fred", "Tom", "min(editor_id)", "group_concat(editor_id)", "test"],
1✔
4134
        ["1", 1, 23, "23", 27],
1✔
4135
        ["11", 0, 21, "21,24,28", 21],
1✔
4136
        ["12", 1, 25, "25", 29],
1✔
4137
        ["13", 1, 23, "23", 27],
1✔
4138
        ["14", 0, 24, "24", 24],
1✔
4139
        ["15", 2, 22, "22,22", 30]];
1✔
4140

1✔
4141
        return this.isEqual("selectCalculatedFieldWitinGroupBY", data, expected);
1✔
4142
    }
1✔
4143

1✔
4144
    selectCalculatedFieldNotInSelectFieldsWitinGroupBY() {
1✔
4145
        let stmt = "select author_id, Count(translators.id) as Tom, (COUNT(translators.id) * 5 + min(editor_id ) - COUNT(translators.id)) as test from books left join translators on books.translator_id = translators.id group by  author_id";
1✔
4146

1✔
4147
        let data = new TestSql()
1✔
4148
            .addTableData("books", this.bookTable())
1✔
4149
            .addTableData("translators", this.translatorsTable())
1✔
4150
            .enableColumnTitle(true)
1✔
4151
            .execute(stmt);
1✔
4152

1✔
4153
        let expected = [["author_id", "Tom", "test"],
1✔
4154
        ["1", 1, 27],
1✔
4155
        ["11", 0, 21],
1✔
4156
        ["12", 1, 29],
1✔
4157
        ["13", 1, 27],
1✔
4158
        ["14", 0, 24],
1✔
4159
        ["15", 2, 30]];
1✔
4160

1✔
4161
        return this.isEqual("selectCalculatedFieldNotInSelectFieldsWitinGroupBY", data, expected);
1✔
4162
    }
1✔
4163

1✔
4164
    selectJoinCaseInSensitiveCondition() {
1✔
4165
        let stmt = "select customers.id, min(bookreturns.price) from bookreturns join customers on bookreturns.customer_id = customers.id group by customers.id";
1✔
4166

1✔
4167
        let data = new TestSql()
1✔
4168
            .addTableData("customers", this.customerTable())
1✔
4169
            .addTableData("bookreturns", this.bookReturnsTable())
1✔
4170
            .enableColumnTitle(true)
1✔
4171
            .execute(stmt);
1✔
4172

1✔
4173
        let expected = [["customers.id", "min(bookreturns.price)"],
1✔
4174
        ["C1", 33.97],
1✔
4175
        ["C2", 17.99],
1✔
4176
        ["C3", 59.99],
1✔
4177
        ["C4", 19.99]];
1✔
4178

1✔
4179
        return this.isEqual("selectJoinCaseInSensitiveCondition", data, expected);
1✔
4180
    }
1✔
4181

1✔
4182
    selectCaseInSensitiveCondition() {
1✔
4183
        let stmt = "select * from bookreturns where customer_id = 'C1'";
1✔
4184

1✔
4185
        let data = new TestSql()
1✔
4186
            .addTableData("bookreturns", this.bookReturnsTable())
1✔
4187
            .enableColumnTitle(true)
1✔
4188
            .execute(stmt);
1✔
4189

1✔
4190
        let expected = [["BOOKRETURNS.RMA", "BOOKRETURNS.BOOK_ID", "BOOKRETURNS.CUSTOMER_ID", "BOOKRETURNS.QUANTITY", "BOOKRETURNS.PRICE", "BOOKRETURNS.DATE"],
1✔
4191
        ["Rma001", "9", "c1", 10, 34.95, "05/01/2022"],
1✔
4192
        ["rma005", "1", "c1", 1, 90, "05/02/2022"],
1✔
4193
        ["RMA900", "7", "c1", 1, 33.97, "05/04/2022"]];
1✔
4194

1✔
4195
        return this.isEqual("selectInSensitiveCondition", data, expected);
1✔
4196
    }
1✔
4197

1✔
4198
    concatWsWithDayFunction() {
1✔
4199
        let stmt = "select CONCAT_WS('/', DAY(Date), MONTH(Date), YEAR(Date)) from bookreturns";
1✔
4200

1✔
4201
        let data = new TestSql()
1✔
4202
            .addTableData("bookreturns", this.bookReturnsTable())
1✔
4203
            .enableColumnTitle(true)
1✔
4204
            .execute(stmt);
1✔
4205

1✔
4206
        let expected = [["CONCAT_WS('/', DAY(Date), MONTH(Date), YEAR(Date))"],
1✔
4207
        ["1/5/2022"],
1✔
4208
        ["1/5/2022"],
1✔
4209
        ["1/5/2022"],
1✔
4210
        ["2/5/2022"],
1✔
4211
        ["2/5/2022"],
1✔
4212
        ["3/5/2022"],
1✔
4213
        ["3/5/2022"],
1✔
4214
        ["3/5/2022"],
1✔
4215
        ["4/5/2022"],
1✔
4216
        ["4/5/2022"]];
1✔
4217

1✔
4218
        return this.isEqual("concatWsWithDayFunction", data, expected);
1✔
4219
    }
1✔
4220

1✔
4221
    selectAddDateLastDay() {
1✔
4222
        let stmt = "select date as 'Invoice Date', AddDate(date,-1), Last_Day(Date)from booksales where date <= adddate('05/01/2022',1)";
1✔
4223

1✔
4224
        let data = new TestSql()
1✔
4225
            .addTableData("BookSales", this.bookSalesTable())
1✔
4226
            .enableColumnTitle(true)
1✔
4227
            .execute(stmt);
1✔
4228

1✔
4229
        let expected = [["Invoice Date", "AddDate(date,-1)", "Last_Day(Date)"],
1✔
4230
        ["05/01/2022", "2022-04-30T04:00:00.000Z", "2022-05-31T04:00:00.000Z"],
1✔
4231
        ["05/01/2022", "2022-04-30T04:00:00.000Z", "2022-05-31T04:00:00.000Z"],
1✔
4232
        ["05/01/2022", "2022-04-30T04:00:00.000Z", "2022-05-31T04:00:00.000Z"],
1✔
4233
        ["05/02/2022", "2022-05-01T04:00:00.000Z", "2022-05-31T04:00:00.000Z"],
1✔
4234
        ["05/02/2022", "2022-05-01T04:00:00.000Z", "2022-05-31T04:00:00.000Z"]];
1✔
4235

1✔
4236
        return this.isEqual("selectAddDateLastDay", data, expected);
1✔
4237
    }
1✔
4238

1✔
4239
    selectLocate() {
1✔
4240
        let stmt = "select title, locate('Your', title, 3), locate('your', title, 3), locate('book', title), instr(title, 'book') from books";
1✔
4241
        let data = new TestSql()
1✔
4242
            .addTableData("Books", this.bookTable())
1✔
4243
            .enableColumnTitle(true)
1✔
4244
            .execute(stmt);
1✔
4245

1✔
4246
        let expected = [["title", "locate('Your', title, 3)", "locate('your', title, 3)", "locate('book', title)", "instr(title, 'book')"],
1✔
4247
        ["Time to Grow Up!", 0, 0, 0, 0],
1✔
4248
        ["Your Trip", 0, 0, 0, 0],
1✔
4249
        ["Lovely Love", 0, 0, 0, 0],
1✔
4250
        ["Dream Your Life", 7, 7, 0, 0],
1✔
4251
        ["Oranges", 0, 0, 0, 0],
1✔
4252
        ["Your Happy Life", 0, 0, 0, 0],
1✔
4253
        ["Applied AI", 0, 0, 0, 0],
1✔
4254
        ["Book with Mysterious Author", 0, 0, 1, 1],
1✔
4255
        ["My Last Book", 0, 0, 9, 9]];
1✔
4256

1✔
4257
        return this.isEqual("selectLocate", data, expected);
1✔
4258
    }
1✔
4259

1✔
4260
    selectSumMinusSum() {
1✔
4261
        // let stmt = "select sum(quantity) - sum(price) from booksales";
×
4262
        let stmt = "select sum(quantity - price) from booksales";
×
4263
        let data = new TestSql()
×
4264
            .addTableData("booksales", this.bookSalesTable())
×
4265
            .enableColumnTitle(true)
×
4266
            .execute(stmt);
×
4267

×
NEW
4268
        let expected = [["sum(quantity) - sum(price)"], [24.73]];
×
4269

×
4270
        return this.isEqual("selectSumMinusSum", data, expected);
×
4271
    }
×
4272

1✔
4273
    innerSelectWithComments() {
1✔
4274
        let stmt = "SELECT *, customers.name FROM bookSales " +
1✔
4275
            "\n -- We join books to customers\n" +
1✔
4276
            "LEFT JOIN customers ON bookSales.customer_ID = customers.ID " +
1✔
4277
            "\n-- We only want the highest booksales\n" +
1✔
4278
            "WHERE bookSales.quantity > (select AVG(quantity) from booksales)";
1✔
4279

1✔
4280
        let data = new TestSql()
1✔
4281
            .addTableData("bookSales", this.bookSalesTable())
1✔
4282
            .addTableData("customers", this.customerTable())
1✔
4283
            .enableColumnTitle(true)
1✔
4284
            .execute(stmt);
1✔
4285

1✔
4286
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "CUSTOMERS.ID", "CUSTOMERS.NAME", "CUSTOMERS.ADDRESS", "CUSTOMERS.CITY", "CUSTOMERS.PHONE", "CUSTOMERS.EMAIL", "customers.name"],
1✔
4287
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "ForMe Resellers"],
1✔
4288
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "ForMe Resellers"],
1✔
4289
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com", "ForMe Resellers"],
1✔
4290
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com", "Dewy Tuesdays"]];
1✔
4291

1✔
4292
        return this.isEqual("innerSelectWithComments", data, expected);
1✔
4293
    }
1✔
4294

1✔
4295
    JoinTableNotEqualCondition() {
1✔
4296
        let stmt = "select * from booksales join customers on booksales.customer_id <> customers.id";
1✔
4297

1✔
4298
        let data = new TestSql()
1✔
4299
            .addTableData("customers", this.customerTable())
1✔
4300
            .addTableData("booksales", this.bookSalesTable())
1✔
4301
            .enableColumnTitle(true)
1✔
4302
            .execute(stmt);
1✔
4303

1✔
4304
        let expected = [["BOOKSALES.INVOICE", "BOOKSALES.BOOK_ID", "BOOKSALES.CUSTOMER_ID", "BOOKSALES.QUANTITY", "BOOKSALES.PRICE", "BOOKSALES.DATE", "CUSTOMERS.ID", "CUSTOMERS.NAME", "CUSTOMERS.ADDRESS", "CUSTOMERS.CITY", "CUSTOMERS.PHONE", "CUSTOMERS.EMAIL"],
1✔
4305
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "],
1✔
4306
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
4307
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
1✔
4308
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"],
1✔
4309
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
1✔
4310
        ["I7200", "9", "C1", 10, 34.95, "05/01/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"],
1✔
4311
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022", "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "],
1✔
4312
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022", "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
4313
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022", "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
1✔
4314
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"],
1✔
4315
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
1✔
4316
        ["I7201", "8", "C2", 3, 29.95, "05/01/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
1✔
4317
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "],
1✔
4318
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
4319
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
1✔
4320
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"],
1✔
4321
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
1✔
4322
        ["I7201", "7", "C2", 5, 18.99, "05/01/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
1✔
4323
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "],
1✔
4324
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
4325
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
1✔
4326
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"],
1✔
4327
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"],
1✔
4328
        ["I7202", "9", "C3", 1, 59.99, "05/02/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
1✔
4329
        ["I7203", "1", "", 1, 90, "05/02/2022", "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "],
1✔
4330
        ["I7203", "1", "", 1, 90, "05/02/2022", "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
4331
        ["I7203", "1", "", 1, 90, "05/02/2022", "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
1✔
4332
        ["I7203", "1", "", 1, 90, "05/02/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"],
1✔
4333
        ["I7203", "1", "", 1, 90, "05/02/2022", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
1✔
4334
        ["I7203", "1", "", 1, 90, "05/02/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"],
1✔
4335
        ["I7203", "1", "", 1, 90, "05/02/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
1✔
4336
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "],
1✔
4337
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
4338
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
1✔
4339
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
1✔
4340
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"],
1✔
4341
        ["I7204", "2", "C4", 100, 65.49, "05/03/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
1✔
4342
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "],
1✔
4343
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
4344
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
1✔
4345
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
1✔
4346
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"],
1✔
4347
        ["I7204", "3", "C4", 150, 24.95, "05/03/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
1✔
4348
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "],
1✔
4349
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
4350
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
1✔
4351
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
1✔
4352
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"],
1✔
4353
        ["I7204", "4", "C4", 50, 19.99, "05/03/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"],
1✔
4354
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "],
1✔
4355
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
4356
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
1✔
4357
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"],
1✔
4358
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
1✔
4359
        ["I7205", "7", "C1", 1, 33.97, "05/04/2022", "C2", "Dewy Tuesdays", "202 Second St.", "Second City", "4162022222", "twoguys@gmail.com"],
1✔
4360
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "C7", "7th Heaven", "7 Eight Crt.", "Lucky City", "5551117777", " timesAcharm@gmail.com "],
1✔
4361
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "C6", "Sx in Cars", "6 Seventh St", "Sx City", "6661116666", "gotyourSix@hotmail.com   "],
1✔
4362
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "C5", "Fe Fi Fo Giant Tiger", "5 ohFive St.", "FifthDom", "4165551234", "   fiver@gmail.com"],
1✔
4363
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "C4", "ForMe Resellers", "40 Four St", "FourtNight City", "2894441234", "fourtimes@hotmail.com"],
1✔
4364
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "C3", "Tres Buon Goods", "3 Way St", "Tres City", "5193133303", "thrice@hotmail.com"],
1✔
4365
        ["I7206", "7", "C2", 100, 17.99, "05/04/2022", "C1", "Numereo Uno", "101 One Way", "One Point City", "9051112111", "bigOne@gmail.com"]];
1✔
4366

1✔
4367
        return this.isEqual("JoinTableNotEqualCondition", data, expected);
1✔
4368
    }
1✔
4369

1✔
4370
    JoinTableNotEqualCalcCondition() {
1✔
4371
        let stmt = " select invoice, rma from booksales join bookreturns on substr(booksales.customer_id, 2, 1) <> substr(bookreturns.customer_id, 2, 1) where rma = 'Rma001' order by invoice, rma";
1✔
4372

1✔
4373
        let data = new TestSql()
1✔
4374
            .addTableData("bookreturns", this.bookReturnsTable())
1✔
4375
            .addTableData("booksales", this.bookSalesTable())
1✔
4376
            .enableColumnTitle(true)
1✔
4377
            .execute(stmt);
1✔
4378

1✔
4379
        let expected = [["invoice", "rma"],
1✔
4380
        ["I7201", "Rma001"],
1✔
4381
        ["I7201", "Rma001"],
1✔
4382
        ["I7202", "Rma001"],
1✔
4383
        ["I7203", "Rma001"],
1✔
4384
        ["I7204", "Rma001"],
1✔
4385
        ["I7204", "Rma001"],
1✔
4386
        ["I7204", "Rma001"],
1✔
4387
        ["I7206", "Rma001"]];
1✔
4388

1✔
4389
        return this.isEqual("JoinTableNotEqualCalcCondition", data, expected);
1✔
4390
    }
1✔
4391

1✔
4392
    SelectTableSelfJoin() {
1✔
4393
        let stmt = "select A.name as custname1, B.name as custname2 from customers as A join customers as B on A.id <> B.id";
1✔
4394

1✔
4395
        let data = new TestSql()
1✔
4396
            .addTableData("customers", this.customerTable())
1✔
4397
            .enableColumnTitle(true)
1✔
4398
            .execute(stmt);
1✔
4399

1✔
4400
        let expected = [["custname1", "custname2"],
1✔
4401
        ["Numereo Uno", "7th Heaven"],
1✔
4402
        ["Numereo Uno", "Sx in Cars"],
1✔
4403
        ["Numereo Uno", "Fe Fi Fo Giant Tiger"],
1✔
4404
        ["Numereo Uno", "ForMe Resellers"],
1✔
4405
        ["Numereo Uno", "Tres Buon Goods"],
1✔
4406
        ["Numereo Uno", "Dewy Tuesdays"],
1✔
4407
        ["Dewy Tuesdays", "7th Heaven"],
1✔
4408
        ["Dewy Tuesdays", "Sx in Cars"],
1✔
4409
        ["Dewy Tuesdays", "Fe Fi Fo Giant Tiger"],
1✔
4410
        ["Dewy Tuesdays", "ForMe Resellers"],
1✔
4411
        ["Dewy Tuesdays", "Tres Buon Goods"],
1✔
4412
        ["Dewy Tuesdays", "Numereo Uno"],
1✔
4413
        ["Tres Buon Goods", "7th Heaven"],
1✔
4414
        ["Tres Buon Goods", "Sx in Cars"],
1✔
4415
        ["Tres Buon Goods", "Fe Fi Fo Giant Tiger"],
1✔
4416
        ["Tres Buon Goods", "ForMe Resellers"],
1✔
4417
        ["Tres Buon Goods", "Dewy Tuesdays"],
1✔
4418
        ["Tres Buon Goods", "Numereo Uno"],
1✔
4419
        ["ForMe Resellers", "7th Heaven"],
1✔
4420
        ["ForMe Resellers", "Sx in Cars"],
1✔
4421
        ["ForMe Resellers", "Fe Fi Fo Giant Tiger"],
1✔
4422
        ["ForMe Resellers", "Tres Buon Goods"],
1✔
4423
        ["ForMe Resellers", "Dewy Tuesdays"],
1✔
4424
        ["ForMe Resellers", "Numereo Uno"],
1✔
4425
        ["Fe Fi Fo Giant Tiger", "7th Heaven"],
1✔
4426
        ["Fe Fi Fo Giant Tiger", "Sx in Cars"],
1✔
4427
        ["Fe Fi Fo Giant Tiger", "ForMe Resellers"],
1✔
4428
        ["Fe Fi Fo Giant Tiger", "Tres Buon Goods"],
1✔
4429
        ["Fe Fi Fo Giant Tiger", "Dewy Tuesdays"],
1✔
4430
        ["Fe Fi Fo Giant Tiger", "Numereo Uno"],
1✔
4431
        ["Sx in Cars", "7th Heaven"],
1✔
4432
        ["Sx in Cars", "Fe Fi Fo Giant Tiger"],
1✔
4433
        ["Sx in Cars", "ForMe Resellers"],
1✔
4434
        ["Sx in Cars", "Tres Buon Goods"],
1✔
4435
        ["Sx in Cars", "Dewy Tuesdays"],
1✔
4436
        ["Sx in Cars", "Numereo Uno"],
1✔
4437
        ["7th Heaven", "Sx in Cars"],
1✔
4438
        ["7th Heaven", "Fe Fi Fo Giant Tiger"],
1✔
4439
        ["7th Heaven", "ForMe Resellers"],
1✔
4440
        ["7th Heaven", "Tres Buon Goods"],
1✔
4441
        ["7th Heaven", "Dewy Tuesdays"],
1✔
4442
        ["7th Heaven", "Numereo Uno"]];
1✔
4443

1✔
4444
        return this.isEqual("SelectTableSelfJoin", data, expected);
1✔
4445
    }
1✔
4446

1✔
4447
    //  S T A R T   O T H E R   T E S T S
1✔
4448
    removeTrailingEmptyRecords() {
1✔
4449
        let authors = this.authorsTable();
1✔
4450

1✔
4451
        for (let i = 0; i < 10; i++) {
1✔
4452
            authors.push(["", "", ""]);
10✔
4453
        }
10✔
4454

1✔
4455
        let stmt = "select * from authors";
1✔
4456

1✔
4457
        let data = new TestSql()
1✔
4458
            .addTableData("authors", authors)
1✔
4459
            .enableColumnTitle(true)
1✔
4460
            .execute(stmt);
1✔
4461

1✔
4462
        let expected = [["AUTHORS.ID", "AUTHORS.FIRST_NAME", "AUTHORS.LAST_NAME"],
1✔
4463
        ["11", "Ellen", "Writer"],
1✔
4464
        ["12", "Olga", "Savelieva"],
1✔
4465
        ["13", "Jack", "Smart"],
1✔
4466
        ["14", "Donald", "Brain"],
1✔
4467
        ["15", "Yao", "Dou"]];
1✔
4468

1✔
4469
        return this.isEqual("removeTrailingEmptyRecords", data, expected);
1✔
4470
    }
1✔
4471

1✔
4472
    parseTableSettings1() {
1✔
4473
        let data = GasSql.parseTableSettings([['authors', 'authorsNamedRange', 60, false], ['editors', 'editorsRange', 30], ['people', 'peopleRange']], "", false);
1✔
4474
        let expected = [["authors", "authorsNamedRange", 60, false],
1✔
4475
        ["editors", "editorsRange", 30, true],
1✔
4476
        ["people", "peopleRange", 60, true]];
1✔
4477

1✔
4478
        return this.isEqual("parseTableSettings1", data, expected);
1✔
4479
    }
1✔
4480

1✔
4481
    parseTableSettings2() {
1✔
4482
        let data = GasSql.parseTableSettings([['authors', 'authorsNamedRange', 60], ['editors', 'editorsRange', 30], ['people']], "", false);
1✔
4483
        let expected = [["authors", "authorsNamedRange", 60, true],
1✔
4484
        ["editors", "editorsRange", 30, true],
1✔
4485
        ["people", "people", 60, true]];
1✔
4486
        return this.isEqual("parseTableSettings2", data, expected);
1✔
4487
    }
1✔
4488

1✔
4489
    parseTableSettings3() {
1✔
4490
        let stmt = "select *, books.title, authors.first_name, editors.first_name, customers.name, customers.email, booksales.quantity from bookSales " +
1✔
4491
            "LEFT JOIN books ON booksales.book_id = books.id " +
1✔
4492
            "LEFT JOIN authors on books.author_id = authors.id " +
1✔
4493
            "LEFT JOIN editors on books.editor_id = editors.id " +
1✔
4494
            "LEFT JOIN customers on bookSales.customer_id = customers.id " +
1✔
4495
            "WHERE customers.email NOT LIKE '%gmail.com' " +
1✔
4496
            "UNION select * from bookSales2";
1✔
4497

1✔
4498
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4499
        let expected = [["BOOKSALES", "BOOKSALES", 60, true],
1✔
4500
        ["BOOKS", "BOOKS", 60, true],
1✔
4501
        ["AUTHORS", "AUTHORS", 60, true],
1✔
4502
        ["EDITORS", "EDITORS", 60, true],
1✔
4503
        ["CUSTOMERS", "CUSTOMERS", 60, true],
1✔
4504
        ["BOOKSALES2", "BOOKSALES2", 60, true]];
1✔
4505
        return this.isEqual("parseTableSettings3", data, expected);
1✔
4506
    }
1✔
4507

1✔
4508
    parseTableSettings4() {
1✔
4509
        let stmt = "select * from 'master transactions' where account in (select account_name from accounts) ";
1✔
4510

1✔
4511
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4512
        let expected = [["'MASTER TRANSACTIONS'", "'MASTER TRANSACTIONS'", 60, true],
1✔
4513
        ["ACCOUNTS", "ACCOUNTS", 60, true]];
1✔
4514
        return this.isEqual("parseTableSettings4", data, expected);
1✔
4515
    }
1✔
4516

1✔
4517
    parseTableSettings5() {
1✔
4518
        let stmt = "SELECT * " +
1✔
4519
            "FROM books " +
1✔
4520
            "WHERE author_id IN (select a.id from authors as a where first_name = ?) " +
1✔
4521
            "or editor_id in (select e.id from editors as e where last_name = ?) " +
1✔
4522
            "or title = ? " +
1✔
4523
            "ORDER BY title";
1✔
4524

1✔
4525
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4526
        let expected = [["BOOKS", "BOOKS", 60, true],
1✔
4527
        ["AUTHORS", "AUTHORS", 60, true],
1✔
4528
        ["EDITORS", "EDITORS", 60, true]];
1✔
4529
        return this.isEqual("parseTableSettings5", data, expected);
1✔
4530
    }
1✔
4531

1✔
4532
    parseTableSettings6() {
1✔
4533
        let stmt = "SELECT books.id, books.title, books.author_id " +
1✔
4534
            "FROM books " +
1✔
4535
            "WHERE books.author_id NOT IN (SELECT id from authors)" +
1✔
4536
            "ORDER BY books.title";
1✔
4537

1✔
4538
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4539
        let expected = [["BOOKS", "BOOKS", 60, true],
1✔
4540
        ["AUTHORS", "AUTHORS", 60, true]];
1✔
4541
        return this.isEqual("parseTableSettings6", data, expected);
1✔
4542
    }
1✔
4543

1✔
4544
    parseTableSettings7() {
1✔
4545
        let stmt = "SELECT booksales.A as 'Invoice', booksales.B as 'Book ID', CUST.A, CUST.B FROM booksales " +
1✔
4546
            "LEFT JOIN customers as CUST on booksales.C = customers.A ";
1✔
4547

1✔
4548
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4549
        let expected = [["BOOKSALES", "BOOKSALES", 60, true],
1✔
4550
        ["CUSTOMERS", "CUSTOMERS", 60, true]];
1✔
4551

1✔
4552
        return this.isEqual("parseTableSettings7", data, expected);
1✔
4553
    }
1✔
4554

1✔
4555
    parseTableSettings8() {
1✔
4556
        let stmt = "select id, title, (select count(*) from booksales where books.id = booksales.book_id) from books";
1✔
4557

1✔
4558
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4559
        let expected = [["BOOKS", "BOOKS", 60, true],
1✔
4560
        ["BOOKSALES", "BOOKSALES", 60, true]];
1✔
4561

1✔
4562
        return this.isEqual("parseTableSettings8", data, expected);
1✔
4563
    }
1✔
4564

1✔
4565
    parseTableSettings9() {
1✔
4566
        let stmt = "select concat_ws('-', *) as Concatenated from booksales left join customers on booksales.customer_id = customers.id where concat_ws('-', *) like '%Way%'";
1✔
4567

1✔
4568
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4569
        let expected = [["BOOKSALES", "BOOKSALES", 60, true],
1✔
4570
        ["CUSTOMERS", "CUSTOMERS", 60, true]];
1✔
4571

1✔
4572
        return this.isEqual("parseTableSettings9", data, expected);
1✔
4573
    }
1✔
4574

1✔
4575
    parseTableSettings10() {
1✔
4576
        let stmt = "select * from customers where exists (SELECT * FROM booksales WHERE booksales.customer_id = customers.id) and email like '%gmail.com' ";
1✔
4577

1✔
4578
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4579
        let expected = [["CUSTOMERS", "CUSTOMERS", 60, true],
1✔
4580
        ["BOOKSALES", "BOOKSALES", 60, true]];
1✔
4581

1✔
4582
        return this.isEqual("parseTableSettings10", data, expected);
1✔
4583
    }
1✔
4584

1✔
4585
    parseTableSettings11() {
1✔
4586
        let stmt = "select customer_id, wins, loss, (wins / (wins+loss)) as rate from (select customer_id, sum(case when quantity < 100 then 1 else 0 end) as wins, sum(case when quantity >= 100 then 1 else 0 end) as loss from booksales group by customer_id) as score";
1✔
4587

1✔
4588
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4589
        let expected = [["BOOKSALES", "BOOKSALES", 60, true]];
1✔
4590

1✔
4591
        return this.isEqual("parseTableSettings11", data, expected);
1✔
4592
    }
1✔
4593

1✔
4594

1✔
4595
    parseTableSettings12() {
1✔
4596
        let stmt = "select table3.invoice from " +
1✔
4597
            "(select invoice, quantity from " +
1✔
4598
            "(select invoice, table1.QTY as quantity from " +
1✔
4599
            "(select invoice, quantity as QTY, customer_id from booksales where quantity <= 10) as table1 "
1✔
4600
            + "where customer_id = 'C1') as table2) "
1✔
4601
            + "as table3";
1✔
4602

1✔
4603
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4604
        let expected = [["BOOKSALES", "BOOKSALES", 60, true]];
1✔
4605

1✔
4606
        return this.isEqual("parseTableSettings12", data, expected);
1✔
4607
    }
1✔
4608

1✔
4609
    parseTableSettings13() {
1✔
4610
        let stmt = "select table3.invoice, table3.name from (select * from (select invoice, table1.QTY as quantity, customers.name from (select invoice, quantity as QTY, customer_id from booksales where quantity <= 10) as table1 join customers on table1.customer_id = customers.id where customer_id = 'C1') as table2) as table3";
1✔
4611

1✔
4612
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4613
        let expected = [["BOOKSALES", "BOOKSALES", 60, true],
1✔
4614
        ["CUSTOMERS", "CUSTOMERS", 60, true]];
1✔
4615

1✔
4616
        return this.isEqual("parseTableSettings13", data, expected);
1✔
4617
    }
1✔
4618

1✔
4619
    parseTableSettings14() {
1✔
4620
        let stmt = "select * from booksales join (select * from booksales where customer_id = 'C1') as subsales on booksales.book_id = subsales.book_id";
1✔
4621

1✔
4622
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4623
        let expected = [["BOOKSALES", "BOOKSALES", 60, true]];
1✔
4624

1✔
4625
        return this.isEqual("parseTableSettings14", data, expected);
1✔
4626
    }
1✔
4627

1✔
4628
    parseTableSettings15() {
1✔
4629
        let stmt = "select * from booksales join bookreturns on booksales.quantity = bookreturns.quantity and booksales.date = bookreturns.date or booksales.book_id = bookreturns.book_id";
1✔
4630

1✔
4631
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4632
        let expected = [["BOOKSALES", "BOOKSALES", 60, true],
1✔
4633
        ["BOOKRETURNS", "BOOKRETURNS", 60, true]];
1✔
4634

1✔
4635
        return this.isEqual("parseTableSettings15", data, expected);
1✔
4636
    }
1✔
4637

1✔
4638
    parseTableSettings16() {
1✔
4639
        let stmt = "select id, first_name, last_name, count(*) from (select id, first_name, last_name from editors union all select id, first_name, last_name from Authors union all select id, first_name, last_name from translators) as test group by id, first_name, last_name";
1✔
4640

1✔
4641
        let data = GasSql.parseTableSettings([], stmt, false);
1✔
4642
        let expected = [["AUTHORS", "AUTHORS", 60, true],
1✔
4643
        ["TRANSLATORS", "TRANSLATORS", 60, true],
1✔
4644
        ["EDITORS", "EDITORS", 60, true]];
1✔
4645

1✔
4646
        return this.isEqual("parseTableSettings16", data, expected);
1✔
4647
    }
1✔
4648

1✔
4649
    //  Mock the GAS sheets functions required to load.
1✔
4650
    testTableData1() {
1✔
4651
        try {
1✔
4652
            if (SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master Transactions") === null) {
1!
4653
                //  Skip tests if Master Transactions does not exist. (so anybody not CJD)
×
4654
                //  BUT it will work if test run in NODE.
×
4655
                return true;
×
4656
            }
×
4657
        }
1✔
4658
        catch (ex) {
1!
4659
            //  Test will fail running in gas-local.
×
4660
            return true;
×
4661
        }
×
4662

1✔
4663
        let [selectTrans, allTrans, allTrans2, allTrans3, allTrans4] = this.testTableData();
1✔
4664

1✔
4665
        let masterTrans = this.masterTransactionsTable();
1✔
4666
        masterTrans.shift();
1✔
4667

1✔
4668
        let expected = [["Transaction Date", "Gross", "Net"],
1✔
4669
        ["2019-06-07T04:00:00.000Z", 0, 12399.19]];
1✔
4670

1✔
4671
        let result = true;
1✔
4672
        result = result && this.isEqual("testTableData1.a", selectTrans, expected);
1✔
4673
        result = result && this.isEqual("testTableData1.b", allTrans, masterTrans);
1✔
4674
        result = result && this.isEqual("testTableData1.c", allTrans2, masterTrans);
1✔
4675
        result = result && this.isEqual("testTableData1.d", allTrans3, masterTrans);
1✔
4676
        result = result && this.isEqual("testTableData1.e", allTrans4, masterTrans);
1✔
4677

1✔
4678
        let data = gsSQL("select Name_of_Institution, Transaction_Date, Description_1, Description_2, Amount, Expense_Category, Account, Gross, Balance " +
1✔
4679
            "from 'Master Transactions' " +
1✔
4680
            "where transaction_date >= '6/7/2019' and transaction_date <= '6/20/2019'");
1✔
4681
        data.shift();
1✔
4682

1✔
4683
        result = result && this.isEqual("testTableData1.e", data, masterTrans);
1✔
4684

1✔
4685
        return result;
1✔
4686
    }
1✔
4687

1✔
4688
    testTableData2() {
1✔
4689
        let result = true;
1✔
4690

1✔
4691
        let data = gsSQL("select id, first_name, last_name from authors", "authors", this.authorsTable(), "editors", this.editorsTable(), true);
1✔
4692
        result = result && this.isEqual("testTableData2.a", data, this.authorsTable());
1✔
4693

1✔
4694
        data = gsSQL("select id, first_name, last_name from authors", "authors", this.authorsTable(), "editors", this.editorsTable());
1✔
4695
        result = result && this.isEqual("testTableData2.b", data, this.authorsTable());
1✔
4696

1✔
4697
        return result;
1✔
4698
    }
1✔
4699

1✔
4700
    testTableData() {
1✔
4701
        //  Hey CJD, remember to set the startIncomeDate and endIncomeDate - June 7 to June 20 2019
1✔
4702
        const itemData = new TestSql()
1✔
4703
            .addTableData('mastertransactions', 'Master Transactions!$A$1:$I', 60)
1✔
4704
            .enableColumnTitle(true)
1✔
4705
            .addBindNamedRangeParameter('startIncomeDate')
1✔
4706
            .addBindNamedRangeParameter('endIncomeDate')
1✔
4707
            .execute("select transaction_date as 'Transaction Date', sum(gross) as Gross, sum(amount) as Net " +
1✔
4708
                "from mastertransactions " +
1✔
4709
                "where transaction_date >=  ?1 and transaction_date <= ?2 ");
1✔
4710

1✔
4711
        //  Load load from sheet.
1✔
4712
        let trans = new TestSql()
1✔
4713
            .addTableData('mastertransactions', 'Master Transactions!$A$1:$I', .1)
1✔
4714
            .enableColumnTitle(false)
1✔
4715
            .addBindNamedRangeParameter('startIncomeDate')
1✔
4716
            .addBindNamedRangeParameter('endIncomeDate')
1✔
4717
            .execute("select * " +
1✔
4718
                "from mastertransactions " +
1✔
4719
                "where transaction_date >=  ?1 and transaction_date <= ?2 ");
1✔
4720

1✔
4721
        Utilities.sleep(.12);
1✔
4722

1✔
4723
        //  Should load from sheet.
1✔
4724
        trans = new TestSql()
1✔
4725
            .addTableData('mastertransactions', 'Master Transactions!$A$1:$I', 0)
1✔
4726
            .enableColumnTitle(false)
1✔
4727
            .addBindNamedRangeParameter('startIncomeDate')
1✔
4728
            .addBindNamedRangeParameter('endIncomeDate')
1✔
4729
            .execute("select * " +
1✔
4730
                "from mastertransactions " +
1✔
4731
                "where transaction_date >=  ?1 and transaction_date <= ?2 ");
1✔
4732

1✔
4733
        //  Save to long term cache.
1✔
4734
        let trans2 = new TestSql()
1✔
4735
            .addTableData('mastertransactions', 'Master Transactions!$A$1:$I30', 25000)
1✔
4736
            .enableColumnTitle(false)
1✔
4737
            .addBindNamedRangeParameter('startIncomeDate')
1✔
4738
            .addBindNamedRangeParameter('endIncomeDate')
1✔
4739
            .execute("select * " +
1✔
4740
                "from mastertransactions " +
1✔
4741
                "where transaction_date >=  ?1 and transaction_date <= ?2 ");
1✔
4742

1✔
4743
        //  Load from long term cache.
1✔
4744
        let trans3 = new TestSql()
1✔
4745
            .addTableData('mastertransactions', 'Master Transactions!$A$1:$I30', 25000)
1✔
4746
            .enableColumnTitle(false)
1✔
4747
            .addBindNamedRangeParameter('startIncomeDate')
1✔
4748
            .addBindNamedRangeParameter('endIncomeDate')
1✔
4749
            .execute("select * " +
1✔
4750
                "from mastertransactions " +
1✔
4751
                "where transaction_date >=  ?1 and transaction_date <= ?2 ");
1✔
4752

1✔
4753
        //  Force the expiry times for all items in long term cache.
1✔
4754
        //  It does not remove items from cache, it just forces that check -
1✔
4755
        //  which would never happen in testing since the check timeout is 21,000 seconds.
1✔
4756
        TableData.forceLongCacheExpiryCheck();
1✔
4757
        let trans4 = new TestSql()
1✔
4758
            .addTableData('mastertransactions', 'Master Transactions!$A$1:$I30', 25000)
1✔
4759
            .enableColumnTitle(false)
1✔
4760
            .addBindNamedRangeParameter('startIncomeDate')
1✔
4761
            .addBindNamedRangeParameter('endIncomeDate')
1✔
4762
            .execute("select * " +
1✔
4763
                "from mastertransactions " +
1✔
4764
                "where transaction_date >=  ?1 and transaction_date <= ?2 ");
1✔
4765

1✔
4766
        //  This test is not going to run long enough for long cache to be forceably 
1✔
4767
        //  expired, so we should make that long cache expire.
1✔
4768

1✔
4769
        return [itemData, trans, trans2, trans3, trans4];
1✔
4770
    }
1✔
4771

1✔
4772

1✔
4773
    selectBadTable1() {
1✔
4774
        let stmt = "SELECT quantity, price, quantity * price from booksail where price * quantity > 100";
1✔
4775

1✔
4776
        let testSQL = new TestSql()
1✔
4777
            .addTableData("booksales", this.bookSalesTable())
1✔
4778
            .addTableData("editors", this.editorsTable())
1✔
4779
            .enableColumnTitle(true);
1✔
4780

1✔
4781
        let ex = "";
1✔
4782
        try {
1✔
4783
            testSQL.execute(stmt);
1✔
4784
        }
1✔
4785
        catch (exceptionErr) {
1✔
4786
            ex = exceptionErr;
1✔
4787
        }
1✔
4788

1✔
4789
        return this.isFail("selectBadTable1", ex);
1✔
4790
    }
1✔
4791

1✔
4792
    selectBadMath1() {
1✔
4793
        let stmt = "SELECT quantity, price, quantity # price from booksales where price * quantity > 100";
1✔
4794

1✔
4795
        let testSQL = new TestSql()
1✔
4796
            .addTableData("booksales", this.bookSalesTable())
1✔
4797
            .enableColumnTitle(true);
1✔
4798

1✔
4799
        let ex = "";
1✔
4800
        try {
1✔
4801
            testSQL.execute(stmt);
1✔
4802
        }
1✔
4803
        catch (exceptionErr) {
1✔
4804
            ex = exceptionErr;
1✔
4805
        }
1✔
4806

1✔
4807
        return this.isFail("selectBadMath1", ex);
1✔
4808
    }
1✔
4809

1✔
4810
    selectBadField1() {
1✔
4811
        let stmt = "SELECT quantity, prices from booksales ";
1✔
4812

1✔
4813
        let testSQL = new TestSql()
1✔
4814
            .addTableData("booksales", this.bookSalesTable())
1✔
4815
            .enableColumnTitle(true);
1✔
4816

1✔
4817
        let ex = "";
1✔
4818
        try {
1✔
4819
            testSQL.execute(stmt);
1✔
4820
        }
1✔
4821
        catch (exceptionErr) {
1✔
4822
            ex = exceptionErr;
1✔
4823
        }
1✔
4824

1✔
4825
        return this.isFail("selectBadField1", ex);
1✔
4826
    }
1✔
4827

1✔
4828
    selectBadField1a() {
1✔
4829
        //  A SELECT you would encounter in the sub-query of a correlated lookup.
1✔
4830
        let stmt = "select count(*) from booksales where books.id = booksales.book_id";
1✔
4831

1✔
4832
        let testSQL = new TestSql()
1✔
4833
            .addTableData("booksales", this.bookSalesTable())
1✔
4834
            .enableColumnTitle(true);
1✔
4835

1✔
4836
        let ex = "";
1✔
4837
        try {
1✔
4838
            testSQL.execute(stmt);
1✔
4839
        }
1✔
4840
        catch (exceptionErr) {
1✔
4841
            ex = exceptionErr;
1✔
4842
        }
1✔
4843

1✔
4844
        return this.isFail("selectBadField1a", ex);
1✔
4845
    }
1✔
4846

1✔
4847
    selectBadField2() {
1✔
4848
        let stmt = "SELECT sum(quantitys) from booksales ";
1✔
4849

1✔
4850
        let testSQL = new TestSql()
1✔
4851
            .addTableData("booksales", this.bookSalesTable())
1✔
4852
            .enableColumnTitle(true);
1✔
4853

1✔
4854
        let ex = "";
1✔
4855
        try {
1✔
4856
            testSQL.execute(stmt);
1✔
4857
        }
1✔
4858
        catch (exceptionErr) {
1✔
4859
            ex = exceptionErr;
1✔
4860
        }
1✔
4861

1✔
4862
        return this.isFail("selectBadField2", ex);
1✔
4863
    }
1✔
4864

1✔
4865
    selectBadField3() {
1✔
4866
        let stmt = "SELECT  quantity, Sumthing(price) from booksales ";
1✔
4867

1✔
4868
        let testSQL = new TestSql()
1✔
4869
            .addTableData("booksales", this.bookSalesTable())
1✔
4870
            .enableColumnTitle(true);
1✔
4871

1✔
4872
        let ex = "";
1✔
4873
        try {
1✔
4874
            testSQL.execute(stmt);
1✔
4875
        }
1✔
4876
        catch (exceptionErr) {
1✔
4877
            ex = exceptionErr;
1✔
4878
        }
1✔
4879

1✔
4880
        return this.isFail("selectBadField3", ex);
1✔
4881
    }
1✔
4882

1✔
4883
    selectBadField4() {
1✔
4884
        let stmt = "SELECT invoice, SUMM(quantity) from booksales group by invoice";
1✔
4885

1✔
4886
        let testSQL = new TestSql()
1✔
4887
            .addTableData("booksales", this.bookSalesTable())
1✔
4888
            .enableColumnTitle(true);
1✔
4889

1✔
4890
        let ex = "";
1✔
4891
        try {
1✔
4892
            testSQL.execute(stmt);
1✔
4893
        }
1✔
4894
        catch (exceptionErr) {
1✔
4895
            ex = exceptionErr;
1✔
4896
        }
1✔
4897

1✔
4898
        return this.isFail("selectBadField4", ex);
1✔
4899
    }
1✔
4900

1✔
4901
    selectBadField5() {
1✔
4902
        let stmt = "SELECT from booksales group by invoice";
1✔
4903

1✔
4904
        let testSQL = new TestSql()
1✔
4905
            .addTableData("booksales", this.bookSalesTable())
1✔
4906
            .enableColumnTitle(true);
1✔
4907

1✔
4908
        let ex = "";
1✔
4909
        try {
1✔
4910
            testSQL.execute(stmt);
1✔
4911
        }
1✔
4912
        catch (exceptionErr) {
1✔
4913
            ex = exceptionErr;
1✔
4914
        }
1✔
4915

1✔
4916
        return this.isFail("selectBadField5", ex);
1✔
4917
    }
1✔
4918

1✔
4919
    selectBadField6() {
1✔
4920
        let stmt = "SELECT invoice date from booksales";
1✔
4921

1✔
4922
        let testSQL = new TestSql()
1✔
4923
            .addTableData("booksales", this.bookSalesTable())
1✔
4924
            .enableColumnTitle(true);
1✔
4925

1✔
4926
        let ex = "";
1✔
4927
        try {
1✔
4928
            testSQL.execute(stmt);
1✔
4929
        }
1✔
4930
        catch (exceptionErr) {
1✔
4931
            ex = exceptionErr;
1✔
4932
        }
1✔
4933

1✔
4934
        return this.isFail("selectBadField6", ex);
1✔
4935
    }
1✔
4936

1✔
4937
    selectBadOp1() {
1✔
4938
        let stmt = "SELECT  quantity, Sum(price) from booksales where price >>! 0 ";
1✔
4939

1✔
4940
        let testSQL = new TestSql()
1✔
4941
            .addTableData("booksales", this.bookSalesTable())
1✔
4942
            .enableColumnTitle(true);
1✔
4943

1✔
4944
        let ex = "";
1✔
4945
        try {
1✔
4946
            testSQL.execute(stmt);
1✔
4947
        }
1✔
4948
        catch (exceptionErr) {
1✔
4949
            ex = exceptionErr;
1✔
4950
        }
1✔
4951

1✔
4952
        return this.isFail("selectBadOp1", ex);
1✔
4953
    }
1✔
4954

1✔
4955
    selectBadAs1() {
1✔
4956
        let stmt = "SELECT  quantity, price ASE PrIcE from booksales ";
1✔
4957

1✔
4958
        let testSQL = new TestSql()
1✔
4959
            .addTableData("booksales", this.bookSalesTable())
1✔
4960
            .enableColumnTitle(true);
1✔
4961

1✔
4962
        let ex = "";
1✔
4963
        try {
1✔
4964
            testSQL.execute(stmt);
1✔
4965
        }
1✔
4966
        catch (exceptionErr) {
1✔
4967
            ex = exceptionErr;
1✔
4968
        }
1✔
4969

1✔
4970
        return this.isFail("selectBadAs1", ex);
1✔
4971
    }
1✔
4972

1✔
4973
    selectBadConstant1() {
1✔
4974
        let stmt = "SELECT  quantity, price AS PrIcE from booksales where invoice = 'I7200 ";
1✔
4975

1✔
4976
        let testSQL = new TestSql()
1✔
4977
            .addTableData("booksales", this.bookSalesTable())
1✔
4978
            .enableColumnTitle(true);
1✔
4979

1✔
4980
        let ex = "";
1✔
4981
        try {
1✔
4982
            testSQL.execute(stmt);
1✔
4983
        }
1✔
4984
        catch (exceptionErr) {
1✔
4985
            ex = exceptionErr;
1✔
4986
        }
1✔
4987

1✔
4988
        return this.isFail("selectBadConstant1", ex);
1✔
4989
    }
1✔
4990

1✔
4991
    selectBadConstant2() {
1✔
4992
        let stmt = "SELECT  quantity, price AS PrIcE from booksales where price > 1O0 ";
1✔
4993

1✔
4994
        let testSQL = new TestSql()
1✔
4995
            .addTableData("booksales", this.bookSalesTable())
1✔
4996
            .enableColumnTitle(true);
1✔
4997

1✔
4998
        let ex = "";
1✔
4999
        try {
1✔
5000
            testSQL.execute(stmt);
1✔
5001
        }
1✔
5002
        catch (exceptionErr) {
1✔
5003
            ex = exceptionErr;
1✔
5004
        }
1✔
5005

1✔
5006
        return this.isFail("selectBadConstant2", ex);
1✔
5007
    }
1✔
5008

1✔
5009
    nonSelect1() {
1✔
5010
        let stmt = "delete from booksales where price > 1O0 ";
1✔
5011

1✔
5012
        let testSQL = new TestSql()
1✔
5013
            .addTableData("booksales", this.bookSalesTable())
1✔
5014
            .enableColumnTitle(true);
1✔
5015

1✔
5016
        let ex = "";
1✔
5017
        try {
1✔
5018
            testSQL.execute(stmt);
1✔
5019
        }
1✔
5020
        catch (exceptionErr) {
1✔
5021
            ex = exceptionErr;
1✔
5022
        }
1✔
5023

1✔
5024
        return this.isFail("nonSelect1", ex);
1✔
5025
    }
1✔
5026

1✔
5027
    badJoin1() {
1✔
5028
        let stmt = "SELECT books.id, books.title, authors.first_name, authors.last_name " +
1✔
5029
            "FROM books " +
1✔
5030
            "INNER JOIN authors " +
1✔
5031
            "ON books.author_id = authors.di " +
1✔
5032
            "ORDER BY books.id";
1✔
5033

1✔
5034
        let testSQL = new TestSql()
1✔
5035
            .addTableData("books", this.bookTable())
1✔
5036
            .addTableData("authors", this.authorsTable())
1✔
5037
            .enableColumnTitle(true);
1✔
5038

1✔
5039
        let ex = "";
1✔
5040
        try {
1✔
5041
            testSQL.execute(stmt);
1✔
5042
        }
1✔
5043
        catch (exceptionErr) {
1✔
5044
            ex = exceptionErr;
1✔
5045
        }
1✔
5046

1✔
5047
        return this.isFail("badJoin1", ex);
1✔
5048
    }
1✔
5049

1✔
5050
    badJoin2() {
1✔
5051
        let stmt = "SELECT books.id, books.title, authors.first_name, authors.last_name " +
1✔
5052
            "FROM books " +
1✔
5053
            "INNER JOIN authors " +
1✔
5054
            "ON books.author_di = authors.id " +
1✔
5055
            "ORDER BY books.id";
1✔
5056

1✔
5057
        let testSQL = new TestSql()
1✔
5058
            .addTableData("books", this.bookTable())
1✔
5059
            .addTableData("authors", this.authorsTable())
1✔
5060
            .enableColumnTitle(true);
1✔
5061

1✔
5062
        let ex = "";
1✔
5063
        try {
1✔
5064
            testSQL.execute(stmt);
1✔
5065
        }
1✔
5066
        catch (exceptionErr) {
1✔
5067
            ex = exceptionErr;
1✔
5068
        }
1✔
5069

1✔
5070
        return this.isFail("badJoin2", ex);
1✔
5071
    }
1✔
5072

1✔
5073
    badJoin3() {
1✔
5074
        let stmt = "SELECT books.id, books.title, authors.first_name, authors.last_name " +
1✔
5075
            "FROM books " +
1✔
5076
            "INNER JOIN on authors " +
1✔
5077
            "books.author_id = authors.id " +
1✔
5078
            "ORDER BY books.id";
1✔
5079

1✔
5080
        let testSQL = new TestSql()
1✔
5081
            .addTableData("books", this.bookTable())
1✔
5082
            .addTableData("authors", this.authorsTable())
1✔
5083
            .enableColumnTitle(true);
1✔
5084

1✔
5085
        let ex = "";
1✔
5086
        try {
1✔
5087
            testSQL.execute(stmt);
1✔
5088
        }
1✔
5089
        catch (exceptionErr) {
1✔
5090
            ex = exceptionErr;
1✔
5091
        }
1✔
5092

1✔
5093
        return this.isFail("badJoin3", ex);
1✔
5094
    }
1✔
5095

1✔
5096

1✔
5097
    badJoin4() {
1✔
5098
        let stmt = "select invoice, name from booksales inner join customers on substr(booksales.nonExistingColumn, 2, 1) = substr(customers.id, 2, 1)";
1✔
5099

1✔
5100
        let testSQL = new TestSql()
1✔
5101
            .addTableData("books", this.bookTable())
1✔
5102
            .addTableData("authors", this.authorsTable())
1✔
5103
            .enableColumnTitle(true);
1✔
5104

1✔
5105
        let ex = "";
1✔
5106
        try {
1✔
5107
            testSQL.execute(stmt);
1✔
5108
        }
1✔
5109
        catch (exceptionErr) {
1✔
5110
            ex = exceptionErr;
1✔
5111
        }
1✔
5112

1✔
5113
        return this.isFail("badJoin4", ex);
1✔
5114
    }
1✔
5115

1✔
5116
    badJoin5() {
1✔
5117
        let stmt = "select invoice, name, title from customers inner join booksales on 'BB' + substr(booksales.customer_id, 2, 1) = 'BB' + substr(customers.id, 2, 1) join books on 'CC' + books.badColumnName = 'CC' + booksales.book_id";
1✔
5118

1✔
5119
        let testSQL = new TestSql()
1✔
5120
            .addTableData("books", this.bookTable())
1✔
5121
            .addTableData("booksales", this.bookSalesTable())
1✔
5122
            .addTableData("customers", this.customerTable())
1✔
5123
            .enableColumnTitle(true);
1✔
5124

1✔
5125
        let ex = "";
1✔
5126
        try {
1✔
5127
            testSQL.execute(stmt);
1✔
5128
        }
1✔
5129
        catch (exceptionErr) {
1✔
5130
            ex = exceptionErr;
1✔
5131
        }
1✔
5132

1✔
5133
        return this.isFail("badJoin5", ex);
1✔
5134
    }
1✔
5135

1✔
5136
    badOrderBy1() {
1✔
5137
        let stmt = "select * from bookSales order by DATE DSC, customer_id asc";
1✔
5138

1✔
5139
        let testSQL = new TestSql()
1✔
5140
            .addTableData("bookSales", this.bookSalesTable())
1✔
5141
            .enableColumnTitle(true);
1✔
5142

1✔
5143
        let ex = "";
1✔
5144
        try {
1✔
5145
            testSQL.execute(stmt);
1✔
5146
        }
1✔
5147
        catch (exceptionErr) {
1✔
5148
            ex = exceptionErr;
1✔
5149
        }
1✔
5150

1✔
5151
        return this.isFail("badOrderBy1", ex);
1✔
5152

1✔
5153
    }
1✔
5154

1✔
5155
    badOrderBy2() {
1✔
5156
        let stmt = "select * from bookSales order by ORDER_DATE";
1✔
5157

1✔
5158
        let testSQL = new TestSql()
1✔
5159
            .addTableData("bookSales", this.bookSalesTable())
1✔
5160
            .enableColumnTitle(true);
1✔
5161

1✔
5162
        let ex = "";
1✔
5163
        try {
1✔
5164
            testSQL.execute(stmt);
1✔
5165
        }
1✔
5166
        catch (exceptionErr) {
1✔
5167
            ex = exceptionErr;
1✔
5168
        }
1✔
5169

1✔
5170
        return this.isFail("badOrderBy2", ex);
1✔
5171

1✔
5172
    }
1✔
5173

1✔
5174
    badOrderBy3() {
1✔
5175
        let stmt = "select * from bookSales order invoice";
1✔
5176

1✔
5177
        let testSQL = new TestSql()
1✔
5178
            .addTableData("bookSales", this.bookSalesTable())
1✔
5179
            .enableColumnTitle(true);
1✔
5180

1✔
5181
        let ex = "";
1✔
5182
        try {
1✔
5183
            testSQL.execute(stmt);
1✔
5184
        }
1✔
5185
        catch (exceptionErr) {
1✔
5186
            ex = exceptionErr;
1✔
5187
        }
1✔
5188

1✔
5189
        return this.isFail("badOrderBy3", ex);
1✔
5190

1✔
5191
    }
1✔
5192

1✔
5193
    badGroupBy1() {
1✔
5194
        let stmt = "select date from bookSales group date";
1✔
5195

1✔
5196
        let testSQL = new TestSql()
1✔
5197
            .addTableData("bookSales", this.bookSalesTable())
1✔
5198
            .enableColumnTitle(true);
1✔
5199

1✔
5200
        let ex = "";
1✔
5201
        try {
1✔
5202
            testSQL.execute(stmt);
1✔
5203
        }
1✔
5204
        catch (exceptionErr) {
1✔
5205
            ex = exceptionErr;
1✔
5206
        }
1✔
5207

1✔
5208
        return this.isFail("badGroupBy1", ex);
1✔
5209

1✔
5210
    }
1✔
5211

1✔
5212
    selectBadGroupByField() {
1✔
5213
        let stmt = "SELECT invoice, count(*) from booksales group by invoice_id";
1✔
5214

1✔
5215
        let testSQL = new TestSql()
1✔
5216
            .addTableData("booksales", this.bookSalesTable())
1✔
5217
            .enableColumnTitle(true);
1✔
5218

1✔
5219
        let ex = "";
1✔
5220
        try {
1✔
5221
            testSQL.execute(stmt);
1✔
5222
        }
1✔
5223
        catch (exceptionErr) {
1✔
5224
            ex = exceptionErr;
1✔
5225
        }
1✔
5226

1✔
5227
        return this.isFail("selectBadGroupByField", ex);
1✔
5228
    }
1✔
5229

1✔
5230

1✔
5231
    bindVariableMissing() {
1✔
5232
        let stmt = "select * from bookSales where date > ?1 AND date < ?2 OR book_id = ?3";
1✔
5233

1✔
5234
        let testSQL = new TestSql()
1✔
5235
            .addTableData("bookSales", this.bookSalesTable())
1✔
5236
            .enableColumnTitle(true)
1✔
5237
            .addBindParameter('05/01/2022')
1✔
5238
            .addBindParameter('05/04/2022')
1✔
5239

1✔
5240
        let ex = "";
1✔
5241
        try {
1✔
5242
            testSQL.execute(stmt);
1✔
5243
        }
1✔
5244
        catch (exceptionErr) {
1✔
5245
            ex = exceptionErr;
1✔
5246
        }
1✔
5247

1✔
5248
        return this.isFail("bindVariableMissing", ex);
1✔
5249
    }
1✔
5250

1✔
5251
    bindVariableMissing1() {
1✔
5252
        let stmt = "select * from bookSales where date > ? AND date < ?";
1✔
5253

1✔
5254
        let testSQL = new TestSql()
1✔
5255
            .addTableData("bookSales", this.bookSalesTable())
1✔
5256
            .enableColumnTitle(true)
1✔
5257
            .addBindParameter('05/01/2022')
1✔
5258
            .addBindParameter('05/04/2022')
1✔
5259

1✔
5260
        let ex = "";
1✔
5261
        try {
1✔
5262
            testSQL.execute(stmt);
1✔
5263
        }
1✔
5264
        catch (exceptionErr) {
1✔
5265
            ex = exceptionErr;
1✔
5266
        }
1✔
5267

1✔
5268
        return this.isFail("bindVariableMissing1", ex);
1✔
5269
    }
1✔
5270

1✔
5271
    selectNoFrom() {
1✔
5272
        let stmt = "SELECT quantity, prices for booksales ";
1✔
5273

1✔
5274
        let testSQL = new TestSql()
1✔
5275
            .addTableData("booksales", this.bookSalesTable())
1✔
5276
            .enableColumnTitle(true);
1✔
5277

1✔
5278
        let ex = "";
1✔
5279
        try {
1✔
5280
            testSQL.execute(stmt);
1✔
5281
        }
1✔
5282
        catch (exceptionErr) {
1✔
5283
            ex = exceptionErr;
1✔
5284
        }
1✔
5285

1✔
5286
        return this.isFail("selectNoFrom", ex);
1✔
5287
    }
1✔
5288

1✔
5289
    selectNoTitles() {
1✔
5290
        let stmt = "SELECT quantity, prices from booksales ";
1✔
5291
        let dataTable = this.bookSalesTable();
1✔
5292
        dataTable.shift();
1✔
5293
        let ex = "";
1✔
5294

1✔
5295
        try {
1✔
5296
            let testSQL = new TestSql()
1✔
5297
                .addTableData("booksales", dataTable)
1✔
5298
                .enableColumnTitle(true);
1✔
5299

1✔
5300
            testSQL.execute(stmt);
1✔
5301
        }
1✔
5302
        catch (exceptionErr) {
1✔
5303
            ex = exceptionErr;
1✔
5304
        }
1✔
5305

1✔
5306
        return this.isFail("selectNoTitles", ex);
1✔
5307
    }
1✔
5308

1✔
5309

1✔
5310
    selectFromSubQueryNoAlias() {
1✔
5311
        let stmt = "select invoice from (select invoice from booksales where customer_id = 'C1')";
1✔
5312
        let ex = "";
1✔
5313

1✔
5314
        let testSQL = new TestSql()
1✔
5315
            .addTableData("booksales", this.bookSalesTable())
1✔
5316
            .enableColumnTitle(true);
1✔
5317

1✔
5318
        try {
1✔
5319
            testSQL.execute(stmt);
1✔
5320
        }
1✔
5321
        catch (exceptionErr) {
1✔
5322
            ex = exceptionErr;
1✔
5323
        }
1✔
5324

1✔
5325
        return this.isFail("selectFromSubQueryNoAlias", ex);
1✔
5326
    }
1✔
5327

1✔
5328
    badParseTableSettings1() {
1✔
5329
        let ex = "";
1✔
5330
        try {
1✔
5331
            GasSql.parseTableSettings([['authors', 'authorsNamedRange', true, 60, true], ['editors', 'editorsRange', 30], ['people']], "", false);
1✔
5332
        }
1✔
5333
        catch (exceptionErr) {
1✔
5334
            ex = exceptionErr;
1✔
5335
        }
1✔
5336

1✔
5337
        return this.isFail("badParseTableSettings1", ex);
1✔
5338
    }
1✔
5339

1✔
5340
    pivotGroupByMissing() {
1✔
5341
        let stmt = "select sum(quantity) from bookSales where date > ?1 AND date < ?2 OR book_id = ?3 pivot customer_id";
1✔
5342

1✔
5343
        let testSQL = new TestSql()
1✔
5344
            .addTableData("bookSales", this.bookSalesTable())
1✔
5345
            .enableColumnTitle(true)
1✔
5346
            .addBindParameter('05/01/2022')
1✔
5347
            .addBindParameter('05/04/2022')
1✔
5348

1✔
5349
        let ex = "";
1✔
5350
        try {
1✔
5351
            testSQL.execute(stmt);
1✔
5352
        }
1✔
5353
        catch (exceptionErr) {
1✔
5354
            ex = exceptionErr;
1✔
5355
        }
1✔
5356

1✔
5357
        return this.isFail("pivotGroupByMissing", ex);
1✔
5358
    }
1✔
5359

1✔
5360
    badUnion1() {
1✔
5361
        let stmt = "select * from authors UNION select * from customers";
1✔
5362

1✔
5363
        let testSQL = new TestSql()
1✔
5364
            .addTableData("authors", this.authorsTable())
1✔
5365
            .addTableData("customers", this.customerTable())
1✔
5366
            .enableColumnTitle(true);
1✔
5367

1✔
5368
        let ex = "";
1✔
5369
        try {
1✔
5370
            testSQL.execute(stmt);
1✔
5371
        }
1✔
5372
        catch (exceptionErr) {
1✔
5373
            ex = exceptionErr;
1✔
5374
        }
1✔
5375

1✔
5376
        return this.isFail("badUnion1", ex);
1✔
5377
    }
1✔
5378

1✔
5379
    badFieldNames1() {
1✔
5380
        let stmt = "select id from books where author_id is not null";
1✔
5381

1✔
5382
        let booksTable = this.bookTable();
1✔
5383
        booksTable.shift();
1✔
5384
        booksTable.unshift(["id", "title", "type", "author id", "author_id", "translator id"]);
1✔
5385

1✔
5386
        let ex = "";
1✔
5387
        try {
1✔
5388
            let testSQL = new TestSql()
1✔
5389
                .addTableData("books", booksTable)
1✔
5390
                .enableColumnTitle(true);
1✔
5391

1✔
5392
            testSQL.execute(stmt);
1✔
5393
        }
1✔
5394
        catch (exceptionErr) {
1✔
5395
            ex = exceptionErr;
1✔
5396
        }
1✔
5397

1✔
5398
        return this.isFail("badFieldNames1", ex);
1✔
5399
    }
1✔
5400

1✔
5401
    viewsToUpperCaseExceptQuoted() {
1✔
5402
        const data = SelectTables.toUpperCaseExceptQuoted("stuff(email, 2, 3, 'Cjd') + stuff(email, 2, 3, 'Dd')");
1✔
5403

1✔
5404
        return this.isEqual("viewsToUpperCaseExceptQuoted", data, "STUFF(EMAIL, 2, 3, 'Cjd') + STUFF(EMAIL, 2, 3, 'Dd')");
1✔
5405
    }
1✔
5406

1✔
5407
    columnLetterTest() {
1✔
5408
        let noColumnTitleData = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]];
1✔
5409
        const data = Table.addColumnLetters(noColumnTitleData);
1✔
5410

1✔
5411
        const expected = [["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB"],
1✔
5412
        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]];
1✔
5413

1✔
5414
        return this.isEqual("columnLetterTest", data, expected);
1✔
5415
    }
1✔
5416

1✔
5417
    isFail(functionName, exceptionErr) {
1✔
5418
        if (exceptionErr != "") {
33✔
5419
            Logger.log(functionName + "  Captured Error:  " + exceptionErr)
33✔
5420
            Logger.log(functionName + "() ***   S U C C E S S   ***");
33✔
5421
            return true;
33✔
5422
        }
33✔
5423
        else {
×
5424
            Logger.log(functionName + "() ***   F A I L E D   ***");
×
5425
            Logger.log("Exception was expected !!");
×
5426
            return false;
×
5427
        }
×
5428
    }
33✔
5429

1✔
5430
    isEqual(functionName, sqlDataArray, expectedArry) {
1✔
5431
        let isEqualTest = false;
199✔
5432
        let jsonData = JSON.stringify(sqlDataArray);
199✔
5433
        let expectedJSON = JSON.stringify(expectedArry);
199✔
5434

199✔
5435
        let isEqual = jsonData == expectedJSON;
199✔
5436

199✔
5437
        if (!isEqual) {
199!
5438
            //  May have "10" != 10 and fail.  We should not fail in that case.
×
5439
            //isEqual = sqlDataArray.toString() === expectedArry.toString();
×
5440
            Logger.log("JSON comp failed. toString(): " + sqlDataArray.toString() + " === " + expectedArry.toString());
×
5441
        }
×
5442

199✔
5443
        if (!isEqual) {
199!
5444
            Logger.log(functionName + "() ----------   F A I L E D   ----------");
×
5445
            Logger.log(jsonData);
×
5446

×
5447
            for (let i = 0; i < jsonData.length; i++) {
×
5448
                if (i >= jsonData.length)
×
5449
                    break;
×
5450
                if (jsonData.charAt(i) !== expectedJSON.charAt(i)) {
×
5451
                    Logger.log("Pos=" + i + ".  DIFF=" + jsonData.substring(i, i + 20) + " != " + expectedJSON.substring(i, i + 20));
×
5452
                    break;
×
5453
                }
×
5454
            }
×
5455
        }
×
5456
        else {
199✔
5457
            Logger.log(functionName + "() ***   S U C C E S S   ***");
199✔
5458
            isEqualTest = true;
199✔
5459
        }
199✔
5460

199✔
5461
        return isEqualTest;
199✔
5462
    }
199✔
5463
}
1✔
5464

1✔
5465
/*  *** DEBUG START ***
1✔
5466
//  Remove comments for testing in NODE
1✔
5467
testerSql();
1✔
5468
//  *** DEBUG END ***/
1✔
5469

1✔
5470
function testerSql() {
1✔
5471
    let result = true;
1✔
5472
    let tester = new SqlTester();
1✔
5473

1✔
5474
    result = result && tester.selectAll1();
1✔
5475
    result = result && tester.selectAllCase1();
1✔
5476
    result = result && tester.selectIsNotNull1();
1✔
5477
    result = result && tester.selectAllAuthorsToObject();
1✔
5478
    result = result && tester.selectAnAuthorsToObject();
1✔
5479
    result = result && tester.selectIsNull1();
1✔
5480
    result = result && tester.innerJoin1a();
1✔
5481
    result = result && tester.innerJoin1case();
1✔
5482
    result = result && tester.innerJoin2();
1✔
5483
    result = result && tester.innerJoin2ToObject();
1✔
5484
    result = result && tester.innerJoinAlias1();
1✔
5485
    result = result && tester.innerJoinAlias2();
1✔
5486
    result = result && tester.join2a();
1✔
5487
    result = result && tester.join2b();
1✔
5488
    result = result && tester.join3();
1✔
5489
    result = result && tester.joinLimit1();
1✔
5490
    result = result && tester.leftJoin1();
1✔
5491
    result = result && tester.rightJoin1();
1✔
5492
    result = result && tester.rightJoin1a();
1✔
5493
    result = result && tester.rightJoin2();
1✔
5494
    result = result && tester.fullJoin1();
1✔
5495
    result = result && tester.fullJoin2();
1✔
5496
    result = result && tester.fullJoin3();
1✔
5497
    result = result && tester.whereIn1();
1✔
5498
    result = result && tester.whereIn2();
1✔
5499
    result = result && tester.whereIn3();
1✔
5500
    result = result && tester.whereIn4();
1✔
5501
    result = result && tester.whereIn5();
1✔
5502
    result = result && tester.whereIn6();
1✔
5503
    result = result && tester.whereIn7();
1✔
5504
    result = result && tester.whereNotIn1();
1✔
5505
    result = result && tester.whereNotIn2();
1✔
5506
    result = result && tester.whereNotIn3();
1✔
5507
    result = result && tester.whereNotIn4();
1✔
5508
    result = result && tester.whereAndOr1();
1✔
5509
    result = result && tester.whereAndOr2();
1✔
5510
    result = result && tester.whereAndOr3();
1✔
5511
    result = result && tester.whereAndNotEqual2();
1✔
5512
    result = result && tester.whereAndNotEqual3();
1✔
5513
    result = result && tester.groupBy1();
1✔
5514
    result = result && tester.selectAgainNewBinds1();
1✔
5515
    result = result && tester.groupBy2();
1✔
5516
    result = result && tester.groupBy3();
1✔
5517
    result = result && tester.groupBy4();
1✔
5518
    result = result && tester.avgSelect1();
1✔
5519
    result = result && tester.funcsSelect2();
1✔
5520
    result = result && tester.innerSelect1();
1✔
5521
    result = result && tester.whereLike1();
1✔
5522
    result = result && tester.whereLike2();
1✔
5523
    result = result && tester.whereNotLike1();
1✔
5524
    result = result && tester.union1();
1✔
5525
    result = result && tester.unionAlias1();
1✔
5526
    result = result && tester.unionBind1();
1✔
5527
    result = result && tester.unionAll1();
1✔
5528
    result = result && tester.unionAll2();
1✔
5529
    result = result && tester.unionJoin1();
1✔
5530
    result = result && tester.except1();
1✔
5531
    result = result && tester.intersect1();
1✔
5532
    result = result && tester.orderByDesc1();
1✔
5533
    result = result && tester.orderByDesc2();
1✔
5534
    result = result && tester.orderByDesc3();
1✔
5535
    result = result && tester.distinct1();
1✔
5536
    result = result && tester.selectMath1();
1✔
5537
    result = result && tester.selectMathFunc1();
1✔
5538
    result = result && tester.selectMathFunc2();
1✔
5539
    result = result && tester.selectFuncs2();
1✔
5540
    result = result && tester.selectFuncs3();
1✔
5541
    result = result && tester.selectFuncs4();
1✔
5542
    result = result && tester.selectFuncs5();
1✔
5543
    result = result && tester.selectFuncs6();
1✔
5544
    result = result && tester.selectFuncs7();
1✔
5545
    result = result && tester.selectFuncInFunc1();
1✔
5546
    result = result && tester.selectFuncInFunc2();
1✔
5547
    result = result && tester.selectIF1();
1✔
5548
    result = result && tester.selectIF2();
1✔
5549
    result = result && tester.selectIF3();
1✔
5550
    result = result && tester.selectIF4();
1✔
5551
    result = result && tester.selectWhereCalc1();
1✔
5552
    result = result && tester.selectWhereCalc2();
1✔
5553
    result = result && tester.selectCase1();
1✔
5554
    result = result && tester.selectCase2();
1✔
5555
    result = result && tester.selectAlias1();
1✔
5556
    result = result && tester.groupPivot1();
1✔
5557
    result = result && tester.groupPivot2();
1✔
5558
    result = result && tester.groupPivot3();
1✔
5559
    result = result && tester.groupFunc1();
1✔
5560
    result = result && tester.groupFunc2();
1✔
5561
    result = result && tester.selectInGroupByPivot1();
1✔
5562
    result = result && tester.selectInGroupByPivot2();
1✔
5563
    result = result && tester.selectInGroupByPivot3();
1✔
5564
    result = result && tester.selectCount1();
1✔
5565
    result = result && tester.selectCount2();
1✔
5566
    result = result && tester.selectCount3();
1✔
5567
    result = result && tester.selectCount4();
1✔
5568
    result = result && tester.selectCount5();
1✔
5569
    result = result && tester.selectCount6();
1✔
5570
    result = result && tester.selectGroupByNotInSelect();
1✔
5571
    result = result && tester.selectGroupByNotInSelect2();
1✔
5572
    result = result && tester.selectOrderByNotInSelect();
1✔
5573
    result = result && tester.selectCoalesce();
1✔
5574
    result = result && tester.selectConcat_Ws();
1✔
5575
    result = result && tester.selectConcat_Ws2();
1✔
5576
    result = result && tester.selectNoTitle1();
1✔
5577
    result = result && tester.selectNested();
1✔
5578
    result = result && tester.selectNested2();
1✔
5579
    result = result && tester.selectCorrelatedSubQuery1();
1✔
5580
    result = result && tester.selectCorrelatedSubQuery2();
1✔
5581
    result = result && tester.selectCorrelatedSubQuery3();
1✔
5582
    result = result && tester.selectCorrelatedSubQuery4();
1✔
5583
    result = result && tester.selectCorrelatedSubQuery5();
1✔
5584
    result = result && tester.selectCorrelatedSubQuery6();
1✔
5585
    result = result && tester.selectCorrelatedSubQuery7();
1✔
5586
    result = result && tester.selectCorrelatedSubQuery8();
1✔
5587
    result = result && tester.selectCorrelatedSubQuery9();
1✔
5588
    result = result && tester.selectCorrelatedSubQuery10();
1✔
5589
    result = result && tester.selectCorrelatedSubQuery11();
1✔
5590
    result = result && tester.selectFromSubQuery1();
1✔
5591
    result = result && tester.selectFromSubQuery2();
1✔
5592
    result = result && tester.selectFromSubQuery3();
1✔
5593
    result = result && tester.selectFromSubQuery4();
1✔
5594
    result = result && tester.selectFromSubQuery5();
1✔
5595
    result = result && tester.selectFromSubQuery6();
1✔
5596
    result = result && tester.selectFromSubQuery7();
1✔
5597
    result = result && tester.selectConvertFunction();
1✔
5598
    result = result && tester.selectJoinMultipleConditions();
1✔
5599
    result = result && tester.selectJoinOnExpression1();
1✔
5600
    result = result && tester.selectJoinMultipleConditions2();
1✔
5601
    result = result && tester.selectJoinOnExpression2();
1✔
5602
    result = result && tester.selectJoinOnExpression3();
1✔
5603
    result = result && tester.selectJoinLeftRightSwitchedInCondition();
1✔
5604
    result = result && tester.selectJoinMultipleConditions3();
1✔
5605
    result = result && tester.selectSingleQuoteDataWithCalculation();
1✔
5606
    result = result && tester.selectWithBadDate();
1✔
5607
    result = result && tester.selectWhereBadDate();
1✔
5608
    result = result && tester.selectGroupByCalculatedField();
1✔
5609
    result = result && tester.selectGroupByCalculatedFieldNotInSelectFieldList();
1✔
5610
    result = result && tester.selectGroupByCalculatedField2();
1✔
5611
    result = result && tester.selectOrderByCalculated();
1✔
5612
    result = result && tester.selectOrderByCalculated2();
1✔
5613
    //  This test causes problems on gsSqlTest sheet (too big)
1✔
5614
    // result = result && tester.joinBigTables1();
1✔
5615
    result = result && tester.removeTrailingEmptyRecords();
1✔
5616
    result = result && tester.selectWhereLike3();
1✔
5617
    result = result && tester.selectWhereLike4();
1✔
5618
    result = result && tester.selectFromSubQuery8();
1✔
5619
    result = result && tester.selectFromSubQuery9();
1✔
5620
    result = result && tester.selectConcat1();
1✔
5621
    result = result && tester.selectBadHavingButStillWork();
1✔
5622
    // result = result && tester.selectDateDiff();      // Test fails after 8pm local time.
1✔
5623
    result = result && tester.selectDateDiff2();
1✔
5624
    result = result && tester.selectNotLikeInMiddle1();
1✔
5625
    result = result && tester.selectGroupConcat();
1✔
5626
    result = result && tester.selectGroupConcat2();
1✔
5627
    result = result && tester.unionAll3();
1✔
5628
    result = result && tester.unionAll4();
1✔
5629
    result = result && tester.groupBy5();
1✔
5630
    result = result && tester.selectBetween1();
1✔
5631
    result = result && tester.selectNotBetween1();
1✔
5632
    result = result && tester.selectNotBetweenAndIN();
1✔
5633
    result = result && tester.selectBetweenFromFunction();
1✔
5634
    result = result && tester.selectCountWithNullOnJoin();
1✔
5635
    result = result && tester.selectCalculatedFieldWitinGroupBY();
1✔
5636
    result = result && tester.selectJoinCaseInSensitiveCondition();
1✔
5637
    result = result && tester.selectCaseInSensitiveCondition();
1✔
5638
    result = result && tester.concatWsWithDayFunction();
1✔
5639
    result = result && tester.selectAddDateLastDay();
1✔
5640
    result = result && tester.selectCalculatedFieldNotInSelectFieldsWitinGroupBY();
1✔
5641
    result = result && tester.selectLocate();
1✔
5642
    result = result && tester.innerSelectWithComments();
1✔
5643
    result = result && tester.JoinTableNotEqualCondition();
1✔
5644
    result = result && tester.JoinTableNotEqualCalcCondition();
1✔
5645
    result = result && tester.SelectTableSelfJoin();
1✔
5646
    //  Not supported (yet)
1✔
5647
    // result = result && tester.selectSumMinusSum();
1✔
5648

1✔
5649
    Logger.log("============================================================================");
1✔
5650

1✔
5651
    result = result && tester.selectBadTable1();
1✔
5652
    result = result && tester.selectBadMath1();
1✔
5653
    result = result && tester.selectBadField1();
1✔
5654
    result = result && tester.selectBadField1a();
1✔
5655
    result = result && tester.selectBadField2();
1✔
5656
    result = result && tester.selectBadField3();
1✔
5657
    result = result && tester.selectBadField4();
1✔
5658
    result = result && tester.selectBadField5();
1✔
5659
    result = result && tester.selectBadField6();
1✔
5660
    result = result && tester.selectBadOp1();
1✔
5661
    result = result && tester.selectBadAs1();
1✔
5662
    result = result && tester.selectBadConstant1();
1✔
5663
    result = result && tester.selectBadConstant2();
1✔
5664
    result = result && tester.nonSelect1();
1✔
5665
    result = result && tester.badJoin1();
1✔
5666
    result = result && tester.badJoin2();
1✔
5667
    result = result && tester.badJoin3();
1✔
5668
    result = result && tester.badJoin4();
1✔
5669
    result = result && tester.badJoin5();
1✔
5670
    result = result && tester.badOrderBy1();
1✔
5671
    result = result && tester.badOrderBy2();
1✔
5672
    result = result && tester.badOrderBy3();
1✔
5673
    result = result && tester.badGroupBy1();
1✔
5674
    result = result && tester.selectBadGroupByField();
1✔
5675
    result = result && tester.bindVariableMissing();
1✔
5676
    result = result && tester.bindVariableMissing1();
1✔
5677
    result = result && tester.selectNoFrom();
1✔
5678
    result = result && tester.selectNoTitles();
1✔
5679
    result = result && tester.selectFromSubQueryNoAlias();
1✔
5680
    result = result && tester.pivotGroupByMissing();
1✔
5681
    result = result && tester.badUnion1();
1✔
5682
    result = result && tester.badFieldNames1();
1✔
5683

1✔
5684
    //  Sql.js unit tests.
1✔
5685
    result = result && tester.parseTableSettings1();
1✔
5686
    result = result && tester.parseTableSettings2();
1✔
5687
    result = result && tester.parseTableSettings3();
1✔
5688
    result = result && tester.parseTableSettings4();
1✔
5689
    result = result && tester.parseTableSettings5();
1✔
5690
    result = result && tester.parseTableSettings6();
1✔
5691
    result = result && tester.parseTableSettings7();
1✔
5692
    result = result && tester.parseTableSettings8();
1✔
5693
    result = result && tester.parseTableSettings9();
1✔
5694
    result = result && tester.parseTableSettings10();
1✔
5695
    result = result && tester.parseTableSettings11();
1✔
5696
    result = result && tester.parseTableSettings12();
1✔
5697
    result = result && tester.parseTableSettings13();
1✔
5698
    result = result && tester.parseTableSettings14();
1✔
5699
    result = result && tester.parseTableSettings15();
1✔
5700
    result = result && tester.parseTableSettings16();
1✔
5701

1✔
5702
    result = result && tester.testTableData1();
1✔
5703
    result = result && tester.testTableData2();
1✔
5704
    result = result && tester.badParseTableSettings1();
1✔
5705

1✔
5706
    result = result && tester.viewsToUpperCaseExceptQuoted();
1✔
5707
    result = result && tester.columnLetterTest();
1✔
5708

1✔
5709
    tester.isEqual("===  E N D   O F   T E S T S  ===", true, result);
1✔
5710

1✔
5711
    return result;
1✔
5712
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc