-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
155 lines (132 loc) · 3.37 KB
/
main.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
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
package main
import (
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
)
type Town struct {
Name string `db:"town_name"`
}
type District struct {
Name string `db:"district_name"`
Towns []string `db:"towns"`
}
type Region struct {
Name string `db:"region_name"`
Districts []District `db:"districts"`
}
type MalawiData struct {
Country string `db:"country"`
Regions []Region `db:"regions"`
}
func main() {
db, err := sqlx.Connect("postgres", "user=postgres dbname=malawi_admin_divs sslmode=disable password=root host=localhost")
if err != nil {
log.Fatalln(err)
}
defer db.Close()
router := gin.Default()
router.POST("/insert-data", func(c *gin.Context) {
var data MalawiData
if err := c.BindJSON(&data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
err := insertData(db, data)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Data inserted successfully"})
})
router.Use(func(c *gin.Context) {
c.Set("db", db)
c.Next()
})
router.GET("/divisions", getDivisions)
router.GET("/divisions/:division/districts", getDistrictsInDivision)
router.GET("/divisions/:division/districts/:district/towns", getTownsInDistrict)
router.Run("localhost:8080")
}
func insertData(db *sqlx.DB, data MalawiData) error {
tx, err := db.Beginx()
if err != nil {
return err
}
defer tx.Rollback()
for _, region := range data.Regions {
// Insert region
var regionID int
err := tx.QueryRow(
"INSERT INTO regions (region_name) VALUES ($1) RETURNING id",
region.Name,
).Scan(®ionID)
if err != nil {
return err
}
for _, district := range region.Districts {
// Insert district
var districtID int
err := tx.QueryRow(
"INSERT INTO districts (district_name, region_id) VALUES ($1, $2) RETURNING id",
district.Name, regionID,
).Scan(&districtID)
if err != nil {
return err
}
// Insert towns
for _, town := range district.Towns {
_, err := tx.Exec(
"INSERT INTO towns (town_name, district_id) VALUES ($1, $2)",
town, districtID,
)
if err != nil {
return err
}
}
}
}
return tx.Commit()
}
func getDivisions(c *gin.Context) {
db := c.MustGet("db").(*sqlx.DB)
var regions []Region
err := db.Select(®ions, "SELECT region_name FROM regions")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, regions)
}
func getDistrictsInDivision(c *gin.Context) {
db := c.MustGet("db").(*sqlx.DB)
division := c.Param("division")
var districts []District
err := db.Select(&districts,
`SELECT d.district_name
FROM districts d
JOIN regions r ON d.region_id = r.id
WHERE r.region_name = $1`, division)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, districts)
}
func getTownsInDistrict(c *gin.Context) {
db := c.MustGet("db").(*sqlx.DB)
district := c.Param("district")
var towns []Town
err := db.Select(&towns,
`SELECT t.town_name
FROM towns t
JOIN districts d ON t.district_id = d.id
WHERE d.district_name = $1`, district)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, towns)
}