shiny-pancake/internal/gui/data.go
2020-11-07 20:24:12 -06:00

368 lines
12 KiB
Go

package gui
//
//import (
// "database/sql"
// "fmt"
// "github.com/sirupsen/logrus"
// "reflect"
// "shiny-pancake/internal/database"
// "shiny-pancake/logger"
// "strconv"
// "sync"
// "time"
//
// "github.com/gdamore/tcell/v2"
// _ "github.com/lib/pq"
// "github.com/rivo/tview"
//)
//
//const (
// batchSize = 80 // The number of rows loaded per batch.
// finderPage = "*finder*" // The name of the Finder page.
//)
//
//var (
// app *tview.Application // The tview application.
// panels *tview.Pages // The application panels.
// finderFocus tview.Primitive // The primitive in the Finder that last had focus.
//)
//
//// Main entry point.
//func data(host database.HostDetails) {
// var h string
// var u string
// var pw string
// var dbn string
// var psqlInfo string
// h = host.Hostname
// u = host.Username
// pw = host.Secret
// dbn = host.DatabaseName
// // Start the application.
// psqlInfo = fmt.Sprintf("host=%s port=%d user=%s "+
// "password=%s dbname=%s sslmode=disable",
// h, 5432, u, pw, dbn)
// app = tview.NewApplication()
// finder(psqlInfo)
// if err := app.Run(); err != nil {
// fmt.Printf("Error running application: %s\n", err)
// }
//}
//
//// Sets up a "Finder" used to navigate the databases, tables, and columns.
//func finder(connString string) {
// // Create the basic objects.
// databases := tview.NewList().ShowSecondaryText(false)
// databases.SetBorder(true).SetTitle("Databases")
// columns := tview.NewTable().SetBorders(true)
// columns.SetBorder(true).SetTitle("Columns")
// tables := tview.NewList()
// tables.ShowSecondaryText(false).
// SetDoneFunc(func() {
// tables.Clear()
// columns.Clear()
// app.SetFocus(databases)
// })
// tables.SetBorder(true).SetTitle("Tables")
//
// // Create the layout.
// flex := tview.NewFlex().
// AddItem(databases, 0, 1, true).
// AddItem(tables, 0, 1, false).
// AddItem(columns, 0, 3, false)
//
// // We keep one connection pool per database.
// dbMutex := sync.Mutex{}
// dbs := make(map[string]*sql.DB)
// getDB := func(database string) *sql.DB {
// // Connect to a new database.
// dbMutex.Lock()
// defer dbMutex.Unlock()
// if db, ok := dbs[database]; ok {
// return db
// }
// db, err := sql.Open("postgres", connString)
// if err != nil {
// panic(err)
// }
// dbs[database] = db
// return db
// }
//
// // Get a list of all databases.
// generalDB, err := sql.Open("postgres", connString)
// if err != nil {
// panic(err)
// }
// defer generalDB.Close() // We really close the DB because we only use it for this one query.
// rows, err := generalDB.Query("select datname from pg_database where datistemplate = false")
// if err != nil {
// panic(err)
// }
// defer rows.Close()
// for rows.Next() {
// var dbName string
// if err := rows.Scan(&dbName); err != nil {
// panic(err)
// }
// databases.AddItem(dbName, "", 0, func() {
// // A database was selected. Show all of its tables.
// columns.Clear()
// tables.Clear()
// db := getDB(dbName)
// t, err := db.Query("select table_name from information_schema.tables where table_schema not in ('information_schema','pg_catalog')")
// if err != nil {
// panic(err)
// }
// defer t.Close()
// for t.Next() {
// var tableName string
// if err := t.Scan(&tableName); err != nil {
// panic(err)
// }
// tables.AddItem(tableName, "", 0, nil)
// }
// if err := t.Err(); err != nil {
// panic(err)
// }
// app.SetFocus(tables)
//
// // When the user navigates to a table, show its columns.
// tables.SetChangedFunc(func(i int, tableName string, t string, s rune) {
// // A table was selected. Show its columns.
// columns.Clear()
// c, err := db.Query(`
// select
// c.column_name,
// c.is_nullable,
// c.data_type,
// c.character_maximum_length,
// c.numeric_precision,
// c.numeric_scale,
// c.ordinal_position,
// tc.constraint_type pkey
// from
// information_schema.columns c
// left join
// information_schema.constraint_column_usage as ccu
// on
// c.table_schema = ccu.table_schema
// and c.table_name = ccu.table_name
// and c.column_name = ccu.column_name
// left join
// information_schema.table_constraints as tc
// on
// ccu.constraint_schema = tc.constraint_schema
// and ccu.constraint_name = tc.constraint_name
// where
// c.table_schema not in ('information_schema','pg_catalog')
// and c.table_name = $1
// `, tableName)
// if err != nil {
// var l logger.Log
// l = logger.Log{"error", logrus.Fields{"database": err.Error()}, "an error occured in view."}
// logger.Lgr(&l)
// }
// defer c.Close()
// columns.SetCell(0, 0, &tview.TableCell{Text: "Name", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
// SetCell(0, 1, &tview.TableCell{Text: "Type", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
// SetCell(0, 2, &tview.TableCell{Text: "Size", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
// SetCell(0, 3, &tview.TableCell{Text: "Null", Align: tview.AlignCenter, Color: tcell.ColorYellow}).
// SetCell(0, 4, &tview.TableCell{Text: "Constraint", Align: tview.AlignCenter, Color: tcell.ColorYellow})
// for c.Next() {
// var (
// columnName, isNullable, dataType string
// constraintType sql.NullString
// size, numericPrecision, numericScale sql.NullInt64
// ordinalPosition int
// )
// if err := c.Scan(&columnName,
// &isNullable,
// &dataType,
// &size,
// &numericPrecision,
// &numericScale,
// &ordinalPosition,
// &constraintType,
// ); err != nil {
// panic(err)
// }
// sizeText := ""
// if size.Valid {
// sizeText = strconv.Itoa(int(size.Int64))
// } else if numericPrecision.Valid {
// sizeText = strconv.Itoa(int(numericPrecision.Int64))
// if numericScale.Valid {
// sizeText += "," + strconv.Itoa(int(numericScale.Int64))
// }
// }
// color := tcell.ColorWhite
// if constraintType.Valid {
// color = map[string]tcell.Color{
// "CHECK": tcell.ColorGreen,
// "FOREIGN KEY": tcell.ColorDarkMagenta,
// "PRIMARY KEY": tcell.ColorRed,
// "UNIQUE": tcell.ColorDarkCyan,
// }[constraintType.String]
// }
// columns.SetCell(ordinalPosition, 0, &tview.TableCell{Text: columnName, Color: color}).
// SetCell(ordinalPosition, 1, &tview.TableCell{Text: dataType, Color: color}).
// SetCell(ordinalPosition, 2, &tview.TableCell{Text: sizeText, Align: tview.AlignRight, Color: color}).
// SetCell(ordinalPosition, 3, &tview.TableCell{Text: isNullable, Align: tview.AlignRight, Color: color}).
// SetCell(ordinalPosition, 4, &tview.TableCell{Text: constraintType.String, Align: tview.AlignLeft, Color: color})
// }
// if err := c.Err(); err != nil {
// panic(err)
// }
// })
// tables.SetCurrentItem(0) // Trigger the initial selection.
//
// // When the user selects a table, show its content.
// tables.SetSelectedFunc(func(i int, tableName string, t string, s rune) {
// content(db, dbName, tableName)
// })
// })
// }
// if err := rows.Err(); err != nil {
// panic(err)
// }
//
// // Set up the panels and show the Finder.
// panels = tview.NewPages().
// AddPage(finderPage, flex, true, true)
// app.SetRoot(panels, true)
//}
//
//// Shows the contents of the given table.
//func content(db *sql.DB, dbName, tableName string) {
// finderFocus = app.GetFocus()
//
// // If this page already exists, just show it.
// if panels.HasPage(dbName + "." + tableName) {
// panels.SwitchToPage(dbName + "." + tableName)
// return
// }
// var l logger.Log
// l = logger.Log{"info", logrus.Fields{"database": tableName}, "selected table to view"}
// logger.Lgr(&l)
// var schemaName string
// err := db.QueryRow(fmt.Sprintf("select table_schema from information_schema.tables where table_schema not in ('information_schema','pg_catalog') and table_name = '%s'", tableName)).Scan(&schemaName)
// if err != nil {
// panic(err)
// }
//
// // We display the data in a table embedded in a frame.
// table := tview.NewTable().
// SetFixed(1, 0).
// SetBordersColor(tcell.ColorYellow)
// frame := tview.NewFrame(table).
// SetBorders(0, 0, 0, 0, 0, 0)
// frame.SetBorder(true).
// SetTitle(fmt.Sprintf(`Contents of table "%s.%s"`, schemaName, tableName))
//
// // How many rows does this table have?
// var rowCount int
// err = db.QueryRow(fmt.Sprintf("select count(*) from %s.%s", schemaName, tableName)).Scan(&rowCount)
// if err != nil {
// panic(err)
// }
//
// // Load a batch of rows.
// loadRows := func(offset int) {
// rows, err := db.Query(fmt.Sprintf("select * from %s.%s limit $1 offset $2", schemaName, tableName), batchSize, offset)
// if err != nil {
// panic(err)
// }
// defer rows.Close()
//
// // The first row in the table is the list of column names.
// columnNames, err := rows.Columns()
// if err != nil {
// panic(err)
// }
// for index, name := range columnNames {
// table.SetCell(0, index, &tview.TableCell{Text: name, Align: tview.AlignCenter, Color: tcell.ColorYellow})
// }
//
// // Read the rows.
// columns := make([]interface{}, len(columnNames))
// columnPointers := make([]interface{}, len(columns))
// for index := range columnPointers {
// columnPointers[index] = &columns[index]
// }
// for rows.Next() {
// // Read the columns.
// err := rows.Scan(columnPointers...)
// if err != nil {
// panic(err)
// }
//
// // Transfer them to the table.
// row := table.GetRowCount()
// for index, column := range columns {
// switch value := column.(type) {
// case int64:
// table.SetCell(row, index, &tview.TableCell{Text: strconv.Itoa(int(value)), Align: tview.AlignRight, Color: tcell.ColorDarkCyan})
// case float64:
// table.SetCell(row, index, &tview.TableCell{Text: strconv.FormatFloat(value, 'f', 2, 64), Align: tview.AlignRight, Color: tcell.ColorDarkCyan})
// case string:
// table.SetCellSimple(row, index, value)
// case time.Time:
// t := value.Format("2006-01-02")
// table.SetCell(row, index, &tview.TableCell{Text: t, Align: tview.AlignRight, Color: tcell.ColorDarkMagenta})
// case []uint8:
// str := make([]byte, len(value))
// for index, num := range value {
// str[index] = byte(num)
// }
// table.SetCell(row, index, &tview.TableCell{Text: string(str), Align: tview.AlignRight, Color: tcell.ColorGreen})
// case nil:
// table.SetCell(row, index, &tview.TableCell{Text: "NULL", Align: tview.AlignCenter, Color: tcell.ColorRed})
// default:
// // We've encountered a type that we don't know yet.
// t := reflect.TypeOf(value)
// str := "?nil?"
// if t != nil {
// str = "?" + t.String() + "?"
// }
// table.SetCellSimple(row, index, str)
// }
// }
// }
// if err := rows.Err(); err != nil {
// panic(err)
// }
//
// // Show how much we've loaded.
// frame.Clear()
// loadMore := ""
// if table.GetRowCount()-1 < rowCount {
// loadMore = " - press Enter to load more"
// }
// loadMore = fmt.Sprintf("Loaded %d of %d rows%s. esc to return to previous menu", table.GetRowCount()-1, rowCount, loadMore)
// frame.AddText(loadMore, false, tview.AlignCenter, tcell.ColorYellow)
// }
//
// // Load the first batch of rows.
// loadRows(0)
//
// // Handle key presses.
// table.SetDoneFunc(func(key tcell.Key) {
// switch key {
// case tcell.KeyEscape:
// // Go back to Finder.
// panels.SwitchToPage(finderPage)
// if finderFocus != nil {
// app.SetFocus(finderFocus)
// }
// case tcell.KeyEnter:
// // Load the next batch of rows.
// loadRows(table.GetRowCount() - 1)
// table.ScrollToEnd()
// }
// })
//
// // Add a new page and show it.
// panels.AddPage(dbName+"."+tableName, frame, true, true)
//}