sqlc: impement topic data logic

r/paopao-ce-pro
Michael Li 3 years ago
parent bfef2fe7f9
commit 3f3cebed70
No known key found for this signature in database

@ -12,9 +12,9 @@ type PTag struct {
UserID int64 UserID int64
Tag string Tag string
QuoteNum int64 QuoteNum int64
CreatedOn int32 CreatedOn int64
ModifiedOn int32 ModifiedOn int64
DeletedOn int32 DeletedOn int64
// 是否删除 // 是否删除
IsDel bool IsDel bool
} }

@ -6,21 +6,16 @@ package dbr
import ( import (
"context" "context"
"github.com/jackc/pgx/v5/pgtype"
) )
type Querier interface { type Querier interface {
DecrTagsById(ctx context.Context, arg *DecrTagsByIdParams) error DecrTagsById(ctx context.Context, arg *DecrTagsByIdParams) error
HotTags(ctx context.Context, arg *HotTagsParams) ([]*HotTagsRow, error) HotTags(ctx context.Context, arg *HotTagsParams) ([]*HotTagsRow, error)
IncrTagsById(ctx context.Context, arg *IncrTagsByIdParams) error IncrTags(ctx context.Context, arg *IncrTagsParams) ([]*IncrTagsRow, error)
InsertTags(ctx context.Context, arg *InsertTagsParams) (*InsertTagsRow, error) InsertTags(ctx context.Context, arg *InsertTagsParams) (int64, error)
NewestTags(ctx context.Context, arg *NewestTagsParams) ([]*NewestTagsRow, error) NewestTags(ctx context.Context, arg *NewestTagsParams) ([]*NewestTagsRow, error)
TagsByIdA(ctx context.Context, ids pgtype.Array[int64]) ([]int64, error)
TagsByIdB(ctx context.Context, ids pgtype.Array[int64]) ([]*TagsByIdBRow, error)
TagsByKeywordA(ctx context.Context) ([]*TagsByKeywordARow, error) TagsByKeywordA(ctx context.Context) ([]*TagsByKeywordARow, error)
TagsByKeywordB(ctx context.Context, tag string) ([]*TagsByKeywordBRow, error) TagsByKeywordB(ctx context.Context, tag string) ([]*TagsByKeywordBRow, error)
TagsByName(ctx context.Context, tags pgtype.Array[string]) ([]*TagsByNameRow, error)
} }
var _ Querier = (*Queries)(nil) var _ Querier = (*Queries)(nil)

@ -29,30 +29,26 @@ OFFSET 0 LIMIT 6;
-- name: InsertTags :one -- name: InsertTags :one
INSERT INTO p_tag (user_id, tag, created_on, modified_on, quote_num) INSERT INTO p_tag (user_id, tag, created_on, modified_on, quote_num)
VALUES ($1, $2, $3, $3, 1) VALUES ($1, $2, $3, $3, 1)
RETURNING id, user_id, tag, quote_num; RETURNING id;
-- name: TagsByIdA :many
SELECT id
FROM p_tag
WHERE id = ANY(@ids::bigserial[]) AND is_del = false AND quote_num >= 0;
-- name: TagsByIdB :many
SELECT id, user_id, tag, quote_num
FROM p_tag
WHERE id = ANY(@ids::bigserial[]);
-- name: DecrTagsById :exec -- name: DecrTagsById :exec
UPDATE p_tag UPDATE p_tag
SET quote_num = quote_num-1, SET quote_num = quote_num-1,
modified_on=$1 modified_on=$1
WHERE id = ANY(@ids::bigserial[]); WHERE id IN (
SELECT id
FROM p_tag
WHERE id = ANY(@ids::bigserial[]) AND is_del = false AND quote_num >= 1
);
-- name: TagsByName :many -- name: IncrTags :many
SELECT id, user_id, tag, quote_num
FROM p_tag
WHERE tag = ANY(@tags::varchar[]) AND is_del = false AND quote_num >= 0;
-- name: IncrTagsById :exec
UPDATE p_tag UPDATE p_tag
SET quote_num = quote_num+1, modified_on = $1 SET quote_num = quote_num+1,
WHERE id = ANY(@ids::bigserial[]); modified_on = $1,
id_del = false
WHERE id IN (
SELECT id
FROM p_tag
WHERE tag = ANY(@tags::varchar[])
)
RETURNING id, user_id, tag, quote_num;

