Ошибка в плагине Player Preferences by ufame.

Сообщения
752
Реакции
124
Помог
24 раз(а)
Ошибка
L 09/12/2023 - 05:24:17: [zp/systems/zp43_system_player_prefs.amxx] [PP] Error[1452]: Cannot add or update a child row: a foreign key constraint fails (`sborka`.`pp_preferences`, CONSTRAINT `pp_preferences_ibfk_2` FOREIGN KEY (`key_id`) REFERENCES `pp_keys` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)

L 09/12/2023 - 05:24:17: [zp/systems/zp43_system_player_prefs.amxx] [PP] Query with error: INSERT INTO `pp_preferences` (`player_id`, `key_id`, `value`) VALUES (5, 0, '8') ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);
ОС
Windows
Amx Mod X
AMX Mod X 1.10.0.5461 (http://www.amxmodx.org)
Authors:
David "BAILOPAN" Anderson, Pavol "PM OnoTo" Marko
Felix "SniperBeamer" Geyer, Jonny "Got His Gun" Bergstrom
Lukasz "SidLuke" Wlasinski, Christian "Basic-Master" Hammacher
Borja "faluco" Ferrer, Scott "DS" Ehlert
Compiled: Dec 6 2021 17:37:35
Built from: https://github.com/alliedmodders/amxmodx/commit/ec82e3f3
Build ID: 5461:ec82e3f3
Core mode: JIT+ASM32
Билд
Protocol version 48
Exe version 1.1.2.7/Stdio (cstrike)
ReHLDS version: 3.13.0.788-dev
Build date: 07:37:36 Jul 12 2023 (3378)
Build from: https://github.com/dreamstalker/rehlds/commit/f955b07
ReGamedll
ReGameDLL version: 5.22.0.593-dev
Build date: 03:10:24 Jul 11 2023
Build from: https://github.com/s1lentq/ReGameDLL_CS/commit/e1d1c11
Версия Metamod
Metamod-r v1.3.0.128, API (5:13)
Metamod-r build: 15:47:38 Aug 24 2018
Metamod-r from: https://github.com/theAsmodai/metamod-r/commit/0cf2f70
Список метамодулей
Currently loaded plugins:
description stat pend file vers src load unload
[ 1] AMX Mod X RUN - amxmodx_mm.dll v1.10.0.5461 ini Start ANY
[ 2] Reunion RUN - reunion_mm.dll v0.1.92d ini Start Never
[ 3] Ham Sandwich RUN - hamsandwich_amxx.dll v1.10.0.5461 pl1 ANY ANY
[ 4] CSX RUN - csx_amxx.dll v1.10.0.5461 pl1 ANY ANY
[ 5] FakeMeta RUN - fakemeta_amxx.dll v1.10.0.5461 pl1 ANY ANY
[ 6] CStrike RUN - cstrike_amxx.dll v1.10.0.5461 pl1 ANY ANY
[ 7] MySQL RUN - mysql_amxx.dll v1.10.0.5461 pl1 ANY ANY
[ 8] ReAPI RUN - reapi_amxx.dll v5.22.0.254-dev pl1 ANY Never
8 plugins, 8 running
Список плагинов
Currently loaded plugins:
id name version author url file status
[ 1] 0 Admin Base 1.10.0.546 AMXX Dev Team admin.amxx running
[ 2] 1 Admin Commands 1.10.0.546 AMXX Dev Team admincmd.am running
[ 3] 2 Admin Help 1.10.0.546 AMXX Dev Team adminhelp.a running
[ 4] 3 Slots Reservation 1.10.0.546 AMXX Dev Team adminslots. running
[ 5] 4 Multi-Lingual System 1.10.0.546 AMXX Dev Team multilingua running
[ 6] 5 Menus Front-End 1.10.0.546 AMXX Dev Team menufront.a running
[ 7] 6 Commands Menu 1.10.0.546 AMXX Dev Team cmdmenu.amx running
[ 8] 7 Players Menu 1.10.0.546 AMXX Dev Team plmenu.amxx running
[ 9] 8 Maps Menu 1.10.0.546 AMXX Dev Team mapsmenu.am running
[ 10] 9 Plugin Menu 1.10.0.546 AMXX Dev Team pluginmenu. running
[ 11] 10 Admin Chat 1.10.0.546 AMXX Dev Team adminchat.a running
[ 12] 11 Scrolling Message 1.10.0.546 AMXX Dev Team scrollmsg.a running
[ 13] 12 Info. Messages 1.10.0.546 AMXX Dev Team imessage.am running
[ 14] 13 Admin Votes 1.10.0.546 AMXX Dev Team adminvote.a running
[ 15] 14 NextMap 1.10.0.546 AMXX Dev Team nextmap.amx running
[ 16] 15 Nextmap Chooser 1.10.0.546 AMXX Dev Team mapchooser. running
[ 17] 16 TimeLeft 1.10.0.546 AMXX Dev Team timeleft.am running
[ 18] 17 Pause Plugins 1.10.0.546 AMXX Dev Team pausecfg.am running
[ 19] 18 Stats Configuration 1.10.0.546 AMXX Dev Team statscfg.am running
[ 20] 19 StatsX 1.10.0.546 AMXX Dev Team statsx.amxx running
[ 21] 20 Bot Tester; With help Never rele Chrescoe1 unknown bot.amxx running
[ 22] 21 [ZP 4.3] Main Mode 4.3 Fix6a MeRcyLeZZ zp/main/zp4 running
[ 23] 22 [ZP 4.3] ZClass: Defau 1.0.0 ImmortalAmxx zp/zclass/z running
[ 24] 23 [ZP 4.3] System: Regis 1.0.0 ImmortalAmxx zp/systems/ running
[ 25] 24 [ZP 4.3] System: Playe 1.1.0 ufame zp/systems/ running
[ 26] 25 [AMXX] Addon: Floating 1.0.6 Yoshioka Haruki zp/addons/z running
[ 27] 26 [ZP 4.3] Save: Ammo 1.0.0 ImmortalAmxx zp/save/zp_ running
27 plugins, 27 running
Автор плагина
ufame
Версия плагина
1.1.0 github
Исходный код
#include <amxmodx>
#include <sqlx>
#include <player_prefs>

#pragma semicolon 1

const MAX_QUERY_LENGTH = 4096;

enum {
State_LoadKeys,
State_LoadPlayer,
State_InsertPlayer,
State_LoadPreferences,
State_InsertKey,
State_InsertPreference,
State_SetDefaultValue
};

enum _: Forwards {
Forward_Initialized,
Forward_PlayerLoaded,
Forward_PlayerSaved
};

new g_iPlayerDatabaseId[MAX_PLAYERS + 1];
new Trie: g_tPlayerPreferences[MAX_PLAYERS + 1];

new Trie: g_tKeys;
new Trie: g_tKeysIds;

new g_szSqlHost[32], g_szSqlUser[32], g_szSqlPassword[128], g_szSqlDatabase[32];
new g_iForwards[Forwards];

new g_szQuery[MAX_QUERY_LENGTH];
new Handle: g_hSqlTuple;

new bool: g_bDebugMode;

public plugin_init() {
register_plugin("[ZP 4.3] System: Player Preferences", "1.1.0", "ufame");

CreateForwards();
CreateCvars();

g_bDebugMode = bool: (plugin_flags() & AMX_FLAG_DEBUG);
}

public client_putinserver(iPlayer) {
if (is_user_hltv(iPlayer) || is_user_bot(iPlayer))
return;

g_iPlayerDatabaseId[iPlayer] = 0;
TrieDestroy(g_tPlayerPreferences[iPlayer]);

LoadPreferences(iPlayer);
}

public plugin_natives() {
register_native("pp_is_loaded", "native_is_loaded");
register_native("pp_get_preference", "native_get_preference");
register_native("pp_set_preference", "native_set_preference");

register_native("pp_set_key_default_value", "native_set_key_default_value");
}

public bool: native_is_loaded(iPlugin, iArgs) {
enum {
arg_player_id = 1
};

new iPlayer = get_param(arg_player_id);

if (!is_user_connected(iPlayer))
return false;

return bool: g_iPlayerDatabaseId[iPlayer];
}

public bool: native_get_preference(iPlugin, iArgs) {
enum {
arg_player_id = 1,
arg_key,
arg_dest,
arg_destlen
};

new iPlayer = get_param(arg_player_id);

if (!is_user_connected(iPlayer) || g_tPlayerPreferences[iPlayer] == Invalid_Trie)
return false;

new szKey[32], szValue[256];
new iLen = get_param(arg_destlen);

get_string(arg_key, szKey, charsmax(szKey));

if (!TrieGetString(g_tPlayerPreferences[iPlayer], szKey, szValue, charsmax(szValue)))
TrieGetString(g_tKeys, szKey, szValue, charsmax(szValue));

set_string(arg_dest, szValue, iLen);

return true;
}

public bool: native_set_preference(iPlugin, iArgs) {
enum {
arg_player_id = 1,
arg_key,
arg_value,
arg_default_value
};

new iPlayer = get_param(arg_player_id);

if (!is_user_connected(iPlayer))
return false;

new szKey[32], szValue[256], szDefaultValue[256];

get_string(arg_key, szKey, charsmax(szKey));
get_string(arg_value, szValue, charsmax(szValue));
get_string(arg_default_value, szDefaultValue, charsmax(szDefaultValue));

return bool: SetPreference(iPlayer, szKey, szValue, szDefaultValue);
}

public bool: native_set_key_default_value(iPlugin, iArgs) {
enum {
arg_key = 1,
arg_default_value
};

new szKey[32], szDefaultValue[256];

get_string(arg_key, szKey, charsmax(szKey));
get_string(arg_default_value, szDefaultValue, charsmax(szDefaultValue));

if (g_hSqlTuple != Empty_Handle) {
formatex(g_szQuery, charsmax(g_szQuery),
"INSERT INTO `pp_keys` (`key`, `default_value`) VALUES ('%s', '%s') \
ON DUPLICATE KEY UPDATE `default_value` = VALUES(`default_value`);",
szKey, szDefaultValue
);

__debug("Insert key %s <%s>: %s", szKey, szDefaultValue, g_szQuery);

new iData[1];
iData[0] = State_SetDefaultValue;

SQL_ThreadQuery(g_hSqlTuple, "ThreadQuery_Handler", g_szQuery, iData, sizeof iData);
}

if (g_tKeys == Invalid_Trie)
g_tKeys = TrieCreate();

return bool: TrieSetString(g_tKeys, szKey, szDefaultValue);
}

stock LoadPreferences(iPlayer) {
if (g_hSqlTuple == Empty_Handle) {
ExecuteForward(g_iForwards[Forward_PlayerLoaded], _, iPlayer);

return;
}

new szAuth[MAX_AUTHID_LENGTH];
get_user_authid(iPlayer, szAuth, charsmax(szAuth));

formatex(g_szQuery, charsmax(g_szQuery),
"SELECT `id` FROM `pp_players` WHERE `authid` = '%s';",
szAuth
);

new iData[3];
iData[0] = State_LoadPlayer;
iData[1] = iPlayer;
iData[2] = get_user_userid(iPlayer);

SQL_ThreadQuery(g_hSqlTuple, "ThreadQuery_Handler", g_szQuery, iData, sizeof iData);
}

stock SetPreference(iPlayer, szKey[], szValue[], szDefaultValue[]) {
if (g_hSqlTuple != Empty_Handle) {
// TODO: Было бы неплохо, при наличии ключа в g_tKeysIds, слать сразу значения, и только в ином случае начинать с ключа
// И даже если начинать с ключа, в колбеке всё ровно перепроверять g_tKeysIds (szData[3]) т.к. сраная асинхронщина
formatex(g_szQuery, charsmax(g_szQuery),
"INSERT INTO `pp_keys` (`key`, `default_value`) VALUES ('%s', '%s') \
ON DUPLICATE KEY UPDATE `default_value` = VALUES(`default_value`);",
szKey, szDefaultValue
);

// TODO: Было бы неплохо в глобаг скоп выкинуть
enum data {
query_state,
player_id,
player_userid,
key_id,
value[256]
};

new szData[data];

szData[query_state] = State_InsertKey;
szData[player_id] = iPlayer;
szData[player_userid] = get_user_userid(iPlayer);
TrieGetCell(g_tKeysIds, szKey, szData[key_id]);
formatex(szData[value], charsmax(szData[value]), szValue);

__debug("Insert key %s: %d / %d - %s",
szKey, szData[player_id], szData[player_userid], szValue
);

SQL_ThreadQuery(g_hSqlTuple, "ThreadQuery_Handler", g_szQuery, szData, sizeof szData);
}

if (g_tPlayerPreferences[iPlayer] == Invalid_Trie)
g_tPlayerPreferences[iPlayer] = TrieCreate();

return bool: TrieSetString(g_tPlayerPreferences[iPlayer], szKey, szValue);
}

public ThreadQuery_Handler(iFailState, Handle: hQuery, szError[], iError, szData[], iDataSize, Float: flQueueTime) {
if (iFailState != TQUERY_SUCCESS) {
SQL_ThreadError(hQuery, szError, iError, flQueueTime);

return;
}

switch (szData[0]) {
case State_LoadKeys: {
new szKey[64], szDefaultValue[256], sKeyId[11];

TrieDestroy(g_tKeysIds);
g_tKeysIds = TrieCreate();

while (SQL_MoreResults(hQuery)) {
SQL_ReadResult(hQuery, SQL_FieldNameToNum(hQuery, "id"), sKeyId, charsmax(sKeyId));
SQL_ReadResult(hQuery, SQL_FieldNameToNum(hQuery, "key"), szKey, charsmax(szKey));
SQL_ReadResult(hQuery, SQL_FieldNameToNum(hQuery, "default_value"), szDefaultValue, charsmax(szDefaultValue));

TrieSetString(g_tKeys, szKey, szDefaultValue);
TrieSetCell(g_tKeysIds, szKey, str_to_num(sKeyId));

SQL_NextRow(hQuery);
}

log_amx("Successfully loaded %d keys", SQL_AffectedRows(hQuery));
}

case State_LoadPlayer: {
new iPlayer = szData[1];
new iUserid = szData[2];

__debug("State: Load Player #1 <%d><%d><%d>", iPlayer, iUserid, get_user_userid(iPlayer));

if (iUserid != get_user_userid(iPlayer))
return;

new szAuth[MAX_AUTHID_LENGTH];
get_user_authid(iPlayer, szAuth, charsmax(szAuth));

__debug("State: Load Player #2 <%d><%d><%d><%s>", iPlayer, iUserid, get_user_userid(iPlayer), szAuth);

if (!SQL_NumResults(hQuery)) {
formatex(g_szQuery, charsmax(g_szQuery),
"INSERT INTO `pp_players` (`authid`) VALUES ('%s');",
szAuth
);

szData[0] = State_InsertPlayer;

SQL_ThreadQuery(g_hSqlTuple, "ThreadQuery_Handler", g_szQuery, szData, iDataSize);

__debug("State: Insert Player #1 <%d><%d><%d><%s>: %s", iPlayer, iUserid, get_user_userid(iPlayer), szAuth, g_szQuery);

return;
}

g_iPlayerDatabaseId[iPlayer] = SQL_ReadResult(hQuery, SQL_FieldNameToNum(hQuery, "id"));

formatex(g_szQuery, charsmax(g_szQuery),
"SELECT `pp_keys`.`key`, `pp_preferences`.`value` \
FROM `pp_keys` \
JOIN `pp_preferences` \
ON `pp_keys`.`id` = `pp_preferences`.`key_id` \
WHERE `pp_preferences`.`player_id` = %d;",
g_iPlayerDatabaseId[iPlayer]
);

szData[0] = State_LoadPreferences;

SQL_ThreadQuery(g_hSqlTuple, "ThreadQuery_Handler", g_szQuery, szData, iDataSize);

__debug("State: Load Preferences #1 <%d><%d><%d><%s>: %s", iPlayer, iUserid, get_user_userid(iPlayer), szAuth, g_szQuery);
}

case State_InsertPlayer: {
new iPlayer = szData[1];
new iUserid = szData[2];

__debug("State: Insert Player #2 <%d><%d><%d>", iPlayer, iUserid, get_user_userid(iPlayer));

if (iUserid != get_user_userid(iPlayer))
return;

__debug("State: Insert Player #3 <%d><%d><%d>", iPlayer, iUserid, get_user_userid(iPlayer));

g_iPlayerDatabaseId[iPlayer] = SQL_GetInsertId(hQuery);

ExecuteForward(g_iForwards[Forward_PlayerLoaded], _, iPlayer);
}

case State_LoadPreferences: {
new iPlayer = szData[1];
new iUserid = szData[2];

__debug("State: Load Preferences #2 <%d><%d><%d>", iPlayer, iUserid, get_user_userid(iPlayer));

if (iUserid != get_user_userid(iPlayer))
return;

__debug("State: Load Preferences #3 <%d><%d><%d>", iPlayer, iUserid, get_user_userid(iPlayer));

new szKey[64], szValue[256];

if (g_tPlayerPreferences[iPlayer] == Invalid_Trie)
g_tPlayerPreferences[iPlayer] = TrieCreate();

while (SQL_MoreResults(hQuery)) {
SQL_ReadResult(hQuery, SQL_FieldNameToNum(hQuery, "key"), szKey, charsmax(szKey));
SQL_ReadResult(hQuery, SQL_FieldNameToNum(hQuery, "value"), szValue, charsmax(szValue));

TrieSetString(g_tPlayerPreferences[iPlayer], szKey, szValue);

SQL_NextRow(hQuery);
}

ExecuteForward(g_iForwards[Forward_PlayerLoaded], _, iPlayer);
}

case State_InsertKey: {
new iPlayer = szData[1];
new iUserid = szData[2];

__debug("State: Insert key #2 <%d><%d><%d>", iPlayer, iUserid, get_user_userid(iPlayer));

if (iUserid != get_user_userid(iPlayer))
return;

new iKeyId = szData[3] == 0 ? SQL_GetInsertId(hQuery) : szData[3];

formatex(g_szQuery, charsmax(g_szQuery),
"INSERT INTO `pp_preferences` (`player_id`, `key_id`, `value`) VALUES (%d, %d, '%s') \
ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);",
g_iPlayerDatabaseId[iPlayer], iKeyId, szData[4]
);

__debug("State: Insert key #3 <%d><%d><%d><%s>: %s", iPlayer, iUserid, get_user_userid(iPlayer), szData[4], g_szQuery);

szData[0] = State_InsertPreference;

SQL_ThreadQuery(g_hSqlTuple, "ThreadQuery_Handler", g_szQuery, szData, iDataSize);
}

case State_InsertPreference: {
new iPlayer = szData[1];
new iUserid = szData[2];

__debug("State: Insert Preference #2 <%d><%d><%d>", iPlayer, iUserid, get_user_userid(iPlayer));

if (iUserid != get_user_userid(iPlayer))
return;

ExecuteForward(g_iForwards[Forward_PlayerSaved], _, iPlayer);
}

case State_SetDefaultValue: {

}
}
}

CreateCvars() {
bind_pcvar_string(create_cvar("pp_host", "localhost", FCVAR_SPONLY | FCVAR_PROTECTED | FCVAR_UNLOGGED), g_szSqlHost, charsmax(g_szSqlHost));
bind_pcvar_string(create_cvar("pp_user", "root", FCVAR_SPONLY | FCVAR_PROTECTED | FCVAR_UNLOGGED), g_szSqlUser, charsmax(g_szSqlUser));
bind_pcvar_string(create_cvar("pp_pass", "", FCVAR_SPONLY | FCVAR_PROTECTED | FCVAR_UNLOGGED), g_szSqlPassword, charsmax(g_szSqlPassword));
bind_pcvar_string(create_cvar("pp_db", "sborka", FCVAR_SPONLY | FCVAR_PROTECTED | FCVAR_UNLOGGED), g_szSqlDatabase, charsmax(g_szSqlDatabase));

AutoExecConfig(true, "player_prefs", "system");

ConnectionTest();
}

CreateForwards() {
g_iForwards[Forward_Initialized] = CreateMultiForward("pp_init", ET_IGNORE, FP_CELL);
g_iForwards[Forward_PlayerLoaded] = CreateMultiForward("pp_player_loaded", ET_IGNORE, FP_CELL);
g_iForwards[Forward_PlayerSaved] = CreateMultiForward("pp_player_saved", ET_IGNORE, FP_CELL);
}

ConnectionTest() {
SQL_SetAffinity("mysql");
g_hSqlTuple = SQL_MakeDbTuple(g_szSqlHost, g_szSqlUser, g_szSqlPassword, g_szSqlDatabase);

new szError[512], iErrorCode;
new Handle: hConnection = SQL_Connect(g_hSqlTuple, iErrorCode, szError, charsmax(szError));

if (hConnection == Empty_Handle) {
SQL_FreeHandle(g_hSqlTuple);
g_hSqlTuple = Empty_Handle;

abort(AMX_ERR_NATIVE, "[PP] Connection error[%d]: %s", iErrorCode, szError);

ExecuteForward(g_iForwards[Forward_Initialized], _, false);

return;
}

log_amx("[PP] Connection to database successfully estabilished");

formatex(g_szQuery, charsmax(g_szQuery),
"SELECT `id`, `key`, `default_value` FROM `pp_keys`"
);

new iData[1];
iData[0] = State_LoadKeys;

SQL_ThreadQuery(g_hSqlTuple, "ThreadQuery_Handler", g_szQuery, iData, sizeof iData);

ExecuteForward(g_iForwards[Forward_Initialized], _, true);
}

SQL_ThreadError(Handle: hQuery, szError[], iError, Float: flQueueTime) {
SQL_GetQueryString(hQuery, g_szQuery, charsmax(g_szQuery));

log_amx("[PP] Queue time: %.4f", flQueueTime);
log_amx("[PP] Error[%d]: %s", iError, szError);
log_amx("[PP] Query with error: %s", g_szQuery);
}

__debug(const debug_message[], any: ...) {
if (!g_bDebugMode)
return;

new szMessage[1024];
vformat(szMessage, charsmax(szMessage), debug_message, 2);

log_to_file("pp_debug.log", szMessage);
}
Возникает ошибка в запросе к базе данных.
Суть такая: есть у меня меню, в нём идёт кнопка сохранения. Нажимая на кнопку, если у человека нету ключей, то они добавляються в таблицу, с этим проблем нет, но проблема заключается в том, что если человек нажмёт еще раз кнопку сохранения, то вылезает ошибка запроса.
SQL:
L 09/12/2023 - 05:24:17: [zp/systems/zp43_system_player_prefs.amxx] [PP] Error[1452]: Cannot add or update a child row: a foreign key constraint fails (`sborka`.`pp_preferences`, CONSTRAINT `pp_preferences_ibfk_2` FOREIGN KEY (`key_id`) REFERENCES `pp_keys` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
L 09/12/2023 - 05:24:17: [zp/systems/zp43_system_player_prefs.amxx] [PP] Query with error: INSERT INTO `pp_preferences` (`player_id`, `key_id`, `value`) VALUES (5, 0, '8') ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);
Сохранял я по примеру, который есть в архиве. Еще странно то, что после смены карты ошибка пропадает, и игрок может сохранять сколько угодно раз новые значения, при этом плагин не будет выдавать ошибки. Может кто сталкивался?
 
Сообщения
842
Реакции
169
Помог
3 раз(а)
Работаешь с данными которых нет
 
Сообщения
842
Реакции
169
Помог
3 раз(а)
Nordic Warrior, потому что квары и подключение происходят в init
Лучше уже в подключение делать после загрузки всех кфг
 
Сообщения
2,861
Реакции
1,278
Помог
98 раз(а)
BiZaJe, спасибо, я в курсе. В issue всё расписано.
 
Сообщения
433
Реакции
241
Помог
8 раз(а)
BiZaJe, да, ведь ишью создан не в моем репозитории, откуда мне знать.
Некоторые ребята говорят быстрее чем думают.

ImmortalAmxx к вечеру конкретно этот кейс решу, не знаю залью ли на форум обнову, советую следить за репозиторием на гитхабе
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу