Форум Pawn-Wiki.Ru - Воплоти мечту в реальность!: Ошибка с записью и извлечением данных. - Форум Pawn-Wiki.Ru - Воплоти мечту в реальность!

Перейти к содержимому

Страница 1 из 1
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

[ MySQL ]
Ошибка с записью и извлечением данных.

#1
Пользователь офлайн   ane4ka :3 

  • Новичок
  • Вставить ник
  • Раскрыть информацию
Делаю систему блокировки аккаунта и столкнулась с 2-мя проблемами.

1-е - не записывает причину блокировки. В случае, если стоит кодировка utf8_general_ci в поле `reason` не вписывает ничего. Ставила cp1251, вместо причины записывало знаки вопросов (т. е '????').
2-е - далее уже проблема с проверкой на блокировку.
Этот код идет в OnPlayerConnect().
format(query, sizeof(query), "SELECT * FROM `ban_list` WHERE `name` = '%s'", account[playerid][name]);
result = mysql_query(c_handle, query, true);
cache_get_row_count(rows);
if(rows)
{
	new unban_date_unix;
	format(query, sizeof(query), "SELECT UNIX_TIMESTAMP (`unban_date`) AS `unban_date_unix` FROM `ban_list` WHERE `name` = '%s'", account[playerid][name]);
	mysql_query(c_handle, query, true);
	cache_get_value_name_int(0, "unban_date_unix", unban_date_unix);
	if(gettime() > unban_date_unix)
	{
		format(query, sizeof(query), "DELETE FROM `ban_list` WHERE `name` = '%s'", account[playerid][name]);
		mysql_query(c_handle, query, false);
	}
	else
	{
		cache_set_active(result);
		new msg[300], reason[20], aname[MAX_PLAYER_NAME], date[2][10+1];
		cache_get_value_name(0, "admin_name", aname, MAX_PLAYER_NAME);
		cache_get_value_name(0, "reason", reason, 20);
		format(query, sizeof(query), "SELECT DATE_FORMAT(`unban_date`, '%d.%m.%Y') AS `ban_date_format` FROM `ban_list` WHERE `name` = '%s'", account[playerid][name]);
		mysql_query(c_handle, query, true);
		cache_get_value_name(0, "ban_date_format", date[0], 10);
		format(query, sizeof(query), "SELECT DATE_FORMAT(`ban_date`, '%d.%m.%Y') AS `unban_date_format` FROM `ban_list` WHERE `name` = '%s'", account[playerid][name]);
		mysql_query(c_handle, query, true);
		cache_get_value_name(0, "unban_date_format", date[1], 10);
		format(msg, sizeof(query),
			"{FFFFFF}Ваш аккаунт заблокирован.\n\n\
			Никнейм: %s\n\
			Никнейм администратора: %s\n\
			Дата блокировки: %s\n\
			Дата разблокировки: %s\n\
			Причина: %s\n\n",
				account[playerid][name], aname, date[0], date[1], reason);
		ShowPlayerDialog(playerid, dBan, DIALOG_STYLE_MSGBOX, "{D40000}Сообщение о блокировке", msg, "{D40000}Закрыть", "");
		return Kickk(playerid);
	}
}

Проверка на блокировку работает корректно, однако здесь уже MySQL ругается и в логах выдает "Invalid row index '0'" (ну или как там):
format(query, sizeof(query), "SELECT DATE_FORMAT(`unban_date`, '%d.%m.%Y') AS `ban_date_format` FROM `ban_list` WHERE `name` = '%s'", account[playerid][name]);
mysql_query(c_handle, query, true);
cache_get_value_name(0, "ban_date_format", date[0], 10);
format(query, sizeof(query), "SELECT DATE_FORMAT(`ban_date`, '%d.%m.%Y') AS `unban_date_format` FROM `ban_list` WHERE `name` = '%s'", account[playerid][name]);
mysql_query(c_handle, query, true);
cache_get_value_name(0, "unban_date_format", date[1], 10);

В чем заключаются мои ошибки и как это исправить вообще?

Сообщение отредактировал ane4ka :3: 28 июня 2020 - 16:12

0

#2
Пользователь офлайн   DeimoS 

  • Evil Scripter
  • Вставить ник
  • Раскрыть информацию
1) В OnGameModeInit, после подключения, вставь:
mysql_query(var_connection, "SET character_set_client = 'cp1251'", false);
mysql_query(var_connection, "SET character_set_results = 'cp1251'", false);
mysql_query(var_connection, "SET SESSION character_set_server='utf8'", false);

+ удостоверься, чтоб у столбца в БД кодировка была utf8_general_ci (вообще в таблицах используй только её).

2) Ругается, как я понимаю, в момент, когда игрок не забанен? Если да, то запросы возвращают NULL и, следовательно, никакого кэша нет, а значит и cache_get_value_name не к чему обращаться.
Можно, конечно, сделать проверку на количество возвращённых строк, но можно так сделать (не уверен точно какой из перечисленных вариантов лучше по скорости):
format(query, sizeof(query), "SELECT IFNULL(DATE_FORMAT(`unban_date`, '%d.%m.%Y'), '') AS `ban_date_format` FROM `ban_list` WHERE `name` = '%s'", account[playerid][name]);
mysql_query(c_handle, query, true);
cache_get_value_name(0, "ban_date_format", date[0], 10);
format(query, sizeof(query), "SELECT IFNULL(DATE_FORMAT(`ban_date`, '%d.%m.%Y'), '') AS `unban_date_format` FROM `ban_list` WHERE `name` = '%s'", account[playerid][name]);
mysql_query(c_handle, query, true);
cache_get_value_name(0, "unban_date_format", date[1], 10);

Теперь, если у MySQL не получится сделать выборку данных по указанному условию, то в "ban_date_format" и "unban_date_format" MySQL запишет пустую строку, а не вернёт NULL.
Ну и да: если эти запросы идут друг за другом, то лучше их в один запрос объединить. Ну и если ты делаешь выборку по нику, то лучше создать индекс для столбца с ником, дабы скорость выборки меньше хромала.

И, если что, в качестве имени лэйбла можно указывать название оригинального столбца. То бишь, делать не так:

Цитата

SELECT IFNULL(DATE_FORMAT(`ban_date`, '%d.%m.%Y'), '') AS `unban_date_format` FROM `ban_list` WHERE `name` = '%s'

А так:

Цитата

SELECT IFNULL(DATE_FORMAT(`ban_date`, '%d.%m.%Y'), '') AS `ban_date` FROM `ban_list` WHERE `name` = '%s'

Сообщение отредактировал DeimoS: 28 июня 2020 - 16:28

1

#3
Пользователь офлайн   ane4ka :3 

  • Новичок
  • Вставить ник
  • Раскрыть информацию

Просмотр сообщенияDeimoS (28 июня 2020 - 16:26) писал:

Нажмите сюда, чтобы прочитать это сообщение. [Показать]


Ошибки идут, наоборот, когда игрок заблокирован, из-за чего в диалоговом окне дата не отображается. Но, все же, за ответ спасибо.
0

#4
Пользователь офлайн   DeimoS 

  • Evil Scripter
  • Вставить ник
  • Раскрыть информацию
Хмм, не должно быть такого. Это полный код? Уверена, что именно этот участок вызывает ошибки? Включи полное логирование и скинь логи. И содержимое/структуру таблицы покажи.

К слову, кэш не забывай удалять, если mysql_query используешь.

Сообщение отредактировал DeimoS: 28 июня 2020 - 16:55

1

#5
Пользователь офлайн   ane4ka :3 

  • Новичок
  • Вставить ник
  • Раскрыть информацию

Просмотр сообщенияDeimoS (28 июня 2020 - 16:54) писал:

Хмм, не должно быть такого. Это полный код? Уверена, что именно этот участок вызывает ошибки? Включи полное логирование и скинь логи. И содержимое/структуру таблицы покажи.

К слову, кэш не забывай удалять, если mysql_query используешь.


Посмотрев логи, я поняла, в чем заключается проблема. format() записывает никнейм в спецификатор %d, следовательно спецификатор %s оставался пустой, поэтому выдавало ошибки.

Сообщение отредактировал ane4ka :3: 28 июня 2020 - 17:20

1

#6
Пользователь офлайн   DeimoS 

  • Evil Scripter
  • Вставить ник
  • Раскрыть информацию

Просмотр сообщенияane4ka :3 (28 июня 2020 - 17:20) писал:

Посмотрев логи, я поняла, в чем заключается проблема. format() записывает никнейм в спецификатор %d, следовательно спецификатор %s оставался пустой, поэтому выдавало ошибки.


Да, точно. Главное, посмотрел на это и даже начал исправлять, но потом почему-то подумал, что у тебя запрос сразу в mysql_query прописан, а значит и дублировать "%" там не нужно.

На всякий случай ещё раз повторю про то, чтоб ты добавила удаление кэша для mysql_query. Ибо такими темпами ты будешь ловить утечку памяти после нескольких часов работы сервера и постоянного входа/выхода игроков.
Ну и удаление кэша обязательно нужно снабжать проверкой на то, вернул ли MySQL этот самый кэш (то бишь, проверку на число возвращённых строк ставить). Ибо иначе плагин будет предупреждения в консоль писать о том, что ты просишь удалить несуществующий кэш, когда запрос не возвращает никаких строк.
0

Поделиться темой:


Страница 1 из 1
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

1 человек читают эту тему
0 пользователей, 1 гостей, 0 скрытых пользователей


Яндекс.Метрика