github.com/EngineerKamesh/gofullstack@v0.0.0-20180609171605-d41341d7d4ee/volume3/section5/gopherface/common/datastore/mysql.go (about) 1 package datastore 2 3 import ( 4 "database/sql" 5 "log" 6 7 "github.com/EngineerKamesh/gofullstack/volume3/section5/gopherface/models/socialmedia" 8 9 "github.com/EngineerKamesh/gofullstack/volume3/section5/gopherface/models" 10 11 _ "github.com/go-sql-driver/mysql" 12 ) 13 14 type MySQLDatastore struct { 15 *sql.DB 16 } 17 18 func NewMySQLDatastore(dataSourceName string) (*MySQLDatastore, error) { 19 20 connection, err := sql.Open("mysql", dataSourceName) 21 22 if err != nil { 23 return nil, err 24 } 25 26 return &MySQLDatastore{ 27 DB: connection}, nil 28 } 29 30 func (m *MySQLDatastore) CreateUser(user *models.User) error { 31 32 tx, err := m.Begin() 33 if err != nil { 34 log.Print(err) 35 } 36 37 defer tx.Rollback() 38 39 stmt, err := tx.Prepare("INSERT INTO user(uuid, username, first_name, last_name, email, password_hash) VALUES (?,?,?,?,?,?)") 40 if err != nil { 41 return err 42 } 43 44 defer stmt.Close() 45 46 _, err = stmt.Exec(user.UUID, user.Username, user.FirstName, user.LastName, user.Email, user.PasswordHash) 47 if err != nil { 48 return err 49 } 50 51 err = tx.Commit() 52 if err != nil { 53 return err 54 } 55 56 return nil 57 } 58 59 func (m *MySQLDatastore) GetUser(username string) (*models.User, error) { 60 61 stmt, err := m.Prepare("SELECT uuid, username, first_name, last_name, email, password_hash, UNIX_TIMESTAMP(created_ts), UNIX_TIMESTAMP(updated_ts) FROM user WHERE username = ?") 62 if err != nil { 63 log.Print(err) 64 return nil, err 65 } 66 67 defer stmt.Close() 68 69 row := stmt.QueryRow(username) 70 u := models.User{} 71 err = row.Scan(&u.UUID, &u.Username, &u.FirstName, &u.LastName, &u.Email, &u.PasswordHash, &u.TimestampCreated, &u.TimestampModified) 72 return &u, err 73 } 74 75 func (m *MySQLDatastore) Close() { 76 m.Close() 77 } 78 79 func (m *MySQLDatastore) GetUserProfile(uuid string) (*models.UserProfile, error) { 80 81 stmt, err := m.Prepare("SELECT uuid, about, location, interests, profile_image_path FROM user_profile WHERE uuid = ?") 82 if err != nil { 83 log.Print(err) 84 return nil, err 85 } 86 defer stmt.Close() 87 row := stmt.QueryRow(uuid) 88 u := models.UserProfile{} 89 err = row.Scan(&u.UUID, &u.About, &u.Location, &u.Interests, &u.ProfileImagePath) 90 return &u, err 91 } 92 93 func (m *MySQLDatastore) GetGopherProfile(username string) (*models.UserProfile, error) { 94 95 stmt, err := m.Prepare("SELECT up.uuid, up.about, up.location, up.interests, up.profile_image_path, u.username FROM user_profile up, user u WHERE u.uuid = up.uuid and u.username = ?") 96 if err != nil { 97 log.Print(err) 98 return nil, err 99 } 100 defer stmt.Close() 101 row := stmt.QueryRow(username) 102 u := models.UserProfile{} 103 err = row.Scan(&u.UUID, &u.About, &u.Location, &u.Interests, &u.ProfileImagePath, &u.Username) 104 return &u, err 105 } 106 107 func (m *MySQLDatastore) UpdateUserProfile(uuid, about, location, interests string) error { 108 109 tx, err := m.Begin() 110 if err != nil { 111 log.Print(err) 112 } 113 114 defer tx.Rollback() 115 116 stmt, err := tx.Prepare("INSERT INTO user_profile(uuid, about, location, interests) VALUES(?, ?, ?, ?) ON DUPLICATE KEY UPDATE about=?, location=?, interests=?") 117 if err != nil { 118 return err 119 } 120 121 defer stmt.Close() 122 123 _, err = stmt.Exec(uuid, about, location, interests, about, location, interests) 124 if err != nil { 125 return err 126 } 127 128 err = tx.Commit() 129 if err != nil { 130 return err 131 } 132 133 return nil 134 135 } 136 137 func (m *MySQLDatastore) UpdateUserProfileImage(uuid, profileImagePath string) error { 138 139 tx, err := m.Begin() 140 if err != nil { 141 log.Print(err) 142 } 143 144 defer tx.Rollback() 145 146 stmt, err := tx.Prepare("INSERT INTO user_profile(uuid, profile_image_path) VALUES(?, ?) ON DUPLICATE KEY UPDATE profile_image_path=?") 147 if err != nil { 148 return err 149 } 150 151 defer stmt.Close() 152 153 _, err = stmt.Exec(uuid, profileImagePath, profileImagePath) 154 if err != nil { 155 return err 156 } 157 158 err = tx.Commit() 159 if err != nil { 160 return err 161 } 162 163 return nil 164 165 } 166 167 func (m *MySQLDatastore) FindGophers(owner string, searchTerm string) ([]models.Gopher, error) { 168 169 searchTerm = "%" + searchTerm + "%" 170 gophers := make([]models.Gopher, 0) 171 stmt, err := m.Prepare("SELECT u.uuid, u.username, u.first_name, u.last_name, up.location, up.profile_image_path FROM user u, user_profile up WHERE u.uuid = up.uuid AND CONCAT(u.first_name, '', u.last_name) LIKE ? and u.uuid <> ? and u.uuid not in (select friend_uuid from friend_relation where owner_uuid = ?)") 172 if err != nil { 173 return nil, err 174 } 175 176 defer stmt.Close() 177 178 rows, err := stmt.Query(searchTerm, owner, owner) 179 if err != nil { 180 return nil, err 181 } 182 183 for rows.Next() { 184 g := models.Gopher{} 185 err := rows.Scan(&g.UUID, &g.Username, &g.FirstName, &g.LastName, &g.Location, &g.ProfileImagePath) 186 if err != nil { 187 return nil, err 188 } 189 gophers = append(gophers, g) 190 } 191 return gophers, nil 192 193 } 194 195 func (m *MySQLDatastore) FriendsList(owner string) ([]models.Gopher, error) { 196 197 gophers := make([]models.Gopher, 0) 198 stmt, err := m.Prepare("SELECT u.uuid, u.username, u.first_name, u.last_name, up.location, up.profile_image_path FROM user u, user_profile up, friend_relation f WHERE u.uuid = up.uuid AND u.uuid = f.friend_uuid AND f.owner_uuid=?") 199 if err != nil { 200 return nil, err 201 } 202 203 defer stmt.Close() 204 205 rows, err := stmt.Query(owner) 206 if err != nil { 207 return nil, err 208 } 209 210 for rows.Next() { 211 g := models.Gopher{} 212 err := rows.Scan(&g.UUID, &g.Username, &g.FirstName, &g.LastName, &g.Location, &g.ProfileImagePath) 213 if err != nil { 214 return nil, err 215 } 216 gophers = append(gophers, g) 217 } 218 return gophers, nil 219 220 } 221 222 func (m *MySQLDatastore) FollowGopher(owner string, friend string) error { 223 224 tx, err := m.Begin() 225 if err != nil { 226 log.Print(err) 227 } 228 229 defer tx.Rollback() 230 231 stmt, err := tx.Prepare("INSERT INTO friend_relation(owner_uuid, friend_uuid) VALUES(?, ?)") 232 if err != nil { 233 return err 234 } 235 236 defer stmt.Close() 237 238 _, err = stmt.Exec(owner, friend) 239 if err != nil { 240 return err 241 } 242 243 err = tx.Commit() 244 if err != nil { 245 return err 246 } 247 248 return nil 249 250 } 251 252 func (m *MySQLDatastore) UnfollowGopher(owner string, friend string) error { 253 254 tx, err := m.Begin() 255 if err != nil { 256 log.Print(err) 257 } 258 259 defer tx.Rollback() 260 261 stmt, err := tx.Prepare("DELETE FROM friend_relation WHERE owner_uuid = ? and friend_uuid = ? LIMIT 1") 262 if err != nil { 263 return err 264 } 265 266 defer stmt.Close() 267 268 _, err = stmt.Exec(owner, friend) 269 if err != nil { 270 return err 271 } 272 273 err = tx.Commit() 274 if err != nil { 275 return err 276 } 277 278 return nil 279 280 } 281 282 func (m *MySQLDatastore) SavePost(owner string, title string, body string, mood int) error { 283 284 tx, err := m.Begin() 285 if err != nil { 286 log.Print(err) 287 } 288 289 defer tx.Rollback() 290 291 stmt, err := tx.Prepare("INSERT INTO post(uuid, title, body, mood) VALUES(?, ?, ?, ?)") 292 if err != nil { 293 return err 294 } 295 296 defer stmt.Close() 297 298 _, err = stmt.Exec(owner, title, body, mood) 299 if err != nil { 300 return err 301 } 302 303 err = tx.Commit() 304 if err != nil { 305 return err 306 } 307 308 return nil 309 310 } 311 312 func (m *MySQLDatastore) FetchPosts(owner string) ([]socialmedia.Post, error) { 313 314 posts := make([]socialmedia.Post, 0) 315 stmt, err := m.Prepare("select p.uuid, p.title, p.body, p.mood, UNIX_TIMESTAMP(p.created_ts), UNIX_TIMESTAMP(p.updated_ts), up.profile_image_path, u.username from post p, user u, user_profile up where p.uuid = u.uuid and p.uuid = up.uuid and (p.uuid = ? or p.uuid in (select friend_uuid from friend_relation where owner_uuid=?) ) order by p.created_ts desc") 316 317 if err != nil { 318 return nil, err 319 } 320 321 defer stmt.Close() 322 323 rows, err := stmt.Query(owner, owner) 324 if err != nil { 325 return nil, err 326 } 327 328 for rows.Next() { 329 p := socialmedia.Post{} 330 err := rows.Scan(&p.UUID, &p.Caption, &p.MessageBody, &p.RawMoodValue, &p.TimeCreatedUnixTS, &p.TimeModifiedUnixTS, &p.ProfileImagePath, &p.Username) 331 if err != nil { 332 return nil, err 333 } 334 posts = append(posts, p) 335 } 336 return posts, nil 337 338 }