|
|
@ -3,9 +3,24 @@ import React from 'react'; |
|
|
|
export const DBTypeEnum = { |
|
|
|
export const DBTypeEnum = { |
|
|
|
ALASQL_SQLITE: 1, |
|
|
|
ALASQL_SQLITE: 1, |
|
|
|
ALASQL_INDEXEDDB: 2, |
|
|
|
ALASQL_INDEXEDDB: 2, |
|
|
|
ALASQL_NATIVE: 3 |
|
|
|
ALASQL_NATIVE: 3, |
|
|
|
|
|
|
|
SQLJS_SQLITE: 4 |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const DBSourceEnum = { |
|
|
|
|
|
|
|
ATTACHFILE: 1, |
|
|
|
|
|
|
|
CREATE: 2 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function alasql_async_queries(alasql_object, queries) { |
|
|
|
|
|
|
|
var p = Promise.resolve(null); |
|
|
|
|
|
|
|
for (let i = 0; i < queries.length; i++) { |
|
|
|
|
|
|
|
p = p.then(() => { return alasql_object.promise(queries[i]); }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return p; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export class DB { |
|
|
|
export class DB { |
|
|
|
state = { |
|
|
|
state = { |
|
|
|
db_type: false, |
|
|
|
db_type: false, |
|
|
@ -27,12 +42,7 @@ export class DB { |
|
|
|
this.state.db_type === DBTypeEnum.ALASQL_INDEXEDDB || |
|
|
|
this.state.db_type === DBTypeEnum.ALASQL_INDEXEDDB || |
|
|
|
this.state.db_type === DBTypeEnum.ALASQL_NATIVE) { |
|
|
|
this.state.db_type === DBTypeEnum.ALASQL_NATIVE) { |
|
|
|
var self = this; |
|
|
|
var self = this; |
|
|
|
var p = Promise.resolve(null); |
|
|
|
return alasql_async_queries(self.state.db_object, s); |
|
|
|
for (let i = 0; i < s.length; i++) { |
|
|
|
|
|
|
|
p = p.then(() => { return self.state.db_object.promise(s[i]); }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return p; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
throw new Error("Unsupported database type for async operations: " + this.state.db_type); |
|
|
|
throw new Error("Unsupported database type for async operations: " + this.state.db_type); |
|
|
|
} |
|
|
|
} |
|
|
@ -47,6 +57,12 @@ export class DB { |
|
|
|
} |
|
|
|
} |
|
|
|
return this.state.db_object(s[s.length - 1]); |
|
|
|
return this.state.db_object(s[s.length - 1]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (this.state.db_type === DBTypeEnum.SQLJS_SQLITE) { |
|
|
|
|
|
|
|
for (var i = 0; i < (s.length - 1); i++) { |
|
|
|
|
|
|
|
this.state.db_object.exec(s[i]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return this.state.db_object.exec(s[s.length - 1]); |
|
|
|
|
|
|
|
} |
|
|
|
throw new Error("Unsupported database type for sync operations: " + this.state.db_type); |
|
|
|
throw new Error("Unsupported database type for sync operations: " + this.state.db_type); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -91,6 +107,67 @@ export class DB { |
|
|
|
resolve(); |
|
|
|
resolve(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
} else if (this.state.db_type === DBTypeEnum.SQLJS_SQLITE && db_type === DBTypeEnum.ALASQL_NATIVE) { |
|
|
|
|
|
|
|
return new Promise(function (resolve, reject) { |
|
|
|
|
|
|
|
var tables = self.queries_sync(["SELECT * FROM sqlite_master WHERE type='table';"])[0].values; |
|
|
|
|
|
|
|
console.log(tables); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get all table definition lines.
|
|
|
|
|
|
|
|
var table_definitions = []; |
|
|
|
|
|
|
|
var table_names = []; |
|
|
|
|
|
|
|
tables.forEach(elem => { |
|
|
|
|
|
|
|
table_definitions.push(elem[4]); |
|
|
|
|
|
|
|
table_names.push(elem[1]); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// We want to create all these tables in the AlaSQL database as well. However, that will require
|
|
|
|
|
|
|
|
// us to escape the table names because AlaSQL may break on colums with names equal to keywords
|
|
|
|
|
|
|
|
// (see https://github.com/agershun/alasql/issues/1155).
|
|
|
|
|
|
|
|
// Here we take a dirty shortcut: explicitly escape all occurrences of "value", "query" and "matrix".
|
|
|
|
|
|
|
|
var new_table_definitions = []; |
|
|
|
|
|
|
|
table_definitions.forEach(elem => { |
|
|
|
|
|
|
|
var newelem = elem |
|
|
|
|
|
|
|
.replace(/value/g, "`value`") |
|
|
|
|
|
|
|
.replace(/query/g, "`query`") |
|
|
|
|
|
|
|
.replace(/matrix/g, "`matrix`"); |
|
|
|
|
|
|
|
new_table_definitions.push(newelem); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
console.log(new_table_definitions); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var asql = require('alasql'); |
|
|
|
|
|
|
|
var queries = []; |
|
|
|
|
|
|
|
queries.push("CREATE DATABASE IF NOT EXISTS " + db_name + ";"); |
|
|
|
|
|
|
|
queries.push("USE " + db_name + ";"); |
|
|
|
|
|
|
|
new_table_definitions.forEach(elem => { |
|
|
|
|
|
|
|
queries.push(elem); // Creates the table
|
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
alasql_async_queries(asql, queries) |
|
|
|
|
|
|
|
.then(() => { |
|
|
|
|
|
|
|
// Fill the tables by passing through a JS dictionary object.
|
|
|
|
|
|
|
|
table_names.forEach(elem => { |
|
|
|
|
|
|
|
var res = self.queries_sync(["SELECT * FROM " + elem + ";"])[0]; |
|
|
|
|
|
|
|
if (res) { |
|
|
|
|
|
|
|
var structured = []; |
|
|
|
|
|
|
|
res.values.forEach(vals => { |
|
|
|
|
|
|
|
var row = {}; |
|
|
|
|
|
|
|
var i = 0; |
|
|
|
|
|
|
|
res.columns.forEach(column => { |
|
|
|
|
|
|
|
row[column] = vals[i]; |
|
|
|
|
|
|
|
i++; |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
structured.push(row); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
asql("SELECT * INTO " + elem + " FROM ?", [structured]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
.then(() => { |
|
|
|
|
|
|
|
self.state.db_type = db_type; |
|
|
|
|
|
|
|
self.state.db_name = db_name; |
|
|
|
|
|
|
|
self.state.db_object = asql; |
|
|
|
|
|
|
|
resolve(); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
throw new Error("Unsupported copy creation from db_type " + this.state.db_type + " to " + db_type); |
|
|
|
throw new Error("Unsupported copy creation from db_type " + this.state.db_type + " to " + db_type); |
|
|
|
} |
|
|
|
} |
|
|
@ -113,6 +190,28 @@ function fetch_db_from_sqlite(filename, db_name) { |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fetch_sqljs_db_from_sqlite(filename, db_name) { |
|
|
|
|
|
|
|
return new Promise(function (resolve, reject) { |
|
|
|
|
|
|
|
var initSqlJs = require('sql.js'); |
|
|
|
|
|
|
|
initSqlJs({ locateFile: filename => `/sql.js/dist/${filename}` }) |
|
|
|
|
|
|
|
.then(SQL => { |
|
|
|
|
|
|
|
fetch(filename) |
|
|
|
|
|
|
|
.then(res => { |
|
|
|
|
|
|
|
if (!res.ok) { |
|
|
|
|
|
|
|
throw new Error(res.status); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return res.arrayBuffer(); |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
.then(data => { |
|
|
|
|
|
|
|
var array = new Uint8Array(data); |
|
|
|
|
|
|
|
var sqljs_db = new SQL.Database(array); |
|
|
|
|
|
|
|
var imported_db = new DB(sqljs_db, db_name, DBTypeEnum.SQLJS_SQLITE); |
|
|
|
|
|
|
|
resolve(imported_db); |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function create_indexed_db(name) { |
|
|
|
function create_indexed_db(name) { |
|
|
|
return new Promise(function (resolve, reject) { |
|
|
|
return new Promise(function (resolve, reject) { |
|
|
|
var asql = require('alasql'); |
|
|
|
var asql = require('alasql'); |
|
|
@ -141,11 +240,6 @@ function create_native_db(name) { |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export const DBSourceEnum = { |
|
|
|
|
|
|
|
ATTACHFILE: 1, |
|
|
|
|
|
|
|
CREATE: 2 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export class ProvideDB extends React.Component { |
|
|
|
export class ProvideDB extends React.Component { |
|
|
|
state = { |
|
|
|
state = { |
|
|
|
loading: true, |
|
|
|
loading: true, |
|
|
@ -180,6 +274,15 @@ export class ProvideDB extends React.Component { |
|
|
|
.then(() => { this.setState({ loading: false, done: true, db: db }) }); |
|
|
|
.then(() => { this.setState({ loading: false, done: true, db: db }) }); |
|
|
|
} else { this.setState({ loading: false, done: true, db: db }) }; |
|
|
|
} else { this.setState({ loading: false, done: true, db: db }) }; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
} else if (this.props.db_source_type === DBTypeEnum.SQLJS_SQLITE && this.props.db_source === DBSourceEnum.ATTACHFILE) { |
|
|
|
|
|
|
|
fetch_sqljs_db_from_sqlite(this.props.db_file, this.props.db_source_name) |
|
|
|
|
|
|
|
.then(db => { |
|
|
|
|
|
|
|
if (this.props.db_target_type !== this.props.db_source_type) { |
|
|
|
|
|
|
|
db.migrate_async(this.props.db_target_type, this.props.db_target_name) |
|
|
|
|
|
|
|
.then(() => { this.setState({ loading: false, done: true, db: db }) }); |
|
|
|
|
|
|
|
} else { this.setState({ loading: false, done: true, db: db }) }; |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
.catch(error => this.setState({ loading: false, done: false, error })); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
throw new Error("Unsupported ProvideDB configuration: from source " + this.props.db_source + |
|
|
|
throw new Error("Unsupported ProvideDB configuration: from source " + this.props.db_source + |
|
|
|
" with source type " + this.props.db_source_type + " to target type " + this.props.db_target_type + "."); |
|
|
|
" with source type " + this.props.db_source_type + " to target type " + this.props.db_target_type + "."); |
|
|
|