Skip to content

Instantly share code, notes, and snippets.

@domob1812
Created January 6, 2019 13:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save domob1812/7842edade949b5169edaf9de79f1b6d1 to your computer and use it in GitHub Desktop.
Save domob1812/7842edade949b5169edaf9de79f1b6d1 to your computer and use it in GitHub Desktop.
SQLite session fails with "WITHOUT ROWID" and "INSERT OR REPLACE"
#include <sqlite3.h>
#include <glog/logging.h>
#include <cstdlib>
#include <iostream>
int
printResults (void*, int numColumns, char** values, char** columns)
{
for (int i = 0; i < numColumns; ++i)
std::cout << " " << columns[i] << " = " << values[i];
std::cout << std::endl;
return 0;
}
int
abortOnConflict (void* ctx, int conflict, sqlite3_changeset_iter* it)
{
LOG (ERROR) << "Changeset application has a conflict of type " << conflict;
return SQLITE_CHANGESET_ABORT;
}
int
main (int argc, char** argv)
{
LOG (INFO)
<< "Using SQLite version " << SQLITE_VERSION
<< " (library version: " << sqlite3_libversion () << ")";
CHECK_EQ (SQLITE_VERSION_NUMBER, sqlite3_libversion_number ())
<< "Mismatch between header and library SQLite versions";
sqlite3* db;
CHECK_EQ (sqlite3_open (":memory:", &db), SQLITE_OK);
/* Create schema (table WITHOUT ROWID) and insert some initial data. */
CHECK_EQ (sqlite3_exec (db, R"(
CREATE TABLE `test` (
`id` INTEGER PRIMARY KEY,
`value` INTEGER
)
WITHOUT ROWID
;
INSERT INTO `test` (`id`, `value`) VALUES (100, 1);
)", nullptr, nullptr, nullptr), SQLITE_OK);
/* Make a modification and record a changeset for it. */
sqlite3_session* session;
CHECK_EQ (sqlite3session_create (db, "main", &session), SQLITE_OK);
CHECK_EQ (sqlite3session_attach (session, nullptr), SQLITE_OK);
CHECK_EQ (sqlite3_exec (db, R"(
-- UPDATE `test` SET `value` = 2 WHERE `id` = 100;
-- INSERT INTO `test` (`id`, `value`) VALUES (200, 3);
INSERT OR REPLACE INTO `test`
(`id`, `value`) VALUES (100, 2), (200, 3)
)", nullptr, nullptr, nullptr), SQLITE_OK);
int changeSize;
void* changeBytes;
CHECK_EQ (sqlite3session_changeset (session, &changeSize, &changeBytes),
SQLITE_OK);
sqlite3session_delete (session);
/* Apply the inverted changeset to revert the change. */
int invertedSize;
void* invertedBytes;
CHECK_EQ (sqlite3changeset_invert (changeSize, changeBytes,
&invertedSize, &invertedBytes),
SQLITE_OK);
CHECK_EQ (sqlite3changeset_apply (db, invertedSize, invertedBytes, nullptr,
&abortOnConflict, nullptr),
SQLITE_OK);
sqlite3_free (changeBytes);
sqlite3_free (invertedBytes);
/* Print contents of table for debugging. */
std::cout << "Final values of table:" << std::endl;
CHECK_EQ (sqlite3_exec (db, R"(
SELECT * FROM `test`
)", &printResults, nullptr, nullptr), SQLITE_OK);
sqlite3_close (db);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment