From 9f32323a80924314e74f8c31f8d9431085518348 Mon Sep 17 00:00:00 2001 From: lana-k Date: Tue, 10 Aug 2021 20:31:12 +0200 Subject: [PATCH] fix column order in result set #74 --- package.json | 2 +- src/components/CsvImport/csv.js | 15 ++++- src/components/SqlTable/index.vue | 6 +- src/lib/database/_sql.js | 15 +++-- src/lib/database/index.js | 6 +- src/views/Main/AppDiagnosticInfo.vue | 4 +- src/views/Main/Workspace/Tabs/Tab/index.vue | 2 +- tests/components/CsvImport/CsvImport.spec.js | 67 ++++++++++++------- tests/components/CsvImport/csv.spec.js | 25 ++++--- tests/lib/database/_sql.spec.js | 49 ++++++++------ tests/lib/database/database.spec.js | 27 +++++--- tests/lib/database/sqliteExtensions.spec.js | 20 +++--- .../Main/Workspace/Schema/Schema.spec.js | 9 ++- 13 files changed, 155 insertions(+), 92 deletions(-) diff --git a/package.json b/package.json index fc52d50..0683549 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sqliteviz", - "version": "0.15.1", + "version": "0.15.2", "license": "Apache-2.0", "private": true, "scripts": { diff --git a/src/components/CsvImport/csv.js b/src/components/CsvImport/csv.js index 338e114..0ce1860 100644 --- a/src/components/CsvImport/csv.js +++ b/src/components/CsvImport/csv.js @@ -8,10 +8,15 @@ const hintsByCode = { export default { getResult (source) { - const result = {} + const result = { + columns: [] + } + const values = {} if (source.meta.fields) { source.meta.fields.forEach(col => { - result[col.trim()] = source.data.map(row => { + let colName = col.trim() + result.columns.push(colName) + values[colName] = source.data.map(row => { let value = row[col] if (value instanceof Date) { value = value.toISOString() @@ -21,7 +26,9 @@ export default { }) } else { for (let i = 0; i <= source.data[0].length - 1; i++) { - result[`col${i + 1}`] = source.data.map(row => { + let colName = `col${i + 1}` + result.columns.push(colName) + values[colName] = source.data.map(row => { let value = row[i] if (value instanceof Date) { value = value.toISOString() @@ -30,6 +37,8 @@ export default { }) } } + + result.values = values return result }, diff --git a/src/components/SqlTable/index.vue b/src/components/SqlTable/index.vue index ef2e063..908ac4d 100644 --- a/src/components/SqlTable/index.vue +++ b/src/components/SqlTable/index.vue @@ -30,7 +30,7 @@
- {{ dataSet[col][rowIndex - 1 + currentPageData.start] }} + {{ dataSet.values[col][rowIndex - 1 + currentPageData.start] }}
@@ -74,10 +74,10 @@ export default { }, computed: { columns () { - return Object.keys(this.dataSet) + return this.dataSet.columns }, rowCount () { - return this.dataSet[this.columns[0]].length + return this.dataSet.values[this.columns[0]].length }, cellStyle () { const eq = this.tableWidth / this.columns.length diff --git a/src/lib/database/_sql.js b/src/lib/database/_sql.js index ebe362f..2524491 100644 --- a/src/lib/database/_sql.js +++ b/src/lib/database/_sql.js @@ -48,17 +48,22 @@ export default class Sql { throw new Error('exec: Missing query string') } const sqlResults = this.db.exec(sql, params) - return sqlResults.map(result => _getDataSourcesFromSqlResult(result)) + return sqlResults.map(result => { + return { + columns: result.columns, + values: _getDataSourcesFromSqlResult(result) + } + }) } import (tabName, data, progressCounterId, progressCallback, chunkSize = 1500) { if (this.db === null) { this.createDb() } - const columns = Object.keys(data) - const rowCount = data[columns[0]].length - this.db.exec(dbUtils.getCreateStatement(tabName, data)) - const chunks = dbUtils.generateChunks(data, chunkSize) + const columns = data.columns + const rowCount = data.values[columns[0]].length + this.db.exec(dbUtils.getCreateStatement(tabName, data.values)) + const chunks = dbUtils.generateChunks(data.values, chunkSize) const chunksAmount = Math.ceil(rowCount / chunkSize) let count = 0 const insertStr = dbUtils.getInsertStmt(tabName, columns) diff --git a/src/lib/database/index.js b/src/lib/database/index.js index a46a82c..1f1dca3 100644 --- a/src/lib/database/index.js +++ b/src/lib/database/index.js @@ -88,11 +88,11 @@ class Database { const result = await this.execute(getSchemaSql) // Parse DDL statements to get column names and types const parsedSchema = [] - if (result && result.name) { - result.name.forEach((table, index) => { + if (result && result.values && result.values.name) { + result.values.name.forEach((table, index) => { parsedSchema.push({ name: table, - columns: stms.getColumns(result.sql[index]) + columns: stms.getColumns(result.values.sql[index]) }) }) } diff --git a/src/views/Main/AppDiagnosticInfo.vue b/src/views/Main/AppDiagnosticInfo.vue index d37bb35..3d21d60 100644 --- a/src/views/Main/AppDiagnosticInfo.vue +++ b/src/views/Main/AppDiagnosticInfo.vue @@ -44,13 +44,13 @@ export default { async created () { const state = this.$store.state - let result = await state.db.execute('select sqlite_version()') + let result = (await state.db.execute('select sqlite_version()')).values this.info.push({ name: 'SQLite version', info: result['sqlite_version()'] }) - result = await state.db.execute('PRAGMA compile_options') + result = (await state.db.execute('PRAGMA compile_options')).values this.info.push({ name: 'SQLite compile options', info: result.compile_options diff --git a/src/views/Main/Workspace/Tabs/Tab/index.vue b/src/views/Main/Workspace/Tabs/Tab/index.vue index ea9b6cb..321fb75 100644 --- a/src/views/Main/Workspace/Tabs/Tab/index.vue +++ b/src/views/Main/Workspace/Tabs/Tab/index.vue @@ -38,7 +38,7 @@ { sinon.stub(csv, 'parse').resolves({ delimiter: '|', data: { - col1: [1, 2], - col2: ['foo', 'bar'] + columns: ['col2', 'col1' ], + values: { + col1: [1, 2], + col2: ['foo', 'bar'] + } }, rowCount: 2, messages: [{ @@ -82,10 +85,10 @@ describe('CsvImport.vue', () => { expect(wrapper.findComponent({ name: 'check-box' }).vm.checked).to.equal(true) const rows = wrapper.findAll('tbody tr') expect(rows).to.have.lengthOf(2) - expect(rows.at(0).findAll('td').at(0).text()).to.equal('1') - expect(rows.at(0).findAll('td').at(1).text()).to.equal('foo') - expect(rows.at(1).findAll('td').at(0).text()).to.equal('2') - expect(rows.at(1).findAll('td').at(1).text()).to.equal('bar') + expect(rows.at(0).findAll('td').at(0).text()).to.equal('foo') + expect(rows.at(0).findAll('td').at(1).text()).to.equal('1') + expect(rows.at(1).findAll('td').at(0).text()).to.equal('bar') + expect(rows.at(1).findAll('td').at(1).text()).to.equal('2') expect(wrapper.findComponent({ name: 'logs' }).text()) .to.include('Information about row 0. Comma was used as a standart delimiter.') expect(wrapper.findComponent({ name: 'logs' }).text()) @@ -99,8 +102,11 @@ describe('CsvImport.vue', () => { parse.onCall(0).resolves({ delimiter: '|', data: { - col1: [1], - col2: ['foo'] + columns: ['col2', 'col1'], + values: { + col1: [1], + col2: ['foo'] + } }, rowCount: 1 }) @@ -113,8 +119,11 @@ describe('CsvImport.vue', () => { parse.onCall(1).resolves({ delimiter: ',', data: { - col1: [2], - col2: ['bar'] + columns: ['col2', 'col1'], + values: { + col1: [2], + col2: ['bar'] + } }, rowCount: 1, hasErrors: false @@ -125,16 +134,19 @@ describe('CsvImport.vue', () => { let rows = wrapper.findAll('tbody tr') expect(rows).to.have.lengthOf(1) - expect(rows.at(0).findAll('td').at(0).text()).to.equal('2') - expect(rows.at(0).findAll('td').at(1).text()).to.equal('bar') + expect(rows.at(0).findAll('td').at(0).text()).to.equal('bar') + expect(rows.at(0).findAll('td').at(1).text()).to.equal('2') expect(wrapper.findComponent({ name: 'logs' }).text()) .to.include('Preview parsing is completed in') parse.onCall(2).resolves({ delimiter: ',', data: { - col1: [3], - col2: ['baz'] + columns: ['col2', 'col1'], + values: { + col1: [3], + col2: ['baz'] + } }, rowCount: 1, hasErrors: true, @@ -152,8 +164,8 @@ describe('CsvImport.vue', () => { await csv.parse.returnValues[2] rows = wrapper.findAll('tbody tr') expect(rows).to.have.lengthOf(1) - expect(rows.at(0).findAll('td').at(0).text()).to.equal('3') - expect(rows.at(0).findAll('td').at(1).text()).to.equal('baz') + expect(rows.at(0).findAll('td').at(0).text()).to.equal('baz') + expect(rows.at(0).findAll('td').at(1).text()).to.equal('3') expect(wrapper.findComponent({ name: 'logs' }).text()) .to.contain('Error in row 0. Quote is missed. Edit your CSV so that the field has a closing quote char.') expect(wrapper.findComponent({ name: 'logs' }).text()) @@ -162,8 +174,11 @@ describe('CsvImport.vue', () => { parse.onCall(3).resolves({ delimiter: ',', data: { - col1: [4], - col2: ['qux'] + columns: ['col2', 'col1'], + values: { + col1: [4], + col2: ['qux'] + } }, rowCount: 1, hasErrors: false @@ -173,16 +188,19 @@ describe('CsvImport.vue', () => { await csv.parse.returnValues[3] rows = wrapper.findAll('tbody tr') expect(rows).to.have.lengthOf(1) - expect(rows.at(0).findAll('td').at(0).text()).to.equal('4') - expect(rows.at(0).findAll('td').at(1).text()).to.equal('qux') + expect(rows.at(0).findAll('td').at(0).text()).to.equal('qux') + expect(rows.at(0).findAll('td').at(1).text()).to.equal('4') expect(wrapper.findComponent({ name: 'logs' }).text()) .to.contain('Preview parsing is completed in') parse.onCall(4).resolves({ delimiter: ',', data: { - col1: [5], - col2: ['corge'] + columns: ['col2', 'col1'], + values: { + col1: [5], + col2: ['corge'] + } }, rowCount: 1, hasErrors: false @@ -192,8 +210,9 @@ describe('CsvImport.vue', () => { await csv.parse.returnValues[4] rows = wrapper.findAll('tbody tr') expect(rows).to.have.lengthOf(1) - expect(rows.at(0).findAll('td').at(0).text()).to.equal('5') - expect(rows.at(0).findAll('td').at(1).text()).to.equal('corge') + expect(rows.at(0).findAll('td').at(0).text()).to.equal('corge') + expect(rows.at(0).findAll('td').at(1).text()).to.equal('5') + expect(wrapper.findComponent({ name: 'logs' }).text()) .to.include('Preview parsing is completed in') }) diff --git a/tests/components/CsvImport/csv.spec.js b/tests/components/CsvImport/csv.spec.js index 43fcebd..c849962 100644 --- a/tests/components/CsvImport/csv.spec.js +++ b/tests/components/CsvImport/csv.spec.js @@ -19,9 +19,12 @@ describe('csv.js', () => { } } expect(csv.getResult(source)).to.eql({ - id: [1, 2], - name: ['foo', 'bar'], - date: ['2021-06-30T14:10:24.717Z', '2021-07-30T14:10:15.717Z'] + columns: ['id', 'name', 'date'], + values: { + id: [1, 2], + name: ['foo', 'bar'], + date: ['2021-06-30T14:10:24.717Z', '2021-07-30T14:10:15.717Z'] + } }) }) @@ -34,9 +37,12 @@ describe('csv.js', () => { meta: {} } expect(csv.getResult(source)).to.eql({ - col1: [1, 2], - col2: ['foo', 'bar'], - col3: ['2021-06-30T14:10:24.717Z', '2021-07-30T14:10:15.717Z'] + columns: ['col1', 'col2', 'col3'], + values: { + col1: [1, 2], + col2: ['foo', 'bar'], + col3: ['2021-06-30T14:10:24.717Z', '2021-07-30T14:10:15.717Z'] + } }) }) @@ -73,8 +79,11 @@ describe('csv.js', () => { const result = await csv.parse(file) expect(result).to.eql({ data: { - col1: [1, 2], - col2: ['foo', 'bar'] + columns: ['col1', 'col2'], + values: { + col1: [1, 2], + col2: ['foo', 'bar'] + } }, delimiter: ',', rowCount: 2, diff --git a/tests/lib/database/_sql.spec.js b/tests/lib/database/_sql.spec.js index e761452..dd9f035 100644 --- a/tests/lib/database/_sql.spec.js +++ b/tests/lib/database/_sql.spec.js @@ -35,9 +35,12 @@ describe('_sql.js', () => { const result = sql.exec('SELECT * from test') expect(result).to.have.lengthOf(1) expect(result[0]).to.eql({ - id: [1, 2], - name: ['Harry Potter', 'Draco Malfoy'], - faculty: ['Griffindor', 'Slytherin'] + columns: ['id', 'name','faculty'], + values: { + id: [1, 2], + name: ['Harry Potter', 'Draco Malfoy'], + faculty: ['Griffindor', 'Slytherin'] + } }) }) @@ -64,13 +67,16 @@ describe('_sql.js', () => { it('imports', async () => { const data = { - id: [1, 2, 3, 4], - name: [ - 'Harry Potter', - 'Draco Malfoy', - 'Hermione Granger', - 'Ron Weasley' - ] + columns: ['id', 'name'], + values: { + id: [1, 2, 3, 4], + name: [ + 'Harry Potter', + 'Draco Malfoy', + 'Hermione Granger', + 'Ron Weasley' + ] + } } const progressCallback = sinon.stub() const progressCounterId = 1 @@ -104,7 +110,7 @@ describe('_sql.js', () => { anotherSql.open(data) const result = anotherSql.exec('SELECT * from test') expect(result).to.have.lengthOf(1) - expect(result[0]).to.eql({ + expect(result[0].values).to.eql({ id: [1, 2], name: ['Harry Potter', 'Draco Malfoy'], faculty: ['Griffindor', 'Slytherin'] @@ -146,26 +152,29 @@ describe('_sql.js', () => { `) let result = sql.exec('SELECT * from test') - expect(result[0]).to.eql({ + expect(result[0].values).to.eql({ id: [1, 2], name: ['foo', 'bar'] }) const data = { - id: [1, 2, 3, 4], - name: [ - 'Harry Potter', - 'Draco Malfoy', - 'Hermione Granger', - 'Ron Weasley' - ] + columns: ['id', 'name'], + values: { + id: [1, 2, 3, 4], + name: [ + 'Harry Potter', + 'Draco Malfoy', + 'Hermione Granger', + 'Ron Weasley' + ] + } } // import adds table sql.import('foo', data, 1, sinon.stub(), 2) result = sql.exec('SELECT * from foo') expect(result[0]).to.eql(data) result = sql.exec('SELECT * from test') - expect(result[0]).to.eql({ + expect(result[0].values).to.eql({ id: [1, 2], name: ['foo', 'bar'] }) diff --git a/tests/lib/database/database.spec.js b/tests/lib/database/database.spec.js index 3f5b72c..8c965c7 100644 --- a/tests/lib/database/database.spec.js +++ b/tests/lib/database/database.spec.js @@ -85,7 +85,7 @@ describe('database.js', () => { await db.loadDb(buffer) const result = await db.execute('SELECT * from test limit 1; SELECT * from test;') - expect(result).to.eql({ + expect(result.values).to.eql({ id: [1, 2], name: ['Harry Potter', 'Draco Malfoy'], faculty: ['Griffindor', 'Slytherin'] @@ -116,9 +116,12 @@ describe('database.js', () => { it('adds table from csv', async () => { const data = { - id: [1, 2], - name: ['Harry Potter', 'Draco Malfoy'], - faculty: ['Griffindor', 'Slytherin'] + columns: ['id', 'name','faculty'], + values: { + id: [1, 2], + name: ['Harry Potter', 'Draco Malfoy'], + faculty: ['Griffindor', 'Slytherin'] + } } const progressHandler = sinon.spy() const progressCounterId = db.createProgressCounter(progressHandler) @@ -144,9 +147,12 @@ describe('database.js', () => { it('addTableFromCsv throws errors', async () => { const data = { - id: [1, 2], - name: ['Harry Potter', 'Draco Malfoy'], - faculty: null + columns: [], + values: { + id: [1, 2], + name: ['Harry Potter', 'Draco Malfoy'], + faculty: null + } } const progressHandler = sinon.stub() const progressCounterId = db.createProgressCounter(progressHandler) @@ -214,8 +220,11 @@ describe('database.js', () => { // check that new db works and has the same table and data result = await anotherDb.execute('SELECT * from foo') expect(result).to.eql({ - id: [1], - name: ['Harry Potter'] + columns: ['id', 'name'], + values: { + id: [1], + name: ['Harry Potter'] + } }) }) diff --git a/tests/lib/database/sqliteExtensions.spec.js b/tests/lib/database/sqliteExtensions.spec.js index e36db0a..32004f0 100644 --- a/tests/lib/database/sqliteExtensions.spec.js +++ b/tests/lib/database/sqliteExtensions.spec.js @@ -37,7 +37,7 @@ describe('SQLite extensions', function () { abs(pi() / 2 - atan2(1, 0)) < 0.000001 `) - expect(actual).to.eql({ + expect(actual.values).to.eql({ 'abs(3.1415926 - pi()) < 0.000001': [1], 'abs(1 - cos(2 * pi())) < 0.000001': [1], 'abs(0 - sin(pi())) < 0.000001': [1], @@ -71,7 +71,7 @@ describe('SQLite extensions', function () { ceil(-1.95) + ceil(1.95), floor(-1.95) + floor(1.95) `) - expect(actual).to.eql({ + expect(actual.values).to.eql({ 'exp(0)': [1], 'log(exp(1))': [1], 'log10(10000)': [4], @@ -99,7 +99,7 @@ describe('SQLite extensions', function () { padc('foo', 5), strfilter('abcba', 'bc') `) - expect(actual).to.eql({ + expect(actual.values).to.eql({ "replicate('ab', 4)": ['abababab'], "charindex('ab', 'foobarabbarfoo')": [7], "charindex('ab', 'foobarabbarfoo', 8)": [0], @@ -137,7 +137,7 @@ describe('SQLite extensions', function () { VALUES (1) ) `) - expect(actual).to.eql({ + expect(actual.values).to.eql({ 'abs( 3.77406806 - stdev(x)) < 0.000001': [1], 'abs(14.24358974 - variance(x)) < 0.000001': [1], 'mode(x)': [1], @@ -152,7 +152,7 @@ describe('SQLite extensions', function () { SELECT value FROM generate_series(5, 20, 5) `) - expect(actual).to.eql({ + expect(actual.values).to.eql({ value: [5, 10, 15, 20] }) }) @@ -194,7 +194,7 @@ describe('SQLite extensions', function () { WHERE nc.root = 2 AND nc.depth = 2 ); `) - expect(actual).to.eql({ + expect(actual.values).to.eql({ name: [ '_sql.spec.js', '_statements.spec.js', @@ -212,7 +212,7 @@ describe('SQLite extensions', function () { length(uuid()) as length, uuid_str(uuid_blob('26a8349c8a7f4cbeb519bf792c3d7ac6')) as uid `) - expect(actual).to.eql({ + expect(actual.values).to.eql({ length: [36], uid: ['26a8349c-8a7f-4cbe-b519-bf792c3d7ac6'] }) @@ -225,7 +225,7 @@ describe('SQLite extensions', function () { regexpi('=\\s?\\d+', 'const foo = 123; const bar = "bar"') as two, 'const foo = 123; const bar = "bar"' REGEXP '=\\s?\\d+' as three `) - expect(actual).to.eql({ + expect(actual.values).to.eql({ one: [1], two: [1], three: [1] @@ -260,7 +260,7 @@ describe('SQLite extensions', function () { ALTER TABLE surface DROP COLUMN rownum; SELECT * FROM surface; `) - expect(actual).to.eql({ + expect(actual.values).to.eql({ x: [5, 10, 15], y: [3, 6, 9], '5.0': [3.2, 4.3, 5.4], @@ -292,7 +292,7 @@ describe('SQLite extensions', function () { WHERE body MATCH '"full-text" NOT document' ORDER BY rank; `) - expect(actual).to.eql({ + expect(actual.values).to.eql({ sender: ['bar@localhost'] }) }) diff --git a/tests/views/Main/Workspace/Schema/Schema.spec.js b/tests/views/Main/Workspace/Schema/Schema.spec.js index 6f8a429..1d20de5 100644 --- a/tests/views/Main/Workspace/Schema/Schema.spec.js +++ b/tests/views/Main/Workspace/Schema/Schema.spec.js @@ -129,8 +129,11 @@ describe('Schema.vue', () => { sinon.stub(csv, 'parse').resolves({ delimiter: '|', data: { - col1: [1], - col2: ['foo'] + columns: ['col1', 'col2'], + values: { + col1: [1], + col2: ['foo'] + } }, hasErrors: false, messages: [] @@ -168,7 +171,7 @@ describe('Schema.vue', () => { ]) const res = await wrapper.vm.$store.state.db.execute('select * from test') - expect(res).to.eql({ + expect(res.values).to.eql({ col1: [1], col2: ['foo'] })