Version: 0.0.22 Date: November 22, 2014 Change log, Release plan
Alasql - 'Ă la SQL' - is a lightweight client-side in-memory SQL database designed to work in browser and Node.js.
- Alasql was written with pure JavaScript and does not use browser WebSQL database.
- Alasql is fully functional compact SQL server with JOINs, GROUPs, UNIONs, PRIMARY KEYs, ANY, ALL, IN, subqueries and very limited transactions support.
- Alasql supports ROLLUP(), CUBE() and GROUPING SETS() functions
- Alasql works with all modern versions of browsers Chrome, Firefox, IE, Safari, Opera, Node.js, and mobile iOS and Android.
- Alasql is fast, because it uses some optimization methods.
Check Alasql vs other JavaScript SQL databases:
Alasql project is very young and still in active development phase, therefore it may have some bugs. Please, wait a little bit before start to use it in production. I am going to add more tests and clean the code before relaese more stable version 0.1.0 in the mid of November. Please, submit bugs and suggestions in issue page.
Sorry, transactions were temporary turned off in version 0.0.17, because we started to introduce more complex approach for PRIMARY KEYS / FOREIGN KEYS. I will turn transactions on again in one of the future version.
You can check version-0.0.23 branch for new experimental features of new version.
The early prototype of documentation (draft).
Try Alasql in Fiddle: sample 1, sample 2, sample 3, sample 4
Other examples:
Short presentation about Alasql
Include file: alasql.js to the page.
<script src="alasql.js"></script>
<script>
alasql("CREATE TABLE test (language INT, hello STRING)");
alasql("INSERT INTO test VALUES (1,'Hello!')");
alasql("INSERT INTO test VALUES (2,'Aloha!')");
alasql("INSERT INTO test VALUES (3,'Bonjour!')");
console.table(alasql("SELECT * FROM test WHERE language > 1"));
</script>
You can use alasql.js with define()/require() functions in browser as well, because it supports AMD and UMD:
require(['../../alasql.js'], function(alasql) {
var test1 = [{a:1,b:2,c:3},{a:4,b:5,c:6},{a:7,b:8,c:9}];
console.table(alasql('SELECT a, b*c AS bc FROM ? AS t',[test1]));
});
Like in this sample you do not need to CREATE TABLE and INSERTS if you do not need constraints functionality.
Use the following command for installation:
npm install alasql
Then require alasql.js file:
var alasql = require('alasql');
var db = new alasql.Database();
db.exec("CREATE TABLE test (one INT, two INT)");
db.tables.test.data = [ // You can mix SQL and JavaScript
{one:3,two:4},
{one:5,two:6},
];
var res = db.exec("SELECT * FROM test ORDER BY two DESC");
console.log(res[0].one);
- SELECT fields FROM tableid1 JOIN tableid2 ON oncond WHERE cond GROUP BY v1,v2 HAVING cond ORDER BY a,b, LIMIT number OFFSET number
- INSERT INTO table [ (field1, field2) ] VALUES (value1, value2), (value3, value4), ...
- INSERT INTO table SELECT subquery
- UPDATE table SET field = value1, field = value2 WHERE condition
- DELETE FROM table WHERE condition
- CREATE TABLE [IF NOT EXISTS] table (columns type PRIMARY KEY, constraints)
- DROP TABLE [IF EXISTS] table
- CREATE DATABASE, USE DATABASE, DROP DATABASE
- SHOW DATABASES / SHOW TABLES / SHOW COLUMNS
Now Alasql.js supports following subset of SELECT syntax:
- SELECT column1, column2 AS alias3, FUNCTION(field4+field5) AS alias6, SUM(expression7) AS alias8, , table2.
- FROM table1, table2, (SELECT * FROM table3) alias
- LEFT / RIGHT / INNER / OUTER / ANTI / SEMI / CROSS JOIN table2 ON condition / USING columns
- WHERE condition
- GROUP BY column1, column2, ROLLUP(a,b), CUBE(c,d,e), GROUPING SETS(g,h)
- HAVING condition
- ORDER BY column1, column2 DESC,
- LIMIT number [OFFSET number]
- UNION / UNION ALL select / INTERSECT / EXCEPT
- +, -, *, /, %, AND, OR, NOT, BETWEEN, NOT BETWEEN, EXISTS (Subquery), > ALL (subquery/array), > ANY/SOME (subquery / array), [NOT] IN (subquery / array), LIKE
- SUM()
- COUNT()
- MIN()
- MAX()
- FIRST()
- LAST()
- Sorry, AVG still does not work
- ROLLUP()
- CUBE()
- GROUPING SETS()
- ABS(), IIF(), IFNULL(), INSTR(), LOWER(), UPPER(), LCASE(), UCASE(), LEN(), LENGTH()
You can use all benefits of SQL and JavaScript togeather by defining user functions. Just add new functions to alasql.fn object:
alasql.fn.double = function(x){return x*2};
alasql.fn.sum10 = function(x,y) { return x+y*10; }
db.exec('SELECT a, double(a) AS b, sum10(a,b) FROM test1');
User-defined functions are related to current database. You can define different functions in different databases.
alasql is a main variable of module. You can use it immediatly as default database
In browser:
<script src="alasql.js"></script>
<script>
alasql('CREATE TABLE one (two INT)');
</script>
or in Node.js:
var alasql = require('alasql');
alasql('CREATE TABLE one (two INT)');
Another approach is to create new database:
var mybase = new alasql.Database();
mybase.exec('CREATE TABLE one (two INT)');
You can give a name to database and then access it from alasql:
var mybase = new alasql.Database('mybase');
console.log(alasql.databases.mybase);
Each database can be used with the following methods:
var db = new alasql.Database() - create new alasql-database
var res = db.exec("SELECT * FROM one") - executes SELECT query and returns array of objects
Usually, alasql.js works synchronously, but you can use callback.
db.exec('SELECT * FROM test', [], function(res){
console.log(res);
});
or you can use aexec() - promised version of exec (in this case you need to install es6-promise module for Node.js) (this feature is experimental and may be removed in a future to reduce dependices):
db.aexec('SELECT * FROM test').then(function(res){
console.log(res);
});
You can use compile statements:
var insert = db.compile('INSERT INTO one (1,2)');
insert();
You can use parameters in compiled statements:
var insert1 = db.compile('INSERT INTO one (?,?)');
var insert2 = db.compile('INSERT INTO one ($a,$b)');
var insert3 = db.compile('INSERT INTO one (:a,:b)');
insert1([1,2]);
insert2({a:1,b:2});
insert3({a:3,b:4});
db.exec('INSERT INTO one (?,?)',[5,6]);
You even can use param in FROM clause:
var years = [
{yearid: 2012}, {yearid: 2013},
{yearid: 2014}, {yearid: 2015},
{yearid: 2016},
];
var res = alasql.queryArray('SELECT * FROM ? AS years ' +
'WHERE yearid > ?', [years,2014]);
// res == [2015,2016]
You can use array of arrays to make a query. In this case use square brackets for column name, like [1] or table[2] (remember, all arrays in JavaScript start with 0):
var data = [
[2014, 1, 1], [2015, 2, 1],
[2016, 3, 1], [2017, 4, 2],
[2018, 5, 3], [2019, 6, 3]
];
var res = alasql('SELECT SUM([1]) FROM ? d WHERE [0]>2016', [data]);
Use alasql.queryArrayOfArrays() function to return array of arrays. In this case you can specify array position of selected column with number or number in brackets:
var res = alasql.queryArrayOfArrays(
'SELECT [1] AS 0,[1]+[2] AS [1] FROM ? d WHERE [0]>2016', [data]);
This feature can be used as filter for arrays. Compare:
// Same filter
var res1 = alasql.queryArrayOfArrays('SELECT * FROM ? a WHERE [0]>2016', [data]);
var res2 = data.filter(function(a){return a[0]>2016});
// Complex filter with aggregating, grouping and sorting
var res = alasql.queryArrayOfArrays(
'SELECT [2] AS 0, SUM([1]) AS 1 FROM ? a WHERE a[0]>? GROUP BY [0] ORDER BY [1]',
[data, 2016]);
By default, Alasql is case-insensitive to all standard keywords (like SELECT) and standard functions (like ABS()). All database names, table names, column names, and user-defined functions are case sensitive.
JavaScript is case-sensitive language, so use the same CaSe for Alasql and JavaScript data.
Now you can use databases, tables, and columns with spaces inside square brackets:
CREATE DATABASE [My Database]; -- BTW You can use comments in the SQL statements
USE [My Database]; /* or comments like this */
CREATE TABLE [A.table] ([the-column] INT);
SELECT [the-column] AS [AS] FROM [My Database];
There is a limited support of transactions (with tx.rollback() and tx.commit() functions):
db = new alasql.Database("mydb");
db.transaction(function(tx) {
tx.exec('SELECT COUNT(*) FROM students');
tx.rollback();
});
You can use Alasql to parse to AST and compile SQL statements:
// Parse to AST
var ast = alasql.parse("SELECT * FROM one");
console.log(ast.toString()); // Print restored SQL statement
// Compile to JavaScript function with or without parameters
var statement = alasql.compile("SELECT * FROM one WHERE a > ? AND b < ?");
statement([1,5]);
Alasql uses wonderful Jison parser to produce AST-tree.
According the preliminary performance tests alasql.js is faster than sql.js in 5 to 10 times on more than 1000 records tables, and 2 to 3 times to WebSQL on different queries.
Alasql has four different optimization algorithm:
- Caching of compiled queries
- Joins: Preindexation of joined table
- Joins: Prefiltering of WHERE expressions
Now optimization algorithm has some limitations and therefore "table1 JOIN table2 USING column1, column2" is faster than "table1 JOIN table2 ON table1.column1 = table2.column1 AND table1.column2 = table2.column2 ", but with one column it is ok.
Compare it with Lodash and Underscore:
It is Ok with select for 1000000 records or 2 join two tables by 10000 records in each.
I use mocha for tests. Run mocha from command line:
mocha
or run test/main.html in browser.
- Dates comparing (sorting now is ok)
- Transactions
- ORDER BY clause on three or more UNIONS
- AVG() does not work
- There are many of others. Please, give me a chance to fix them. Thank you!
Read my to do page
Similar projects (SQL database, MDX/OLAP on JavaScript)
Many thanks to Andrew Kent for his SQL Parser and other people for useful tools, which make our work much easier.
(c) 2014, Andrey Gershun ([email protected]), MIT licence information