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  }