-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathcmd_size.go
87 lines (77 loc) · 2.05 KB
/
cmd_size.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package main
import (
"flag"
"fmt"
"os"
"text/tabwriter"
"github.com/BurntSushi/csql"
"github.com/BurntSushi/goim/imdb"
)
var cmdSize = &command{
name: "size",
shortHelp: "lists size of tables and total size of database",
help: "",
flags: flag.NewFlagSet("size", flag.ExitOnError),
run: cmd_size,
}
func cmd_size(c *command) bool {
db := openDb(c.dbinfo())
defer closeDb(db)
tables, err := db.Tables()
if err != nil {
pef("%s", err)
return false
}
tw := tabwriter.NewWriter(os.Stdout, 0, 2, 4, ' ', 0)
for _, table := range tables {
fmt.Fprintf(tw, "%s\t%s\n", table, tableSize(db, table))
}
_, dsn := c.dbinfo()
total := databaseSize(db, dsn)
fmt.Fprintf(tw, "total\t%s\n", total)
tw.Flush()
return true
}
// tableSize returns a pretty string indicating the size in table. Row count
// is always include, but the size on disk is only included if it's supported
// by the database.
// Note that 'name' is assumed to be SQL-safe.
func tableSize(db *imdb.DB, name string) string {
count := csql.Count(db, sf("SELECT COUNT(*) AS count FROM %s", name))
if db.Driver == "sqlite3" {
return sf("%d rows", count)
}
var size string
q := sf("SELECT pg_size_pretty(pg_relation_size('%s'))", name)
csql.Scan(db.QueryRow(q), &size)
return sf("%d rows (%s)", count, size)
}
// databaseSize returns a pretty string indicating the size of the entire
// database on disk.
func databaseSize(db *imdb.DB, dsn string) string {
if db.Driver == "sqlite3" {
fi, err := os.Stat(dsn)
csql.Panic(err)
return prettyFileSize(fi.Size())
}
var size string
q := sf("SELECT pg_size_pretty(pg_database_size(current_database()))")
csql.Scan(db.QueryRow(q), &size)
return size
}
func prettyFileSize(bytes int64) string {
cutoff := int64(1024 * 2)
kb, mb, gb := int64(1024), int64(1024*1024), int64(1024*1024*1024)
if bytes < cutoff {
return sf("%d bytes", bytes)
}
kbytes := bytes / kb
if kbytes < cutoff {
return sf("%d kB", kbytes)
}
mbytes := bytes / mb
if mbytes < cutoff {
return sf("%d MB", mbytes)
}
return sf("%d GB", bytes/gb)
}