diff --git a/src/components/Schema.vue b/src/components/Schema.vue
index 316ae9b..34da10f 100644
--- a/src/components/Schema.vue
+++ b/src/components/Schema.vue
@@ -31,9 +31,9 @@
diff --git a/src/components/SqlEditor.vue b/src/components/SqlEditor.vue
index 65e87ea..a0d60d9 100644
--- a/src/components/SqlEditor.vue
+++ b/src/components/SqlEditor.vue
@@ -17,11 +17,11 @@ import { debounce } from 'debounce'
const sqlHint = CM.hint.sql
CM.hint.sql = (cm, options) => {
- const token = cm.getTokenAt(cm.getCursor()).string
+ const token = cm.getTokenAt(cm.getCursor()).string.toUpperCase()
const result = sqlHint(cm, options)
// Don't show the hint if there is only one option
// and the token is already completed with this option
- if (result.list.length === 1 && result.list[0].text === token) {
+ if (result.list.length === 1 && result.list[0].text.toUpperCase() === token) {
result.list = []
}
return result
@@ -46,13 +46,24 @@ export default {
}
}
},
+ computed: {
+ tables () {
+ const tables = {}
+ if (this.$store.state.schema) {
+ this.$store.state.schema.forEach(table => {
+ tables[table.name] = table.columns.map(column => column.name)
+ })
+ }
+ return tables
+ }
+ },
watch: {
query () {
this.$emit('input', this.query)
}
},
methods: {
- onCmChange: debounce((editor) => {
+ onCmChange: debounce(function (editor) {
// Don't show autocomplete after a space or semicolon or in string literals
const ch = editor.getTokenAt(editor.getCursor()).string.slice(-1)
const tokenType = editor.getTokenAt(editor.getCursor()).type
@@ -61,7 +72,7 @@ export default {
}
const hintOptions = {
- // tables: {table: [col1, col2], table2: [colA, colB]},
+ tables: this.tables,
completeSingle: false,
completeOnSingleClick: true,
alignWithWord: false
diff --git a/src/components/TableDescription.vue b/src/components/TableDescription.vue
index 755f433..2b5ac7a 100644
--- a/src/components/TableDescription.vue
+++ b/src/components/TableDescription.vue
@@ -27,51 +27,14 @@
diff --git a/src/store/index.js b/src/store/index.js
index f20ddf5..8c5ca71 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1,8 +1,46 @@
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,
@@ -16,7 +54,14 @@ export default new Vuex.Store({
},
mutations: {
saveSchema (state, schema) {
- state.schema = schema
+ const parsedSchema = []
+ schema.forEach(item => {
+ parsedSchema.push({
+ name: item[0],
+ columns: getColumns(item[1])
+ })
+ })
+ state.schema = parsedSchema
},
saveDbFile (state, file) {
state.dbFile = file