test.c
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char ** argv)
{
const char * database_file = "/tmp/memusage_test_db";
// Clear old database file is there is one.
unlink(database_file);
sqlite3 * db = NULL;
if (sqlite3_open(database_file, &db) != SQLITE_OK)
return 1;
// Set busy timeout just in case...
if (sqlite3_busy_timeout(db, 10000) != SQLITE_OK) {
sqlite3_close(db);
return 1;
}
// Set pragmas.
if (sqlite3_exec(db,
" PRAGMA page_size = 4096;"
" PRAGMA temp_store = MEMORY;"
" PRAGMA journal_mode = MEMORY;"
" PRAGMA cache_size = 10000;"
" PRAGMA foreign_keys = ON;"
" PRAGMA synchronous = OFF;",
NULL, NULL, NULL) != SQLITE_OK) {
sqlite3_close(db);
return 1;
}
// Create database structure.
if (sqlite3_exec(db,
"CREATE TABLE foo ("
" id INTEGER,"
" x INTEGER,"
" PRIMARY KEY(id)"
");"
""
"CREATE TABLE bar ("
" id INTEGER,"
" y INTEGER,"
" PRIMARY KEY(id, y),"
" FOREIGN KEY(id) REFERENCES foo(id) ON DELETE CASCADE"
");",
NULL, NULL, NULL) != SQLITE_OK) {
sqlite3_close(db);
return 1;
}
// Populate database with data.
{
// Open transaction.
if (sqlite3_exec(db, "BEGIN IMMEDIATE;", NULL, NULL, NULL) !=
SQLITE_OK) {
sqlite3_close(db);
return 1;
}
char buffer[256];
for (int i = 0; i < 100000; ++i) {
snprintf(buffer, sizeof(buffer), "INSERT INTO foo(id, x) VALUES(%u,
%u)", i + 1, 2 * i + 1);
if (sqlite3_exec(db, buffer, NULL, NULL, NULL) != SQLITE_OK) {
sqlite3_close(db);
return 1;
}
#ifndef NO_CHILD_RECORDS
snprintf(buffer, sizeof(buffer), "INSERT INTO bar(id, y) VALUES(%u,
%u)", i + 1, 2 * i + 1);
if (sqlite3_exec(db, buffer, NULL, NULL, NULL) != SQLITE_OK) {
sqlite3_close(db);
return 1;
}
snprintf(buffer, sizeof(buffer), "INSERT INTO bar(id, y) VALUES(%u,
%u)", i + 1, 2 * i + 3);
if (sqlite3_exec(db, buffer, NULL, NULL, NULL) != SQLITE_OK) {
sqlite3_close(db);
return 1;
}
#endif
}
// Commit transaction.
if (sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL) != SQLITE_OK) {
sqlite3_close(db);
return 1;
}
}
// Create an outer transaction.
// Note: replacing transaction with another savepoint yields same
behaviour.
#ifndef NO_NESTED_TRANSACTION
// Open transaction.
if (sqlite3_exec(db, "BEGIN IMMEDIATE;", NULL, NULL, NULL) != SQLITE_OK) {
sqlite3_close(db);
return 1;
}
#endif
if (sqlite3_exec(db, "SAVEPOINT XXX;", NULL, NULL, NULL) != SQLITE_OK) {
sqlite3_close(db);
return 1;
}
// Now, inside a nested transaction we remove 'parent' table, so that
// rows from 'child' table will be removed automatically to satisfy FK
constraint.
sqlite3_stmt * statement = NULL;
const char * delete_query = "DELETE FROM foo WHERE id = ?001;";
if (sqlite3_prepare_v2(db, delete_query, strlen(delete_query) + 1,
&statement, NULL) != SQLITE_OK) {
sqlite3_close(db);
return 1;
}
for (int i = 0; i < 100000; ++i) {
// Bind id value.
if (sqlite3_bind_int(statement, 1, i) != SQLITE_OK) {
sqlite3_finalize(statement);
sqlite3_close(db);
return 1;
}
// Status must be SQLITE_DONE if everything is cool.
if (sqlite3_step(statement) != SQLITE_DONE) {
sqlite3_finalize(statement);
sqlite3_close(db);
return 1;
}
// Reset statement.
sqlite3_reset(statement);
sqlite3_clear_bindings(statement);
}
sqlite3_finalize(statement);
// Rollback savepoint (no need to commit anything).
if (sqlite3_exec(db, "ROLLBACK TO SAVEPOINT XXX;", NULL, NULL, NULL) !=
SQLITE_OK) {
sqlite3_close(db);
return 1;
}
#ifndef NO_NESTED_TRANSACTION
// Rollback transaction.
if (sqlite3_exec(db, "ROLLBACK;", NULL, NULL, NULL) != SQLITE_OK) {
sqlite3_close(db);
return 1;
}
#endif
sqlite3_close(db);
// Dump memory usage statistics.
int current_mem = 0;
int hi_mem = 0;
sqlite3_status(SQLITE_STATUS_MEMORY_USED, ¤t_mem, &hi_mem, 0);
printf("Current mem: %u\nHi mem: %u\n", current_mem, hi_mem);
// Do not leave database file behind.
unlink(database_file);
return 0;
}
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users