mirror of
https://github.com/lana-k/sqliteviz.git
synced 2025-12-06 18:18:53 +08:00
103 lines
3.1 KiB
JavaScript
103 lines
3.1 KiB
JavaScript
import sqliteParser from 'sqlite-parser'
|
|
const worker = new Worker('js/worker.sql-wasm.js')
|
|
|
|
export default {
|
|
loadDb (file) {
|
|
return new Promise((resolve, reject) => {
|
|
const f = file
|
|
const r = new FileReader()
|
|
r.onload = () => {
|
|
// on 'action: open' completed
|
|
worker.onmessage = () => {
|
|
const getSchemaSql = `
|
|
SELECT name, sql
|
|
FROM sqlite_master
|
|
WHERE type='table' AND name NOT LIKE 'sqlite_%';`
|
|
|
|
// on 'action: exec' completed
|
|
worker.onmessage = event => {
|
|
// Parse DDL statements to get column names and types
|
|
const parsedSchema = []
|
|
event.data.results[0].values.forEach(item => {
|
|
parsedSchema.push({
|
|
name: item[0],
|
|
columns: getColumns(item[1])
|
|
})
|
|
})
|
|
|
|
// Return db name and schema
|
|
resolve({
|
|
dbName: file.name,
|
|
schema: parsedSchema
|
|
})
|
|
}
|
|
worker.postMessage({ action: 'exec', sql: getSchemaSql })
|
|
}
|
|
|
|
try {
|
|
worker.postMessage({ action: 'open', buffer: r.result }, [r.result])
|
|
} catch (exception) {
|
|
worker.postMessage({ action: 'open', buffer: r.result })
|
|
}
|
|
}
|
|
r.readAsArrayBuffer(f)
|
|
})
|
|
},
|
|
execute (commands) {
|
|
return new Promise((resolve, reject) => {
|
|
worker.onmessage = (event) => {
|
|
if (event.data.error) {
|
|
reject(event.data.error)
|
|
}
|
|
// if it was more than one select - take only the first one
|
|
resolve(event.data.results[0])
|
|
}
|
|
worker.postMessage({ action: 'exec', sql: commands })
|
|
})
|
|
}
|
|
}
|
|
|
|
function getAst (sql) {
|
|
// There is a bug is sqlite-parser
|
|
// It throws an error if tokenizer has an arguments:
|
|
// https://github.com/codeschool/sqlite-parser/issues/59
|
|
const fixedSql = sql
|
|
.replace(/(?<=tokenize=.+)"tokenchars=.+"/, '')
|
|
.replace(/(?<=tokenize=.+)"remove_diacritics=.+"/, '')
|
|
.replace(/(?<=tokenize=.+)"separators=.+"/, '')
|
|
.replace(/tokenize=.+(?=(,|\)))/, 'tokenize=unicode61')
|
|
|
|
return sqliteParser(fixedSql)
|
|
}
|
|
|
|
/*
|
|
* Return an array of columns with name and type. E.g.:
|
|
* [
|
|
* { name: 'id', type: 'INTEGER' },
|
|
* { name: 'title', type: 'NVARCHAR(30)' },
|
|
* ]
|
|
*/
|
|
function getColumns (sql) {
|
|
const columns = []
|
|
const ast = getAst(sql)
|
|
|
|
const columnDefinition = ast.statement[0].format === 'table'
|
|
? ast.statement[0].definition
|
|
: ast.statement[0].result.args.expression // virtual table
|
|
|
|
columnDefinition.forEach(item => {
|
|
if (item.variant === 'column' && ['identifier', 'definition'].includes(item.type)) {
|
|
let type = item.datatype ? item.datatype.variant : 'N/A'
|
|
if (item.datatype && item.datatype.args) {
|
|
type = type + '(' + item.datatype.args.expression[0].value
|
|
if (item.datatype.args.expression.length === 2) {
|
|
type = type + ', ' + item.datatype.args.expression[1].value
|
|
}
|
|
type = type + ')'
|
|
}
|
|
columns.push({ name: item.name, type: type })
|
|
}
|
|
})
|
|
return columns
|
|
}
|