svn_sqlite.h revision 289166
1/* svn_sqlite.h 2 * 3 * ==================================================================== 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 * ==================================================================== 21 */ 22 23 24#ifndef SVN_SQLITE_H 25#define SVN_SQLITE_H 26 27#include <apr_pools.h> 28 29#include "svn_types.h" 30#include "svn_checksum.h" 31#include "svn_error.h" 32 33#include "private/svn_token.h" /* for svn_token_map_t */ 34 35#ifdef __cplusplus 36extern "C" { 37#endif /* __cplusplus */ 38 39 40/* Because the SQLite code can be inlined into libsvn_subre/sqlite.c, 41 we define accessors to its compile-time and run-time version 42 numbers here. */ 43 44/* Return the value that SQLITE_VERSION had at compile time. */ 45const char *svn_sqlite__compiled_version(void); 46 47/* Return the value of sqlite3_libversion() at run time. */ 48const char *svn_sqlite__runtime_version(void); 49 50 51typedef struct svn_sqlite__db_t svn_sqlite__db_t; 52typedef struct svn_sqlite__stmt_t svn_sqlite__stmt_t; 53typedef struct svn_sqlite__context_t svn_sqlite__context_t; 54typedef struct svn_sqlite__value_t svn_sqlite__value_t; 55 56typedef enum svn_sqlite__mode_e { 57 svn_sqlite__mode_readonly, /* open the database read-only */ 58 svn_sqlite__mode_readwrite, /* open the database read-write */ 59 svn_sqlite__mode_rwcreate /* open/create the database read-write */ 60} svn_sqlite__mode_t; 61 62/* The type used for callback functions. */ 63typedef svn_error_t *(*svn_sqlite__func_t)(svn_sqlite__context_t *sctx, 64 int argc, 65 svn_sqlite__value_t *values[], 66 apr_pool_t *scatch_pool); 67 68 69/* Step the given statement; if it returns SQLITE_DONE, reset the statement. 70 Otherwise, raise an SVN error. */ 71svn_error_t * 72svn_sqlite__step_done(svn_sqlite__stmt_t *stmt); 73 74/* Step the given statement; raise an SVN error (and reset the 75 statement) if it doesn't return SQLITE_ROW. */ 76svn_error_t * 77svn_sqlite__step_row(svn_sqlite__stmt_t *stmt); 78 79/* Step the given statement; raise an SVN error (and reset the 80 statement) if it doesn't return SQLITE_DONE or SQLITE_ROW. Set 81 *GOT_ROW to true iff it got SQLITE_ROW. 82*/ 83svn_error_t * 84svn_sqlite__step(svn_boolean_t *got_row, svn_sqlite__stmt_t *stmt); 85 86/* Perform an insert as given by the prepared and bound STMT, and set 87 *ROW_ID to the id of the inserted row if ROW_ID is non-NULL. 88 STMT will be reset prior to returning. */ 89svn_error_t * 90svn_sqlite__insert(apr_int64_t *row_id, svn_sqlite__stmt_t *stmt); 91 92/* Perform an update/delete and then return the number of affected rows. 93 If AFFECTED_ROWS is not NULL, then set *AFFECTED_ROWS to the 94 number of rows changed. 95 STMT will be reset prior to returning. */ 96svn_error_t * 97svn_sqlite__update(int *affected_rows, svn_sqlite__stmt_t *stmt); 98 99/* Return in *VERSION the version of the schema in DB. Use SCRATCH_POOL 100 for temporary allocations. */ 101svn_error_t * 102svn_sqlite__read_schema_version(int *version, 103 svn_sqlite__db_t *db, 104 apr_pool_t *scratch_pool); 105 106 107 108/* Open a connection in *DB to the database at PATH. Validate the schema, 109 creating/upgrading to LATEST_SCHEMA if needed using the instructions 110 in UPGRADE_SQL. The resulting DB is allocated in RESULT_POOL, and any 111 temporary allocations are made in SCRATCH_POOL. 112 113 STATEMENTS is an array of strings which may eventually be executed, the 114 last element of which should be NULL. These strings and the array itself 115 are not duplicated internally, and should have a lifetime at least as long 116 as RESULT_POOL. 117 STATEMENTS itself may be NULL, in which case it has no impact. 118 See svn_sqlite__get_statement() for how these strings are used. 119 120 The statements will be finalized and the SQLite database will be closed 121 when RESULT_POOL is cleaned up. */ 122svn_error_t * 123svn_sqlite__open(svn_sqlite__db_t **db, const char *repos_path, 124 svn_sqlite__mode_t mode, const char * const statements[], 125 int latest_schema, const char * const *upgrade_sql, 126 apr_pool_t *result_pool, apr_pool_t *scratch_pool); 127 128/* Explicitly close the connection in DB. */ 129svn_error_t * 130svn_sqlite__close(svn_sqlite__db_t *db); 131 132/* Add a custom function to be used with this database connection. The data 133 in BATON should live at least as long as the connection in DB. */ 134svn_error_t * 135svn_sqlite__create_scalar_function(svn_sqlite__db_t *db, 136 const char *func_name, 137 int argc, 138 svn_sqlite__func_t func, 139 void *baton); 140 141/* Execute the (multiple) statements in the STATEMENTS[STMT_IDX] string. */ 142svn_error_t * 143svn_sqlite__exec_statements(svn_sqlite__db_t *db, int stmt_idx); 144 145/* Return the statement in *STMT which has been prepared from the 146 STATEMENTS[STMT_IDX] string, where STATEMENTS is the array that was 147 passed to svn_sqlite__open(). This statement is allocated in the same 148 pool as the DB, and will be cleaned up when DB is closed. */ 149svn_error_t * 150svn_sqlite__get_statement(svn_sqlite__stmt_t **stmt, svn_sqlite__db_t *db, 151 int stmt_idx); 152 153 154/* --------------------------------------------------------------------- 155 156 BINDING VALUES 157 158*/ 159 160/* Bind values to SQL parameters in STMT, according to FMT. FMT may contain: 161 162 Spec Argument type Item type 163 ---- ----------------- --------- 164 n <none, absent> Column assignment skip 165 d int Number 166 L apr_int64_t Number 167 i apr_int64_t Number (deprecated format spec) 168 s const char * String 169 b const void * Blob data 170 apr_size_t Blob length 171 r svn_revnum_t Revision number 172 t const svn_token_map_t * Token mapping table 173 int Token value 174 175 Each character in FMT maps to one SQL parameter, and one or two function 176 parameters, in the order they appear. 177*/ 178svn_error_t * 179svn_sqlite__bindf(svn_sqlite__stmt_t *stmt, const char *fmt, ...); 180 181/* Error-handling wrapper around sqlite3_bind_int. */ 182svn_error_t * 183svn_sqlite__bind_int(svn_sqlite__stmt_t *stmt, int slot, int val); 184 185/* Error-handling wrapper around sqlite3_bind_int64. */ 186svn_error_t * 187svn_sqlite__bind_int64(svn_sqlite__stmt_t *stmt, int slot, 188 apr_int64_t val); 189 190/* Error-handling wrapper around sqlite3_bind_text. VAL cannot contain 191 zero bytes; we always pass SQLITE_TRANSIENT. */ 192svn_error_t * 193svn_sqlite__bind_text(svn_sqlite__stmt_t *stmt, int slot, 194 const char *val); 195 196/* Error-handling wrapper around sqlite3_bind_blob. */ 197svn_error_t * 198svn_sqlite__bind_blob(svn_sqlite__stmt_t *stmt, 199 int slot, 200 const void *val, 201 apr_size_t len); 202 203/* Look up VALUE in MAP, and bind the resulting token word at SLOT. */ 204svn_error_t * 205svn_sqlite__bind_token(svn_sqlite__stmt_t *stmt, 206 int slot, 207 const svn_token_map_t *map, 208 int value); 209 210/* Bind the value to SLOT, unless SVN_IS_VALID_REVNUM(value) is false, 211 in which case it binds NULL. */ 212svn_error_t * 213svn_sqlite__bind_revnum(svn_sqlite__stmt_t *stmt, int slot, 214 svn_revnum_t value); 215 216/* Bind a set of properties to the given slot. If PROPS is NULL, then no 217 binding will occur. PROPS will be stored as a serialized skel. */ 218svn_error_t * 219svn_sqlite__bind_properties(svn_sqlite__stmt_t *stmt, 220 int slot, 221 const apr_hash_t *props, 222 apr_pool_t *scratch_pool); 223 224/* Bind a set of inherited properties to the given slot. If INHERITED_PROPS 225 is NULL, then no binding will occur. INHERITED_PROPS will be stored as a 226 serialized skel. */ 227svn_error_t * 228svn_sqlite__bind_iprops(svn_sqlite__stmt_t *stmt, 229 int slot, 230 const apr_array_header_t *inherited_props, 231 apr_pool_t *scratch_pool); 232 233/* Bind a checksum's value to the given slot. If CHECKSUM is NULL, then no 234 binding will occur. */ 235svn_error_t * 236svn_sqlite__bind_checksum(svn_sqlite__stmt_t *stmt, 237 int slot, 238 const svn_checksum_t *checksum, 239 apr_pool_t *scratch_pool); 240 241 242/* --------------------------------------------------------------------- 243 244 FETCHING VALUES 245 246*/ 247 248/* Wrapper around sqlite3_column_blob and sqlite3_column_bytes. The return 249 value will be NULL if the column is null. 250 251 If RESULT_POOL is not NULL, allocate the return value (if any) in it. 252 If RESULT_POOL is NULL, the return value will be valid until an 253 invocation of svn_sqlite__column_* performs a data type conversion (as 254 described in the SQLite documentation) or the statement is stepped or 255 reset or finalized. */ 256const void * 257svn_sqlite__column_blob(svn_sqlite__stmt_t *stmt, int column, 258 apr_size_t *len, apr_pool_t *result_pool); 259 260/* Wrapper around sqlite3_column_text. If the column is null, then the 261 return value will be NULL. 262 263 If RESULT_POOL is not NULL, allocate the return value (if any) in it. 264 If RESULT_POOL is NULL, the return value will be valid until an 265 invocation of svn_sqlite__column_* performs a data type conversion (as 266 described in the SQLite documentation) or the statement is stepped or 267 reset or finalized. */ 268const char * 269svn_sqlite__column_text(svn_sqlite__stmt_t *stmt, int column, 270 apr_pool_t *result_pool); 271 272/* Wrapper around sqlite3_column_int64. If the column is null, then the 273 return value will be SVN_INVALID_REVNUM. */ 274svn_revnum_t 275svn_sqlite__column_revnum(svn_sqlite__stmt_t *stmt, int column); 276 277/* Wrapper around sqlite3_column_int64. If the column is null, then the 278 return value will be FALSE. */ 279svn_boolean_t 280svn_sqlite__column_boolean(svn_sqlite__stmt_t *stmt, int column); 281 282/* Wrapper around sqlite3_column_int. If the column is null, then the 283 return value will be 0. */ 284int 285svn_sqlite__column_int(svn_sqlite__stmt_t *stmt, int column); 286 287/* Wrapper around sqlite3_column_int64. If the column is null, then the 288 return value will be 0. */ 289apr_int64_t 290svn_sqlite__column_int64(svn_sqlite__stmt_t *stmt, int column); 291 292/* Fetch the word at COLUMN, look it up in the MAP, and return its value. 293 MALFUNCTION is thrown if the column is null or contains an unknown word. */ 294int 295svn_sqlite__column_token(svn_sqlite__stmt_t *stmt, 296 int column, 297 const svn_token_map_t *map); 298 299/* Fetch the word at COLUMN, look it up in the MAP, and return its value. 300 Returns NULL_VAL if the column is null. MALFUNCTION is thrown if the 301 column contains an unknown word. */ 302int 303svn_sqlite__column_token_null(svn_sqlite__stmt_t *stmt, 304 int column, 305 const svn_token_map_t *map, 306 int null_val); 307 308/* Return the column as a hash of const char * => const svn_string_t *. 309 If the column is null, then set *PROPS to NULL. The 310 results will be allocated in RESULT_POOL, and any temporary allocations 311 will be made in SCRATCH_POOL. */ 312svn_error_t * 313svn_sqlite__column_properties(apr_hash_t **props, 314 svn_sqlite__stmt_t *stmt, 315 int column, 316 apr_pool_t *result_pool, 317 apr_pool_t *scratch_pool); 318 319/* Return the column as an array of depth-first ordered array of 320 svn_prop_inherited_item_t * structures. If the column is null, then 321 set *IPROPS to NULL. The results will be allocated in RESULT_POOL, 322 and any temporary allocations will be made in SCRATCH_POOL. */ 323svn_error_t * 324svn_sqlite__column_iprops(apr_array_header_t **iprops, 325 svn_sqlite__stmt_t *stmt, 326 int column, 327 apr_pool_t *result_pool, 328 apr_pool_t *scratch_pool); 329 330/* Return the column as a checksum. If the column is null, then NULL will 331 be stored into *CHECKSUM. The result will be allocated in RESULT_POOL. */ 332svn_error_t * 333svn_sqlite__column_checksum(const svn_checksum_t **checksum, 334 svn_sqlite__stmt_t *stmt, 335 int column, 336 apr_pool_t *result_pool); 337 338/* Return TRUE if the result of selecting the column is null, 339 FALSE otherwise */ 340svn_boolean_t 341svn_sqlite__column_is_null(svn_sqlite__stmt_t *stmt, int column); 342 343/* Return the number of bytes the column uses in a text or blob representation. 344 0 for NULL columns. */ 345int 346svn_sqlite__column_bytes(svn_sqlite__stmt_t *stmt, int column); 347 348 349/* --------------------------------------------------------------------- */ 350 351#define SVN_SQLITE__INTEGER 1 352#define SVN_SQLITE__FLOAT 2 353#define SVN_SQLITE__TEXT 3 354#define SVN_SQLITE__BLOB 4 355#define SVN_SQLITE__NULL 5 356 357/* */ 358int 359svn_sqlite__value_type(svn_sqlite__value_t *val); 360 361/* */ 362const char * 363svn_sqlite__value_text(svn_sqlite__value_t *val); 364 365 366/* --------------------------------------------------------------------- */ 367 368/* */ 369void 370svn_sqlite__result_null(svn_sqlite__context_t *sctx); 371 372void 373svn_sqlite__result_int64(svn_sqlite__context_t *sctx, apr_int64_t val); 374 375 376/* --------------------------------------------------------------------- */ 377 378 379/* Error-handling wrapper around sqlite3_finalize. */ 380svn_error_t * 381svn_sqlite__finalize(svn_sqlite__stmt_t *stmt); 382 383/* Reset STMT by calling sqlite3_reset(), and also clear any bindings to it. 384 385 Note: svn_sqlite__get_statement() calls this function automatically if 386 the requested statement has been used and has not yet been reset. */ 387svn_error_t * 388svn_sqlite__reset(svn_sqlite__stmt_t *stmt); 389 390 391/* Begin a transaction in DB. */ 392svn_error_t * 393svn_sqlite__begin_transaction(svn_sqlite__db_t *db); 394 395/* Like svn_sqlite__begin_transaction(), but takes out a 'RESERVED' lock 396 immediately, instead of using the default deferred locking scheme. */ 397svn_error_t * 398svn_sqlite__begin_immediate_transaction(svn_sqlite__db_t *db); 399 400/* Begin a savepoint in DB. */ 401svn_error_t * 402svn_sqlite__begin_savepoint(svn_sqlite__db_t *db); 403 404/* Commit the current transaction in DB if ERR is SVN_NO_ERROR, otherwise 405 * roll back the transaction. Return a composition of ERR and any error 406 * that may occur during the commit or roll-back. */ 407svn_error_t * 408svn_sqlite__finish_transaction(svn_sqlite__db_t *db, 409 svn_error_t *err); 410 411/* Release the current savepoint in DB if EXPR is SVN_NO_ERROR, otherwise 412 * roll back to the savepoint and then release it. Return a composition of 413 * ERR and any error that may occur during the release or roll-back. */ 414svn_error_t * 415svn_sqlite__finish_savepoint(svn_sqlite__db_t *db, 416 svn_error_t *err); 417 418/* Evaluate the expression EXPR within a transaction. 419 * 420 * Begin a transaction in DB; evaluate the expression EXPR, which would 421 * typically be a function call that does some work in DB; finally commit 422 * the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back 423 * the transaction. 424 */ 425#define SVN_SQLITE__WITH_TXN(expr, db) \ 426 do { \ 427 svn_sqlite__db_t *svn_sqlite__db = (db); \ 428 svn_error_t *svn_sqlite__err; \ 429 \ 430 SVN_ERR(svn_sqlite__begin_transaction(svn_sqlite__db)); \ 431 svn_sqlite__err = (expr); \ 432 SVN_ERR(svn_sqlite__finish_transaction(svn_sqlite__db, svn_sqlite__err)); \ 433 } while (0) 434 435/* Callback function to for use with svn_sqlite__with_transaction(). */ 436typedef svn_error_t *(*svn_sqlite__transaction_callback_t)( 437 void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool); 438 439/* Helper function to handle SQLite transactions. All the work done inside 440 CB_FUNC will be wrapped in an SQLite transaction, which will be committed 441 if CB_FUNC does not return an error. If any error is returned from CB_FUNC, 442 the transaction will be rolled back. DB and CB_BATON will be passed to 443 CB_FUNC. SCRATCH_POOL will be passed to the callback (NULL is valid). */ 444svn_error_t * 445svn_sqlite__with_transaction(svn_sqlite__db_t *db, 446 svn_sqlite__transaction_callback_t cb_func, 447 void *cb_baton, apr_pool_t *scratch_pool); 448 449/* Like SVN_SQLITE__WITH_TXN(), but takes out a 'RESERVED' lock 450 immediately, instead of using the default deferred locking scheme. */ 451#define SVN_SQLITE__WITH_IMMEDIATE_TXN(expr, db) \ 452 do { \ 453 svn_sqlite__db_t *svn_sqlite__db = (db); \ 454 svn_error_t *svn_sqlite__err; \ 455 \ 456 SVN_ERR(svn_sqlite__begin_immediate_transaction(svn_sqlite__db)); \ 457 svn_sqlite__err = (expr); \ 458 SVN_ERR(svn_sqlite__finish_transaction(svn_sqlite__db, svn_sqlite__err)); \ 459 } while (0) 460 461/* Like svn_sqlite__with_transaction(), but takes out a 'RESERVED' lock 462 immediately, instead of using the default deferred locking scheme. */ 463svn_error_t * 464svn_sqlite__with_immediate_transaction(svn_sqlite__db_t *db, 465 svn_sqlite__transaction_callback_t cb_func, 466 void *cb_baton, 467 apr_pool_t *scratch_pool); 468 469/* Evaluate the expression EXPR within a 'savepoint'. Savepoints can be 470 * nested. 471 * 472 * Begin a savepoint in DB; evaluate the expression EXPR, which would 473 * typically be a function call that does some work in DB; finally release 474 * the savepoint if EXPR evaluated to SVN_NO_ERROR, otherwise roll back 475 * to the savepoint and then release it. 476 */ 477#define SVN_SQLITE__WITH_LOCK(expr, db) \ 478 do { \ 479 svn_sqlite__db_t *svn_sqlite__db = (db); \ 480 svn_error_t *svn_sqlite__err; \ 481 \ 482 SVN_ERR(svn_sqlite__begin_savepoint(svn_sqlite__db)); \ 483 svn_sqlite__err = (expr); \ 484 SVN_ERR(svn_sqlite__finish_savepoint(svn_sqlite__db, svn_sqlite__err)); \ 485 } while (0) 486 487/* Evaluate the expression EXPR1..EXPR4 within a 'savepoint'. Savepoints can 488 * be nested. 489 * 490 * Begin a savepoint in DB; evaluate the expression EXPR1, which would 491 * typically be a function call that does some work in DB; if no error occurred, 492 * run EXPR2; if no error occurred EXPR3; ... and finally release 493 * the savepoint if EXPR evaluated to SVN_NO_ERROR, otherwise roll back 494 * to the savepoint and then release it. 495 */ 496#define SVN_SQLITE__WITH_LOCK4(expr1, expr2, expr3, expr4, db) \ 497 do { \ 498 svn_sqlite__db_t *svn_sqlite__db = (db); \ 499 svn_error_t *svn_sqlite__err; \ 500 \ 501 SVN_ERR(svn_sqlite__begin_savepoint(svn_sqlite__db)); \ 502 svn_sqlite__err = (expr1); \ 503 if (!svn_sqlite__err) \ 504 svn_sqlite__err = (expr2); \ 505 if (!svn_sqlite__err) \ 506 svn_sqlite__err = (expr3); \ 507 if (!svn_sqlite__err) \ 508 svn_sqlite__err = (expr4); \ 509 SVN_ERR(svn_sqlite__finish_savepoint(svn_sqlite__db, svn_sqlite__err)); \ 510 } while (0) 511 512 513/* Helper function to handle several SQLite operations inside a shared lock. 514 This callback is similar to svn_sqlite__with_transaction(), but can be 515 nested (even with a transaction). 516 517 Using this function as a wrapper around a group of operations can give a 518 *huge* performance boost as the shared-read lock will be shared over 519 multiple statements, instead of being reobtained every time, which may 520 require disk and/or network io, depending on SQLite's locking strategy. 521 522 SCRATCH_POOL will be passed to the callback (NULL is valid). 523 524 ### Since we now require SQLite >= 3.6.18, this function has the effect of 525 always behaving like a defered transaction. Can it be combined with 526 svn_sqlite__with_transaction()? 527 */ 528svn_error_t * 529svn_sqlite__with_lock(svn_sqlite__db_t *db, 530 svn_sqlite__transaction_callback_t cb_func, 531 void *cb_baton, 532 apr_pool_t *scratch_pool); 533 534 535/* Hotcopy an SQLite database from SRC_PATH to DST_PATH. */ 536svn_error_t * 537svn_sqlite__hotcopy(const char *src_path, 538 const char *dst_path, 539 apr_pool_t *scratch_pool); 540 541#ifdef __cplusplus 542} 543#endif /* __cplusplus */ 544 545#endif /* SVN_SQLITE_H */ 546