PDA

Просмотр полной версии : [Вопрос] ORM запросы



_MegaMix_
15.05.2017, 18:02
Здравствуйте, возникла такая проблема, сделал команду выдачи vip, должно записать в бд 3 параметра, но почему-то 1 параметр записывает как 0.

Параметр vip_id записывает как 0.
В логах такие ошибки:


orm_setkey: orm error: variable not found
[ERROR] COrm::UpdateKeyValue - inserted id is zero



COMMAND:makevip(adminid,params[])
{
CheckAdminLevel(adminid, ADMIN_LVL_makeadmin);

extract params -> new playerid, level, day; else
{
return SendClientMessage(adminid, HEX_COLOR_ERROR,
!"Используйте: /makevip [playerid] [уровень] [дни]");
}

else if(!IsPlayerConnected(playerid))
return CMD_INVALID_PLAYER_ID;

else if(admin[adminid][admin_level] < admin[playerid][admin_level])
return CMD_INVALID_PERMISSIONS;

else if(!(-1 < level < MAX_VIP_LEVEL))
return SendClientMessage(adminid, HEX_COLOR_ERROR, !"Уровень не может быть больше чем "#MAX_VIP_LEVEL" и меньше чем 0!");

else if(!(0 < day < 365))
return SendClientMessage(adminid, HEX_COLOR_ERROR, !"Количество дней должно быть от 1 до 365!");

else if(level == vip[playerid][v_level])
return SendClientMessage(adminid, HEX_COLOR_ERROR, !"У игрока уже установлен данный уровень!");

else if(0 == level)
{
vip[playerid][v_level] = 0;
orm_delete(vip[playerid][vip_orm]);

static const string_content[] = ""COLOR_ERROR"%s "COLOR_NOTE"забрал VIP привелегии у "COLOR_ERROR"%s";
new string[sizeof string_content - (2*3) + MAX_ADMIN_RANK + (MAX_PLAYER_NAME*2)];

format(string, sizeof string, string_content, player[adminid][player_name], player[playerid][player_name]);
SendMessageToAdmins(string);
SendMessageToVips(string);

format(string, sizeof string, ""COLOR_ERROR"%s "COLOR_NOTE" забрал у вас VIP привелегии!", player[adminid][player_name]);
SendClientMessage(playerid, HEX_COLOR_NOTE, string);
return 1;
}
else if(!vip[playerid][v_level])
{
static const string_content[] = ""COLOR_ERROR" %s "COLOR_NOTE" выдал вам VIP уровень: "COLOR_ERROR"%s";
new string[sizeof string_content + (-2 + MAX_PLAYER_NAME) + (-2 + 9)];
format(string, sizeof string, string_content, player[adminid][player_name], vip_level[level]);
SendClientMessage(playerid, HEX_COLOR_NOTE, string);

static const string_content2[] = ""COLOR_ERROR" %s "COLOR_NOTE" выдал "COLOR_ERROR"%s "COLOR_NOTE"VIP уровень: "COLOR_ERROR"%s";
new string2[sizeof string_content2 + (-2 + MAX_PLAYER_NAME)*2 + (-2 + 9)];
format(string2, sizeof string2, string_content2, player[adminid][player_name], player[playerid][player_name], vip_level[level]);
SendMessageToAdmins(string2);

vip[playerid][vip_day] = 86400 * day;
vip[playerid][v_id] = player[playerid][player_unique_id];
vip[playerid][v_level] = level;

orm_setkey(vip[playerid][vip_orm], "vad");
orm_insert(vip[playerid][vip_orm]);
return 1;
}
else
{
vip[playerid][v_level] = level;
vip[playerid][vip_day] = 86400 * day;
vip[playerid][v_id] = player[playerid][player_unique_id];
orm_update(vip[playerid][vip_orm]);
}
return true;
}


enum VIP_DATA
{
ORM: vip_orm,
v_level,
vip_day,
v_id
};

new
vip[MAX_PLAYERS][VIP_DATA];




public OnPlayerSpawn(playerid)
{
if(IsPVarSet(playerid, "_adsss_connect")
&& player[playerid][player_status] == PLAYER_STATUS_LOGGED)
{
vip[playerid][vip_orm] = orm_create("vips");

orm_addvar_int(vip[playerid][vip_orm],
vip[playerid][v_id], "vip_id");

orm_addvar_int(vip[playerid][vip_orm],
vip[playerid][v_level], "vip_level");

orm_addvar_int(vip[playerid][vip_orm],
vip[playerid][vip_day], "vip_days");

orm_setkey(vip[playerid][vip_orm], "vip_id");

orm_select(vip[playerid][vip_orm], "CheckPlayerForVip", "i", playerid);

DeletePVar(playerid, "_adsss_connect");
}
#if defined adsv_OnPlayerSpawn
return adsv_OnPlayerSpawn(playerid);
#else
return 1;
#endif
}
#if defined _ALS_OnPlayerSpawn
#undef OnPlayerSpawn
#else
#define _ALS_OnPlayerSpawn
#endif
#define OnPlayerSpawn adsv_OnPlayerSpawn
#if defined adsv_OnPlayerSpawn
forward adsv_OnPlayerSpawn(playerid);
#endif


public OnPlayerConnect(playerid)
{
vip[playerid] = clear_vip_data;
SetPVarInt(playerid, "_adsss_connect", 1);
#if defined adsv_OnPlayerConnect
return adsv_OnPlayerConnect(playerid);
#else
return 1;
#endif
}
#if defined _ALS_OnPlayerConnect
#undef OnPlayerConnect
#else
#define _ALS_OnPlayerConnect
#endif
#define OnPlayerConnect adsv_OnPlayerConnect
#if defined adsv_OnPlayerConnect
forward adsv_OnPlayerConnect(playerid);
#endif


public OnPlayerDisconnect(playerid, reason)
{
if(vip[playerid][v_level]
&& player[playerid][player_status] == PLAYER_STATUS_LOGGED)
{
orm_update(vip[playerid][vip_orm]);
orm_destroy(vip[playerid][vip_orm]);
}
#if defined adsv_OnPlayerDisconnect
return adsv_OnPlayerDisconnect(playerid, reason);
#else
return 1;
#endif
}
#if defined _ALS_OnPlayerDisconnect
#undef OnPlayerDisconnect
#else
#define _ALS_OnPlayerDisconnect
#endif
#define OnPlayerDisconnect adsv_OnPlayerDisconnect
#if defined adsv_OnPlayerDisconnect
forward adsv_OnPlayerDisconnect(playerid, reason);
#endif

DeimoS
15.05.2017, 18:15
orm_setkey(vip[playerid][vip_orm], "vad");

Так вот тут ты пытаешься установить переменную, которую не объявлял, в качестве ключа, не?

_MegaMix_
15.05.2017, 18:23
Так вот тут ты пытаешься установить переменную, которую не объявлял, в качестве ключа, не?

У меня при спавне ставится ключ : orm_setkey(vip[playerid][vip_orm], "vip_id"); , я пробовал такой же в команде вызывать, результат не изменился. А как правильно нужно ключ установить?

DeimoS
15.05.2017, 18:38
У меня при спавне ставится ключ : orm_setkey(vip[playerid][vip_orm], "vip_id"); , я пробовал такой же в команде вызывать, результат не изменился. А как правильно нужно ключ установить?

Нужно указывать имя того столбца, по которому нужно делать выборку в запросе. В твоём случае это vip_id, как я понимаю.
Измени на него, отчисти лог MySQL и попробуй повторно использовать команду. Будут ли ошибки в MySQL лог при этом?

_MegaMix_
15.05.2017, 18:43
Нужно указывать имя того столбца, по которому нужно делать выборку в запросе. В твоём случае это vip_id, как я понимаю.
Измени на него, отчисти лог MySQL и попробуй повторно использовать команду. Будут ли ошибки в MySQL лог при этом?

05/15/17 17:42:02] [ERROR] orm_setkey: orm error: variable not found (58 строчка)
[05/15/17 17:42:02] [ERROR] COrm::UpdateKeyValue - inserted id is zero

