sqlite: pull table schema

This commit is contained in:
mappu 2024-06-08 14:23:38 +12:00
parent 232a1dd0e8
commit 00a96bfe84
3 changed files with 47 additions and 14 deletions

View File

@ -82,7 +82,7 @@ var _ loadedDatabase = &boltLoadedDatabase{} // interface assertion
// //
func (f *TMainForm) addDatabaseFromFile(path string) { func (f *TMainForm) boltAddDatabaseFromFile(path string) {
// TODO load in background thread to stop blocking the UI // TODO load in background thread to stop blocking the UI
db, err := bbolt.Open(path, 0644, &bbolt.Options{Timeout: 1 * time.Second}) db, err := bbolt.Open(path, 0644, &bbolt.Options{Timeout: 1 * time.Second})
if err != nil { if err != nil {

31
main.go
View File

@ -41,14 +41,19 @@ func (f *TMainForm) OnFormCreate(sender vcl.IObject) {
mnuFile.SetCaption("File") mnuFile.SetCaption("File")
mnuFileOpen := vcl.NewMenuItem(mnuFile) mnuFileOpen := vcl.NewMenuItem(mnuFile)
mnuFileOpen.SetCaption("Open...") mnuFileOpen.SetCaption("Open Bolt database...")
mnuFileOpen.SetShortCutFromString("Ctrl+O") mnuFileOpen.SetShortCutFromString("Ctrl+O")
mnuFileOpen.SetOnClick(f.OnMnuFileOpenClick) mnuFileOpen.SetOnClick(f.OnMnuFileOpenClick)
mnuFile.Add(mnuFileOpen) mnuFile.Add(mnuFileOpen)
mnuFileSqliteOpen := vcl.NewMenuItem(mnuFile)
mnuFileSqliteOpen.SetCaption("Open SQLite database...")
mnuFileSqliteOpen.SetOnClick(f.OnMnuFileSqliteOpenClick)
mnuFile.Add(mnuFileSqliteOpen)
mnuFileSqliteMemory := vcl.NewMenuItem(mnuFile) mnuFileSqliteMemory := vcl.NewMenuItem(mnuFile)
mnuFileSqliteMemory.SetCaption("New SQLite in-memory database") mnuFileSqliteMemory.SetCaption("New SQLite in-memory database")
mnuFileSqliteMemory.SetOnClick(f.OnmnuFileSqliteMemoryClick) mnuFileSqliteMemory.SetOnClick(f.OnMnuFileSqliteMemoryClick)
mnuFile.Add(mnuFileSqliteMemory) mnuFile.Add(mnuFileSqliteMemory)
mnuSep := vcl.NewMenuItem(mnuFile) mnuSep := vcl.NewMenuItem(mnuFile)
@ -116,21 +121,31 @@ func (f *TMainForm) OnFormCreate(sender vcl.IObject) {
func (f *TMainForm) OnMnuFileOpenClick(sender vcl.IObject) { func (f *TMainForm) OnMnuFileOpenClick(sender vcl.IObject) {
dlg := vcl.NewOpenDialog(f) dlg := vcl.NewOpenDialog(f)
dlg.SetTitle("Select a database file...") dlg.SetTitle("Select a database file...")
dlg.SetFilter("Bolt database|*.db|SQLite database|*.db3|All files|*.*") dlg.SetFilter("Bolt database|*.db|All files|*.*")
ret := dlg.Execute() // Fake blocking ret := dlg.Execute() // Fake blocking
if ret { if ret {
f.addDatabaseFromFile(dlg.FileName()) f.boltAddDatabaseFromFile(dlg.FileName())
} }
} }
func (f *TMainForm) OnMnuFileSqliteOpenClick(sender vcl.IObject) {
dlg := vcl.NewOpenDialog(f)
dlg.SetTitle("Select a database file...")
dlg.SetFilter("SQLite database|*.db;*.db3;*.sqlite;*.sqlite3|All files|*.*")
ret := dlg.Execute() // Fake blocking
if ret {
f.sqliteAddDatabaseFromFile(dlg.FileName())
}
}
func (f *TMainForm) OnMnuFileSqliteMemoryClick(sender vcl.IObject) {
f.sqliteAddDatabaseFromFile(`:memory:`)
}
func (f *TMainForm) OnMnuFileExitClick(sender vcl.IObject) { func (f *TMainForm) OnMnuFileExitClick(sender vcl.IObject) {
os.Exit(0) os.Exit(0)
} }
func (f *TMainForm) OnmnuFileSqliteMemoryClick(sender vcl.IObject) {
f.SQLite_AddFromFile(`:memory:`)
}
func (f *TMainForm) OnNavChange(sender vcl.IObject, node *vcl.TTreeNode) { func (f *TMainForm) OnNavChange(sender vcl.IObject, node *vcl.TTreeNode) {
if node.Data() == nil { if node.Data() == nil {

View File

@ -49,10 +49,24 @@ func (ld *sqliteLoadedDatabase) RenderForNav(f *TMainForm, ndata *navData) {
f.contentBox.SetEnabled(false) f.contentBox.SetEnabled(false)
f.contentBox.Clear() f.contentBox.Clear()
} else if ndata.bucketPath[0] == sqliteTablesCaption { } else if len(ndata.bucketPath) == 2 && ndata.bucketPath[0] == sqliteTablesCaption {
// Render for specific table // Render for specific table
f.propertiesBox.SetText(fmt.Sprintf("Selected table %q", ndata.bucketPath[1])) tableName := ndata.bucketPath[1]
// Load schema
// Get some basic properties
r := ld.db.QueryRow(`SELECT sql FROM sqlite_schema WHERE name = ?;`, tableName)
var schemaStmt string
err := r.Scan(&schemaStmt)
if err != nil {
schemaStmt = fmt.Sprintf("* Failed to describe table %q: %s", tableName, err.Error())
}
// Display table properties
f.propertiesBox.SetText(fmt.Sprintf("Selected table %q\n\nSchema:\n\n%s", tableName, schemaStmt))
// Load column details
ld.db.Query(`pragma table_info(?)`, tableName)
// Select * with small limit // Select * with small limit
f.contentBox.SetEnabled(false) f.contentBox.SetEnabled(false)
f.contentBox.Clear() f.contentBox.Clear()
@ -71,7 +85,7 @@ func (ld *sqliteLoadedDatabase) NavChildren(ndata *navData) ([]string, error) {
return []string{sqliteTablesCaption}, nil return []string{sqliteTablesCaption}, nil
} }
if ndata.bucketPath[0] == sqliteTablesCaption { if len(ndata.bucketPath) == 1 && ndata.bucketPath[0] == sqliteTablesCaption {
rr, err := ld.db.Query(`SELECT name FROM sqlite_master WHERE type='table' ORDER BY name ASC;`) rr, err := ld.db.Query(`SELECT name FROM sqlite_master WHERE type='table' ORDER BY name ASC;`)
if err != nil { if err != nil {
return nil, err return nil, err
@ -95,6 +109,10 @@ func (ld *sqliteLoadedDatabase) NavChildren(ndata *navData) ([]string, error) {
return gather, nil return gather, nil
} }
if len(ndata.bucketPath) == 2 {
return nil, nil // Never any deeper children
}
return nil, fmt.Errorf("unknown nav path %#v", ndata.bucketPath) return nil, fmt.Errorf("unknown nav path %#v", ndata.bucketPath)
} }
@ -102,7 +120,7 @@ var _ loadedDatabase = &sqliteLoadedDatabase{} // interface assertion
// //
func (f *TMainForm) SQLite_AddFromFile(path string) { func (f *TMainForm) sqliteAddDatabaseFromFile(path string) {
// TODO load in background thread to stop blocking the UI // TODO load in background thread to stop blocking the UI
db, err := sql.Open("sqlite3", path) db, err := sql.Open("sqlite3", path)