Compare commits

...

3 Commits

18 changed files with 572 additions and 470 deletions

2
go.mod
View File

@ -4,6 +4,7 @@ go 1.22.1
require ( require (
github.com/jackc/pgx/v5 v5.5.5 github.com/jackc/pgx/v5 v5.5.5
github.com/llehouerou/go-graphql-client v0.9.6
github.com/shopspring/decimal v1.3.1 github.com/shopspring/decimal v1.3.1
github.com/spf13/cobra v1.8.0 github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.18.2 github.com/spf13/viper v1.18.2
@ -18,7 +19,6 @@ require (
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/compress v1.17.0 // indirect github.com/klauspost/compress v1.17.0 // indirect
github.com/llehouerou/go-graphql-client v0.9.6 // indirect
github.com/magiconair/properties v1.8.7 // indirect github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.19 // indirect

View File

@ -8,8 +8,10 @@ package model
import ( import (
"context" "context"
"errors" "errors"
"time"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
) )
var ( var (
@ -91,3 +93,424 @@ func (b *CreateOrUpdateCompetitionsBatchResults) Close() error {
b.closed = true b.closed = true
return b.br.Close() return b.br.Close()
} }
const createOrUpdateCountries = `-- name: CreateOrUpdateCountries :batchexec
INSERT INTO countries (
slug,
code,
display_name,
three_letter_code,
flag_flat_64_url,
flag_flat_32_url,
flag_round_64_url,
flag_round_32_url
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
ON CONFLICT (slug)
DO UPDATE
SET code = EXCLUDED.code,
display_name = EXCLUDED.display_name,
three_letter_code = EXCLUDED.three_letter_code,
flag_flat_64_url = EXCLUDED.flag_flat_64_url,
flag_flat_32_url = EXCLUDED.flag_flat_32_url,
flag_round_64_url = EXCLUDED.flag_round_64_url,
flag_round_32_url = EXCLUDED.flag_round_32_url
`
type CreateOrUpdateCountriesBatchResults struct {
br pgx.BatchResults
tot int
closed bool
}
type CreateOrUpdateCountriesParams struct {
Slug string
Code string
DisplayName string
ThreeLetterCode string
FlagFlat64Url string
FlagFlat32Url string
FlagRound64Url string
FlagRound32Url string
}
func (q *Queries) CreateOrUpdateCountries(ctx context.Context, arg []CreateOrUpdateCountriesParams) *CreateOrUpdateCountriesBatchResults {
batch := &pgx.Batch{}
for _, a := range arg {
vals := []interface{}{
a.Slug,
a.Code,
a.DisplayName,
a.ThreeLetterCode,
a.FlagFlat64Url,
a.FlagFlat32Url,
a.FlagRound64Url,
a.FlagRound32Url,
}
batch.Queue(createOrUpdateCountries, vals...)
}
br := q.db.SendBatch(ctx, batch)
return &CreateOrUpdateCountriesBatchResults{br, len(arg), false}
}
func (b *CreateOrUpdateCountriesBatchResults) Exec(f func(int, error)) {
defer b.br.Close()
for t := 0; t < b.tot; t++ {
if b.closed {
if f != nil {
f(t, ErrBatchAlreadyClosed)
}
continue
}
_, err := b.br.Exec()
if f != nil {
f(t, err)
}
}
}
func (b *CreateOrUpdateCountriesBatchResults) Close() error {
b.closed = true
return b.br.Close()
}
const createOrUpdateFixtures = `-- name: CreateOrUpdateFixtures :batchexec
INSERT INTO fixtures (slug, display_name, state, start_date, end_date, game_week)
VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (slug) DO UPDATE
SET display_name = $2, state = $3, start_date = $4, end_date = $5, game_week = $6
`
type CreateOrUpdateFixturesBatchResults struct {
br pgx.BatchResults
tot int
closed bool
}
type CreateOrUpdateFixturesParams struct {
Slug string
DisplayName string
State string
StartDate pgtype.Timestamptz
EndDate pgtype.Timestamptz
GameWeek int32
}
func (q *Queries) CreateOrUpdateFixtures(ctx context.Context, arg []CreateOrUpdateFixturesParams) *CreateOrUpdateFixturesBatchResults {
batch := &pgx.Batch{}
for _, a := range arg {
vals := []interface{}{
a.Slug,
a.DisplayName,
a.State,
a.StartDate,
a.EndDate,
a.GameWeek,
}
batch.Queue(createOrUpdateFixtures, vals...)
}
br := q.db.SendBatch(ctx, batch)
return &CreateOrUpdateFixturesBatchResults{br, len(arg), false}
}
func (b *CreateOrUpdateFixturesBatchResults) Exec(f func(int, error)) {
defer b.br.Close()
for t := 0; t < b.tot; t++ {
if b.closed {
if f != nil {
f(t, ErrBatchAlreadyClosed)
}
continue
}
_, err := b.br.Exec()
if f != nil {
f(t, err)
}
}
}
func (b *CreateOrUpdateFixturesBatchResults) Close() error {
b.closed = true
return b.br.Close()
}
const createOrUpdateGamePlayers = `-- name: CreateOrUpdateGamePlayers :batchexec
INSERT INTO game_players(
game_id,
player_slug,
status,
team_slug)
VALUES(
$1,
$2,
$3,
$4)
ON CONFLICT (game_id, player_slug) DO UPDATE
SET status = $3,
team_slug = $4
`
type CreateOrUpdateGamePlayersBatchResults struct {
br pgx.BatchResults
tot int
closed bool
}
type CreateOrUpdateGamePlayersParams struct {
GameID string
PlayerSlug string
Status string
TeamSlug string
}
func (q *Queries) CreateOrUpdateGamePlayers(ctx context.Context, arg []CreateOrUpdateGamePlayersParams) *CreateOrUpdateGamePlayersBatchResults {
batch := &pgx.Batch{}
for _, a := range arg {
vals := []interface{}{
a.GameID,
a.PlayerSlug,
a.Status,
a.TeamSlug,
}
batch.Queue(createOrUpdateGamePlayers, vals...)
}
br := q.db.SendBatch(ctx, batch)
return &CreateOrUpdateGamePlayersBatchResults{br, len(arg), false}
}
func (b *CreateOrUpdateGamePlayersBatchResults) Exec(f func(int, error)) {
defer b.br.Close()
for t := 0; t < b.tot; t++ {
if b.closed {
if f != nil {
f(t, ErrBatchAlreadyClosed)
}
continue
}
_, err := b.br.Exec()
if f != nil {
f(t, err)
}
}
}
func (b *CreateOrUpdateGamePlayersBatchResults) Close() error {
b.closed = true
return b.br.Close()
}
const createOrUpdateGames = `-- name: CreateOrUpdateGames :batchexec
INSERT INTO games (id, date, coverage_status, low_coverage, minutes, period_type, scored, status, competition_slug, fixture_slug, away_team_slug, away_goals, away_extra_time_score, away_penalty_score, home_team_slug, home_goals, home_extra_time_score, home_penalty_score, winner_team_slug)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)
ON CONFLICT (id) DO UPDATE
SET date = EXCLUDED.date, coverage_status = EXCLUDED.coverage_status, low_coverage = EXCLUDED.low_coverage, minutes = EXCLUDED.minutes, period_type = EXCLUDED.period_type, scored = EXCLUDED.scored, status = EXCLUDED.status, competition_slug = EXCLUDED.competition_slug, fixture_slug = EXCLUDED.fixture_slug, away_team_slug = EXCLUDED.away_team_slug, away_goals = EXCLUDED.away_goals, away_extra_time_score = EXCLUDED.away_extra_time_score, away_penalty_score = EXCLUDED.away_penalty_score, home_team_slug = EXCLUDED.home_team_slug, home_goals = EXCLUDED.home_goals, home_extra_time_score = EXCLUDED.home_extra_time_score, home_penalty_score = EXCLUDED.home_penalty_score, winner_team_slug = EXCLUDED.winner_team_slug
`
type CreateOrUpdateGamesBatchResults struct {
br pgx.BatchResults
tot int
closed bool
}
type CreateOrUpdateGamesParams struct {
ID string
Date pgtype.Timestamptz
CoverageStatus string
LowCoverage bool
Minutes int32
PeriodType string
Scored bool
Status string
CompetitionSlug string
FixtureSlug string
AwayTeamSlug string
AwayGoals int32
AwayExtraTimeScore int32
AwayPenaltyScore int32
HomeTeamSlug string
HomeGoals int32
HomeExtraTimeScore int32
HomePenaltyScore int32
WinnerTeamSlug *string
}
func (q *Queries) CreateOrUpdateGames(ctx context.Context, arg []CreateOrUpdateGamesParams) *CreateOrUpdateGamesBatchResults {
batch := &pgx.Batch{}
for _, a := range arg {
vals := []interface{}{
a.ID,
a.Date,
a.CoverageStatus,
a.LowCoverage,
a.Minutes,
a.PeriodType,
a.Scored,
a.Status,
a.CompetitionSlug,
a.FixtureSlug,
a.AwayTeamSlug,
a.AwayGoals,
a.AwayExtraTimeScore,
a.AwayPenaltyScore,
a.HomeTeamSlug,
a.HomeGoals,
a.HomeExtraTimeScore,
a.HomePenaltyScore,
a.WinnerTeamSlug,
}
batch.Queue(createOrUpdateGames, vals...)
}
br := q.db.SendBatch(ctx, batch)
return &CreateOrUpdateGamesBatchResults{br, len(arg), false}
}
func (b *CreateOrUpdateGamesBatchResults) Exec(f func(int, error)) {
defer b.br.Close()
for t := 0; t < b.tot; t++ {
if b.closed {
if f != nil {
f(t, ErrBatchAlreadyClosed)
}
continue
}
_, err := b.br.Exec()
if f != nil {
f(t, err)
}
}
}
func (b *CreateOrUpdateGamesBatchResults) Close() error {
b.closed = true
return b.br.Close()
}
const createOrUpdatePlayers = `-- name: CreateOrUpdatePlayers :batchexec
INSERT INTO players (slug, display_name, birth_date, country_slug, team_slug, domestic_league_slug, avatar_url, field_position, status, shirt_number)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
ON CONFLICT (slug) DO UPDATE
SET display_name = $2, birth_date = $3, country_slug = $4, team_slug = $5, domestic_league_slug = $6, avatar_url = $7, field_position = $8, status = $9, shirt_number = $10
`
type CreateOrUpdatePlayersBatchResults struct {
br pgx.BatchResults
tot int
closed bool
}
type CreateOrUpdatePlayersParams struct {
Slug string
DisplayName string
BirthDate time.Time
CountrySlug string
TeamSlug *string
DomesticLeagueSlug *string
AvatarUrl string
FieldPosition string
Status string
ShirtNumber int32
}
func (q *Queries) CreateOrUpdatePlayers(ctx context.Context, arg []CreateOrUpdatePlayersParams) *CreateOrUpdatePlayersBatchResults {
batch := &pgx.Batch{}
for _, a := range arg {
vals := []interface{}{
a.Slug,
a.DisplayName,
a.BirthDate,
a.CountrySlug,
a.TeamSlug,
a.DomesticLeagueSlug,
a.AvatarUrl,
a.FieldPosition,
a.Status,
a.ShirtNumber,
}
batch.Queue(createOrUpdatePlayers, vals...)
}
br := q.db.SendBatch(ctx, batch)
return &CreateOrUpdatePlayersBatchResults{br, len(arg), false}
}
func (b *CreateOrUpdatePlayersBatchResults) Exec(f func(int, error)) {
defer b.br.Close()
for t := 0; t < b.tot; t++ {
if b.closed {
if f != nil {
f(t, ErrBatchAlreadyClosed)
}
continue
}
_, err := b.br.Exec()
if f != nil {
f(t, err)
}
}
}
func (b *CreateOrUpdatePlayersBatchResults) Close() error {
b.closed = true
return b.br.Close()
}
const createOrUpdateTeams = `-- name: CreateOrUpdateTeams :batchexec
INSERT INTO teams (slug, display_name, country_slug, domestic_league_slug, short_name, picture_url, team_type)
VALUES ($1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (slug) DO UPDATE
SET display_name = $2, country_slug = $3, domestic_league_slug = $4, short_name = $5, picture_url = $6, team_type = $7
`
type CreateOrUpdateTeamsBatchResults struct {
br pgx.BatchResults
tot int
closed bool
}
type CreateOrUpdateTeamsParams struct {
Slug string
DisplayName string
CountrySlug string
DomesticLeagueSlug *string
ShortName string
PictureUrl string
TeamType string
}
func (q *Queries) CreateOrUpdateTeams(ctx context.Context, arg []CreateOrUpdateTeamsParams) *CreateOrUpdateTeamsBatchResults {
batch := &pgx.Batch{}
for _, a := range arg {
vals := []interface{}{
a.Slug,
a.DisplayName,
a.CountrySlug,
a.DomesticLeagueSlug,
a.ShortName,
a.PictureUrl,
a.TeamType,
}
batch.Queue(createOrUpdateTeams, vals...)
}
br := q.db.SendBatch(ctx, batch)
return &CreateOrUpdateTeamsBatchResults{br, len(arg), false}
}
func (b *CreateOrUpdateTeamsBatchResults) Exec(f func(int, error)) {
defer b.br.Close()
for t := 0; t < b.tot; t++ {
if b.closed {
if f != nil {
f(t, ErrBatchAlreadyClosed)
}
continue
}
_, err := b.br.Exec()
if f != nil {
f(t, err)
}
}
}
func (b *CreateOrUpdateTeamsBatchResults) Close() error {
b.closed = true
return b.br.Close()
}

View File

@ -1,251 +0,0 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.25.0
// source: copyfrom.go
package model
import (
"context"
)
// iteratorForBatchInsertGamePlayers implements pgx.CopyFromSource.
type iteratorForBatchInsertGamePlayers struct {
rows []BatchInsertGamePlayersParams
skippedFirstNextCall bool
}
func (r *iteratorForBatchInsertGamePlayers) Next() bool {
if len(r.rows) == 0 {
return false
}
if !r.skippedFirstNextCall {
r.skippedFirstNextCall = true
return true
}
r.rows = r.rows[1:]
return len(r.rows) > 0
}
func (r iteratorForBatchInsertGamePlayers) Values() ([]interface{}, error) {
return []interface{}{
r.rows[0].GameID,
r.rows[0].PlayerSlug,
r.rows[0].Status,
r.rows[0].TeamSlug,
}, nil
}
func (r iteratorForBatchInsertGamePlayers) Err() error {
return nil
}
func (q *Queries) BatchInsertGamePlayers(ctx context.Context, arg []BatchInsertGamePlayersParams) (int64, error) {
return q.db.CopyFrom(ctx, []string{"game_players"}, []string{"game_id", "player_slug", "status", "team_slug"}, &iteratorForBatchInsertGamePlayers{rows: arg})
}
// iteratorForBatchInsertGames implements pgx.CopyFromSource.
type iteratorForBatchInsertGames struct {
rows []BatchInsertGamesParams
skippedFirstNextCall bool
}
func (r *iteratorForBatchInsertGames) Next() bool {
if len(r.rows) == 0 {
return false
}
if !r.skippedFirstNextCall {
r.skippedFirstNextCall = true
return true
}
r.rows = r.rows[1:]
return len(r.rows) > 0
}
func (r iteratorForBatchInsertGames) Values() ([]interface{}, error) {
return []interface{}{
r.rows[0].ID,
r.rows[0].Date,
r.rows[0].CoverageStatus,
r.rows[0].LowCoverage,
r.rows[0].Minutes,
r.rows[0].PeriodType,
r.rows[0].Scored,
r.rows[0].Status,
r.rows[0].CompetitionSlug,
r.rows[0].FixtureSlug,
r.rows[0].AwayTeamSlug,
r.rows[0].AwayGoals,
r.rows[0].AwayExtraTimeScore,
r.rows[0].AwayPenaltyScore,
r.rows[0].HomeTeamSlug,
r.rows[0].HomeGoals,
r.rows[0].HomeExtraTimeScore,
r.rows[0].HomePenaltyScore,
r.rows[0].WinnerTeamSlug,
}, nil
}
func (r iteratorForBatchInsertGames) Err() error {
return nil
}
func (q *Queries) BatchInsertGames(ctx context.Context, arg []BatchInsertGamesParams) (int64, error) {
return q.db.CopyFrom(ctx, []string{"games"}, []string{"id", "date", "coverage_status", "low_coverage", "minutes", "period_type", "scored", "status", "competition_slug", "fixture_slug", "away_team_slug", "away_goals", "away_extra_time_score", "away_penalty_score", "home_team_slug", "home_goals", "home_extra_time_score", "home_penalty_score", "winner_team_slug"}, &iteratorForBatchInsertGames{rows: arg})
}
// iteratorForBatchInsertPlayers implements pgx.CopyFromSource.
type iteratorForBatchInsertPlayers struct {
rows []BatchInsertPlayersParams
skippedFirstNextCall bool
}
func (r *iteratorForBatchInsertPlayers) Next() bool {
if len(r.rows) == 0 {
return false
}
if !r.skippedFirstNextCall {
r.skippedFirstNextCall = true
return true
}
r.rows = r.rows[1:]
return len(r.rows) > 0
}
func (r iteratorForBatchInsertPlayers) Values() ([]interface{}, error) {
return []interface{}{
r.rows[0].Slug,
r.rows[0].DisplayName,
r.rows[0].BirthDate,
r.rows[0].CountrySlug,
r.rows[0].TeamSlug,
r.rows[0].DomesticLeagueSlug,
r.rows[0].AvatarUrl,
r.rows[0].FieldPosition,
r.rows[0].Status,
r.rows[0].ShirtNumber,
}, nil
}
func (r iteratorForBatchInsertPlayers) Err() error {
return nil
}
func (q *Queries) BatchInsertPlayers(ctx context.Context, arg []BatchInsertPlayersParams) (int64, error) {
return q.db.CopyFrom(ctx, []string{"players"}, []string{"slug", "display_name", "birth_date", "country_slug", "team_slug", "domestic_league_slug", "avatar_url", "field_position", "status", "shirt_number"}, &iteratorForBatchInsertPlayers{rows: arg})
}
// iteratorForBatchInsertTeams implements pgx.CopyFromSource.
type iteratorForBatchInsertTeams struct {
rows []BatchInsertTeamsParams
skippedFirstNextCall bool
}
func (r *iteratorForBatchInsertTeams) Next() bool {
if len(r.rows) == 0 {
return false
}
if !r.skippedFirstNextCall {
r.skippedFirstNextCall = true
return true
}
r.rows = r.rows[1:]
return len(r.rows) > 0
}
func (r iteratorForBatchInsertTeams) Values() ([]interface{}, error) {
return []interface{}{
r.rows[0].Slug,
r.rows[0].DisplayName,
r.rows[0].CountrySlug,
r.rows[0].DomesticLeagueSlug,
r.rows[0].ShortName,
r.rows[0].PictureUrl,
r.rows[0].TeamType,
}, nil
}
func (r iteratorForBatchInsertTeams) Err() error {
return nil
}
func (q *Queries) BatchInsertTeams(ctx context.Context, arg []BatchInsertTeamsParams) (int64, error) {
return q.db.CopyFrom(ctx, []string{"teams"}, []string{"slug", "display_name", "country_slug", "domestic_league_slug", "short_name", "picture_url", "team_type"}, &iteratorForBatchInsertTeams{rows: arg})
}
// iteratorForCreateCountries implements pgx.CopyFromSource.
type iteratorForCreateCountries struct {
rows []CreateCountriesParams
skippedFirstNextCall bool
}
func (r *iteratorForCreateCountries) Next() bool {
if len(r.rows) == 0 {
return false
}
if !r.skippedFirstNextCall {
r.skippedFirstNextCall = true
return true
}
r.rows = r.rows[1:]
return len(r.rows) > 0
}
func (r iteratorForCreateCountries) Values() ([]interface{}, error) {
return []interface{}{
r.rows[0].Slug,
r.rows[0].Code,
r.rows[0].DisplayName,
r.rows[0].ThreeLetterCode,
r.rows[0].FlagFlat64Url,
r.rows[0].FlagFlat32Url,
r.rows[0].FlagRound64Url,
r.rows[0].FlagRound32Url,
}, nil
}
func (r iteratorForCreateCountries) Err() error {
return nil
}
func (q *Queries) CreateCountries(ctx context.Context, arg []CreateCountriesParams) (int64, error) {
return q.db.CopyFrom(ctx, []string{"countries"}, []string{"slug", "code", "display_name", "three_letter_code", "flag_flat_64_url", "flag_flat_32_url", "flag_round_64_url", "flag_round_32_url"}, &iteratorForCreateCountries{rows: arg})
}
// iteratorForCreateFixtures implements pgx.CopyFromSource.
type iteratorForCreateFixtures struct {
rows []CreateFixturesParams
skippedFirstNextCall bool
}
func (r *iteratorForCreateFixtures) Next() bool {
if len(r.rows) == 0 {
return false
}
if !r.skippedFirstNextCall {
r.skippedFirstNextCall = true
return true
}
r.rows = r.rows[1:]
return len(r.rows) > 0
}
func (r iteratorForCreateFixtures) Values() ([]interface{}, error) {
return []interface{}{
r.rows[0].Slug,
r.rows[0].DisplayName,
r.rows[0].State,
r.rows[0].StartDate,
r.rows[0].EndDate,
r.rows[0].GameWeek,
}, nil
}
func (r iteratorForCreateFixtures) Err() error {
return nil
}
// Active: 1709890109198@@192.168.1.250@5436@sorare
func (q *Queries) CreateFixtures(ctx context.Context, arg []CreateFixturesParams) (int64, error) {
return q.db.CopyFrom(ctx, []string{"fixtures"}, []string{"slug", "display_name", "state", "start_date", "end_date", "game_week"}, &iteratorForCreateFixtures{rows: arg})
}

View File

@ -9,17 +9,6 @@ import (
"context" "context"
) )
type CreateCountriesParams struct {
Slug string
Code string
DisplayName string
ThreeLetterCode string
FlagFlat64Url string
FlagFlat32Url string
FlagRound64Url string
FlagRound32Url string
}
const createOrUpdateCountry = `-- name: CreateOrUpdateCountry :exec const createOrUpdateCountry = `-- name: CreateOrUpdateCountry :exec
INSERT INTO countries ( INSERT INTO countries (
slug, slug,
@ -67,3 +56,25 @@ func (q *Queries) CreateOrUpdateCountry(ctx context.Context, arg CreateOrUpdateC
) )
return err return err
} }
const getCountryBySlug = `-- name: GetCountryBySlug :one
SELECT slug, code, display_name, three_letter_code, flag_flat_64_url, flag_flat_32_url, flag_round_64_url, flag_round_32_url
FROM countries
WHERE slug = $1
`
func (q *Queries) GetCountryBySlug(ctx context.Context, slug string) (Country, error) {
row := q.db.QueryRow(ctx, getCountryBySlug, slug)
var i Country
err := row.Scan(
&i.Slug,
&i.Code,
&i.DisplayName,
&i.ThreeLetterCode,
&i.FlagFlat64Url,
&i.FlagFlat32Url,
&i.FlagRound64Url,
&i.FlagRound32Url,
)
return i, err
}

View File

@ -15,7 +15,6 @@ type DBTX interface {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error) Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row QueryRow(context.Context, string, ...interface{}) pgx.Row
CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error)
SendBatch(context.Context, *pgx.Batch) pgx.BatchResults SendBatch(context.Context, *pgx.Batch) pgx.BatchResults
} }

