Compare commits

...

2 Commits

Author SHA1 Message Date
ad08e6ab31 adjust response with pgx type 2024-03-04 16:09:55 +07:00
6b9ec051bd fix search response, to only server data 2024-03-03 20:38:23 +07:00
8 changed files with 126 additions and 123 deletions

View File

@ -1,7 +1,6 @@
package api package api
import ( import (
"database/sql"
"fmt" "fmt"
"net/http" "net/http"
"os" "os"
@ -11,6 +10,7 @@ import (
db "git.nochill.in/nochill/hiling_go/db/sqlc" db "git.nochill.in/nochill/hiling_go/db/sqlc"
"git.nochill.in/nochill/hiling_go/util" "git.nochill.in/nochill/hiling_go/util"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
"github.com/meilisearch/meilisearch-go" "github.com/meilisearch/meilisearch-go"
ysqlc "github.com/yiplee/sqlc" ysqlc "github.com/yiplee/sqlc"
@ -63,7 +63,7 @@ func (server *Server) createLocation(ctx *gin.Context) {
SubmittedBy: req.SubmittedBy, SubmittedBy: req.SubmittedBy,
RegencyID: req.RegencyID, RegencyID: req.RegencyID,
IsDeleted: false, IsDeleted: false,
ApprovedBy: sql.NullInt32{Int32: 0, Valid: false}, ApprovedBy: pgtype.Int4{Int32: 0, Valid: false},
GoogleMapsLink: pgtype.Text{Valid: len(req.GoogleMapsLink) > 0, String: req.GoogleMapsLink}, GoogleMapsLink: pgtype.Text{Valid: len(req.GoogleMapsLink) > 0, String: req.GoogleMapsLink},
Thumbnail: tempImg, Thumbnail: tempImg,
} }
@ -111,7 +111,7 @@ type getTopListLocationsReq struct {
Page int32 `form:"page" binding:"required,min=1"` Page int32 `form:"page" binding:"required,min=1"`
PageSize int32 `form:"page_size" binding:"required,min=5"` PageSize int32 `form:"page_size" binding:"required,min=5"`
OrderBy int16 `form:"order_by" binding:"numeric,min=1,max=3"` OrderBy int16 `form:"order_by" binding:"numeric,min=1,max=3"`
RegionType int16 `form:"region_type" binding:"numeric,min=0,max=7"` RegionType int32 `form:"region_type" binding:"numeric,min=0,max=7"`
} }
func (server *Server) getTopListLocations(ctx *gin.Context) { func (server *Server) getTopListLocations(ctx *gin.Context) {
@ -136,7 +136,7 @@ func (server *Server) getTopListLocations(ctx *gin.Context) {
Limit: req.PageSize, Limit: req.PageSize,
Offset: (req.Page - 1) * req.PageSize, Offset: (req.Page - 1) * req.PageSize,
OrderBy: orderby, OrderBy: orderby,
RegionType: sql.NullInt16{Valid: req.RegionType > 0, Int16: req.RegionType}, RegionType: pgtype.Int4{Valid: req.RegionType > 0, Int32: req.RegionType},
} }
locations, err := server.Store.GetTopListLocations(ctx, arg) locations, err := server.Store.GetTopListLocations(ctx, arg)
@ -192,7 +192,7 @@ func (server *Server) getLocation(ctx *gin.Context) {
location, err := server.Store.GetLocation(ctx, req.ID) location, err := server.Store.GetLocation(ctx, req.ID)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == pgx.ErrNoRows {
ctx.JSON(http.StatusNotFound, ErrorResponse(err, "")) ctx.JSON(http.StatusNotFound, ErrorResponse(err, ""))
return return
} }
@ -272,7 +272,7 @@ func (server *Server) getListLocationReviews(ctx *gin.Context) {
reviews, err := server.Store.GetListLocationReviews(ctx, arg) reviews, err := server.Store.GetListLocationReviews(ctx, arg)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == pgx.ErrNoRows {
ctx.JSON(http.StatusNotFound, ErrorResponse(err, "There's no critics reviews for this location yet")) ctx.JSON(http.StatusNotFound, ErrorResponse(err, "There's no critics reviews for this location yet"))
return return
} }
@ -294,7 +294,7 @@ func (server *Server) getListLocationReviews(ctx *gin.Context) {
reviews, err := server.Store.GetListLocationReviews(ctx, arg) reviews, err := server.Store.GetListLocationReviews(ctx, arg)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == pgx.ErrNoRows {
ctx.JSON(http.StatusNotFound, ErrorResponse(err, "There's no critics reviews for this location yet")) ctx.JSON(http.StatusNotFound, ErrorResponse(err, "There's no critics reviews for this location yet"))
return return
} }
@ -332,5 +332,5 @@ func (server *Server) searchLocations(ctx *gin.Context) {
return return
} }
ctx.JSON(http.StatusOK, searchRes) ctx.JSON(http.StatusOK, searchRes.Hits)
} }

View File

@ -1,12 +1,13 @@
package api package api
import ( import (
"database/sql" "log"
"net/http" "net/http"
db "git.nochill.in/nochill/hiling_go/db/sqlc" db "git.nochill.in/nochill/hiling_go/db/sqlc"
"git.nochill.in/nochill/hiling_go/util/token" "git.nochill.in/nochill/hiling_go/util/token"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/jackc/pgx/v5"
) )
type createReviewReq struct { type createReviewReq struct {
@ -76,6 +77,8 @@ func (server *Server) getUserReviewByLocation(ctx *gin.Context) {
authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload) authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload)
log.Println(authPayload)
arg := db.GetUserReviewByLocationParams{ arg := db.GetUserReviewByLocationParams{
SubmittedBy: int32(authPayload.UserID), SubmittedBy: int32(authPayload.UserID),
LocationID: req.LocationID, LocationID: req.LocationID,
@ -84,7 +87,7 @@ func (server *Server) getUserReviewByLocation(ctx *gin.Context) {
review, err := server.Store.GetUserReviewByLocation(ctx, arg) review, err := server.Store.GetUserReviewByLocation(ctx, arg)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == pgx.ErrNoRows {
ctx.JSON(http.StatusNotFound, ErrorResponse(err, "Review not found")) ctx.JSON(http.StatusNotFound, ErrorResponse(err, "Review not found"))
return return
} }

View File

@ -1,12 +1,12 @@
package api package api
import ( import (
"database/sql"
"fmt" "fmt"
"net/http" "net/http"
"time" "time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/jackc/pgx/v5"
) )
type renewAccessRequest struct { type renewAccessRequest struct {
@ -33,7 +33,7 @@ func (server *Server) renewAccessToken(ctx *gin.Context) {
session, err := server.Store.GetSession(ctx, int32(refreshPayload.UserID)) session, err := server.Store.GetSession(ctx, int32(refreshPayload.UserID))
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == pgx.ErrNoRows {
ctx.JSON(http.StatusNotFound, ErrorResponse(err, "")) ctx.JSON(http.StatusNotFound, ErrorResponse(err, ""))
return return
} }
@ -67,7 +67,7 @@ func (server *Server) renewAccessToken(ctx *gin.Context) {
user, err := server.Store.GetUser(ctx, refreshPayload.Username) user, err := server.Store.GetUser(ctx, refreshPayload.Username)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == pgx.ErrNoRows {
ctx.JSON(http.StatusNotFound, ErrorResponse(err, "")) ctx.JSON(http.StatusNotFound, ErrorResponse(err, ""))
return return
} }

View File

@ -1,7 +1,6 @@
package api package api
import ( import (
"database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
@ -13,6 +12,7 @@ import (
"git.nochill.in/nochill/hiling_go/util" "git.nochill.in/nochill/hiling_go/util"
"git.nochill.in/nochill/hiling_go/util/token" "git.nochill.in/nochill/hiling_go/util/token"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
@ -22,18 +22,18 @@ type createUserRequest struct {
} }
type createUserResponse struct { type createUserResponse struct {
ID int32 `json:"id"` ID int32 `json:"id"`
Username string `json:"username"` Username string `json:"username"`
AvatarPicture string `json:"avatar_picture"` // avatar_url AvatarPicture string `json:"avatar_picture"` // avatar_url
BannedAt sql.NullTime `json:"banned_at"` BannedAt pgtype.Timestamp `json:"banned_at"`
BannedUntil sql.NullTime `json:"banned_until"` BannedUntil pgtype.Timestamp `json:"banned_until"`
BanReason string `json:"ban_reason"` BanReason string `json:"ban_reason"`
IsPermaban bool `json:"is_permaban"` IsPermaban bool `json:"is_permaban"`
IsAdmin bool `json:"is_admin"` IsAdmin bool `json:"is_admin"`
IsCritics bool `json:"is_critics"` IsCritics bool `json:"is_critics"`
IsVerified bool `json:"is_verified"` IsVerified bool `json:"is_verified"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
} }
func (server *Server) createUser(ctx *gin.Context) { func (server *Server) createUser(ctx *gin.Context) {
@ -101,8 +101,8 @@ func (server *Server) createUser(ctx *gin.Context) {
ID: user.ID, ID: user.ID,
Username: user.Username, Username: user.Username,
AvatarPicture: user.AvatarPicture.String, AvatarPicture: user.AvatarPicture.String,
BannedAt: sql.NullTime{Valid: user.BannedAt.Valid, Time: user.BannedAt.Time}, BannedAt: pgtype.Timestamp{Valid: user.BannedAt.Valid, Time: user.BannedAt.Time},
BannedUntil: sql.NullTime{Valid: user.BannedUntil.Valid, Time: user.BannedUntil.Time}, BannedUntil: pgtype.Timestamp{Valid: user.BannedUntil.Valid, Time: user.BannedUntil.Time},
BanReason: user.BanReason.String, BanReason: user.BanReason.String,
IsPermaban: user.IsPermaban.Bool, IsPermaban: user.IsPermaban.Bool,
IsAdmin: user.IsAdmin.Bool, IsAdmin: user.IsAdmin.Bool,
@ -177,9 +177,9 @@ func (server *Server) updateUser(ctx *gin.Context) {
authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload) authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload)
user, err := server.Store.UpdateUser(ctx, db.UpdateUserParams{ user, err := server.Store.UpdateUser(ctx, db.UpdateUserParams{
About: sql.NullString{String: req.About, Valid: true}, About: pgtype.Text{String: req.About, Valid: true},
SocialMedia: req.SocialMedia, SocialMedia: req.SocialMedia,
Website: sql.NullString{String: req.Website, Valid: len(req.Website) > 0}, Website: pgtype.Text{String: req.Website, Valid: len(req.Website) > 0},
ID: int32(authPayload.UserID), ID: int32(authPayload.UserID),
}) })
@ -258,7 +258,7 @@ func (server *Server) login(ctx *gin.Context) {
user, err := server.Store.GetUser(ctx, req.Username) user, err := server.Store.GetUser(ctx, req.Username)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == pgx.ErrNoRows {
ctx.JSON(http.StatusNotFound, ErrorResponse(err, "User not found")) ctx.JSON(http.StatusNotFound, ErrorResponse(err, "User not found"))
return return
} }

View File

@ -2,7 +2,6 @@ package db
import ( import (
"context" "context"
"database/sql"
"fmt" "fmt"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
@ -12,33 +11,33 @@ type GetTopListLocationsParams struct {
Limit int32 Limit int32
Offset int32 Offset int32
OrderBy string OrderBy string
RegionType sql.NullInt16 RegionType pgtype.Int4
} }
type GetTopListLocationsRow struct { type GetTopListLocationsRow struct {
RowNumber int32 `json:"row_number"` RowNumber int32 `json:"row_number"`
ID int32 `json:"id"` ID int32 `json:"id"`
Name string `json:"name"` Name string `json:"name"`
RegionName string `json:"region_name"` RegionName string `json:"region_name"`
Thumbnail sql.NullString `json:"thumbnail"` Thumbnail pgtype.Text `json:"thumbnail"`
Address string `json:"address"` Address string `json:"address"`
GoogleMapsLink string `json:"google_maps_link"` GoogleMapsLink string `json:"google_maps_link"`
RegencyName string `json:"regency_name"` RegencyName string `json:"regency_name"`
CriticScore int16 `json:"critic_score"` CriticScore int16 `json:"critic_score"`
CriticCount int16 `json:"critic_count"` CriticCount int16 `json:"critic_count"`
UserScore int16 `json:"user_score"` UserScore int16 `json:"user_score"`
UserCount int16 `json:"user_count"` UserCount int16 `json:"user_count"`
TotalCount int16 `json:"total_count"` TotalCount int16 `json:"total_count"`
CriticBayes int16 `json:"critic_bayes"` CriticBayes int16 `json:"critic_bayes"`
UserBayes int16 `json:"user_bayes"` UserBayes int16 `json:"user_bayes"`
AvgBayes int16 `json:"avg_bayes"` AvgBayes int16 `json:"avg_bayes"`
} }
func (q *Queries) GetTopListLocations(ctx context.Context, arg GetTopListLocationsParams) ([]GetTopListLocationsRow, error) { func (q *Queries) GetTopListLocations(ctx context.Context, arg GetTopListLocationsParams) ([]GetTopListLocationsRow, error) {
regionType := "" regionType := ""
if arg.RegionType.Valid { if arg.RegionType.Valid {
regionType = fmt.Sprintf("AND reg.id = %d", arg.RegionType.Int16) regionType = fmt.Sprintf("AND reg.id = %d", arg.RegionType.Int32)
} }
// https://fulmicoton.com/posts/bayesian_rating/ // https://fulmicoton.com/posts/bayesian_rating/
@ -111,19 +110,19 @@ func (q *Queries) GetTopListLocations(ctx context.Context, arg GetTopListLocatio
} }
type GetLocationRow struct { type GetLocationRow struct {
ID int32 `json:"id"` ID int32 `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Address string `json:"address"` Address string `json:"address"`
RegencyName string `json:"regency_name"` RegencyName string `json:"regency_name"`
ProvinceName string `json:"province_name"` ProvinceName string `json:"province_name"`
RegionName string `json:"region_name"` RegionName string `json:"region_name"`
GoogleMapsLink string `json:"google_maps_link"` GoogleMapsLink string `json:"google_maps_link"`
Thumbnail sql.NullString `json:"thumbnail"` Thumbnail pgtype.Text `json:"thumbnail"`
SubmittedBy string `json:"submitted_by"` SubmittedBy string `json:"submitted_by"`
CriticScore int32 `json:"critic_score"` CriticScore int32 `json:"critic_score"`
CriticCount int32 `json:"critic_count"` CriticCount int32 `json:"critic_count"`
UserScore int32 `json:"user_score"` UserScore int32 `json:"user_score"`
UserCount int32 `json:"user_count"` UserCount int32 `json:"user_count"`
} }
var getLocationQ = ` var getLocationQ = `
@ -189,14 +188,14 @@ RETURNING id
` `
type CreateLocationParams struct { type CreateLocationParams struct {
Address string `json:"address"` Address string `json:"address"`
Name string `json:"name"` Name string `json:"name"`
SubmittedBy int32 `json:"submitted_by"` SubmittedBy int32 `json:"submitted_by"`
LocationType LocationType `json:"location_type"` LocationType LocationType `json:"location_type"`
RegencyID int16 `json:"regency_id"` RegencyID int16 `json:"regency_id"`
GoogleMapsLink pgtype.Text `json:"google_maps_link"` GoogleMapsLink pgtype.Text `json:"google_maps_link"`
IsDeleted bool `json:"is_deleted"` IsDeleted bool `json:"is_deleted"`
ApprovedBy sql.NullInt32 `json:"approved_by"` ApprovedBy pgtype.Int4 `json:"approved_by"`
} }
func (q *Queries) CreateLocation(ctx context.Context, arg CreateLocationParams) (int32, error) { func (q *Queries) CreateLocation(ctx context.Context, arg CreateLocationParams) (int32, error) {

View File

@ -2,8 +2,9 @@ package db
import ( import (
"context" "context"
"database/sql"
"time" "time"
"github.com/jackc/pgx/v5/pgtype"
) )
const createReview = `-- name: CreateReview :one const createReview = `-- name: CreateReview :one
@ -59,14 +60,14 @@ type GetListLocationReviewsParams struct {
} }
type GetListLocationReviewsRow struct { type GetListLocationReviewsRow struct {
ID int32 `json:"id"` ID int32 `json:"id"`
Score int8 `json:"score"` Score int8 `json:"score"`
Comment string `json:"comments"` Comment string `json:"comments"`
UserID int32 `json:"user_id"` UserID int32 `json:"user_id"`
Username string `json:"username"` Username string `json:"username"`
UserAvatar sql.NullString `json:"user_avatar"` UserAvatar pgtype.Text `json:"user_avatar"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
} }
const getListLocationReviews = ` const getListLocationReviews = `

View File

@ -2,7 +2,6 @@ package db
import ( import (
"context" "context"
"database/sql"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
@ -15,7 +14,7 @@ type CreateLocationTxParams struct {
RegencyID int16 `json:"regency_id"` RegencyID int16 `json:"regency_id"`
GoogleMapsLink pgtype.Text `json:"google_maps_link"` GoogleMapsLink pgtype.Text `json:"google_maps_link"`
IsDeleted bool `json:"is_deleted"` IsDeleted bool `json:"is_deleted"`
ApprovedBy sql.NullInt32 `json:"approved_by"` ApprovedBy pgtype.Int4 `json:"approved_by"`
Thumbnail []CreateImageParams `json:"thumbnails"` Thumbnail []CreateImageParams `json:"thumbnails"`
} }

View File

@ -2,9 +2,10 @@ package db
import ( import (
"context" "context"
"database/sql"
"encoding/json" "encoding/json"
"time" "time"
"github.com/jackc/pgx/v5/pgtype"
) )
const getUserQ = `-- name: GetUser :one const getUserQ = `-- name: GetUser :one
@ -32,24 +33,24 @@ WHERE username = $1
` `
type GetUserRow struct { type GetUserRow struct {
ID int32 `json:"id"` ID int32 `json:"id"`
Email string `json:"email"` Email string `json:"email"`
Password string `json:"-"` Password string `json:"-"`
About string `json:"about"` About string `json:"about"`
Website string `json:"website"` Website string `json:"website"`
Username string `json:"username"` Username string `json:"username"`
GoogleSignInPayload string `json:"google_sign_in_payload"` GoogleSignInPayload string `json:"google_sign_in_payload"`
AvatarPicture string `json:"avatar_picture"` AvatarPicture string `json:"avatar_picture"`
BannedAt sql.NullTime `json:"banned_at"` BannedAt pgtype.Timestamp `json:"banned_at"`
BannedUntil sql.NullTime `json:"banned_until"` BannedUntil pgtype.Timestamp `json:"banned_until"`
BanReason string `json:"ban_reason"` BanReason string `json:"ban_reason"`
IsPermaban bool `json:"is_permaban"` IsPermaban bool `json:"is_permaban"`
IsAdmin bool `json:"is_admin"` IsAdmin bool `json:"is_admin"`
IsCritics bool `json:"is_critics"` IsCritics bool `json:"is_critics"`
IsVerified bool `json:"is_verified"` IsVerified bool `json:"is_verified"`
SocialMedia json.RawMessage `json:"social_media"` SocialMedia json.RawMessage `json:"social_media"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
} }
func (q *Queries) GetUser(ctx context.Context, username string) (GetUserRow, error) { func (q *Queries) GetUser(ctx context.Context, username string) (GetUserRow, error) {
@ -173,31 +174,31 @@ RETURNING
` `
type UpdateUserParams struct { type UpdateUserParams struct {
About sql.NullString `json:"about"` About pgtype.Text `json:"about"`
SocialMedia interface{} `json:"social_media"` SocialMedia interface{} `json:"social_media"`
Website sql.NullString `json:"website"` Website pgtype.Text `json:"website"`
ID int32 `json:"id"` ID int32 `json:"id"`
} }
type UpdateUserRow struct { type UpdateUserRow struct {
ID int32 `json:"id"` ID int32 `json:"id"`
Email string `json:"email"` Email string `json:"email"`
Username string `json:"username"` Username string `json:"username"`
AvatarPicture string `json:"avatar_picture"` AvatarPicture string `json:"avatar_picture"`
About string `json:"about"` About string `json:"about"`
Website string `json:"website"` Website string `json:"website"`
GoogleSignInPayload string `json:"google_sign_in_payload"` GoogleSignInPayload string `json:"google_sign_in_payload"`
BannedAt sql.NullTime `json:"banned_at"` BannedAt pgtype.Timestamp `json:"banned_at"`
BannedUntil sql.NullTime `json:"banned_until"` BannedUntil pgtype.Timestamp `json:"banned_until"`
BanReason string `json:"ban_reason"` BanReason string `json:"ban_reason"`
IsPermaban bool `json:"is_permaban"` IsPermaban bool `json:"is_permaban"`
IsAdmin bool `json:"is_admin"` IsAdmin bool `json:"is_admin"`
IsCritics bool `json:"is_critics"` IsCritics bool `json:"is_critics"`
IsVerified bool `json:"is_verified"` IsVerified bool `json:"is_verified"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
SocialMedia json.RawMessage `json:"social_media"` SocialMedia json.RawMessage `json:"social_media"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
} }
func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) (UpdateUserRow, error) { func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) (UpdateUserRow, error) {