@ -3,9 +3,9 @@ CREATE TABLE p_tag (
user_id bigserial NOT NULL DEFAULT 0, user_id bigserial NOT NULL DEFAULT 0,
tag varchar(255) NOT NULL, tag varchar(255) NOT NULL,
quote_num bigint NOT NULL DEFAULT 0, quote_num bigint NOT NULL DEFAULT 0,
created_on int NOT NULL DEFAULT 0, created_on bigint NOT NULL DEFAULT 0,
modified_on int NOT NULL DEFAULT 0, modified_on bigint NOT NULL DEFAULT 0,
deleted_on int NOT NULL DEFAULT 0, deleted_on bigint NOT NULL DEFAULT 0,
is_del boolean NOT NULL DEFAULT false, is_del boolean NOT NULL DEFAULT false,
UNIQUE (tag) UNIQUE (tag)
); );

@ -15,11 +15,15 @@ const decrTagsById = `-- name: DecrTagsById :exec
UPDATE p_tag UPDATE p_tag
SET quote_num = quote_num-1, SET quote_num = quote_num-1,
modified_on=$1 modified_on=$1
WHERE id = ANY($2::bigserial[]) WHERE id IN (
SELECT id
FROM p_tag
WHERE id = ANY($2::bigserial[]) AND is_del = false AND quote_num >= 1
)
` `
type DecrTagsByIdParams struct { type DecrTagsByIdParams struct {
ModifiedOn int32 ModifiedOn int64
Ids pgtype.Array[int64] Ids pgtype.Array[int64]
} }
@ -73,82 +77,40 @@ func (q *Queries) HotTags(ctx context.Context, arg *HotTagsParams) ([]*HotTagsRo
return items, nil return items, nil
} }
const incrTagsById = `-- name: IncrTagsById :exec const incrTags = `-- name: IncrTags :many
UPDATE p_tag UPDATE p_tag
SET quote_num = quote_num+1, modified_on = $1 SET quote_num = quote_num+1,
WHERE id = ANY($2::bigserial[]) modified_on = $1,
` id_del = false
WHERE id IN (
type IncrTagsByIdParams struct { SELECT id
ModifiedOn int32 FROM p_tag
Ids pgtype.Array[int64] WHERE tag = ANY($2::varchar[])
} )
func (q *Queries) IncrTagsById(ctx context.Context, arg *IncrTagsByIdParams) error {
_, err := q.db.Exec(ctx, incrTagsById, arg.ModifiedOn, arg.Ids)
return err
}
const insertTags = `-- name: InsertTags :one
INSERT INTO p_tag (user_id, tag, created_on, modified_on, quote_num)
VALUES ($1, $2, $3, $3, 1)
RETURNING id, user_id, tag, quote_num RETURNING id, user_id, tag, quote_num
` `
type InsertTagsParams struct { type IncrTagsParams struct {
UserID int64 ModifiedOn int64
Tag string Tags pgtype.Array[string]
CreatedOn int32
} }
type InsertTagsRow struct { type IncrTagsRow struct {
ID int64 ID int64
UserID int64 UserID int64
Tag string Tag string
QuoteNum int64 QuoteNum int64
} }
func (q *Queries) InsertTags(ctx context.Context, arg *InsertTagsParams) (*InsertTagsRow, error) { func (q *Queries) IncrTags(ctx context.Context, arg *IncrTagsParams) ([]*IncrTagsRow, error) {
row := q.db.QueryRow(ctx, insertTags, arg.UserID, arg.Tag, arg.CreatedOn) rows, err := q.db.Query(ctx, incrTags, arg.ModifiedOn, arg.Tags)
var i InsertTagsRow
err := row.Scan(
&i.ID,
&i.UserID,
&i.Tag,
&i.QuoteNum,
)
return &i, err
}
const newestTags = `-- name: NewestTags :many
SELECT id, user_id, tag, quote_num
FROM p_tag
WHERE is_del = false AND quote_num > 0
ORDER BY id DESC
OFFSET $1 LIMIT $2
`
type NewestTagsParams struct {
Offset int32
Limit int32
}
type NewestTagsRow struct {
ID int64
UserID int64
Tag string
QuoteNum int64
}
func (q *Queries) NewestTags(ctx context.Context, arg *NewestTagsParams) ([]*NewestTagsRow, error) {
rows, err := q.db.Query(ctx, newestTags, arg.Offset, arg.Limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
var items []*NewestTagsRow var items []*IncrTagsRow
for rows.Next() { for rows.Next() {
var i NewestTagsRow var i IncrTagsRow
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.UserID, &i.UserID,
@ -165,54 +127,54 @@ func (q *Queries) NewestTags(ctx context.Context, arg *NewestTagsParams) ([]*New
return items, nil return items, nil
} }
const tagsByIdA = `-- name: TagsByIdA :many const insertTags = `-- name: InsertTags :one
SELECT id INSERT INTO p_tag (user_id, tag, created_on, modified_on, quote_num)
FROM p_tag VALUES ($1, $2, $3, $3, 1)
WHERE id = ANY($1::bigserial[]) AND is_del = false AND quote_num >= 0 RETURNING id
` `
func (q *Queries) TagsByIdA(ctx context.Context, ids pgtype.Array[int64]) ([]int64, error) { type InsertTagsParams struct {
rows, err := q.db.Query(ctx, tagsByIdA, ids) UserID int64
if err != nil { Tag string
return nil, err CreatedOn int64
} }
defer rows.Close()
var items []int64 func (q *Queries) InsertTags(ctx context.Context, arg *InsertTagsParams) (int64, error) {
for rows.Next() { row := q.db.QueryRow(ctx, insertTags, arg.UserID, arg.Tag, arg.CreatedOn)
var id int64 var id int64
if err := rows.Scan(&id); err != nil { err := row.Scan(&id)
return nil, err return id, err
}
items = append(items, id)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
} }
const tagsByIdB = `-- name: TagsByIdB :many const newestTags = `-- name: NewestTags :many
SELECT id, user_id, tag, quote_num SELECT id, user_id, tag, quote_num
FROM p_tag FROM p_tag
WHERE id = ANY($1::bigserial[]) WHERE is_del = false AND quote_num > 0
ORDER BY id DESC
OFFSET $1 LIMIT $2
` `
type TagsByIdBRow struct { type NewestTagsParams struct {
Offset int32
Limit int32
}
type NewestTagsRow struct {
ID int64 ID int64
UserID int64 UserID int64
Tag string Tag string
QuoteNum int64 QuoteNum int64
} }
func (q *Queries) TagsByIdB(ctx context.Context, ids pgtype.Array[int64]) ([]*TagsByIdBRow, error) { func (q *Queries) NewestTags(ctx context.Context, arg *NewestTagsParams) ([]*NewestTagsRow, error) {
rows, err := q.db.Query(ctx, tagsByIdB, ids) rows, err := q.db.Query(ctx, newestTags, arg.Offset, arg.Limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
var items []*TagsByIdBRow var items []*NewestTagsRow
for rows.Next() { for rows.Next() {
var i TagsByIdBRow var i NewestTagsRow
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.UserID, &i.UserID,
@ -308,41 +270,3 @@ func (q *Queries) TagsByKeywordB(ctx context.Context, tag string) ([]*TagsByKeyw
} }
return items, nil return items, nil
} }
const tagsByName = `-- name: TagsByName :many
SELECT id, user_id, tag, quote_num
FROM p_tag
WHERE tag = ANY($1::varchar[]) AND is_del = false AND quote_num >= 0
`
type TagsByNameRow struct {
ID int64
UserID int64
Tag string
QuoteNum int64
}
func (q *Queries) TagsByName(ctx context.Context, tags pgtype.Array[string]) ([]*TagsByNameRow, error) {
rows, err := q.db.Query(ctx, tagsByName, tags)
if err != nil {
return nil, err
}
defer rows.Close()
var items []*TagsByNameRow
for rows.Next() {
var i TagsByNameRow
if err := rows.Scan(
&i.ID,
&i.UserID,
&i.Tag,
&i.QuoteNum,
); err != nil {
return nil, err
}
items = append(items, &i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}

@ -7,11 +7,12 @@ package slonik
import ( import (
"context" "context"
"strings" "strings"
"time"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
dbr "github.com/rocboss/paopao-ce/internal/dao/slonik/ce/postgres" dbr "github.com/rocboss/paopao-ce/internal/dao/slonik/ce/postgres"
"github.com/rocboss/paopao-ce/pkg/debug" "github.com/rocboss/paopao-ce/pkg/types"
) )
var ( var (
@ -22,24 +23,62 @@ type topicServant struct {
*pgxServant *pgxServant
} }
func (s *topicServant) UpsertTags(userId int64, tags []string) ([]*core.Tag, error) { // UpsertTags update/insert tags info.
// TODO // Assume tags slice is distinct elements.
return nil, debug.ErrNotImplemented func (s *topicServant) UpsertTags(userId int64, tags []string) (res []*core.Tag, err error) {
err = s.with(func(c context.Context, q dbr.Querier) error {
now := time.Now().Unix()
upTags, err := q.IncrTags(c, &dbr.IncrTagsParams{
Tags: types.PgxArray(tags),
ModifiedOn: now,
})
if err != nil {
return err
}
if len(upTags) > 0 {
for _, t := range upTags {
for i := 0; i < len(tags); {
if tags[i] == t.Tag {
latestIdx := len(tags) - 1
tags[i] = tags[latestIdx]
tags = tags[:latestIdx]
break
}
}
res = append(res, &core.Tag{
ID: t.ID,
UserID: t.UserID,
Tag: t.Tag,
QuoteNum: t.QuoteNum,
})
}
}
for _, tag := range tags {
id, err := q.InsertTags(c, &dbr.InsertTagsParams{
UserID: userId,
Tag: tag,
CreatedOn: now,
})
if err != nil {
return err
}
res = append(res, &core.Tag{
ID: id,
UserID: userId,
Tag: tag,
QuoteNum: 1,
})
}
return nil
})
return
} }
func (s *topicServant) DecrTagsById(ids []int64) error { func (s *topicServant) DecrTagsById(ids []int64) error {
// return s.with(func(c context.Context, q dbr.Querier) error { return s.q.DecrTagsById(context.Background(), &dbr.DecrTagsByIdParams{
// tagIds, err := q.TagsByIdA(c, pgtype.Array[int64](ids)) Ids: types.PgxArray(ids),
// if err != nil { ModifiedOn: time.Now().Unix(),
// return err })
// }
// err := q.DecrTagsById(c, &dbr.DecrTagsByIdParams{ModifiedOn: time.Now().Unix(), Ids: tagIds})
// if err != nil {
// return err
// }
// return nil
// })
return debug.ErrNotImplemented
} }
func (s *topicServant) GetTags(category core.TagCategory, offset int, limit int) (res []*core.Tag, _ error) { func (s *topicServant) GetTags(category core.TagCategory, offset int, limit int) (res []*core.Tag, _ error) {

@ -4,8 +4,21 @@
package types package types
import (
"github.com/jackc/pgx/v5/pgtype"
)
// Empty empty alias type // Empty empty alias type
type Empty = struct{} type Empty = struct{}
// Fn empty argument func alias type // Fn empty argument func alias type
type Fn = func() type Fn = func()
// PgxArray returns an object usable by pg drivers for passing a []T slice
// into a database as type T[].
func PgxArray[T any](elements []T) pgtype.Array[T] {
return pgtype.Array[T]{
Elements: elements,
Dims: []pgtype.ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
}
}

Loading…
Cancel
Save