Explorer
KNOW-ANT-FIVEM-005

FiveM - SQL Auto-Insert sans verification : risque de doublons et ecrasement

Domaine
database
Type
anti-pattern
Priorité
P3

Parent : [[INDEX-FIVEM-DATABASE]]

FiveM - SQL Auto-Insert sans vérification : risque de doublons et écrasement

Problème

Config.AutoInsertSQL = true insère automatiquement les tables SQL au démarrage sans vérifier si elles existent déjà. Cela peut causer :

  • Des erreurs SQL à chaque restart
  • Des écrasements potentiels de données si le INSERT est mal écrit
  • Des doublons si la table a une clé primaire mal définie
-- cd_dispatch/config.lua (PROBLEMATIQUE)
Config.AutoInsertSQL = true

-- Au démarrage :
if Config.AutoInsertSQL then
    MySQL.insert('INSERT INTO dispatch_config (key, value) VALUES (?, ?)', {
        'version', '1.0'
    })
    -- Si la ligne existe déjà → erreur DUPLICATE KEY
end

Conséquences

  • Erreurs au démarrage : le resource démarre avec des erreurs SQL visibles dans les logs
  • Données corrompues : si INSERT OR REPLACE est utilisé à la place de INSERT IGNORE
  • Rollback difficile : impossible de savoir quelles données étaient là avant l'écrasement

Solution

Correct

-- Vérification avant insertion
if Config.AutoInsertSQL then
    local exists = MySQL.scalar.await('SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?', {
        'dispatch_config'
    })
    
    if exists == 0 then
        MySQL.query([[CREATE TABLE IF NOT EXISTS dispatch_config (
            id INT AUTO_INCREMENT PRIMARY KEY,
            `key` VARCHAR(50) NOT NULL UNIQUE,
            value TEXT,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )]])
        
        MySQL.insert('INSERT INTO dispatch_config (`key`, value) VALUES (?, ?)', {
            'version', '1.0'
        })
        print('[^2INFO^7] Table dispatch_config créée avec succès')
    else
        -- Vérification de la version pour migration
        local version = MySQL.scalar.await('SELECT value FROM dispatch_config WHERE `key` = ?', { 'version' })
        if version ~= '1.1' then
            -- Migration
            MySQL.update('UPDATE dispatch_config SET value = ? WHERE `key` = ?', { '1.1', 'version' })
        end
    end
end

Incorrect

-- Insertion brute sans vérification
CreateThread(function()
    MySQL.insert('INSERT INTO dispatch_config (`key`, value) VALUES (?, ?)', {'version', '1.0'})
end)

Détection

Rechercher :

AutoInsertSQL.*true
INSERT INTO.*startup
onResourceStart.*INSERT

Références

  • cd_dispatch/config.lua L16