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

Статус
В этой теме нельзя размещать новые ответы.
Сообщения
865
Реакции
144
Помог
25 раз(а)
Ошибка
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`);
Сохранял я по примеру, который есть в архиве. Еще странно то, что после смены карты ошибка пропадает, и игрок может сохранять сколько угодно раз новые значения, при этом плагин не будет выдавать ошибки. Может кто сталкивался?
 
В этой теме было размещено решение! Перейти к решению.
Сообщения
940
Реакции
188
Помог
4 раз(а)
Работаешь с данными которых нет
 
Сообщения
940
Реакции
188
Помог
4 раз(а)
Nordic Warrior, потому что квары и подключение происходят в init
Лучше уже в подключение делать после загрузки всех кфг
 
Сообщения
3,387
Реакции
1,485
Помог
125 раз(а)
BiZaJe, спасибо, я в курсе. В issue всё расписано.
 
Сообщения
453
Реакции
255
Помог
9 раз(а)
BiZaJe, да, ведь ишью создан не в моем репозитории, откуда мне знать.
Некоторые ребята говорят быстрее чем думают.

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

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

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