А вот эта строчка :

orm_setkey(vip[playerid][vip_orm], "vip_id");

DeimoS
16.05.2017, 03:03
Покажи весь код, что относится к orm для этой системы и пометь эту 58 строку

_MegaMix_
17.05.2017, 14:42
Покажи весь код, что относится к orm для этой системы и пометь эту 58 строку

А это весь код что есть

DeimoS
17.05.2017, 14:59
Там не хватает некоторых функций.
Если проблема ещё актуальна, вырежи всю систему в отдельный файл так, чтоб он компилировался и скинь в личку.

DeimoS
18.05.2017, 14:27
Не уверен, что причиной ошибки является именно то, о чём я сейчас буду говорить (с ORM в плагине особо не работал), но вот тут


Тебе следовало установить значение для

vip[playerid][v_id]
прежде чем вызывать эту строку:

orm_addvar_int(vip[playerid][vip_orm],
vip[playerid][v_id], "vip_id");
А потом и эту

orm_setkey(vip[playerid][vip_orm], "vip_id");

Ибо сейчас у тебя, как я понимаю, этой строкой

vip[playerid] = clear_vip_data;
идёт обнуление данных в массиве и, соответственно, ID аккаунта в "vip[playerid][v_id]" равен нулю, когда ты устанавливаешь его в качестве ключа для запроса

