This repository has been archived on 2020-04-27. You can view files and clone it, but cannot push or open issues or pull requests.
cmd/xorm/shell.go
Lunny Xiao 9ccdb0ebed
All checks were successful
continuous-integration/drone/push Build is passing
upgrade to xorm v1.0.1
2020-04-27 09:43:43 +08:00

298 lines
7.1 KiB
Go

// Copyright 2017 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"context"
"fmt"
"strings"
"xorm.io/xorm"
"xorm.io/xorm/log"
)
var CmdShell = &Command{
UsageLine: "shell driverName datasourceName",
Short: "a general shell to operate all kinds of database",
Long: `
general database's shell for sqlite3, mysql, postgres.
driverName Database driver name, now supported four: mysql mymysql sqlite3 postgres
datasourceName Database connection uri, for detail infomation please visit driver's project page
`,
}
func init() {
CmdShell.Run = runShell
CmdShell.Flags = map[string]bool{}
}
var engine *xorm.Engine
func shellHelp() {
fmt.Println(`
show tables show all tables
columns <table_name> show table's column info
indexes <table_name> show table's index info
exit exit shell
source <sql_file> exec sql file to current database
dump [-nodata] <sql_file> dump structs or records to sql file
help show this document
<statement> SQL statement
`)
}
func runShell(cmd *Command, args []string) {
if len(args) != 2 {
fmt.Println("params error, please see xorm help shell")
return
}
var err error
engine, err = xorm.NewEngine(args[0], args[1])
if err != nil {
fmt.Println(err)
return
}
engine.ShowSQL(false)
engine.Logger().SetLevel(log.LOG_UNKNOWN)
err = engine.Ping()
if err != nil {
fmt.Println(err)
return
}
var scmd string
fmt.Print("xorm$ ")
for {
var input string
_, err := fmt.Scan(&input)
if err != nil {
fmt.Println(err)
continue
}
if strings.ToLower(input) == "help" {
shellHelp()
scmd = ""
fmt.Print("xorm$ ")
continue
}
if strings.ToLower(input) == "exit" {
fmt.Println("bye")
return
}
if !strings.HasSuffix(input, ";") {
scmd = scmd + " " + input
continue
}
scmd = scmd + " " + input
lcmd := strings.TrimSpace(strings.ToLower(scmd))
lcmd = strings.TrimRight(lcmd, ";")
if strings.HasPrefix(lcmd, "select") {
res, err := engine.Query(scmd + "\n")
if err != nil {
fmt.Println(err)
} else {
if len(res) <= 0 {
fmt.Println("no records")
} else {
columns := make(map[string]int)
for k, _ := range res[0] {
columns[k] = len(k)
}
for _, m := range res {
for k, s := range m {
l := len(string(s))
if l > columns[k] {
columns[k] = l
}
}
}
var maxlen = 0
for _, l := range columns {
maxlen = maxlen + l + 3
}
maxlen = maxlen + 1
fmt.Println(strings.Repeat("-", maxlen))
fmt.Print("|")
slice := make([]string, 0)
for k, l := range columns {
fmt.Print(" " + k + " ")
fmt.Print(strings.Repeat(" ", l-len(k)))
fmt.Print("|")
slice = append(slice, k)
}
fmt.Print("\n")
for _, r := range res {
fmt.Print("|")
for _, k := range slice {
fmt.Print(" " + string(r[k]) + " ")
fmt.Print(strings.Repeat(" ", columns[k]-len(string(r[k]))))
fmt.Print("|")
}
fmt.Print("\n")
}
fmt.Println(strings.Repeat("-", maxlen))
//fmt.Println(res)
}
}
} else if lcmd == "show tables" {
tables, err := engine.DBMetas()
if err != nil {
fmt.Println(err)
} else {
var maxlen int
for _, table := range tables {
if len(table.Name) > maxlen {
maxlen = len(table.Name)
}
}
head := "Table Name"
if maxlen < len(head) {
maxlen = len(head)
}
maxlen = maxlen + 2
fmt.Println(strings.Repeat("-", maxlen+3))
fmt.Print("| " + head + strings.Repeat(" ", maxlen-len(head)))
fmt.Println("|")
fmt.Println(strings.Repeat("-", maxlen+3))
for _, table := range tables {
fmt.Print("|")
fmt.Print(" " + table.Name)
fmt.Print(strings.Repeat(" ", maxlen-len(table.Name)))
fmt.Println("|")
}
fmt.Println(strings.Repeat("-", maxlen+3))
}
} else if strings.HasPrefix(lcmd, "dump") {
fields := strings.Fields(strings.TrimRight(scmd, ";"))
if len(fields) == 2 {
err = engine.DumpAllToFile(fields[1])
if err != nil {
fmt.Println(err)
} else {
fmt.Println("dump successfully!")
}
} else {
fmt.Println("param error")
}
} else if strings.HasPrefix(lcmd, "source") {
fields := strings.Fields(strings.TrimRight(scmd, ";"))
if len(fields) == 2 {
_, err = engine.ImportFile(fields[1])
if err.Error() == "not an error" {
err = nil
}
if err != nil {
fmt.Println(err)
}
} else {
fmt.Println("param error")
}
} else if strings.HasPrefix(lcmd, "columns") {
fields := strings.Fields(strings.TrimRight(scmd, ";"))
if len(fields) == 2 {
_, columns, err := engine.Dialect().GetColumns(engine.DB(), context.Background(), fields[1])
if err != nil {
fmt.Println(err)
} else {
if len(columns) == 0 {
fmt.Println("no column in", fields[1])
} else {
var maxlen int
for name := range columns {
if len(name) > maxlen {
maxlen = len(name)
}
}
head := "Column Name"
if maxlen < len(head) {
maxlen = len(head)
}
maxlen = maxlen + 2
fmt.Println(strings.Repeat("-", maxlen+3))
fmt.Print("| " + head + strings.Repeat(" ", maxlen-len(head)))
fmt.Println("|")
fmt.Println(strings.Repeat("-", maxlen+3))
for name, _ := range columns {
fmt.Print("|")
fmt.Print(" " + name)
fmt.Print(strings.Repeat(" ", maxlen-len(name)))
fmt.Println("|")
}
fmt.Println(strings.Repeat("-", maxlen+3))
}
}
} else {
fmt.Println("param error")
}
} else if strings.HasPrefix(lcmd, "indexes") {
fields := strings.Fields(strings.TrimRight(scmd, ";"))
if len(fields) == 2 {
indexes, err := engine.Dialect().GetIndexes(engine.DB(), context.Background(), fields[1])
if err != nil {
fmt.Println(err)
} else {
if len(indexes) == 0 {
fmt.Println("no index in", fields[1])
} else {
var maxlen int
for name, _ := range indexes {
if len(name) > maxlen {
maxlen = len(name)
}
}
head := "Index Name"
if maxlen < len(head) {
maxlen = len(head)
}
maxlen = maxlen + 2
fmt.Println(strings.Repeat("-", maxlen+3))
fmt.Print("| " + head + strings.Repeat(" ", maxlen-len(head)))
fmt.Println("|")
fmt.Println(strings.Repeat("-", maxlen+3))
for name, _ := range indexes {
fmt.Print("|")
fmt.Print(" " + name)
fmt.Print(strings.Repeat(" ", maxlen-len(name)))
fmt.Println("|")
}
fmt.Println(strings.Repeat("-", maxlen+3))
}
}
} else {
fmt.Println("param error")
}
} else {
res, err := engine.Exec(scmd)
if err != nil {
fmt.Println(err)
} else {
cnt, err := res.RowsAffected()
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("%d records changed.\n", cnt)
}
}
}
scmd = ""
fmt.Print("xorm$ ")
}
}