forked from lukasmartinelli/pgfutter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
postgres.go
118 lines (101 loc) · 2.93 KB
/
postgres.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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package main
import (
"database/sql"
"fmt"
"log"
"math/rand"
"regexp"
"strconv"
"strings"
"github.com/urfave/cli"
"github.com/kennygrant/sanitize"
)
//tries to create the schema and ignores failures to do so.
//versions after Postgres 9.3 support the "IF NOT EXISTS" sql syntax
func tryCreateSchema(db *sql.DB, importSchema string) {
createSchema, err := db.Prepare(fmt.Sprintf("CREATE SCHEMA %s", importSchema))
if err == nil {
createSchema.Exec()
}
}
//setup a database connection and create the import schema
func connect(connStr string, importSchema string) (*sql.DB, error) {
db, err := sql.Open("postgres", connStr)
if err != nil {
return db, err
}
err = db.Ping()
if err != nil {
return db, err
}
tryCreateSchema(db, importSchema)
return db, nil
}
//Makes sure that a string is a valid PostgreSQL identifier
func postgresify(identifier string) string {
str := sanitize.BaseName(identifier)
str = strings.ToLower(identifier)
str = strings.TrimSpace(str)
replacements := map[string]string{
" ": "_",
"/": "_",
".": "_",
":": "_",
";": "_",
"|": "_",
"-": "_",
",": "_",
"#": "_",
}
for oldString, newString := range replacements {
str = strings.Replace(str, oldString, newString, -1)
}
reg, err := regexp.Compile("[^A-Za-z0-9_]+")
if err != nil {
log.Fatal(err)
}
str = reg.ReplaceAllString(str, "")
if len(str) == 0 {
str = fmt.Sprintf("_col%d", rand.Intn(10000))
} else {
firstLetter := string(str[0])
if _, err := strconv.Atoi(firstLetter); err == nil {
str = "_" + str
}
}
return str
}
//parse sql connection string from cli flags
func parseConnStr(c *cli.Context) string {
otherParams := "sslmode=disable connect_timeout=5"
if c.GlobalBool("ssl") {
otherParams = "sslmode=require connect_timeout=5"
}
return fmt.Sprintf("user=%s dbname=%s password='%s' host=%s port=%s %s",
c.GlobalString("username"),
c.GlobalString("dbname"),
c.GlobalString("pass"),
c.GlobalString("host"),
c.GlobalString("port"),
otherParams,
)
}
//create table with a single JSON or JSONB column data
func createJSONTable(db *sql.DB, schema string, tableName string, column string, dataType string) (*sql.Stmt, error) {
fullyQualifiedTable := fmt.Sprintf("%s.%s", schema, tableName)
tableSchema := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (%s %s)", fullyQualifiedTable, column, dataType)
statement, err := db.Prepare(tableSchema)
return statement, err
}
//create table with TEXT columns
func createTable(db *sql.DB, schema string, tableName string, columns []string) (*sql.Stmt, error) {
columnTypes := make([]string, len(columns))
for i, col := range columns {
columnTypes[i] = fmt.Sprintf("%s TEXT", col)
}
columnDefinitions := strings.Join(columnTypes, ",")
fullyQualifiedTable := fmt.Sprintf("%s.%s", schema, tableName)
tableSchema := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (%s)", fullyQualifiedTable, columnDefinitions)
statement, err := db.Prepare(tableSchema)
return statement, err
}