-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsudsSql.go
More file actions
230 lines (183 loc) · 5.17 KB
/
sudsSql.go
File metadata and controls
230 lines (183 loc) · 5.17 KB
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
)
// InitDb Initializes the DB interface
func InitDb(driverName string, dbPath string) {
db, err = sql.Open("sqlite3", "./foo.db")
if err != nil {
log.Fatal(err)
}
}
// AddColumnToTable will add a column to the given table.
func AddColumnToTable(tableName string, columnName string) error {
query := `ALTER TABLE ` + tableName + ` ADD COLUMN ` + columnName + ` TEXT NULL DEFAULT ""; `
_, err := db.Exec(query)
if err != nil {
return err
}
return nil
}
// GetTableColumns will get an array of all the columns in the table.
func GetTableColumns(tableName string) ([]string, error) {
// we only need one record for this.
query := "SELECT * FROM " + tableName + " LIMIT 1"
rows, err := db.Query(query)
if err != nil {
return nil, err
}
columns, err := rows.Columns()
if err != nil {
return nil, err
}
return columns, nil
}
// GetTables will return all the tables in the db
func GetTables() ([]string, error) {
query := "SELECT name FROM sqlite_master WHERE type ='table' AND name NOT LIKE 'sqlite_%';"
rows, err := db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
names := make([]string, 0)
for rows.Next() {
var name string
rows.Scan(&name)
names = append(names, name)
}
return names, nil
}
// InsertValues inserts the values in the given JSON values.
func InsertValues(insertValues string) {
if !json.Valid([]byte(insertValues)) {
fmt.Println("Error: Invalid JSON data")
fmt.Println("Data: ", insertValues)
return
}
var inVal interface{}
// Decode bytes b into interface i
json.Unmarshal([]byte(insertValues), &inVal)
// convert the top level to an array of interfaces
tlVal := inVal.([]interface{})
// there should be only one entry in the top level, so grab that and convert it grabbing the table key
tableNameTmp := tlVal[0].(map[string]interface{})["table"]
tableName := tableNameTmp.(string)
// now let's grab the values key, which is a map, but this converts it to an interface{}
colsIntf := tlVal[0].(map[string]interface{})["values"]
// convert the interface to a map so we can iterate over it.
values := colsIntf.(map[string]interface{})
err = CreateTable(tableName, values)
if err != nil {
fmt.Println("Error: unable to verify table.")
fmt.Println(err.Error())
return
}
// should be good here, insert the values to the table.
var columnsSlice, valuesSlice []string
for column, value := range values {
columnsSlice = append(columnsSlice, column)
valueStr := value.(string)
valuesSlice = append(valuesSlice, valueStr)
}
query := "INSERT INTO " + tableName + " ("
for i := 0; i < len(columnsSlice); i++ {
query += columnsSlice[i] + ", "
}
query = query[0:len(query)-2] + ") VALUES ("
for i := 0; i < len(valuesSlice); i++ {
query += "'" + valuesSlice[i] + "', "
}
query = query[0:len(query)-2] + ");"
_, err = db.Exec(query)
if err != nil {
fmt.Println("Error: Unable to insert data.")
fmt.Println(err.Error())
}
}
// CreateTable creates the table in the db, if it does not exist,
// using the given string as a structure
func CreateTable(tableName string, tableVals map[string]interface{}) error {
// see if this table name already exists
tables, err := GetTables()
if err != nil {
fmt.Println("Error: unable to get table names")
fmt.Println(err.Error())
return err
}
if ContainsString(tables, tableName) {
// get the column names from the table.
columns, err := GetTableColumns(tableName)
if err != nil {
fmt.Println("Error: unable to get column names from table: " + tableName)
fmt.Println(err.Error())
return err
}
// this table already exists so let's check the columns
for column := range tableVals {
if !ContainsString(columns, column) {
AddColumnToTable(tableName, column)
}
}
} else {
// this table doesn't exist. Create it.
query := "CREATE TABLE " + tableName + "( "
query += `id INTEGER PRIMARY KEY AUTOINCREMENT,
t TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `
for column := range tableVals {
query += column + " TEXT NULL DEFAULT \"\", "
}
query = query[0 : len(query)-2]
query += `);`
_, err := db.Exec(query)
if err != nil {
fmt.Println("Error: Unable to create table: " + tableName)
fmt.Println(err.Error())
return nil
}
}
return nil
}
// DumpTable dumps the contents of a table to a sting.
func DumpTable(tableName string) (string, error) {
rows, err := db.Query("SELECT * FROM " + tableName + ";")
if err != nil {
return "", err
}
defer rows.Close()
columns, err := rows.Columns()
if err != nil {
return "", err
}
count := len(columns)
tableData := make([]map[string]interface{}, 0)
values := make([]interface{}, count)
valuePtrs := make([]interface{}, count)
for rows.Next() {
for i := 0; i < count; i++ {
valuePtrs[i] = &values[i]
}
rows.Scan(valuePtrs...)
entry := make(map[string]interface{})
for i, col := range columns {
var v interface{}
val := values[i]
b, ok := val.([]byte)
if ok {
v = string(b)
} else {
v = val
}
entry[col] = v
}
tableData = append(tableData, entry)
}
jsonData, err := json.Marshal(tableData)
if err != nil {
return "", err
}
return string(jsonData), nil
}