diff --git a/src/lib/database/_statements.js b/src/lib/database/_statements.js index eb0652c..3a89b62 100644 --- a/src/lib/database/_statements.js +++ b/src/lib/database/_statements.js @@ -1,5 +1,3 @@ -import sqliteParser from 'sqlite-parser' - export default { * generateChunks (data, size) { const matrix = Object.keys(data).map(col => data[col]) @@ -47,49 +45,5 @@ export default { result = result.replace(/,\s$/, ');') return result - }, - - 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=.+?"/, '$1') - .replace(/(tokenize=[^,]+)"remove_diacritics=.+?"/, '$1') - .replace(/(tokenize=[^,]+)"separators=.+?"/, '$1') - .replace(/tokenize=.+?(,|\))/, 'tokenize=unicode61$1') - - return sqliteParser(fixedSql) - }, - - /* - * Return an array of columns with name and type. E.g.: - * [ - * { name: 'id', type: 'INTEGER' }, - * { name: 'title', type: 'NVARCHAR(30)' }, - * ] - */ - getColumns (sql) { - const columns = [] - const ast = this.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/lib/database/index.js b/src/lib/database/index.js index 1f1dca3..92264d6 100644 --- a/src/lib/database/index.js +++ b/src/lib/database/index.js @@ -1,4 +1,3 @@ -import stms from './_statements' import fu from '@/lib/utils/fileIo' // We can import workers like so because of worker-loader: // https://webpack.js.org/loaders/worker-loader/ @@ -81,24 +80,14 @@ class Database { async refreshSchema () { const getSchemaSql = ` - SELECT name, sql - FROM sqlite_master - WHERE type='table' AND name NOT LIKE 'sqlite_%'; + WITH columns as (SELECT a.tbl_name, json_group_array(json_object('name', b.name,'type', IIF(b.type = '', 'N/A', b.type))) as column_json + FROM sqlite_master a, pragma_table_info(a.name) b + WHERE a.type in ('table','view') AND a.name NOT LIKE 'sqlite_%' group by tbl_name + ) + SELECT json_group_array(json_object('name',tbl_name, 'columns', json(column_json))) objects from columns; ` const result = await this.execute(getSchemaSql) - // Parse DDL statements to get column names and types - const parsedSchema = [] - if (result && result.values && result.values.name) { - result.values.name.forEach((table, index) => { - parsedSchema.push({ - name: table, - columns: stms.getColumns(result.values.sql[index]) - }) - }) - } - - // Refresh schema - this.schema = parsedSchema + this.schema = JSON.parse(result.values.objects[0]) } async execute (commands) { diff --git a/tests/lib/database/_statements.spec.js b/tests/lib/database/_statements.spec.js index 1d44633..d0c1a55 100644 --- a/tests/lib/database/_statements.spec.js +++ b/tests/lib/database/_statements.spec.js @@ -35,32 +35,4 @@ describe('_statements.js', () => { 'CREATE table "foo"("id" REAL, "name" TEXT, "isAdmin" INTEGER, "startDate" TEXT);' ) }) - - it('getColumns', () => { - const sql = `CREATE TABLE test ( - col1, - col2 integer, - col3 decimal(5,2), - col4 varchar(30) - )` - expect(stmts.getColumns(sql)).to.eql([ - { name: 'col1', type: 'N/A' }, - { name: 'col2', type: 'integer' }, - { name: 'col3', type: 'decimal(5, 2)' }, - { name: 'col4', type: 'varchar(30)' } - ]) - }) - - it('getColumns with virtual table', async () => { - const sql = ` - CREATE VIRTUAL TABLE test_virtual USING fts4( - col1, col2, - notindexed=col1, notindexed=col2, - tokenize=unicode61 "tokenchars=.+#") - ` - expect(stmts.getColumns(sql)).to.eql([ - { name: 'col1', type: 'N/A' }, - { name: 'col2', type: 'N/A' } - ]) - }) }) diff --git a/tests/lib/database/database.spec.js b/tests/lib/database/database.spec.js index 082beab..0a13a1d 100644 --- a/tests/lib/database/database.spec.js +++ b/tests/lib/database/database.spec.js @@ -133,9 +133,9 @@ describe('database.js', () => { expect(db.schema).to.have.lengthOf(1) expect(db.schema[0].name).to.equal('foo') expect(db.schema[0].columns).to.have.lengthOf(3) - expect(db.schema[0].columns[0]).to.eql({ name: 'id', type: 'real' }) - expect(db.schema[0].columns[1]).to.eql({ name: 'name', type: 'text' }) - expect(db.schema[0].columns[2]).to.eql({ name: 'faculty', type: 'text' }) + expect(db.schema[0].columns[0]).to.eql({ name: 'id', type: 'REAL' }) + expect(db.schema[0].columns[1]).to.eql({ name: 'name', type: 'TEXT' }) + expect(db.schema[0].columns[2]).to.eql({ name: 'faculty', type: 'TEXT' }) const result = await db.execute('SELECT * from foo') expect(result).to.eql(data) diff --git a/tests/views/Main/Workspace/Schema/Schema.spec.js b/tests/views/Main/Workspace/Schema/Schema.spec.js index 1d20de5..d0680dc 100644 --- a/tests/views/Main/Workspace/Schema/Schema.spec.js +++ b/tests/views/Main/Workspace/Schema/Schema.spec.js @@ -166,8 +166,8 @@ describe('Schema.vue', () => { await state.db.refreshSchema.returnValues[0] expect(wrapper.vm.$store.state.db.schema).to.eql([ - { name: 'test', columns: [{ name: 'col1', type: 'real' }, { name: 'col2', type: 'text' }] }, - { name: 'foo', columns: [{ name: 'id', type: 'N/A' }] } + { name: 'foo', columns: [{ name: 'id', type: 'N/A' }] }, + { name: 'test', columns: [{ name: 'col1', type: 'REAL' }, { name: 'col2', type: 'TEXT' }] } ]) const res = await wrapper.vm.$store.state.db.execute('select * from test')