From 68d27665ddb6450de634856b42a7986c9ef7c97c Mon Sep 17 00:00:00 2001 From: lucioroadtoglory Date: Wed, 5 Oct 2022 10:32:37 -0300 Subject: [PATCH 1/7] feat: using backtick to call the function --- src/17alasql.js | 3 ++- test/test846.js | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 test/test846.js diff --git a/src/17alasql.js b/src/17alasql.js index 1331fd87cf..decb7c28bd 100755 --- a/src/17alasql.js +++ b/src/17alasql.js @@ -28,7 +28,8 @@ alasql.parser.parseError = function (str, hash) { } */ alasql.parse = function (sql) { - return alasqlparser.parse(alasql.utils.uncomment(sql)); + const command = Array.isArray(sql) ? sql[0] : sql; + return alasqlparser.parse(alasql.utils.uncomment(command)); }; /** diff --git a/test/test846.js b/test/test846.js new file mode 100644 index 0000000000..717219cb4e --- /dev/null +++ b/test/test846.js @@ -0,0 +1,15 @@ +if (typeof exports === 'object') { + var assert = require('assert'); + var alasql = require('..'); +} + +describe('Test 846', function () { + it('Create table with args', function (done) { + alasql`create database test846; use test846`; + alasql`DROP TABLE IF EXISTS schools`; + alasql`CREATE TABLE schools (schoolid INT, schoolname STRING)`; + assert.equal(alasql.databases.test846.tables.schools.columns.length, 2); + alasql`drop database test846`; + done(); + }); +}); From 4c55fd7ca2669d7fd1ff5ef312585888189f9519 Mon Sep 17 00:00:00 2001 From: lucioroadtoglory Date: Wed, 5 Oct 2022 10:35:52 -0300 Subject: [PATCH 2/7] feat: using backtick to call the function --- test/test238.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test238.json b/test/test238.json index 5bb1abba08..4dca1cc0b0 100644 --- a/test/test238.json +++ b/test/test238.json @@ -1 +1 @@ -[{"100": 100}] +[{"100":100}] \ No newline at end of file From 83cf55940bec8708c60d2059b73d374784b79afd Mon Sep 17 00:00:00 2001 From: lucioroadtoglory Date: Thu, 15 Dec 2022 15:10:51 -0300 Subject: [PATCH 3/7] feat: backtick call function --- src/10start.js | 28 +++++++++++++++++++++++++--- src/17alasql.js | 3 +-- test/test847.js | 21 +++++++++++++++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 test/test847.js diff --git a/src/10start.js b/src/10start.js index 2a7c2eb4a8..6eddf0e8ba 100644 --- a/src/10start.js +++ b/src/10start.js @@ -2,6 +2,25 @@ "use strict"; +const isBacktickQuery = (arg) => Array.isArray(arg.raw); + +const formatQueryParams = (params) => (queryStr, index) => { + const param = params[index + 1]; + return queryStr + (typeof param === 'undefined' ? '' : param); +}; + +const normalizeBacktickQuery = (args) => { + const stringFormatted = args[0] + .map(formatQueryParams(args)) + .join('') + // Remove breakline in case of characters in same line | optional + .replace(/[\r\n]/g, '') + .replace(/\s+/g, ' ') // Remove extras + .trim(); // Remove extras + console.log(stringFormatted); + return stringFormatted; +}; + /** @fileoverview AlaSQL JavaScript SQL library @see http://github.com/agershun/alasql @@ -57,8 +76,11 @@ alasql().From(data).Where(function(x){return x.a == 10}).exec(); */ -var alasql = function(sql, params, cb, scope) { - +var alasql = function(...args) { + var [sqlQuery, params, cb, scope] = args; + var sql = isBacktickQuery(sqlQuery) ? normalizeBacktickQuery(args) : sqlQuery; + if(isBacktickQuery(sqlQuery)) + console.log(sql, args); params = params||[]; if(typeof importScripts !== 'function' && alasql.webworker) { @@ -122,4 +144,4 @@ alasql.debug = undefined; // Initial debug variable /*only-for-browser/* var require = function(){return null}; // as alasqlparser.js is generated, we can not "remove" referenses to var __dirname = ''; -//*/ +//*/ \ No newline at end of file diff --git a/src/17alasql.js b/src/17alasql.js index 741d529ffe..a233c7cfa4 100755 --- a/src/17alasql.js +++ b/src/17alasql.js @@ -27,8 +27,7 @@ alasql.parser.parseError = function (str, hash) { // My own parser here } */ -alasql.parse = function (sql) { - const command = Array.isArray(sql) ? sql[0] : sql; +alasql.parse = function (command) { return alasqlparser.parse(alasql.utils.uncomment(command)); }; diff --git a/test/test847.js b/test/test847.js new file mode 100644 index 0000000000..05171f5c43 --- /dev/null +++ b/test/test847.js @@ -0,0 +1,21 @@ +if (typeof exports === 'object') { + // var assert = require('assert'); + var alasql = require('..'); +} + +describe('Test 847 - Testing backtick call function', function () { + it('Should create a table', function (done) { + const table = { + name: 'Midnight_Calls', + columns: [ + {name: 'id', type: 'INT'}, + {name: 'track_name', type: 'STRING'}, + {name: 'author', type: 'STRING'}, + ], + }; + alasql`CREATE TABLE ${table.name} (${table.columns.map( + (item) => `${item.name} ${item.type}` + )})`; + done(); + }); +}); From 32d4623b5393240b74a687e541e3371238f83c9f Mon Sep 17 00:00:00 2001 From: lucioroadtoglory Date: Thu, 15 Dec 2022 16:23:04 -0300 Subject: [PATCH 4/7] feat: finish basic support --- src/10start.js | 6 ++--- test/_test847.js | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ test/test847.js | 21 ----------------- 3 files changed, 62 insertions(+), 25 deletions(-) create mode 100644 test/_test847.js delete mode 100644 test/test847.js diff --git a/src/10start.js b/src/10start.js index 6eddf0e8ba..40eee091da 100644 --- a/src/10start.js +++ b/src/10start.js @@ -17,7 +17,6 @@ const normalizeBacktickQuery = (args) => { .replace(/[\r\n]/g, '') .replace(/\s+/g, ' ') // Remove extras .trim(); // Remove extras - console.log(stringFormatted); return stringFormatted; }; @@ -79,8 +78,7 @@ const normalizeBacktickQuery = (args) => { var alasql = function(...args) { var [sqlQuery, params, cb, scope] = args; var sql = isBacktickQuery(sqlQuery) ? normalizeBacktickQuery(args) : sqlQuery; - if(isBacktickQuery(sqlQuery)) - console.log(sql, args); + params = params||[]; if(typeof importScripts !== 'function' && alasql.webworker) { @@ -144,4 +142,4 @@ alasql.debug = undefined; // Initial debug variable /*only-for-browser/* var require = function(){return null}; // as alasqlparser.js is generated, we can not "remove" referenses to var __dirname = ''; -//*/ \ No newline at end of file +//*/ diff --git a/test/_test847.js b/test/_test847.js new file mode 100644 index 0000000000..03c3ad0cb1 --- /dev/null +++ b/test/_test847.js @@ -0,0 +1,60 @@ +if (typeof exports === 'object') { + var alasql = require('..'); +} + +const table = { + name: 'midnightcalls', + columns: [ + {name: 'track_name', type: 'string'}, + {name: 'author', type: 'string'}, + {name: 'views', type: 'int'}, + ], +}; + +describe('Test 847 - Testing backtick call function', function () { + it('1. Create table', function () { + alasql`DROP TABLE IF EXISTS test`; + alasql`CREATE TABLE test (a int, b int)`; + }); + + it('2. Insert values ', function () { + alasql`INSERT INTO test VALUES (1,1)`; + alasql`INSERT INTO test VALUES (1,7)`; + alasql`INSERT INTO test VALUES (2,2)`; + alasql`INSERT INTO test VALUES (3,3)`; + }); + + it('3. Create a new table', function () { + alasql`DROP TABLE IF EXISTS ${table.name}`; + + alasql(` + CREATE TABLE ${table.name} (${table.columns + .map((item) => ` ${item.name} ${item.type.toUpperCase()}`) + .join(', ') + .toString()}) + `); + }); + + it('4. Insert values', function () { + const values = [ + ['qhAfaWdLbIE', 'Baby bi', 'Yunk Vino', 72], + ['YA-db3f8Ak4', 'Sonar', 'Yunk Vino', 809], + ]; + const valuesToInsert = values + .map( + (item, i) => + `('${item[0]}', '${item[1]}', '${item[2]}', ${item[3]})${ + i + 1 === values.length ? '' : ', ' + }` + ) + .join(''); + + console.log(valuesToInsert); + + alasql(` + INSERT INTO ${table.name} + VALUES + ${valuesToInsert} + `); + }); +}); diff --git a/test/test847.js b/test/test847.js deleted file mode 100644 index 05171f5c43..0000000000 --- a/test/test847.js +++ /dev/null @@ -1,21 +0,0 @@ -if (typeof exports === 'object') { - // var assert = require('assert'); - var alasql = require('..'); -} - -describe('Test 847 - Testing backtick call function', function () { - it('Should create a table', function (done) { - const table = { - name: 'Midnight_Calls', - columns: [ - {name: 'id', type: 'INT'}, - {name: 'track_name', type: 'STRING'}, - {name: 'author', type: 'STRING'}, - ], - }; - alasql`CREATE TABLE ${table.name} (${table.columns.map( - (item) => `${item.name} ${item.type}` - )})`; - done(); - }); -}); From 443ac9e7ff420682f7270028a16ae7eddd773cfa Mon Sep 17 00:00:00 2001 From: "M. Wulff" Date: Tue, 13 Jun 2023 23:47:34 +1000 Subject: [PATCH 5/7] WIP starting the work testing model B --- test/test1512.js | 167 +++++++++++++++++++++++++++++++++++++++++++++++ test/test270.js | 2 +- test/test272.js | 2 +- test/test273.js | 2 +- 4 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 test/test1512.js diff --git a/test/test1512.js b/test/test1512.js new file mode 100644 index 0000000000..67e8367d11 --- /dev/null +++ b/test/test1512.js @@ -0,0 +1,167 @@ +if (typeof exports === 'object') { + var assert = require('assert'); + var alasql = require('../dist/alasql'); +} + +/* + Test for PR #1512 +*/ + +var test = '1512'; // insert test file number + +describe('Test ' + test + ' - tagFunction for template strings', function () { + it('Will mark free fields as parameters', function (done) { + assert.deepEqual(tagBraid`SELECT 123 as abc`, ['SELECT 123 as abc']); + assert.deepEqual(tagBraid`SELECT ${123} as abc`, ['SELECT ? as abc', [123]]); + assert.deepEqual(tagBraid`${'SELECT'} ${123} as abc`, ['? ? as abc', ['SELECT', 123]]); + assert.deepEqual(tagBraid`${'SELECT'} ${123} as ${'abc'}`, [ + '? ? as ?', + ['SELECT', 123, 'abc'], + ]); + done(); + }); + + it('Will work second time when data is fetched from the cache', function (done) { + assert.deepEqual(tagBraid`SELECT 123 as abc`, ['SELECT 123 as abc']); + assert.deepEqual(tagBraid`SELECT ${123} as abc`, ['SELECT ? as abc', [123]]); + assert.deepEqual(tagBraid`${'SELECT'} ${123} as abc`, ['? ? as abc', ['SELECT', 123]]); + assert.deepEqual(tagBraid`${'SELECT'} ${123} as ${'abc'}`, [ + '? ? as ?', + ['SELECT', 123, 'abc'], + ]); + done(); + }); + + it('Will inline connected fields', function (done) { + assert.deepEqual(tagBraid`S${'ELECT'} 1${23} as ab${'c'}`, ['SELECT 123 as abc', []]); + assert.deepEqual(tagBraid`SELECT 123 as ${'ab'}${'c'}`, ['SELECT 123 as abc', []]); + done(); + }); + + it('Will treat "()," as free space and become parameter', function (done) { + assert.deepEqual(tagBraid`SELECT AVG(${1},${2},${3}) as abc`, [ + 'SELECT AVG(?,?,?) as abc', + [1, 2, 3], + ]); + done(); + }); + + it('Can force free fields as inline', function (done) { + assert.deepEqual(tagBraid`~${'SELECT'} ~${123} as abc`, ['SELECT 123 as abc', []]); + assert.deepEqual(tagBraid`~${'SELECT'} ~${123} as ${'abc'}`, ['SELECT 123 as ?', ['abc']]); + assert.deepEqual(tagBraid`${'SELECT'} ${123} as ~${'abc'}`, ['? ? as abc', ['SELECT', 123]]); + assert.deepEqual(tagBraid`${'SELECT'} ${123} as ~${'abc'}~`, ['? ? as ~abc~', ['SELECT', 123]]); + assert.deepEqual(tagBraid`SELECT AVG(~${1},~${2},${3}) as abc`, [ + 'SELECT AVG(1,2,?) as abc', + [3], + ]); + done(); + }); + + it('Default to markring as parameter (option B from PR #1512)', function (done) { + let items = `toys`; + let type = 'Montessori'; + let item = 'batman'; + let orderBy = `ORDER BY x desc, y asc`; + + let res = tagBraid` +SELECT author +FROM ${items} +WHERE +AND type = ${type}_v2 +AND name = ${item} +~${orderBy} +`; + + let expected = ` +SELECT author +FROM ? +WHERE +AND type = Montessori_v2 +AND name = ? +ORDER BY x desc, y asc +`; + assert.deepEqual(res, [expected, [`toys`, 'batman']]); + done(); + }); + + /*it('Will return a promise', async function (done) { + let res = alasql`SELECT 123`; + assert(typeof res.then === 'function'); + assert.equal(await alasql`SELECT 123`.then((x) => 555), 555); + done(); + }); + + it('Will return the data from the query', async function (done) { + assert.equal(await alasql`VAlUE OF SELECT 123`, 123); + assert.deepEqual(await alasql`SELECT 123 as abc`, [{abc: 123}]); + done(); + }); + + it('Will inline string connected to other areas', async function (done) { + assert.deepEqual(await alasql`SELECT 123 as abc`, [{abc: 123}]); + done(); + });*/ +}); + +const re = { + preFree: /[\(,\s]~?$/, + postFree: /^[\),\s]/, +}; + +const cache = new Map(); + +function tagBraid(template, ...params) { + if ( + !Array.isArray(template) || + !Array.isArray(template.raw) || + template.length - 1 != params.length + ) + throw 'Please use as tagfunction to provide the right arguments'; + + if (1 == template.length) return [template[0]]; + + let sql = ''; + + let paramsIDs = []; + if (cache[template.raw]) { + ({sql, paramsIDs} = cache.get(template.raw)); + } else { + for (let i = 0; i <= params.length; i++) { + sql += template[i]; + + if (i === params.length) break; + + let inline = true; + + // if the field is "free" and not connected to other texts + if ( + (re.preFree.test(template[i]) || + (0 === i && ('' === template[i] || '~' === template[i]))) && + (re.postFree.test(template[i + 1]) || (params.length - 1 === i && '' === template[i + 1])) + ) { + inline = false; + // force inline if prepended with ~ + if ('~'.charCodeAt(0) === template[i].charCodeAt(template[i].length - 1)) { + sql = sql.slice(0, -1); + inline = true; + } + } + + if (inline) { + if (typeof params[i] !== 'number' && typeof params[i] !== 'string') + console.error( + 'You are inlining a value that is not a string or a number so it might not work. Will proceed with the .toString() value but consider making space around the value so it can be provided as a parameter.', + {parameter: params[i], template: template.raw} + ); + sql += params[i].toString(); + } else { + sql += '?'; + paramsIDs.push(i); + } + } + cache.set(template.raw, {sql, paramsIDs}); + } + + return [sql, [...paramsIDs.map((x) => params[x])]]; +} diff --git a/test/test270.js b/test/test270.js index 0766f20077..270126e879 100644 --- a/test/test270.js +++ b/test/test270.js @@ -6,7 +6,7 @@ if (typeof exports === 'object') { } describe('Test 270 RECORDSET tests', function () { - const pluck = (arr, key) => arr.map(e => e[key]) + const pluck = (arr, key) => arr.map((e) => e[key]); var emptydata = []; var data1 = [ diff --git a/test/test272.js b/test/test272.js index 4793970ddd..599720f47e 100644 --- a/test/test272.js +++ b/test/test272.js @@ -6,7 +6,7 @@ if (typeof exports === 'object') { } describe('Test 272 REMOVE columns', function () { - const pluck = (arr, key) => arr.map(e => e[key]); + const pluck = (arr, key) => arr.map((e) => e[key]); before(function () { alasql('CREATE DATABASE test272; USE test272'); diff --git a/test/test273.js b/test/test273.js index d05cbeb139..6abfb46f48 100644 --- a/test/test273.js +++ b/test/test273.js @@ -6,7 +6,7 @@ if (typeof exports === 'object') { } describe('Test 273 Source columns detextion', function () { - const pluck = (arr, key) => arr.map(e => e[key]) + const pluck = (arr, key) => arr.map((e) => e[key]); before(function () { alasql('CREATE DATABASE test273; USE test273'); From 632f548d8a3da417ebb0d291c8820ec36af8f2ff Mon Sep 17 00:00:00 2001 From: "M. Wulff" Date: Wed, 14 Jun 2023 11:24:34 +1000 Subject: [PATCH 6/7] Rename test files --- test/test000.js | 20 ++++++++++---------- test/{test1512.js => test1723a.js} | 7 +------ test/{_test847.js => test1723b.js} | 6 +++--- 3 files changed, 14 insertions(+), 19 deletions(-) rename test/{test1512.js => test1723a.js} (96%) rename test/{_test847.js => test1723b.js} (89%) diff --git a/test/test000.js b/test/test000.js index c56b71f6c7..de7016ffcc 100644 --- a/test/test000.js +++ b/test/test000.js @@ -3,20 +3,20 @@ if (typeof exports === 'object') { var alasql = require('..'); } -var test = '000'; // insert test file number +const testID = '000'; // Seek to use a github issue number -describe('Test ' + test + ' - multiple statements', function () { +describe('Issue #' + testID + ' - multiple statements', function () { before(function () { - alasql('create database test' + test); - alasql('use test' + test); + alasql('create database test' + testID); + alasql('use test' + testID); }); after(function () { - alasql('drop database test' + test); + alasql('drop database test' + testID); }); it('A) From single lines', function () { - var res = []; + const res = []; res.push(alasql('create table one (a int)')); res.push(alasql('insert into one values (1),(2),(3),(4),(5)')); res.push(alasql('select * from one')); @@ -25,19 +25,19 @@ describe('Test ' + test + ' - multiple statements', function () { it('B) Multiple statements in one string', function () { // - var sql = 'create table two (a int);'; + let sql = 'create table two (a int);'; sql += 'insert into two values (1),(2),(3),(4),(5);'; sql += 'select * from two;'; - var res = alasql(sql); + let res = alasql(sql); assert.deepEqual(res, [1, 5, [{a: 1}, {a: 2}, {a: 3}, {a: 4}, {a: 5}]]); }); it('C) Multiple statements in one string with callback', function (done) { // Please note that first parameter (here `done`) must be called if defined - and is needed when testing async code - var sql = 'create table three (a int);'; + let sql = 'create table three (a int);'; sql += 'insert into three values (1),(2),(3),(4),(5);'; sql += 'select * from three;'; - alasql(sql, function (res) { + alasql.promise(sql).then( function (res) { assert.deepEqual(res, [1, 5, [{a: 1}, {a: 2}, {a: 3}, {a: 4}, {a: 5}]]); done(); }); diff --git a/test/test1512.js b/test/test1723a.js similarity index 96% rename from test/test1512.js rename to test/test1723a.js index 67e8367d11..d1e7300bd5 100644 --- a/test/test1512.js +++ b/test/test1723a.js @@ -3,13 +3,8 @@ if (typeof exports === 'object') { var alasql = require('../dist/alasql'); } -/* - Test for PR #1512 -*/ -var test = '1512'; // insert test file number - -describe('Test ' + test + ' - tagFunction for template strings', function () { +describe('Issue #1723 - tagFunction for template strings', function () { it('Will mark free fields as parameters', function (done) { assert.deepEqual(tagBraid`SELECT 123 as abc`, ['SELECT 123 as abc']); assert.deepEqual(tagBraid`SELECT ${123} as abc`, ['SELECT ? as abc', [123]]); diff --git a/test/_test847.js b/test/test1723b.js similarity index 89% rename from test/_test847.js rename to test/test1723b.js index 03c3ad0cb1..d9ecb93431 100644 --- a/test/_test847.js +++ b/test/test1723b.js @@ -1,5 +1,5 @@ if (typeof exports === 'object') { - var alasql = require('..'); + var alasql = require('../dist/alasql'); } const table = { @@ -11,7 +11,7 @@ const table = { ], }; -describe('Test 847 - Testing backtick call function', function () { +describe('Issue #1723 - Testing backtick call function', function () { it('1. Create table', function () { alasql`DROP TABLE IF EXISTS test`; alasql`CREATE TABLE test (a int, b int)`; @@ -49,7 +49,7 @@ describe('Test 847 - Testing backtick call function', function () { ) .join(''); - console.log(valuesToInsert); + //console.log(valuesToInsert); alasql(` INSERT INTO ${table.name} From a288f1e9b5979d73c9da6abba4cc0763c463a4d0 Mon Sep 17 00:00:00 2001 From: "M. Wulff" Date: Wed, 14 Jun 2023 11:25:24 +1000 Subject: [PATCH 7/7] format --- test/test000.js | 2 +- test/test1723a.js | 1 - test/test238.json | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/test000.js b/test/test000.js index de7016ffcc..91968f079f 100644 --- a/test/test000.js +++ b/test/test000.js @@ -37,7 +37,7 @@ describe('Issue #' + testID + ' - multiple statements', function () { let sql = 'create table three (a int);'; sql += 'insert into three values (1),(2),(3),(4),(5);'; sql += 'select * from three;'; - alasql.promise(sql).then( function (res) { + alasql.promise(sql).then(function (res) { assert.deepEqual(res, [1, 5, [{a: 1}, {a: 2}, {a: 3}, {a: 4}, {a: 5}]]); done(); }); diff --git a/test/test1723a.js b/test/test1723a.js index d1e7300bd5..a1a4628d40 100644 --- a/test/test1723a.js +++ b/test/test1723a.js @@ -3,7 +3,6 @@ if (typeof exports === 'object') { var alasql = require('../dist/alasql'); } - describe('Issue #1723 - tagFunction for template strings', function () { it('Will mark free fields as parameters', function (done) { assert.deepEqual(tagBraid`SELECT 123 as abc`, ['SELECT 123 as abc']); diff --git a/test/test238.json b/test/test238.json index 4dca1cc0b0..5bb1abba08 100644 --- a/test/test238.json +++ b/test/test238.json @@ -1 +1 @@ -[{"100":100}] \ No newline at end of file +[{"100": 100}]