<commit_before>package database

import (
	"database/sql"
	"time"

	"github.com/hackedu/backend/model"
)

// GetUser gets the user from the database with the provided ID.
func GetUser(id int64) (*model.User, error) {
	user := model.User{}
	err := db.Get(&user, "SELECT * FROM users WHERE id=$1", id)
	if err != nil {
		return nil, err
	}
	return &user, nil
}

// GetUserByEmail gets the user from the database with the provided email.
func GetUserByEmail(email string) (*model.User, error) {
	user := model.User{}
	err := db.Get(&user, "SELECT * FROM users WHERE email=$1", email)
	if err != nil {
		return nil, err
	}
	return &user, nil
}

// SaveUser saves the provided user to the database. If the user is a new
// user, then the user.Created field is set to the current time. The
// user.Updated field is set to the current time regardless.
//
// If the user is a new user, then SaveUser also verifies that the user's
// email is unique and returns model.ErrInvalidEmail accordingly.
func SaveUser(u *model.User) error {
	if u.ID == 0 {
		// TODO: Should do this in the user.validate() method, but with the
		// current architecture of the application, that causes an import cycle.
		//
		// Check if email is unique.
		_, err := GetUserByEmail(u.Email)
		if err != sql.ErrNoRows {
			return model.ErrInvalidEmail
		}

		u.Created = time.Now()
	}
	u.Updated = time.Now()

	rows, err := db.Query("INSERT INTO users (created, updated, first_name, last_name, email, github, twitter, password) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id", u.Created, u.Updated, u.FirstName, u.LastName, u.Email, u.GitHub, u.Twitter, u.Password)
	if err != nil {
		return err
	}
	for rows.Next() {
		if err := rows.Scan(&u.ID); err != nil {
			return err
		}
	}
	if err := rows.Err(); err != nil {
		return err
	}

	return nil
}<commit_msg>Isolate SQL for creating users into seperate constant.<commit_after>package database

import (
	"database/sql"
	"time"

	"github.com/hackedu/backend/model"
)

const userCreateStmt = `INSERT INTO users (created, updated, first_name,
last_name, email, github, twitter, password) VALUES ($1, $2, $3, $4, $5, $6,
$7, $8) RETURNING id`

// GetUser gets the user from the database with the provided ID.
func GetUser(id int64) (*model.User, error) {
	user := model.User{}
	err := db.Get(&user, "SELECT * FROM users WHERE id=$1", id)
	if err != nil {
		return nil, err
	}
	return &user, nil
}

// GetUserByEmail gets the user from the database with the provided email.
func GetUserByEmail(email string) (*model.User, error) {
	user := model.User{}
	err := db.Get(&user, "SELECT * FROM users WHERE email=$1", email)
	if err != nil {
		return nil, err
	}
	return &user, nil
}

// SaveUser saves the provided user to the database. If the user is a new
// user, then the user.Created field is set to the current time. The
// user.Updated field is set to the current time regardless.
//
// If the user is a new user, then SaveUser also verifies that the user's
// email is unique and returns model.ErrInvalidEmail accordingly.
func SaveUser(u *model.User) error {
	if u.ID == 0 {
		// TODO: Should do this in the user.validate() method, but with the
		// current architecture of the application, that causes an import cycle.
		//
		// Check if email is unique.
		_, err := GetUserByEmail(u.Email)
		if err != sql.ErrNoRows {
			return model.ErrInvalidEmail
		}

		u.Created = time.Now()
	}
	u.Updated = time.Now()

	rows, err := db.Query(userCreateStmt, u.Created, u.Updated, u.FirstName,
		u.LastName, u.Email, u.GitHub, u.Twitter, u.Password)
	if err != nil {
		return err
	}
	for rows.Next() {
		if err := rows.Scan(&u.ID); err != nil {
			return err
		}
	}
	if err := rows.Err(); err != nil {
		return err
	}

	return nil
}
{'fraction_non_alphanumeric': 0.12973838761345435, 'fraction_numerical': 0.0069407367859049655, 'mean_word_length': 3.367132867132867, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '606128', 'n_tokens_mistral': 1310, 'n_tokens_neox': 1246, 'n_words': 472}