Как переписать SQL-запрос DELETE на UPDATE с добавлением текста в начало
При работе с декомпилированными Android-приложениями часто возникает задача изменить логику удаления сообщений на их модификацию. Вместо выполнения DELETE требуется выполнить UPDATE, добавив в начало поля text символ, например, цифру 1. Рассмотрим корректный синтаксис для SQLite, который используется в Android.
Проблема исходных запросов
Исходные запросы удаляют строки из таблицы messages по условиям:
DELETE FROM messages WHERE chat_id = ? AND delayed_attrs_time_to_fire >= ? AND delayed_attrs_time_to_fire <= ? AND id NOT IN (...)DELETE FROM messages WHERE chat_id = ? AND time >= ? AND time <= ? AND id NOT IN (...)DELETE FROM messages WHERE chat_id = ? AND id in (...)
Задача - заменить удаление на обновление, добавив в начало содержимого поля text цифру 1.
Правильный синтаксис UPDATE с конкатенацией
В SQLite для добавления текста в начало строки используется оператор || (конкатенация) или функция CONCAT. Однако функция CONCAT доступна только в SQLite версии 3.44.0 и выше. Для совместимости с Android (SQLite 3.19-3.28) лучше использовать оператор ||.
Правильный запрос:
UPDATE messages SET text = '1' || COALESCE(text, '') WHERE chat_id = ? AND time >= ? AND time <= ? AND id NOT IN (...)Почему ваши варианты не работали
Вы перечислили несколько попыток. Разберём ошибки:
1. Использование CONCAT
UPDATE messages SET text=CONCAT('1', COALESCE(text,'')) WHERE ... - синтаксически верно, но CONCAT может отсутствовать в старой версии SQLite. В Android 7+ используется SQLite 3.19, где CONCAT не поддерживается. Запрос завершится ошибкой.
2. Ошибка в названии функции CONALESCE
CONALESCE - это несуществующая функция. В SQLite нет такой функции, поэтому запрос не выполнится.
3. Неправильные имена столбцов
В исходном запросе столбец называется chat_id, а вы написали chatid (без подчёркивания). Это приводит к ошибке «no such column».
4. Использование ifnull вместо COALESCE
UPDATE messages SET text='1 ' || ifnull(text, '') WHERE ... - синтаксис верный, но ifnull принимает только два аргумента. В вашем примере он использован корректно, однако если поле text содержит NULL, то ifnull заменит его на пустую строку. Проблема может быть в версии SQLite или в том, что вы не экранировали кавычки.
Итоговые корректные запросы
Вот три переписанных запроса для ваших исходных условий:
- Первый запрос (delayed_attrs_time_to_fire):
UPDATE messages SET text = '1' || COALESCE(text, '') WHERE chat_id = ? AND delayed_attrs_time_to_fire >= ? AND delayed_attrs_time_to_fire <= ? AND id NOT IN (...) - Второй запрос (time):
UPDATE messages SET text = '1' || COALESCE(text, '') WHERE chat_id = ? AND time >= ? AND time <= ? AND id NOT IN (...) - Третий запрос (id in):
UPDATE messages SET text = '1' || COALESCE(text, '') WHERE chat_id = ? AND id IN (...)
Обратите внимание: если вы хотите добавить пробел после единицы, используйте '1 ' ||. Если без пробела - '1' ||.
Дополнительные рекомендации
При внедрении изменений в декомпилированное приложение:
- Убедитесь, что в
smali-коде правильно экранированы кавычки (используйте\"внутри строки). - Проверьте версию SQLite на устройстве. Для Android 10+ (SQLite 3.28)
CONCATможет работать, но||гарантированно поддерживается. - Если нужно добавить символ не в начало, а в конец - используйте
SET text = text || '1'.
Теперь вы можете уверенно заменить DELETE на UPDATE и добавить нужный префикс к тексту сообщения.