Created
January 6, 2019 13:11
-
-
Save domob1812/7842edade949b5169edaf9de79f1b6d1 to your computer and use it in GitHub Desktop.
SQLite session fails with "WITHOUT ROWID" and "INSERT OR REPLACE"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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