Skip to content

Discrepancy between geo.AreaName and pokemon_area_stats primary key causes all stat inserts to fail if an area called World exists #286

@sy1vi3

Description

@sy1vi3

The insert into pokemon_area_stats is done like this

if len(rows) > 0 {
            _, err := statsDb.NamedExec(
                "INSERT INTO pokemon_area_stats "+
                    "(datetime, area, fence, totMon, ivMon, verifiedEnc, unverifiedEnc, verifiedReEnc, encSecLeft, encTthMax5, encTth5to10, encTth10to15, encTth15to20, encTth20to25, encTth25to30, encTth30to35, encTth35to40, encTth40to45, encTth45to50, encTth50to55, encTthMin55, resetMon, re_encSecLeft, numWiEnc, secWiEnc) "+
                    "VALUES (:datetime, :area, :fence, :totMon, :ivMon, :verifiedEnc, :unverifiedEnc, :verifiedReEnc, :encSecLeft, :encTthMax5, :encTth5to10, :encTth10to15, :encTth15to20, :encTth20to25, :encTth25to30, :encTth30to35, :encTth35to40, :encTth40to45, :encTth45to50, :encTth50to55, :encTthMin55, :resetMon, :re_encSecLeft, :numWiEnc, :secWiEnc)",
                rows)
            if err != nil {
                log.Errorf("Error inserting pokemon_area_stats: %v", err)
            }
        }

rows is defined by iterating over pokemonStats, which is a map[geo.AreaName]areaStatsCount. geo.AreaName is defined as

type AreaName struct {
    Parent string
    Name   string
}

These values get mapped as AreaName.Parent -> pokemon_area_stats.area and AreaName.Name -> pokemon_area_stats.fence.

The pokemon_area_stats table is defined with a primary key of (datetime,area,fence), and configured with COLLATE=utf8mb4_unicode_ci (which is case insensitive). The keys of the pokemonStats map are structs with normal Go strings, which are case sensitive (obviously). It appears as if sqlx does everything in a single transaction such that if any of the insert operations fail, none of them take effect.

Golbat also has a reserved area name called world.

The consequences of this are that all area stats will fail to insert if one of the following is true:

  • There is a user-defined area that matches the regex ^[wW][oO][rR][lL][dD]$ but is not exactly world
  • There are two areas such that a != b but strings.ToLower(a) == strings.ToLower(b)

There is probably a similar issue with other tables and stats, but I haven't gone looking yet.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions