1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
/*
* Copyright (C) 2013- The University of Notre Dame
* This software is distributed under the GNU General Public License.
* See the file COPYING for details.
*/
#ifndef CHIRP_SQLITE_H
#define CHIRP_SQLITE_H
#include "buffer.h"
#include "catch.h"
#include "debug.h"
#include "sqlite3.h"
#define CHIRP_SQLITE_TIMEOUT (5000)
#define sqlcatchexec(db,sql) \
do {\
sqlite3 *_db = (db);\
char *errmsg;\
rc = sqlite3_exec(_db, (sql), NULL, NULL, &errmsg);\
if (rc) {\
if (rc == SQLITE_BUSY) {\
rc = EAGAIN;\
} else {\
debug(D_DEBUG, "[%s:%d] sqlite3 error: %d `%s': %s", __FILE__, __LINE__, rc, sqlite3_errstr(rc), errmsg);\
if (rc == SQLITE_CONSTRAINT) {\
rc = EINVAL;\
} else {\
rc = EIO;\
}\
}\
sqlite3_free(errmsg);\
goto out;\
}\
} while (0)
#define sqlcatch(S) \
do {\
rc = S;\
if (rc) {\
if (rc == SQLITE_BUSY) {\
rc = EAGAIN;\
} else {\
debug(D_DEBUG, "[%s:%d] sqlite3 error: %d `%s': %s", __FILE__, __LINE__, rc, sqlite3_errstr(rc), sqlite3_errmsg(db));\
if (rc == SQLITE_CONSTRAINT) {\
rc = EINVAL;\
} else {\
rc = EIO;\
}\
}\
sqlite3_finalize(stmt);\
stmt = NULL;\
goto out;\
}\
} while (0)
#define sqlcatchcode(S, code) \
do {\
rc = S;\
if (rc != code) {\
if (rc == SQLITE_BUSY) {\
rc = EAGAIN;\
} else {\
debug(D_DEBUG, "[%s:%d] sqlite3 error: %d `%s': %s", __FILE__, __LINE__, rc, sqlite3_errstr(rc), sqlite3_errmsg(db));\
if (rc == SQLITE_CONSTRAINT) {\
rc = EINVAL;\
} else {\
rc = EIO;\
}\
}\
sqlite3_finalize(stmt);\
stmt = NULL;\
goto out;\
}\
} while (0)
/* This macro is part of the prologue for any procedure that begins/ends a
* transaction. We cannot simply put the ROLLBACK conflict resolution
* constraint in relevant SQL write operations. The reason for this is because
* not all errors are in SQLite. For example, the code may do a waitpid which
* fails, which requires the entire operation to fail. This macro does a
* rollback of the entire transaction on error, so it handles that case.
*/
#define sqlend(db) \
do {\
sqlite3 *_db = (db);\
if (_db && rc) {\
char *errmsg;\
int erc = sqlite3_exec(_db, "ROLLBACK TRANSACTION;", NULL, NULL, &errmsg);\
if (erc) {\
if (erc == SQLITE_ERROR /* cannot rollback because no transaction is active */) {\
; /* do nothing */\
} else {\
debug(D_DEBUG, "[%s:%d] sqlite3 error: %d `%s': %s", __FILE__, __LINE__, erc, sqlite3_errstr(erc), errmsg);\
}\
sqlite3_free(errmsg);\
}\
}\
} while (0)
#define sqlendsavepoint(savepoint) \
do {\
if (rc) {\
char *errmsg;\
int erc = sqlite3_exec(db, "ROLLBACK TRANSACTION TO SAVEPOINT " #savepoint "; RELEASE SAVEPOINT " #savepoint ";", NULL, NULL, &errmsg);\
if (erc) {\
if (erc == SQLITE_ERROR /* cannot rollback because no transaction is active */) {\
; /* do nothing */\
} else {\
debug(D_DEBUG, "[%s:%d] sqlite3 error: %d `%s': %s", __FILE__, __LINE__, erc, sqlite3_errstr(erc), errmsg);\
}\
sqlite3_free(errmsg);\
}\
}\
} while (0)
#define IMMUTABLE(T) \
"CREATE TRIGGER " T "ImmutableI BEFORE INSERT ON " T " FOR EACH ROW" \
" BEGIN" \
" SELECT RAISE(ABORT, 'cannot insert rows of immutable table');" \
" END;" \
"CREATE TRIGGER " T "ImmutableU BEFORE UPDATE ON " T " FOR EACH ROW" \
" BEGIN" \
" SELECT RAISE(ABORT, 'cannot update rows of immutable table');" \
" END;" \
"CREATE TRIGGER " T "ImmutableD BEFORE DELETE ON " T " FOR EACH ROW" \
" BEGIN" \
" SELECT RAISE(ABORT, 'cannot delete rows of immutable table');" \
" END;"
#endif
int chirp_sqlite3_column_jsonify(sqlite3_stmt *stmt, int n, buffer_t *B);
int chirp_sqlite3_row_jsonify(sqlite3_stmt *stmt, buffer_t *B);
/* vim: set noexpandtab tabstop=4: */
|