View File

@ -7,47 +7,8 @@ package model
import ( import (
"context" "context"
"github.com/jackc/pgx/v5/pgtype"
) )
type CreateFixturesParams struct {
Slug string
DisplayName string
State string
StartDate pgtype.Timestamptz
EndDate pgtype.Timestamptz
GameWeek int32
}
const createOrUpdateFixture = `-- name: CreateOrUpdateFixture :exec
INSERT INTO fixtures (slug, display_name, state, start_date, end_date, game_week)
VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (slug) DO UPDATE
SET display_name = $2, state = $3, start_date = $4, end_date = $5, game_week = $6
`
type CreateOrUpdateFixtureParams struct {
Slug string
DisplayName string
State string
StartDate pgtype.Timestamptz
EndDate pgtype.Timestamptz
GameWeek int32
}
func (q *Queries) CreateOrUpdateFixture(ctx context.Context, arg CreateOrUpdateFixtureParams) error {
_, err := q.db.Exec(ctx, createOrUpdateFixture,
arg.Slug,
arg.DisplayName,
arg.State,
arg.StartDate,
arg.EndDate,
arg.GameWeek,
)
return err
}
const getAllFixtures = `-- name: GetAllFixtures :many const getAllFixtures = `-- name: GetAllFixtures :many
SELECT slug, display_name, state, start_date, end_date, game_week FROM fixtures SELECT slug, display_name, state, start_date, end_date, game_week FROM fixtures
` `

