Skip to content

Commit de59e2f

Browse files
committed
fix(server): MySQL index DDL and retention DELETE compatibility
1 parent 28cc92f commit de59e2f

2 files changed

Lines changed: 27 additions & 3 deletions

File tree

server/db_dialect.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ package server
22

33
import (
44
"database/sql"
5+
"errors"
56
"fmt"
67
"strings"
78
"sync"
9+
10+
mysqlerr "github.com/go-sql-driver/mysql"
811
)
912

1013
type DBDialect string
@@ -120,3 +123,9 @@ func insertIgnoreReadReceiptSQL(db *sql.DB) string {
120123
func supportsLastInsertID(db *sql.DB) bool {
121124
return getDBDialect(db) != DialectPostgres
122125
}
126+
127+
// isMySQLDuplicateKeyName reports whether err is MySQL errno 1061 (index already exists).
128+
func isMySQLDuplicateKeyName(err error) bool {
129+
var me *mysqlerr.MySQLError
130+
return errors.As(err, &me) && me.Number == 1061
131+
}

server/handlers.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,16 @@ func CreateSchema(db *sql.DB) {
253253
}
254254

255255
for _, index := range indexes {
256-
_, err = dbExec(db, index)
256+
q := index
257+
if dialect == DialectMySQL {
258+
// MySQL does not support "CREATE INDEX IF NOT EXISTS ..." (syntax error).
259+
q = strings.Replace(index, "IF NOT EXISTS ", "", 1)
260+
}
261+
_, err = dbExec(db, q)
257262
if err != nil {
263+
if dialect == DialectMySQL && isMySQLDuplicateKeyName(err) {
264+
continue
265+
}
258266
log.Printf("Warning: failed to create index: %v", err)
259267
}
260268
}
@@ -429,8 +437,11 @@ func enforceMessageRetention(db *sql.DB) {
429437

430438
if ttl > 0 {
431439
for {
440+
// Nested subquery keeps MySQL happy (LIMIT inside IN/NOT IN is invalid otherwise).
432441
result, err := dbExec(db, `DELETE FROM messages WHERE id IN (
433-
SELECT id FROM messages WHERE created_at < ? ORDER BY id ASC LIMIT 500
442+
SELECT id FROM (
443+
SELECT id FROM messages WHERE created_at < ? ORDER BY id ASC LIMIT 500
444+
) AS ttl_batch
434445
)`, time.Now().Add(-ttl))
435446
if err != nil {
436447
log.Printf("Error enforcing TTL retention: %v", err)
@@ -443,7 +454,11 @@ func enforceMessageRetention(db *sql.DB) {
443454
}
444455
}
445456

446-
_, err := dbExec(db, `DELETE FROM messages WHERE id NOT IN (SELECT id FROM messages ORDER BY id DESC LIMIT ?)`, maxMessages)
457+
_, err := dbExec(db, `DELETE FROM messages WHERE id NOT IN (
458+
SELECT id FROM (
459+
SELECT id FROM messages ORDER BY id DESC LIMIT ?
460+
) AS keep_batch
461+
)`, maxMessages)
447462
if err != nil {
448463
log.Printf("Error enforcing message cap: %v", err)
449464
}

0 commit comments

Comments
 (0)