diff --git a/sqlite.go b/sqlite.go index 47a75b8..cbaf656 100644 --- a/sqlite.go +++ b/sqlite.go @@ -77,36 +77,16 @@ func (ld *sqliteLoadedDatabase) RenderForNav(f *TMainForm, ndata *navData) { // Use SELECT form instead of common PRAGMA table_info so we can just get names // We could possibly get this from the main data select, but this will // work even when there are 0 results - colr, err := ld.db.Query(`SELECT name FROM pragma_table_info(?)`, tableName) + columnNames, err := ld.sqliteGetColumnNamesForTable(tableName) if err != nil { vcl.ShowMessageFmt("Failed to load columns for table %q: %s", tableName, err.Error()) return } - defer colr.Close() - f.contentBox.Columns().Clear() - numColumns := 0 - for colr.Next() { + populateColumns(columnNames, f.contentBox) - var columnName string - err = colr.Scan(&columnName) - if err != nil { - vcl.ShowMessageFmt("Failed to read column names for table %q: %s", tableName, err.Error()) - return - } - - col := f.contentBox.Columns().Add() - col.SetCaption(columnName) - col.SetWidth(MY_WIDTH) - col.SetAlignment(types.TaLeftJustify) - - numColumns++ - } - if colr.Err() != nil { - vcl.ShowMessageFmt("Failed to load columns for table %q: %s", tableName, err.Error()) - return - } - colr.Close() // will be double-closed + // Select count(*) so we know to display a warning if there are too many entries + // TODO // Select * with small limit datar, err := ld.db.Query(`SELECT * FROM ` + tableName + ` LIMIT 1000`) // WARNING can't prepare this parameter, but it comes from the DB (trusted) @@ -115,27 +95,7 @@ func (ld *sqliteLoadedDatabase) RenderForNav(f *TMainForm, ndata *navData) { return } defer datar.Close() - - for datar.Next() { - fields := make([]interface{}, numColumns) - pfields := make([]interface{}, numColumns) - for i := 0; i < numColumns; i += 1 { - pfields[i] = &fields[i] - } - - err = datar.Scan(pfields...) - if err != nil { - vcl.ShowMessageFmt("Failed to load data for table %q: %s", tableName, err.Error()) - return - } - - dataEntry := f.contentBox.Items().Add() - dataEntry.SetCaption(formatAny(fields[0])) - for i := 1; i < len(fields); i += 1 { - dataEntry.SubItems().Add(formatAny(fields[i])) - } - - } + populateRows(datar, f.contentBox) // We successfully populated the data grid f.contentBox.SetEnabled(true) @@ -147,6 +107,74 @@ func (ld *sqliteLoadedDatabase) RenderForNav(f *TMainForm, ndata *navData) { } +func (ld *sqliteLoadedDatabase) sqliteGetColumnNamesForTable(tableName string) ([]string, error) { + colr, err := ld.db.Query(`SELECT name FROM pragma_table_info(?)`, tableName) + if err != nil { + return nil, fmt.Errorf("Query: %w", err) + } + defer colr.Close() + + var ret []string + + for colr.Next() { + + var columnName string + err = colr.Scan(&columnName) + if err != nil { + return nil, fmt.Errorf("Scan: %w", colr.Err()) + } + + ret = append(ret, columnName) + } + if colr.Err() != nil { + return nil, colr.Err() + } + + return ret, nil +} + +func populateColumns(names []string, dest *vcl.TListView) { + dest.Columns().Clear() + for _, columnName := range names { + col := dest.Columns().Add() + col.SetCaption(columnName) + col.SetWidth(MY_WIDTH) + col.SetAlignment(types.TaLeftJustify) + } +} + +func populateRows(rr *sql.Rows, dest *vcl.TListView) { + + numColumns := int(dest.Columns().Count()) + + for rr.Next() { + fields := make([]interface{}, numColumns) + pfields := make([]interface{}, numColumns) + for i := 0; i < numColumns; i += 1 { + pfields[i] = &fields[i] + } + + err := rr.Scan(pfields...) + if err != nil { + vcl.ShowMessageFmt("Failed to load data: %s", err.Error()) + return + } + + dataEntry := dest.Items().Add() + dataEntry.SetCaption(formatAny(fields[0])) + for i := 1; i < len(fields); i += 1 { + dataEntry.SubItems().Add(formatAny(fields[i])) + } + + } + if rr.Err() != nil { + vcl.ShowMessageFmt("Failed to load data: %s", rr.Err().Error()) + return + } +} + +} + func (ld *sqliteLoadedDatabase) NavChildren(ndata *navData) ([]string, error) { if len(ndata.bucketPath) == 0 {