View File

@ -5,28 +5,4 @@
package model package model
import ( import ()
"github.com/jackc/pgx/v5/pgtype"
)
type BatchInsertGamesParams struct {
ID string
Date pgtype.Timestamptz
CoverageStatus string
LowCoverage bool
Minutes int32
PeriodType string
Scored bool
Status string
CompetitionSlug string
FixtureSlug string
AwayTeamSlug string
AwayGoals int32
AwayExtraTimeScore int32
AwayPenaltyScore int32
HomeTeamSlug string
HomeGoals int32
HomeExtraTimeScore int32
HomePenaltyScore int32
WinnerTeamSlug *string
}

View File

@ -5,46 +5,4 @@
package model package model
import ( import ()
"context"
)
type BatchInsertGamePlayersParams struct {
GameID string
PlayerSlug string
Status string
TeamSlug string
}
const createOrUpdateGamePlayer = `-- name: CreateOrUpdateGamePlayer :exec
INSERT INTO game_players(
game_id,
player_slug,
status,
team_slug)
VALUES(
$1,
$2,
$3,
$4)
ON CONFLICT (game_id, player_slug) DO UPDATE
SET status = $3,
team_slug = $4
`
type CreateOrUpdateGamePlayerParams struct {
GameID string
PlayerSlug string
Status string
TeamSlug string
}
func (q *Queries) CreateOrUpdateGamePlayer(ctx context.Context, arg CreateOrUpdateGamePlayerParams) error {
_, err := q.db.Exec(ctx, createOrUpdateGamePlayer,
arg.GameID,
arg.PlayerSlug,
arg.Status,
arg.TeamSlug,
)
return err
}

View File

@ -5,19 +5,4 @@
package model package model
import ( import ()
"time"
)
type BatchInsertPlayersParams struct {
Slug string
DisplayName string
BirthDate time.Time
CountrySlug string
TeamSlug *string
DomesticLeagueSlug *string
AvatarUrl string
FieldPosition string
Status string
ShirtNumber int32
}

View File

@ -1,4 +1,4 @@
-- name: CreateCountries :copyfrom -- name: CreateOrUpdateCountries :batchexec
INSERT INTO countries ( INSERT INTO countries (
slug, slug,
code, code,
@ -9,7 +9,16 @@ INSERT INTO countries (
flag_round_64_url, flag_round_64_url,
flag_round_32_url flag_round_32_url
) )
VALUES ($1, $2, $3, $4, $5, $6, $7, $8); VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
ON CONFLICT (slug)
DO UPDATE
SET code = EXCLUDED.code,
display_name = EXCLUDED.display_name,
three_letter_code = EXCLUDED.three_letter_code,
flag_flat_64_url = EXCLUDED.flag_flat_64_url,
flag_flat_32_url = EXCLUDED.flag_flat_32_url,
flag_round_64_url = EXCLUDED.flag_round_64_url,
flag_round_32_url = EXCLUDED.flag_round_32_url;
-- name: CreateOrUpdateCountry :exec -- name: CreateOrUpdateCountry :exec
INSERT INTO countries ( INSERT INTO countries (
@ -32,3 +41,9 @@ INSERT INTO countries (
flag_flat_32_url = EXCLUDED.flag_flat_32_url, flag_flat_32_url = EXCLUDED.flag_flat_32_url,
flag_round_64_url = EXCLUDED.flag_round_64_url, flag_round_64_url = EXCLUDED.flag_round_64_url,
flag_round_32_url = EXCLUDED.flag_round_32_url; flag_round_32_url = EXCLUDED.flag_round_32_url;
-- name: GetCountryBySlug :one
SELECT *
FROM countries
WHERE slug = $1;

View File

@ -1,9 +1,4 @@
-- Active: 1709890109198@@192.168.1.250@5436@sorare -- name: CreateOrUpdateFixtures :batchexec
-- name: CreateFixtures :copyfrom
INSERT INTO fixtures (slug, display_name, state, start_date, end_date, game_week)
VALUES ($1, $2, $3, $4, $5, $6);
-- name: CreateOrUpdateFixture :exec
INSERT INTO fixtures (slug, display_name, state, start_date, end_date, game_week) INSERT INTO fixtures (slug, display_name, state, start_date, end_date, game_week)
VALUES ($1, $2, $3, $4, $5, $6) VALUES ($1, $2, $3, $4, $5, $6)
ON CONFLICT (slug) DO UPDATE ON CONFLICT (slug) DO UPDATE

View File

@ -1,4 +1,6 @@
-- name: BatchInsertGames :copyfrom -- name: CreateOrUpdateGames :batchexec
INSERT INTO games (id, date, coverage_status, low_coverage, minutes, period_type, scored, status, competition_slug, fixture_slug, away_team_slug, away_goals, away_extra_time_score, away_penalty_score, home_team_slug, home_goals, home_extra_time_score, home_penalty_score, winner_team_slug) INSERT INTO games (id, date, coverage_status, low_coverage, minutes, period_type, scored, status, competition_slug, fixture_slug, away_team_slug, away_goals, away_extra_time_score, away_penalty_score, home_team_slug, home_goals, home_extra_time_score, home_penalty_score, winner_team_slug)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19); VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)
ON CONFLICT (id) DO UPDATE
SET date = EXCLUDED.date, coverage_status = EXCLUDED.coverage_status, low_coverage = EXCLUDED.low_coverage, minutes = EXCLUDED.minutes, period_type = EXCLUDED.period_type, scored = EXCLUDED.scored, status = EXCLUDED.status, competition_slug = EXCLUDED.competition_slug, fixture_slug = EXCLUDED.fixture_slug, away_team_slug = EXCLUDED.away_team_slug, away_goals = EXCLUDED.away_goals, away_extra_time_score = EXCLUDED.away_extra_time_score, away_penalty_score = EXCLUDED.away_penalty_score, home_team_slug = EXCLUDED.home_team_slug, home_goals = EXCLUDED.home_goals, home_extra_time_score = EXCLUDED.home_extra_time_score, home_penalty_score = EXCLUDED.home_penalty_score, winner_team_slug = EXCLUDED.winner_team_slug;

View File

@ -1,16 +1,4 @@
-- name: BatchInsertGamePlayers :copyfrom -- name: CreateOrUpdateGamePlayers :batchexec
INSERT INTO game_players(
game_id,
player_slug,
status,
team_slug)
VALUES(
$1,
$2,
$3,
$4);
-- name: CreateOrUpdateGamePlayer :exec
INSERT INTO game_players( INSERT INTO game_players(
game_id, game_id,
player_slug, player_slug,

View File

@ -1,3 +1,5 @@
-- name: BatchInsertPlayers :copyfrom -- name: CreateOrUpdatePlayers :batchexec
INSERT INTO players (slug, display_name, birth_date, country_slug, team_slug, domestic_league_slug, avatar_url, field_position, status, shirt_number) INSERT INTO players (slug, display_name, birth_date, country_slug, team_slug, domestic_league_slug, avatar_url, field_position, status, shirt_number)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10); VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
ON CONFLICT (slug) DO UPDATE
SET display_name = $2, birth_date = $3, country_slug = $4, team_slug = $5, domestic_league_slug = $6, avatar_url = $7, field_position = $8, status = $9, shirt_number = $10;

View File

@ -1,3 +1,5 @@
-- name: BatchInsertTeams :copyfrom -- name: CreateOrUpdateTeams :batchexec
INSERT INTO teams (slug, display_name, country_slug, domestic_league_slug, short_name, picture_url, team_type) INSERT INTO teams (slug, display_name, country_slug, domestic_league_slug, short_name, picture_url, team_type)
VALUES ($1, $2, $3, $4, $5, $6, $7); VALUES ($1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (slug) DO UPDATE
SET display_name = $2, country_slug = $3, domestic_league_slug = $4, short_name = $5, picture_url = $6, team_type = $7;

View File

@ -6,13 +6,3 @@
package model package model
import () import ()
type BatchInsertTeamsParams struct {
Slug string
DisplayName string
CountrySlug string
DomesticLeagueSlug *string
ShortName string
PictureUrl string
TeamType string
}

View File

@ -7,8 +7,8 @@ import (
"git.lehouerou.net/laurent/sorarebuddy/model" "git.lehouerou.net/laurent/sorarebuddy/model"
) )
func NewBatchInsertGamesParamsFromSorare(game football.Game) model.BatchInsertGamesParams { func NewCreateOrUpdateGamesParamsFromSorare(game football.Game) model.CreateOrUpdateGamesParams {
return model.BatchInsertGamesParams{ return model.CreateOrUpdateGamesParams{
ID: game.Id.Value, ID: game.Id.Value,
Date: pgtype.Timestamptz{Time: game.Date, Valid: true}, Date: pgtype.Timestamptz{Time: game.Date, Valid: true},
CoverageStatus: game.CoverageStatus, CoverageStatus: game.CoverageStatus,

View File

@ -34,10 +34,10 @@ func (u *UpdateService) InitSyncDatabase(ctx context.Context) error {
} }
log.Debug().Msgf("fixtures: %v", sfixtures) log.Debug().Msgf("fixtures: %v", sfixtures)
cnt, err := u.db.CreateFixtures( batchFixtures := u.db.CreateOrUpdateFixtures(
ctx, ctx,
lo.Map(sfixtures, func(fixture football.So5Fixture, index int) model.CreateFixturesParams { lo.Map(sfixtures, func(fixture football.So5Fixture, index int) model.CreateOrUpdateFixturesParams {
return model.CreateFixturesParams{ return model.CreateOrUpdateFixturesParams{
Slug: fixture.Slug, Slug: fixture.Slug,
DisplayName: fixture.DisplayName, DisplayName: fixture.DisplayName,
State: fixture.AasmState, State: fixture.AasmState,
@ -47,11 +47,19 @@ func (u *UpdateService) InitSyncDatabase(ctx context.Context) error {
} }
}), }),
) )
if err != nil { var batcherr error
batchFixtures.Exec(func(_ int, err error) {
if err != nil {
batcherr = err
batchFixtures.Close()
}
})
if batcherr != nil {
return err return err
} }
log.Debug().Msgf("created %d fixtures", cnt) log.Debug().Msgf("created %d fixtures", len(sfixtures))
fixtures, err := u.db.GetAllFixtures(ctx) fixtures, err := u.db.GetAllFixtures(ctx)
if err != nil { if err != nil {
@ -67,7 +75,7 @@ func (u *UpdateService) InitSyncDatabase(ctx context.Context) error {
log.Info().Msgf("found %d games to process", len(games)) log.Info().Msgf("found %d games to process", len(games))
log.Debug().Msgf("getting players for each game...") log.Debug().Msgf("getting players for each game...")
var gamePlayers []model.BatchInsertGamePlayersParams var gamePlayers []model.CreateOrUpdateGamePlayersParams
for _, game := range games { for _, game := range games {
gameWithFormation, err := u.s.Football.Game.Get(ctx, graphql.IdParams{Id: gql.ID(game.Id.Value)}) gameWithFormation, err := u.s.Football.Game.Get(ctx, graphql.IdParams{Id: gql.ID(game.Id.Value)})
if err != nil { if err != nil {
@ -79,7 +87,7 @@ func (u *UpdateService) InitSyncDatabase(ctx context.Context) error {
} }
playerSlugs := lo.Uniq( playerSlugs := lo.Uniq(
lo.Filter(lo.Map(gamePlayers, func(player model.BatchInsertGamePlayersParams, index int) string { lo.Filter(lo.Map(gamePlayers, func(player model.CreateOrUpdateGamePlayersParams, index int) string {
return player.PlayerSlug return player.PlayerSlug
}), func(slug string, index int) bool { }), func(slug string, index int) bool {
return slug != "" return slug != ""
@ -163,10 +171,10 @@ func (u *UpdateService) InitSyncDatabase(ctx context.Context) error {
log.Debug().Msgf("found %d countries", len(countries)) log.Debug().Msgf("found %d countries", len(countries))
log.Debug().Msg("inserting countries into db...") log.Debug().Msg("inserting countries into db...")
cnt, err = u.db.CreateCountries( batchCountries := u.db.CreateOrUpdateCountries(
ctx, ctx,
lo.Map(countries, func(country sorare.Country, index int) model.CreateCountriesParams { lo.Map(countries, func(country sorare.Country, index int) model.CreateOrUpdateCountriesParams {
return model.CreateCountriesParams{ return model.CreateOrUpdateCountriesParams{
Slug: country.Slug, Slug: country.Slug,
Code: country.Code, Code: country.Code,
DisplayName: country.Name, DisplayName: country.Name,
@ -178,15 +186,21 @@ func (u *UpdateService) InitSyncDatabase(ctx context.Context) error {
} }
}), }),
) )
if err != nil { batcherr = nil
batchCountries.Exec(func(_ int, err error) {
if err != nil {
batcherr = err
batchCountries.Close()
}
})
if batcherr != nil {
return err return err
} }
log.Debug().Msgf("%d countries inserted", cnt) log.Debug().Msgf("%d countries inserted", len(countries))
log.Debug().Msg("inserting competitions into db...") log.Debug().Msg("inserting competitions into db...")
var batcherr error batchCompetitions := u.db.CreateOrUpdateCompetitions(
batch := u.db.CreateOrUpdateCompetitions(
ctx, ctx,
lo.Map(competitions, func(competition football.Competition, index int) model.CreateOrUpdateCompetitionsParams { lo.Map(competitions, func(competition football.Competition, index int) model.CreateOrUpdateCompetitionsParams {
return model.CreateOrUpdateCompetitionsParams{ return model.CreateOrUpdateCompetitionsParams{
@ -200,10 +214,11 @@ func (u *UpdateService) InitSyncDatabase(ctx context.Context) error {
} }
}), }),
) )
batch.Exec(func(_ int, err error) { batcherr = nil
batchCompetitions.Exec(func(_ int, err error) {
if err != nil { if err != nil {
batcherr = err batcherr = err
batch.Close() batchCompetitions.Close()
} }
}) })
if batcherr != nil { if batcherr != nil {
@ -213,9 +228,9 @@ func (u *UpdateService) InitSyncDatabase(ctx context.Context) error {
log.Debug().Msgf("%d competitions inserted", len(competitions)) log.Debug().Msgf("%d competitions inserted", len(competitions))
log.Debug().Msg("inserting teams into db...") log.Debug().Msg("inserting teams into db...")
cnt, err = u.db.BatchInsertTeams(ctx, lo.Union( batchTeams := u.db.CreateOrUpdateTeams(ctx, lo.Union(
lo.Map(clubs, func(club football.Club, index int) model.BatchInsertTeamsParams { lo.Map(clubs, func(club football.Club, index int) model.CreateOrUpdateTeamsParams {
return model.BatchInsertTeamsParams{ return model.CreateOrUpdateTeamsParams{
Slug: club.Slug, Slug: club.Slug,
DisplayName: club.Name, DisplayName: club.Name,
CountrySlug: club.Country.Slug, CountrySlug: club.Country.Slug,
@ -230,8 +245,8 @@ func (u *UpdateService) InitSyncDatabase(ctx context.Context) error {
TeamType: "club", TeamType: "club",
} }
}), }),
lo.Map(nationalTeams, func(nationalTeam football.NationalTeam, index int) model.BatchInsertTeamsParams { lo.Map(nationalTeams, func(nationalTeam football.NationalTeam, index int) model.CreateOrUpdateTeamsParams {
return model.BatchInsertTeamsParams{ return model.CreateOrUpdateTeamsParams{
Slug: nationalTeam.Slug, Slug: nationalTeam.Slug,
DisplayName: nationalTeam.Name, DisplayName: nationalTeam.Name,
CountrySlug: nationalTeam.Country.Slug, CountrySlug: nationalTeam.Country.Slug,
@ -242,28 +257,42 @@ func (u *UpdateService) InitSyncDatabase(ctx context.Context) error {
} }
}), }),
)) ))
if err != nil { batcherr = nil
return err batchTeams.Exec(func(_ int, err error) {
if err != nil {
batcherr = err
batchTeams.Close()
}
})
if batcherr != nil {
return errors.Wrap(batcherr, "inserting teams into db")
} }
log.Debug().Msgf("%d teams inserted", cnt) log.Debug().Msgf("%d teams inserted", len(clubs)+len(nationalTeams))
log.Debug().Msg("inserting games into db...") log.Debug().Msg("inserting games into db...")
cnt, err = u.db.BatchInsertGames( batchGames := u.db.CreateOrUpdateGames(
ctx, ctx,
lo.Map(games, func(game football.Game, index int) model.BatchInsertGamesParams { lo.Map(games, func(game football.Game, index int) model.CreateOrUpdateGamesParams {
return NewBatchInsertGamesParamsFromSorare(game) return NewCreateOrUpdateGamesParamsFromSorare(game)
}), }),
) )
if err != nil { batcherr = nil
batchGames.Exec(func(_ int, err error) {
if err != nil {
batcherr = err
batchGames.Close()
}
})
if batcherr != nil {
return err return err
} }
log.Debug().Msgf("%d games inserted", cnt) log.Debug().Msgf("%d games inserted", len(games))
log.Debug().Msg("inserting players into db...") log.Debug().Msg("inserting players into db...")
cnt, err = u.db.BatchInsertPlayers( batchPlayers := u.db.CreateOrUpdatePlayers(
ctx, ctx,
lo.Map(players, func(player football.Player, index int) model.BatchInsertPlayersParams { lo.Map(players, func(player football.Player, index int) model.CreateOrUpdatePlayersParams {
res := model.BatchInsertPlayersParams{ res := model.CreateOrUpdatePlayersParams{
Slug: player.Slug, Slug: player.Slug,
DisplayName: player.DisplayName, DisplayName: player.DisplayName,
BirthDate: player.BirthDate, BirthDate: player.BirthDate,
@ -284,27 +313,44 @@ func (u *UpdateService) InitSyncDatabase(ctx context.Context) error {
return res return res
}), }),
) )
if err != nil { batcherr = nil
return errors.Wrap(err, "inserting players") batchPlayers.Exec(func(_ int, err error) {
if err != nil {
batcherr = err
batchPlayers.Close()
}
})
if batcherr != nil {
return errors.Wrap(batcherr, "inserting players")
} }
log.Debug().Msgf("%d players inserted", cnt) log.Debug().Msgf("%d players inserted", len(players))
log.Debug().Msg("inserting game players into db...") log.Debug().Msg("inserting game players into db...")
cnt, err = u.db.BatchInsertGamePlayers(ctx, gamePlayers) batchGamePlayers := u.db.CreateOrUpdateGamePlayers(
if err != nil { ctx,
gamePlayers,
)
batcherr = nil
batchGamePlayers.Exec(func(_ int, err error) {
if err != nil {
batcherr = err
batchGamePlayers.Close()
}
})
if batcherr != nil {
return errors.Wrap(err, "inserting game players") return errors.Wrap(err, "inserting game players")
} }
log.Debug().Msgf("%d game players inserted", cnt) log.Debug().Msgf("%d game players inserted", len(gamePlayers))
return nil return nil
} }
func ExtractPlayersFromGameWithFormation( func ExtractPlayersFromGameWithFormation(
gameWithFormation football.GameWithFormation, gameWithFormation football.GameWithFormation,
) []model.BatchInsertGamePlayersParams { ) []model.CreateOrUpdateGamePlayersParams {
var res []model.BatchInsertGamePlayersParams var res []model.CreateOrUpdateGamePlayersParams
for _, p := range gameWithFormation.HomeFormation.Bench { for _, p := range gameWithFormation.HomeFormation.Bench {
res = append(res, model.BatchInsertGamePlayersParams{ res = append(res, model.CreateOrUpdateGamePlayersParams{
GameID: gameWithFormation.Id.Value, GameID: gameWithFormation.Id.Value,
PlayerSlug: p.Slug, PlayerSlug: p.Slug,
TeamSlug: gameWithFormation.HomeTeam.Team.Slug, TeamSlug: gameWithFormation.HomeTeam.Team.Slug,
@ -313,7 +359,7 @@ func ExtractPlayersFromGameWithFormation(
} }
for _, p := range gameWithFormation.HomeFormation.StartingLineup { for _, p := range gameWithFormation.HomeFormation.StartingLineup {
for _, q := range p { for _, q := range p {
res = append(res, model.BatchInsertGamePlayersParams{ res = append(res, model.CreateOrUpdateGamePlayersParams{
GameID: gameWithFormation.Id.Value, GameID: gameWithFormation.Id.Value,
PlayerSlug: q.Slug, PlayerSlug: q.Slug,
TeamSlug: gameWithFormation.HomeTeam.Team.Slug, TeamSlug: gameWithFormation.HomeTeam.Team.Slug,
@ -322,7 +368,7 @@ func ExtractPlayersFromGameWithFormation(
} }
} }
for _, p := range gameWithFormation.AwayFormation.Bench { for _, p := range gameWithFormation.AwayFormation.Bench {
res = append(res, model.BatchInsertGamePlayersParams{ res = append(res, model.CreateOrUpdateGamePlayersParams{
GameID: gameWithFormation.Id.Value, GameID: gameWithFormation.Id.Value,
PlayerSlug: p.Slug, PlayerSlug: p.Slug,
TeamSlug: gameWithFormation.AwayTeam.Team.Slug, TeamSlug: gameWithFormation.AwayTeam.Team.Slug,
@ -331,7 +377,7 @@ func ExtractPlayersFromGameWithFormation(
} }
for _, p := range gameWithFormation.AwayFormation.StartingLineup { for _, p := range gameWithFormation.AwayFormation.StartingLineup {
for _, q := range p { for _, q := range p {
res = append(res, model.BatchInsertGamePlayersParams{ res = append(res, model.CreateOrUpdateGamePlayersParams{
GameID: gameWithFormation.Id.Value, GameID: gameWithFormation.Id.Value,
PlayerSlug: q.Slug, PlayerSlug: q.Slug,
TeamSlug: gameWithFormation.AwayTeam.Team.Slug, TeamSlug: gameWithFormation.AwayTeam.Team.Slug,