Remove bugged tables from DB. Got fast native DB working.

master
Sander Vocke 6 years ago
parent 7cbeaf1a83
commit c122755451
  1. BIN
      public/digikam4.db
  2. BIN
      public/test.sqlite
  3. 107
      src/database.js
  4. 25
      src/index.js

Binary file not shown.

Binary file not shown.

@ -1,8 +1,9 @@
import React from 'react'; import React from 'react';
var DBTypeEnum = { export const DBTypeEnum = {
ALASQL_SQLITE: 1, ALASQL_SQLITE: 1,
ALASQL_INDEXEDDB: 2 // TODO: implement with migration ALASQL_INDEXEDDB: 2,
ALASQL_NATIVE: 3
}; };
export class DB { export class DB {
@ -23,7 +24,8 @@ export class DB {
// starting. Not supported on all database types. // starting. Not supported on all database types.
queries_async(s) { queries_async(s) {
if (this.state.db_type === DBTypeEnum.ALASQL_SQLITE || if (this.state.db_type === DBTypeEnum.ALASQL_SQLITE ||
this.state.db_type === DBTypeEnum.ALASQL_INDEXEDDB) { this.state.db_type === DBTypeEnum.ALASQL_INDEXEDDB ||
this.state.db_type === DBTypeEnum.ALASQL_NATIVE) {
var self = this; var self = this;
var p = Promise.resolve(null); var p = Promise.resolve(null);
for (let i = 0; i < s.length; i++) { for (let i = 0; i < s.length; i++) {
@ -38,7 +40,8 @@ export class DB {
// Perform a series of queries sequentially, then return the last result. // Perform a series of queries sequentially, then return the last result.
// Note that synchronous operation is not supported for all database types. // Note that synchronous operation is not supported for all database types.
queries_sync(s) { queries_sync(s) {
if(this.state.db_type === DBTypeEnum.ALASQL_SQLITE) { if (this.state.db_type === DBTypeEnum.ALASQL_SQLITE ||
this.state.db_type === DBTypeEnum.ALASQL_NATIVE) {
for (var i = 0; i < (s.length - 1); i++) { for (var i = 0; i < (s.length - 1); i++) {
this.state.db_object(s[i]); this.state.db_object(s[i]);
} }
@ -53,7 +56,7 @@ export class DB {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
var tables = self.queries_sync(["SHOW TABLES;"]); var tables = self.queries_sync(["SHOW TABLES;"]);
var queries = []; var queries = [];
queries.push("DROP INDEXEDDB DATABASE " + db_name + ";"); queries.push("DROP INDEXEDDB DATABASE IF EXISTS " + db_name + ";");
queries.push("CREATE INDEXEDDB DATABASE IF NOT EXISTS " + db_name + ";"); queries.push("CREATE INDEXEDDB DATABASE IF NOT EXISTS " + db_name + ";");
queries.push("ATTACH INDEXEDDB DATABASE " + db_name + ";"); queries.push("ATTACH INDEXEDDB DATABASE " + db_name + ";");
tables.forEach(elem => { tables.forEach(elem => {
@ -69,34 +72,81 @@ export class DB {
resolve(); resolve();
}); });
}); });
} else if (this.state.db_type === DBTypeEnum.ALASQL_SQLITE && db_type === DBTypeEnum.ALASQL_NATIVE) {
return new Promise(function (resolve, reject) {
var tables = self.queries_sync(["SHOW TABLES;"]);
var queries = [];
queries.push("DROP DATABASE IF EXISTS " + db_name + ";");
queries.push("CREATE DATABASE IF NOT EXISTS " + db_name + ";");
tables.forEach(elem => {
queries.push("CREATE TABLE " + db_name + "." + elem.tableid + ";");
queries.push("SELECT * INTO " + db_name + "." + elem.tableid +
" FROM " + self.state.db_name + "." + elem.tableid + ";");
});
queries.push("DETACH DATABASE " + self.state.db_name + ";");
queries.push("USE " + db_name + ";");
self.queries_async(queries).then(() => {
self.state.db_type = db_type;
self.state.db_name = db_name;
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);
} }
} }
// TODO random database names // TODO random database names
function fetch_db_from_sqlite(filename) { function fetch_db_from_sqlite(filename, db_name) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
var initSqlJs = require('sql.js'); var initSqlJs = require('sql.js');
initSqlJs({ locateFile: filename => `/sql.js/dist/${filename}` }) initSqlJs({ locateFile: filename => `/sql.js/dist/${filename}` })
.then(SQL => { .then(SQL => {
var asql = require('alasql'); var asql = require('alasql');
// Attach to the SQLite database file, asql.promise("ATTACH SQLITE DATABASE " + db_name + "(\"" + filename + "\");")
// Create an IndexedDB to migrate it to, named "db", .then(res => { asql.promise("USE " + db_name + ";"); })
// Get tables
var query = "";
query += "ATTACH SQLITE DATABASE db(\"" + filename + "\"); USE db;";
asql.promise(query)
.then(res => { .then(res => {
var imported_db = new DB(asql, "db", DBTypeEnum.ALASQL_SQLITE); var imported_db = new DB(asql, db_name, DBTypeEnum.ALASQL_SQLITE);
resolve(imported_db); resolve(imported_db);
}); });
}); });
}); });
} }
// TODO: generalize to FetchDB function create_indexed_db(name) {
export class FetchSQLiteDB extends React.Component { return new Promise(function (resolve, reject) {
var asql = require('alasql');
asql.promise("DROP INDEXEDDB DATABASE " + name + ";")
.then(res => { asql.promise("CREATE INDEXEDDB DATABASE IF NOT EXISTS " + name + ";"); })
.then(res => { asql.promise("ATTACH INDEXEDDB DATABASE " + name + ";"); })
//.then(res => { asql.promise("USE " + name + ";"); }) // TODO why does this break things?
.then(res => {
var created_db = new DB(asql, name, DBTypeEnum.ALASQL_INDEXEDDB);
resolve(created_db);
});
});
}
function create_native_db(name) {
return new Promise(function (resolve, reject) {
var asql = require('alasql');
asql.promise("DROP DATABASE " + name + ";")
.then(res => { asql.promise("CREATE DATABASE IF NOT EXISTS " + name + ";"); })
.then(res => { asql.promise("ATTACH DATABASE " + name + ";"); })
//.then(res => { asql.promise("USE " + name + ";"); }) // TODO why does this break things?
.then(res => {
var created_db = new DB(asql, name, DBTypeEnum.ALASQL_INDEXEDDB);
resolve(created_db);
});
});
}
export const DBSourceEnum = {
ATTACHFILE: 1,
CREATE: 2
}
export class ProvideDB extends React.Component {
state = { state = {
loading: true, loading: true,
error: false, error: false,
@ -105,14 +155,35 @@ export class FetchSQLiteDB extends React.Component {
}; };
componentDidMount() { componentDidMount() {
fetch_db_from_sqlite(this.props.sqlite_file) if (this.props.db_source_type === DBTypeEnum.ALASQL_SQLITE && this.props.db_source === DBSourceEnum.ATTACHFILE) {
fetch_db_from_sqlite(this.props.db_file, this.props.db_source_name)
.then(db => { .then(db => {
if(this.props.migrate_to_indexeddb) { if (this.props.db_target_type !== this.props.db_source_type) {
db.migrate_async(DBTypeEnum.ALASQL_INDEXEDDB, "indexed_db") db.migrate_async(this.props.db_target_type, this.props.db_target_name)
.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 }) };
}) })
.catch(error => this.setState({ loading: false, done: false, error })); .catch(error => this.setState({ loading: false, done: false, error }));
} else if (this.props.db_source_type === DBTypeEnum.ALASQL_INDEXEDDB && this.props.db_source === DBSourceEnum.CREATE) {
create_indexed_db(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 }) };
});
} else if (this.props.db_source_type === DBTypeEnum.ALASQL_NATIVE && this.props.db_source === DBSourceEnum.CREATE) {
create_native_db(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 }) };
});
} else {
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 + ".");
}
} }
render() { render() {

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Fetch } from './fetch.js'; import { Fetch } from './fetch.js';
import { FetchSQLiteDB, DBQueryConsole } from './database.js'; import { ProvideDB, DBQueryConsole, DBTypeEnum, DBSourceEnum } from './database.js';
import { Photo, PhotoView } from './media.js'; import { Photo, PhotoView } from './media.js';
import './index.css'; import './index.css';
@ -33,7 +33,7 @@ export class PhotoFromDB extends React.Component {
} }
componentDidMount() { componentDidMount() {
this.props.database.queries_async(["SELECT * FROM images;"]) this.props.database.queries_async(["SELECT * FROM Images;"])
.then(res => { .then(res => {
var photo = new Photo(res[0]); var photo = new Photo(res[0]);
this.setState({ done: true, photo: photo }); this.setState({ done: true, photo: photo });
@ -50,7 +50,8 @@ export class PhotoFromDB extends React.Component {
} }
const TestDBFetch = ({sqlite_file}) => ( const TestDBFetch = ({sqlite_file}) => (
<FetchSQLiteDB sqlite_file={sqlite_file} migrate_to_indexeddb={true}> <ProvideDB db_file={sqlite_file} db_source_type={DBTypeEnum.ALASQL_SQLITE} db_target_type={DBTypeEnum.ALASQL_NATIVE}
db_source_name="sqlite_db" db_target_name="db" db_source={DBSourceEnum.ATTACHFILE}>
{({ loading, error, done, db }) => ( {({ loading, error, done, db }) => (
<> <>
{ loading && <DBLoading sqlite_file={sqlite_file}/> } { loading && <DBLoading sqlite_file={sqlite_file}/> }
@ -60,15 +61,29 @@ const TestDBFetch = ({sqlite_file}) => (
{ done && <PhotoFromDB database={db}/> } { done && <PhotoFromDB database={db}/> }
</> </>
)} )}
</FetchSQLiteDB> </ProvideDB>
)
const TestDBPlayground = ({db_name}) => (
<ProvideDB db_source_type={DBTypeEnum.ALASQL_INDEXEDDB} db_target_type={DBTypeEnum.ALASQL_INDEXEDDB}
db_source_name={db_name} db_target_name={db_name} db_source={DBSourceEnum.CREATE}>
{({ loading, error, done, db }) => (
<>
{ error && <DBError error={error} />}
{ done && <DBQueryConsole database={db}/> }
</>
)}
</ProvideDB>
) )
ReactDOM.render( ReactDOM.render(
<> <>
<h1>Test file fetching:</h1> <h1>Test file fetching:</h1>
<TestFetch url={process.env.PUBLIC_URL + "/stuff"} /> <TestFetch url={process.env.PUBLIC_URL + "/stuff"} />
<h1>IndexedDB playground:</h1>
<TestDBPlayground db_name="playground_db"/>
<h1>Test DB fetching:</h1> <h1>Test DB fetching:</h1>
<TestDBFetch sqlite_file={process.env.PUBLIC_URL + "/test.sqlite"} /> <TestDBFetch sqlite_file={process.env.PUBLIC_URL + "/digikam4.db"} />
</>, </>,
document.getElementById('root') document.getElementById('root')
); );

Loading…
Cancel
Save