@ -45,16 +45,17 @@ func NewStore(conn string) (*Store, error) {
return nil , fmt . Errorf ( "failed to initialize db migrate: %w" , err )
return nil , fmt . Errorf ( "failed to initialize db migrate: %w" , err )
}
}
err = m . Up ( )
if err != nil && ! errors . Is ( err , migrate . ErrNoChange ) {
return nil , fmt . Errorf ( "failed to roll up migrations: %w" , err )
}
ver , dirty , err := m . Version ( )
ver , dirty , err := m . Version ( )
if err != nil {
if err != nil && err != migrate . ErrNilVersion {
return nil , fmt . Errorf ( "failed to get database migration version: %w" , err )
return nil , fmt . Errorf ( "failed to get database migration version: %w" , err )
}
}
log . Debug ( ) . Uint ( "current_version" , ver ) . Bool ( "dirty" , dirty ) . Msg ( "running database migrations" )
log . Debug ( ) . Uint ( "current_version" , ver ) . Bool ( "dirty" , dirty ) . Msg ( "running database migrations" )
err = m . Up ( )
if err != nil && ! errors . Is ( err , migrate . ErrNoChange ) {
return nil , fmt . Errorf ( "failed to roll up migrations: %w" , err )
}
return & Store {
return & Store {
db : db ,
db : db ,
@ -71,7 +72,7 @@ func (s *Store) Claim(ctx context.Context, userId, player, province string, clai
Ctx ( ctx ) .
Ctx ( ctx ) .
Str ( "userid" , userId ) .
Str ( "userid" , userId ) .
Str ( "player" , player ) .
Str ( "player" , player ) .
Str ( "provi ce", province ) .
Str ( "provi n ce", province ) .
Stringer ( "claim_type" , claimType ) .
Stringer ( "claim_type" , claimType ) .
Msg ( "inserting claim" )
Msg ( "inserting claim" )
audit := & AuditableEvent {
audit := & AuditableEvent {
@ -100,13 +101,14 @@ func (s *Store) Claim(ctx context.Context, userId, player, province string, clai
}
}
// check that provided name matches the claim type
// check that provided name matches the claim type
stmt , err := s . db . PrepareContext ( ctx , fmt . Sprintf ( ` SELECT COUNT(1) FROM provinces WHERE LOWER(provinces.%s) = ? ` , claimTypeToColumn [ claimType ] ) )
stmt , err := s . db . PrepareContext ( ctx , ` SELECT COUNT(1) FROM claimables WHERE lower(name) = ? and typ = ? ` )
if err != nil {
if err != nil {
audit . err = err
audit . err = err
return 0 , fmt . Errorf ( "failed to prepare count query: %w" , err )
return 0 , fmt . Errorf ( "failed to prepare count query: %w" , err )
}
}
defer stmt . Close ( )
row := stmt . QueryRowContext ( ctx , strings . ToLower ( province ) )
row := stmt . QueryRowContext ( ctx , strings . ToLower ( province ) , claimType )
var count int
var count int
err = row . Scan ( & count )
err = row . Scan ( & count )
if err != nil {
if err != nil {
@ -124,6 +126,7 @@ func (s *Store) Claim(ctx context.Context, userId, player, province string, clai
audit . err = err
audit . err = err
return 0 , fmt . Errorf ( "failed to prepare claim query: %w" , err )
return 0 , fmt . Errorf ( "failed to prepare claim query: %w" , err )
}
}
defer stmt . Close ( )
res , err := stmt . ExecContext ( ctx , player , claimType , province , userId )
res , err := stmt . ExecContext ( ctx , player , claimType , province , userId )
if err != nil {
if err != nil {
@ -143,20 +146,24 @@ func (s *Store) Claim(ctx context.Context, userId, player, province string, clai
func ( s * Store ) ListAvailability ( ctx context . Context , claimType ClaimType , search ... string ) ( [ ] string , error ) {
func ( s * Store ) ListAvailability ( ctx context . Context , claimType ClaimType , search ... string ) ( [ ] string , error ) {
log . Debug ( ) . Ctx ( ctx ) . Stringer ( "claim_type" , claimType ) . Strs ( "search_terms" , search ) . Msg ( "listing available entries" )
log . Debug ( ) . Ctx ( ctx ) . Stringer ( "claim_type" , claimType ) . Strs ( "search_terms" , search ) . Msg ( "listing available entries" )
queryParams := [ ] any { string ( claimType ) }
queryParams := [ ] any { string ( claimType ) }
queryPattern := ` SELECT DISTINCT ( provinces . % [ 1 ] s )
FROM provinces LEFT JOIN claims ON provinces . % [ 1 ] s = claims . val AND claims . claim_type = ?
queryPattern := ` SELECT distinct name
FROM claimables
LEFT JOIN claims ON claimables . name = claims . val AND claimables . typ = claims . claim_type
WHERE claims . val IS NULL
WHERE claims . val IS NULL
AND provinces . typ = ' Land ' `
AND claimables . typ = ? `
if len ( search ) > 0 && search [ 0 ] != "" {
if len ( search ) > 0 && search [ 0 ] != "" {
// only take one search param, ignore the rest
// only take one search param, ignore the rest
queryPattern += ` AND provinces.%[1]s LIKE ?`
queryPattern += ` AND claimables.name LIKE ?`
queryParams = append ( queryParams , fmt . Sprintf ( "%%%s%%" , search [ 0 ] ) )
queryParams = append ( queryParams , fmt . Sprintf ( "%%%s%%" , search [ 0 ] ) )
}
}
stmt , err := s . db . PrepareContext ( ctx , fmt. Sprintf ( queryPattern, claimTypeToColumn [ claimType ] ) )
stmt , err := s . db . PrepareContext ( ctx , queryPattern)
if err != nil {
if err != nil {
return nil , fmt . Errorf ( "failed to prepare query: %w" , err )
return nil , fmt . Errorf ( "failed to prepare query: %w" , err )
}
}
defer stmt . Close ( )
rows , err := stmt . QueryContext ( ctx , queryParams ... )
rows , err := stmt . QueryContext ( ctx , queryParams ... )
if err != nil {
if err != nil {
@ -181,6 +188,7 @@ func (s *Store) ListClaims(ctx context.Context) ([]Claim, error) {
if err != nil {
if err != nil {
return nil , fmt . Errorf ( "failed to prepare query: %w" , err )
return nil , fmt . Errorf ( "failed to prepare query: %w" , err )
}
}
defer stmt . Close ( )
rows , err := stmt . QueryContext ( ctx )
rows , err := stmt . QueryContext ( ctx )
if err != nil {
if err != nil {
@ -227,6 +235,7 @@ func (s *Store) DescribeClaim(ctx context.Context, ID int) (ClaimDetail, error)
if err != nil {
if err != nil {
return ClaimDetail { } , fmt . Errorf ( "failed to get claim: %w" , err )
return ClaimDetail { } , fmt . Errorf ( "failed to get claim: %w" , err )
}
}
defer stmt . Close ( )
row := stmt . QueryRowContext ( ctx , ID )
row := stmt . QueryRowContext ( ctx , ID )
@ -245,12 +254,13 @@ func (s *Store) DescribeClaim(ctx context.Context, ID int) (ClaimDetail, error)
}
}
c . Type = cl
c . Type = cl
stmt , err = s . db . PrepareContext ( ctx , fmt . Sprintf ( ` SELECT name FROM provinces where provinces.%s = ? ` , claimTypeToColumn [ cl ] ) )
stmt , err = s . db . PrepareContext ( ctx , ` SELECT province FROM claimables WHERE name = ? AND typ = ? ` )
if err != nil {
if err != nil {
return ClaimDetail { } , fmt . Errorf ( "failed to prepare query: %w" , err )
return ClaimDetail { } , fmt . Errorf ( "failed to prepare query: %w" , err )
}
}
defer stmt . Close ( )
rows , err := stmt . QueryContext ( ctx , c . Name )
rows , err := stmt . QueryContext ( ctx , c . Name , cl )
if err != nil {
if err != nil {
return ClaimDetail { } , fmt . Errorf ( "failed to execute query: %w" , err )
return ClaimDetail { } , fmt . Errorf ( "failed to execute query: %w" , err )
}
}
@ -284,6 +294,7 @@ func (s *Store) DeleteClaim(ctx context.Context, ID int, userId string) error {
audit . err = err
audit . err = err
return fmt . Errorf ( "failed to prepare query: %w" , err )
return fmt . Errorf ( "failed to prepare query: %w" , err )
}
}
defer stmt . Close ( )
res , err := stmt . ExecContext ( ctx , ID , userId )
res , err := stmt . ExecContext ( ctx , ID , userId )
if err != nil {
if err != nil {
@ -309,6 +320,7 @@ func (s *Store) CountClaims(ctx context.Context) (total, uniquePlayers int, err
if err != nil {
if err != nil {
return 0 , 0 , fmt . Errorf ( "failed to prepare query: %w" , err )
return 0 , 0 , fmt . Errorf ( "failed to prepare query: %w" , err )
}
}
defer stmt . Close ( )
res := stmt . QueryRowContext ( ctx )
res := stmt . QueryRowContext ( ctx )