diff --git a/src/dataBase.js b/src/dataBase.js index d2e31a6..73f380c 100644 --- a/src/dataBase.js +++ b/src/dataBase.js @@ -1,3 +1,4 @@ +import sqliteParser from 'sqlite-parser' const worker = new Worker('js/worker.sql-wasm.js') export default { @@ -15,9 +16,19 @@ export default { // 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: event.data.results[0].values + schema: parsedSchema }) } worker.postMessage({ action: 'exec', sql: getSchemaSql }) @@ -45,3 +56,47 @@ export default { }) } } + +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 +} diff --git a/src/store/index.js b/src/store/index.js index 3e558fd..093e4e0 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,46 +1,8 @@ import Vue from 'vue' import Vuex from 'vuex' -import sqliteParser from 'sqlite-parser' Vue.use(Vuex) -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) -} - -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 -} - export default new Vuex.Store({ state: { schema: null, @@ -55,14 +17,7 @@ export default new Vuex.Store({ mutations: { saveSchema (state, { dbName, schema }) { state.dbName = dbName - const parsedSchema = [] - schema.forEach(item => { - parsedSchema.push({ - name: item[0], - columns: getColumns(item[1]) - }) - }) - state.schema = parsedSchema + state.schema = schema }, saveDbFile (state, file) { state.dbFile = file diff --git a/tests/unit/dataBase.spec.js b/tests/unit/dataBase.spec.js index 81415da..8aeb8f3 100644 --- a/tests/unit/dataBase.spec.js +++ b/tests/unit/dataBase.spec.js @@ -30,10 +30,14 @@ describe('dataBase.js', () => { const buffer = new Blob([data]) return db.loadDb(buffer) }) - .then(schema => { + .then(({dbName, schema}) => { + console.log(schema[0].columns) expect(schema.length).to.equal(1) - expect(schema[0][0]).to.equal('test') - expect(schema[0][1]).to.equal('CREATE TABLE test (col1, col2)') + expect(schema[0].name).to.equal('test') + expect(schema[0].columns[0].name).to.equal('col1') + expect(schema[0].columns[0].type).to.equal('N/A') + expect(schema[0].columns[1].name).to.equal('col2') + expect(schema[0].columns[1].type).to.equal('N/A') }) }) }) \ No newline at end of file