orm_select(vip[playerid][vip_orm], "CheckPlayerForVip", "i", playerid);
из-за чего в дальнейшем и аккаунт не находится при входе, и, возможно, ошибка эта появляется в логах.



В общем, попробуй вот так:

public OnPlayerSpawn(playerid)
{
if(IsPVarSet(playerid, "_adsss_connect")
&& player[playerid][player_status] == PLAYER_STATUS_LOGGED)
{
new ORM:ormid = vip[playerid][vip_orm] = orm_create("vips");

orm_addvar_int(ormid, (vip[playerid][v_id] = player[playerid][player_unique_id]), "vip_id");

orm_addvar_int(ormid, vip[playerid][v_level], "vip_level");

orm_addvar_int(ormid, vip[playerid][vip_day], "vip_days");

orm_setkey(ormid, "vip_id");

orm_select(ormid, "CheckPlayerForVip", "i", playerid);

DeletePVar(playerid, "_adsss_connect");
}
#if defined adsv_OnPlayerSpawn
return adsv_OnPlayerSpawn(playerid);
#else
return 1;
#endif
}
#if defined _ALS_OnPlayerSpawn
#undef OnPlayerSpawn
#else
#define _ALS_OnPlayerSpawn
#endif
#define OnPlayerSpawn adsv_OnPlayerSpawn
#if defined adsv_OnPlayerSpawn
forward adsv_OnPlayerSpawn(playerid);
#endif

_MegaMix_
18.05.2017, 20:32
Не уверен, что причиной ошибки является именно то, о чём я сейчас буду говорить (с ORM в плагине особо не работал), но вот тут


Тебе следовало установить значение для

vip[playerid][v_id]
прежде чем вызывать эту строку:

orm_addvar_int(vip[playerid][vip_orm],
vip[playerid][v_id], "vip_id");
А потом и эту

orm_setkey(vip[playerid][vip_orm], "vip_id");

Ибо сейчас у тебя, как я понимаю, этой строкой

vip[playerid] = clear_vip_data;
идёт обнуление данных в массиве и, соответственно, ID аккаунта в "vip[playerid][v_id]" равен нулю, когда ты устанавливаешь его в качестве ключа для запроса

orm_select(vip[playerid][vip_orm], "CheckPlayerForVip", "i", playerid);
из-за чего в дальнейшем и аккаунт не находится при входе, и, возможно, ошибка эта появляется в логах.



В общем, попробуй вот так:

public OnPlayerSpawn(playerid)
{
if(IsPVarSet(playerid, "_adsss_connect")
&& player[playerid][player_status] == PLAYER_STATUS_LOGGED)
{
new ORM:ormid = vip[playerid][vip_orm] = orm_create("vips");

orm_addvar_int(ormid, (vip[playerid][v_id] = player[playerid][player_unique_id]), "vip_id");

orm_addvar_int(ormid, vip[playerid][v_level], "vip_level");

orm_addvar_int(ormid, vip[playerid][vip_day], "vip_days");

orm_setkey(ormid, "vip_id");

orm_select(ormid, "CheckPlayerForVip", "i", playerid);

DeletePVar(playerid, "_adsss_connect");
}
#if defined adsv_OnPlayerSpawn
return adsv_OnPlayerSpawn(playerid);
#else
return 1;
#endif
}
#if defined _ALS_OnPlayerSpawn
#undef OnPlayerSpawn
#else
#define _ALS_OnPlayerSpawn
#endif
#define OnPlayerSpawn adsv_OnPlayerSpawn
#if defined adsv_OnPlayerSpawn
forward adsv_OnPlayerSpawn(playerid);
#endif

К сожалению, всё равно 0 записывается

DeimoS
18.05.2017, 22:07
COMMAND:makevip(adminid,params[])
{
CheckAdminLevel(adminid, ADMIN_LVL_makeadmin);

extract params -> new playerid, level, day; else
{
return SendClientMessage(adminid, HEX_COLOR_ERROR,
!"Используйте: /makevip [playerid] [уровень] [дни]");
}

else if(!IsPlayerConnected(playerid))
return CMD_INVALID_PLAYER_ID;

else if(admin[adminid][admin_level] < admin[playerid][admin_level])
return CMD_INVALID_PERMISSIONS;

else if(!(-1 < level < MAX_VIP_LEVEL))
return SendClientMessage(adminid, HEX_COLOR_ERROR, !"Уровень не может быть больше чем "#MAX_VIP_LEVEL" и меньше чем 0!");

else if(!(0 < day < 365))
return SendClientMessage(adminid, HEX_COLOR_ERROR, !"Количество дней должно быть от 1 до 365!");

else if(level == vip[playerid][v_level])
return SendClientMessage(adminid, HEX_COLOR_ERROR, !"У игрока уже установлен данный уровень!");

else if(0 == level)
{
vip[playerid][v_level] = 0;
orm_delete(vip[playerid][vip_orm]);

static const string_content[] = ""COLOR_ERROR"%s "COLOR_NOTE"забрал VIP привелегии у "COLOR_ERROR"%s";
new string[sizeof string_content - (2*3) + MAX_ADMIN_RANK + (MAX_PLAYER_NAME*2)];

format(string, sizeof string, string_content, player[adminid][player_name], player[playerid][player_name]);
SendMessageToAdmins(string);
SendMessageToVips(string);

format(string, sizeof string, ""COLOR_ERROR"%s "COLOR_NOTE" забрал у вас VIP привелегии!", player[adminid][player_name]);
SendClientMessage(playerid, HEX_COLOR_NOTE, string);
return 1;
}
else if(!vip[playerid][v_level])
{
static const string_content[] = ""COLOR_ERROR" %s "COLOR_NOTE" выдал вам VIP уровень: "COLOR_ERROR"%s";
new string[sizeof string_content + (-2 + MAX_PLAYER_NAME) + (-2 + 9)];
format(string, sizeof string, string_content, player[adminid][player_name], vip_level[level]);
SendClientMessage(playerid, HEX_COLOR_NOTE, string);

static const string_content2[] = ""COLOR_ERROR" %s "COLOR_NOTE" выдал "COLOR_ERROR"%s "COLOR_NOTE"VIP уровень: "COLOR_ERROR"%s";
new string2[sizeof string_content2 + (-2 + MAX_PLAYER_NAME)*2 + (-2 + 9)];
format(string2, sizeof string2, string_content2, player[adminid][player_name], player[playerid][player_name], vip_level[level]);
SendMessageToAdmins(string2);

vip[playerid][vip_day] = 86400 * day;
vip[playerid][v_id] = player[playerid][player_unique_id];
vip[playerid][v_level] = level;


printf("\n\n%d | %d | %d\n\n", vip[playerid][v_id], vip[playerid][v_level], vip[playerid][vip_day]);
orm_save(vip[playerid][vip_orm]);
return 1;
}
else
{
vip[playerid][v_level] = level;
vip[playerid][vip_day] = 86400 * day;
vip[playerid][v_id] = player[playerid][player_unique_id];
orm_update(vip[playerid][vip_orm]);
}
return true;
}

Вот так попробуй и если всё равно будет 0, скинь логи сервера + скрин структуры таблицы.

_MegaMix_
19.05.2017, 11:25
COMMAND:makevip(adminid,params[])
{
CheckAdminLevel(adminid, ADMIN_LVL_makeadmin);

extract params -> new playerid, level, day; else
{
return SendClientMessage(adminid, HEX_COLOR_ERROR,
!"Используйте: /makevip [playerid] [уровень] [дни]");
}

else if(!IsPlayerConnected(playerid))
return CMD_INVALID_PLAYER_ID;

else if(admin[adminid][admin_level] < admin[playerid][admin_level])
return CMD_INVALID_PERMISSIONS;

else if(!(-1 < level < MAX_VIP_LEVEL))
return SendClientMessage(adminid, HEX_COLOR_ERROR, !"Уровень не может быть больше чем "#MAX_VIP_LEVEL" и меньше чем 0!");

else if(!(0 < day < 365))
return SendClientMessage(adminid, HEX_COLOR_ERROR, !"Количество дней должно быть от 1 до 365!");

else if(level == vip[playerid][v_level])
return SendClientMessage(adminid, HEX_COLOR_ERROR, !"У игрока уже установлен данный уровень!");

else if(0 == level)
{
vip[playerid][v_level] = 0;
orm_delete(vip[playerid][vip_orm]);

static const string_content[] = ""COLOR_ERROR"%s "COLOR_NOTE"забрал VIP привелегии у "COLOR_ERROR"%s";
new string[sizeof string_content - (2*3) + MAX_ADMIN_RANK + (MAX_PLAYER_NAME*2)];

format(string, sizeof string, string_content, player[adminid][player_name], player[playerid][player_name]);
SendMessageToAdmins(string);
SendMessageToVips(string);

format(string, sizeof string, ""COLOR_ERROR"%s "COLOR_NOTE" забрал у вас VIP привелегии!", player[adminid][player_name]);
SendClientMessage(playerid, HEX_COLOR_NOTE, string);
return 1;
}
else if(!vip[playerid][v_level])
{
static const string_content[] = ""COLOR_ERROR" %s "COLOR_NOTE" выдал вам VIP уровень: "COLOR_ERROR"%s";
new string[sizeof string_content + (-2 + MAX_PLAYER_NAME) + (-2 + 9)];
format(string, sizeof string, string_content, player[adminid][player_name], vip_level[level]);
SendClientMessage(playerid, HEX_COLOR_NOTE, string);

static const string_content2[] = ""COLOR_ERROR" %s "COLOR_NOTE" выдал "COLOR_ERROR"%s "COLOR_NOTE"VIP уровень: "COLOR_ERROR"%s";
new string2[sizeof string_content2 + (-2 + MAX_PLAYER_NAME)*2 + (-2 + 9)];
format(string2, sizeof string2, string_content2, player[adminid][player_name], player[playerid][player_name], vip_level[level]);
SendMessageToAdmins(string2);

vip[playerid][vip_day] = 86400 * day;
vip[playerid][v_id] = player[playerid][player_unique_id];
vip[playerid][v_level] = level;


printf("\n\n%d | %d | %d\n\n", vip[playerid][v_id], vip[playerid][v_level], vip[playerid][vip_day]);
orm_save(vip[playerid][vip_orm]);
return 1;
}
else
{
vip[playerid][v_level] = level;
vip[playerid][vip_day] = 86400 * day;
vip[playerid][v_id] = player[playerid][player_unique_id];
orm_update(vip[playerid][vip_orm]);
}
return true;
}

Вот так попробуй и если всё равно будет 0, скинь логи сервера + скрин структуры таблицы.

В бд сейчас вообще ничего не записалось, в server_log вывело:

1 | 4 | 691200

А вот скрин структуры:
http://s018.radikal.ru/i508/1705/c1/4a6bf971e766.jpg

DeimoS
19.05.2017, 16:23
И тут всё встало на свои места :)

Причина вот этой ошибки:

[ERROR] COrm::UpdateKeyValue - inserted id is zero
В том, что у тебя столбец vip_id не имеет параметра AUTO_INCREMENT, из-за чего новая строка и создаётся со значением 0, что не совсем верно для MySQL

Вот этот код:

vip[playerid][vip_day] = 86400 * day;
vip[playerid][v_id] = player[playerid][player_unique_id];
vip[playerid][v_level] = level;
orm_setkey(vip[playerid][vip_orm], "vip_id");
orm_insert(vip[playerid][vip_orm]);
В результате сформирует вот такой запрос (можно в логах посмотреть, если прописать в OnGameModeInIt "mysql_log(ALL);":

INSERT INTO `vips` (`vip_level`,`vip_days`) VALUES ('уровень','дни')
То бишь, значение vip_id не будет учитываться, так как этот столбец установлен в качестве уникального ключа.

Что бы всё работало как надо, нужно создать дополнительный столбец, который и будет являться идентификатором строк.
Вот тебе готовый запрос

DROP TABLE IF EXISTS vips;
CREATE TABLE vips (
row_id int(11) NOT NULL,
vip_id int(11) NOT NULL,
vip_level int(11) NOT NULL,
vip_days int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


ALTER TABLE vips
ADD PRIMARY KEY (row_id);

ALTER TABLE vips
MODIFY row_id int(11) NOT NULL AUTO_INCREMENT;

Так же нужно это поле занести в ORM:

enum VIP_DATA
{
ORM: vip_orm,
v_level,
vip_day,
v_id,
v_rid
};


public OnPlayerSpawn(playerid)
{
if(IsPVarSet(playerid, "_adsss_connect")
&& player[playerid][player_status] == PLAYER_STATUS_LOGGED)
{
new ORM:ormid = vip[playerid][vip_orm] = orm_create("vips");

orm_addvar_int(ormid, vip[playerid][v_rid], "row_id");

vip[playerid][v_id] = player[playerid][player_unique_id];// Если этого не сделать, orm_select будет искать vip_id со значением 0

orm_addvar_int(ormid, vip[playerid][v_id], "vip_id");

orm_addvar_int(ormid, vip[playerid][v_level], "vip_level");

orm_addvar_int(ormid, vip[playerid][vip_day], "vip_days");

orm_setkey(ormid, "vip_id");

orm_select(ormid, "CheckPlayerForVip", "i", playerid);

DeletePVar(playerid, "_adsss_connect");
}
#if defined adsv_OnPlayerSpawn
return adsv_OnPlayerSpawn(playerid);
#else
return 1;
#endif
}
#if defined _ALS_OnPlayerSpawn
#undef OnPlayerSpawn
#else
#define _ALS_OnPlayerSpawn
#endif
#define OnPlayerSpawn adsv_OnPlayerSpawn
#if defined adsv_OnPlayerSpawn
forward adsv_OnPlayerSpawn(playerid);
#endif

И уже в самой команде устанавливай в качестве ключа новый столбец:

orm_setkey(vip[playerid][vip_orm], "row_id");
orm_insert(vip[playerid][vip_orm]);

Если я ничего не забыл, то всё должно работать


UPD: Вопрос решён Закрыто.