Генерация набора изменений из объекта сессии
Получить набор изменений, содержащих изменения в таблицах, присоединённых к объекту сессии, переданному в качестве первого аргумента. При успехе установить *ppChangeset, чтобы он указывал на буфер, содержащий набор изменений, и *pnChangeset, чтобы он содержал размер набора изменений в байтах, прежде чем вернуть SQLITE_OK. В случае ошибки установить *ppChangeset и *pnChangeset в ноль и вернуть код ошибки SQLite.
Набор изменений состоит из нуля или более изменений INSERT, UPDATE и/или DELETE, каждое из которых представляет изменение одной строки присоединённой таблицы. Изменение INSERT содержит значения каждого поля новой строки базы данных. Изменение DELETE содержит исходные значения каждого поля удалённой строки базы данных. Изменение UPDATE содержит исходные значения каждого поля обновлённой строки базы данных вместе с обновлёнными значениями каждого обновлённого столбца, не являющегося первичным ключом. Невозможно, чтобы изменение UPDATE представляло изменение, изменяющее значения столбцов первичного ключа. Если такое изменение выполняется, в наборе изменений оно представлено как DELETE, за которым следует INSERT.
Изменения не записываются для строк, в которых в одном или нескольких столбцах первичного ключа хранятся значения NULL. Если такая строка вставляется или удаляется, соответствующего изменения нет в наборах изменений, возвращаемых этой функцией. Если существующая строка с одним или несколькими значениями NULL, хранящимися в столбцах первичного ключа, обновляется таким образом, что все столбцы первичного ключа не равны NULL, в наборе изменений появляется только INSERT. Аналогично, если существующая строка со значениями первичного ключа, отличными от NULL, обновляется таким образом, что один или несколько столбцов первичного ключа устанавливаются в NULL, результирующий набор изменений содержит только изменение DELETE.
Содержимое набора изменений можно просматривать с помощью итератора, созданного с помощью API sqlite3changeset_start(). Набор изменений можно применить к базе данных с совместимой схемой с помощью API sqlite3changeset_apply().
В наборе изменений, сгенерированном этой функцией, все изменения, относящиеся к одной таблице, сгруппированы вместе. Другими словами, при итерации по набору изменений или при применении набора изменений к базе данных все изменения, относящиеся к одной таблице, обрабатываются перед переходом к следующей таблице. Таблицы сортируются в том же порядке, в котором они были присоединены (или автоматически присоединены) к объекту sqlite3_session. Порядок хранения изменений, относящихся к одной таблице, не определён.
После успешного вызова этой функции, ответственность за освобождение буфера, на который указывает *ppChangeset, лежит на вызывающей стороне. Для этого используется sqlite3_free().
Генерация набора изменений
После того как таблица была подключена к объекту сессии, объект сессии записывает значения первичного ключа всех новых строк, вставленных в таблицу. Он также записывает исходные значения первичного ключа и других столбцов для удалённых или обновлённых строк. Для каждого уникального значения первичного ключа данные записываются только один раз — в первый раз, когда строка с данным первичным ключом вставляется, обновляется или удаляется за время существования сессии.
Есть одно исключение к предыдущему абзацу: когда строка вставляется, обновляется или удаляется, если один или несколько столбцов первичного ключа содержат значение NULL, запись об изменении не делается.
Таким образом, объект сессии накапливает два типа записей — те, которые состоят только из значений первичного ключа (созданные, когда пользователь вставляет новую запись), и те, которые состоят из значений первичного ключа и исходных значений других столбцов таблицы (созданные, когда пользователь удаляет или обновляет запись).
При вызове этой функции запрашиваемый набор изменений создаётся с использованием как накопленных записей, так и текущего содержимого файла базы данных. В частности:
- Для каждой записи, сгенерированной операцией insert, база данных проверяет, существует ли строка с совпадающим первичным ключом. Если она найдена, в набор изменений добавляется изменение INSERT. Если такая строка не найдена, изменение в набор изменений не добавляется.
- Для каждой записи, сгенерированной операциями update или delete, база данных проверяет, существует ли строка с совпадающим первичным ключом. Если такая строка найдена и одно или несколько полей, не являющихся первичным ключом, были изменены со своих исходных значений, в набор изменений добавляется изменение UPDATE. Или, если такая строка не найдена в таблице, в набор изменений добавляется изменение DELETE. Если в базе данных есть строка с совпадающим первичным ключом, но все поля содержат свои исходные значения, изменение в набор изменений не добавляется.
Это означает, среди прочего, что если строка вставляется, а затем позже удаляется во время работы объекта сессии, ни вставка, ни удаление не будут присутствовать в наборе изменений. Или, если строка удаляется, а затем позже вставляется строка с теми же значениями первичного ключа, пока объект сессии активен, результирующий набор изменений будет содержать изменение UPDATE вместо DELETE и INSERT.
Когда объект сессии отключён (см. API sqlite3session_enable()), он не накапливает записи при вставке, обновлении или удалении строк. Это может иметь некоторые неинтуитивные последствия, если одна строка записывается более одного раза во время сессии. Например, если строка вставляется, когда объект сессии включён, а затем позже удаляется, когда тот же объект сессии отключён, в наборе изменений не будет записи INSERT, даже если удаление произошло во время отключения сессии. Или, если одно поле строки обновляется, когда сессия отключена, а другое поле той же строки обновляется, когда сессия включена, результирующий набор изменений будет содержать изменение UPDATE, которое обновляет оба поля.
См. также списки Объектов, Констант и Функций.
SQLite is in the Public Domain.
https://sqlite.org/session/sqlite3session_changeset.html