UNPKG

sqlite-plugin-red

Version:

Adding a tab to show and edit the structure of a sqlite database. Needs node-red-node-sqlite.

185 lines (170 loc) 5.2 kB
const { setError } = require('./error.js') const getDefaultTable = () => { return { edit: false, editTableName: false, name: '', oldName: '', isNameUnique: true, isNew: false, header: [ { name: 'id', edit: false }, { name: 'Name', type: 'text' }, { name: 'Type', type: 'select', options: [ { value: 'TEXT', name: 'TEXT' }, { value: 'INTEGER', name: 'INTEGER' }, { value: 'BLOB', name: 'BLOB' }, { value: 'REAL', name: 'REAL' }, { value: 'NUMERIC', name: 'NUMERIC' }, ], }, { name: 'Not null', type: 'checkbox'}, { name: 'Primary key', type: 'checkbox'}, { name: 'Autoincr.', type: 'checkbox'}, { name: 'Unique', type: 'checkbox'} ], rows: [], disableCreation: true, hasAutoincrement: false } } const getIndexes = (header) => { i = { name: header.findIndex(h => h.name === 'Name'), type: header.findIndex(h => h.name === 'Type' ), notnull: header.findIndex(h => h.name === 'Not null' ), pk: header.findIndex(h => h.name === 'Primary key' ), ai: header.findIndex(h => h.name === 'Autoincr.' ), unique: header.findIndex(h => h.name === 'Unique' ) } return i } const createFieldSql = (row, indexes) => { let fieldSql = '' fieldSql += `"${row[indexes.name]}" ${row[indexes.type]}` if (row[indexes.notnull]) fieldSql += ' NOT NULL' if (row[indexes.unique]) fieldSql += ' UNIQUE' return fieldSql } const createPrimaryFieldSql = (row, indexes, primaryKey='') => { if (row[indexes.pk]) { if (!primaryKey) { primaryKey = ', PRIMARY KEY("' + row[indexes.name] + '"' } else { if (primaryKey.endsWith(')')) primaryKey = primaryKey.substring(0, primaryKey.length - 1) primaryKey += ',' + row[indexes.name] } if (row[indexes.ai]) primaryKey += ' AUTOINCREMENT' primaryKey += ')' return primaryKey } return '' } const createFieldsSql = (table) => { const header = table.header const rows = table.rows let fieldDef = '' let primaryKey = '' const indexes = getIndexes(header) rows.forEach(row => { if (fieldDef) fieldDef += ', ' fieldDef += createFieldSql(row, indexes) primaryKey += createPrimaryFieldSql(row, indexes, primaryKey) }) return '(' + fieldDef + ' ' + primaryKey + ')' } const createTableSql = (path, table, copyTableName) => { const fieldSql = createFieldsSql(table) if (!path) { error = 'Database not found!' setError(error) throw new Error(error) } if (table.oldName) { return `CREATE TABLE "__${table.name}_new" ${fieldSql};` } else { let name = table.name if (copyTableName) name = copyTableName return `CREATE TABLE "${name}" ${fieldSql};` } } // const handleAutoincrement = (table, i) => { // const rows = table.rows // const index = getIndexes(table.header) // // rows[i].ai = !rows[i].ai // table.hasAutoincrement = rows[i].ai // // like highlander... there can only be one (autoincr and then also only one pk) // if (rows[i].ai) { // rows.forEach((row, index) => { // if (index === i) { // row.type = 'INTEGER' // row.pk = true // } else { // row.ai = false // row.pk = false // } // }) // } // return table // } const checkTableAndFieldName = (selected, table) => { const index = getIndexes(table.header) table.disableCreation = true // check if name already in db table.isNameUnique = true selected.database.forEach(t => { if (t.name.toLowerCase() === table.name.toLowerCase()) table.isNameUnique = false }) const isFieldNameEmpty = !!(table?.rows.find(f => f[index.name].trim() === '')) const fieldnames = table.rows.map(f => f[index.name]) const hasFieldNameDuplicates = fieldnames.some((val, i) => fieldnames.indexOf(val) !== i) if (table.name && table.isNameUnique && !isFieldNameEmpty && !hasFieldNameDuplicates) { table.disableCreation = false } return table } const prepareNewTable = (table, newTable) => { table = getDefaultTable() table.isNew = newTable table.edit = newTable table.name = '' table.oldName = '' return table } const prepareTable = (table, selected) => { if (selected.table !== null) { table = getDefaultTable() table.name = selected.database[selected.table].name const indexes = getIndexes(table.header) selected.database[selected.table].columns.forEach((col, i) => { const newRow = new Array(table.header.length).fill('') newRow[0] = i for (const [key, value] of Object.entries(col)) { if (indexes[key]) newRow[indexes[key]] = value } table.rows.push(newRow) }) } return table } const prepareEditTableName = (table, selected) => { table.editTableName = !table.editTableName table.name = selected.database[selected.table].name table.oldName = selected.database[selected.table].name return table } module.exports = { getDefaultTable, getIndexes, createFieldsSql, createFieldSql, createPrimaryFieldSql, createTableSql, checkTableAndFieldName, prepareNewTable, prepareTable, prepareEditTableName }