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 36 extern "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. */ 45 const char *svn_sqlite__compiled_version(void); 46 47 /* Return the value of sqlite3_libversion() at run time. */ 48 const char *svn_sqlite__runtime_version(void); 49 50 51 typedef struct svn_sqlite__db_t svn_sqlite__db_t; 52 typedef struct svn_sqlite__stmt_t svn_sqlite__stmt_t; 53 typedef struct svn_sqlite__context_t svn_sqlite__context_t; 54 typedef struct svn_sqlite__value_t svn_sqlite__value_t; 55 56 typedef 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. */ 63 typedef svn_error_t *(*svn_sqlite__func_t)(svn_sqlite__context_t *sctx, 64 int argc, 65 svn_sqlite__value_t *values[], 66 void *baton); 67 68 69 /* Step the given statement; if it returns SQLITE_DONE, reset the statement. 70 Otherwise, raise an SVN error. */ 71 svn_error_t * 72 svn_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. */ 76 svn_error_t * 77 svn_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 */ 83 svn_error_t * 84 svn_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. */ 89 svn_error_t * 90 svn_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. */ 96 svn_error_t * 97 svn_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. */ 101 svn_error_t * 102 svn_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 TIMEOUT defines the SQLite busy timeout, values <= 0 cause a Subversion 121 default to be used. 122 123 The statements will be finalized and the SQLite database will be closed 124 when RESULT_POOL is cleaned up. */ 125 svn_error_t * 126 svn_sqlite__open(svn_sqlite__db_t **db, const char *path, 127 svn_sqlite__mode_t mode, const char * const statements[], 128 int latest_schema, const char * const *upgrade_sql, 129 apr_int32_t timeout, 130 apr_pool_t *result_pool, apr_pool_t *scratch_pool); 131 132 /* Explicitly close the connection in DB. */ 133 svn_error_t * 134 svn_sqlite__close(svn_sqlite__db_t *db); 135 136 /* Add a custom function to be used with this database connection. The data 137 in BATON should live at least as long as the connection in DB. 138 139 Pass TRUE if the result of the function is constant within a statement with 140 a specific set of argument values and FALSE if not (or when in doubt). When 141 TRUE newer Sqlite versions use this knowledge for query optimizations. */ 142 svn_error_t * 143 svn_sqlite__create_scalar_function(svn_sqlite__db_t *db, 144 const char *func_name, 145 int argc, 146 svn_boolean_t deterministic, 147 svn_sqlite__func_t func, 148 void *baton); 149 150 /* Execute the (multiple) statements in the STATEMENTS[STMT_IDX] string. */ 151 svn_error_t * 152 svn_sqlite__exec_statements(svn_sqlite__db_t *db, int stmt_idx); 153 154 /* Return the statement in *STMT which has been prepared from the 155 STATEMENTS[STMT_IDX] string, where STATEMENTS is the array that was 156 passed to svn_sqlite__open(). This statement is allocated in the same 157 pool as the DB, and will be cleaned up when DB is closed. */ 158 svn_error_t * 159 svn_sqlite__get_statement(svn_sqlite__stmt_t **stmt, svn_sqlite__db_t *db, 160 int stmt_idx); 161 162 163 /* --------------------------------------------------------------------- 164 165 BINDING VALUES 166 167 */ 168 169 /* Bind values to SQL parameters in STMT, according to FMT. FMT may contain: 170 171 Spec Argument type Item type 172 ---- ----------------- --------- 173 n <none, absent> Column assignment skip 174 d int Number 175 L apr_int64_t Number 176 i apr_int64_t Number (deprecated format spec) 177 s const char * String 178 b const void * Blob data 179 apr_size_t Blob length 180 r svn_revnum_t Revision number 181 t const svn_token_map_t * Token mapping table 182 int Token value 183 184 Each character in FMT maps to one SQL parameter, and one or two function 185 parameters, in the order they appear. 186 */ 187 svn_error_t * 188 svn_sqlite__bindf(svn_sqlite__stmt_t *stmt, const char *fmt, ...); 189 190 /* Error-handling wrapper around sqlite3_bind_int. */ 191 svn_error_t * 192 svn_sqlite__bind_int(svn_sqlite__stmt_t *stmt, int slot, int val); 193 194 /* Error-handling wrapper around sqlite3_bind_int64. */ 195 svn_error_t * 196 svn_sqlite__bind_int64(svn_sqlite__stmt_t *stmt, int slot, 197 apr_int64_t val); 198 199 /* Error-handling wrapper around sqlite3_bind_text. VAL cannot contain 200 zero bytes; we always pass SQLITE_TRANSIENT. */ 201 svn_error_t * 202 svn_sqlite__bind_text(svn_sqlite__stmt_t *stmt, int slot, 203 const char *val); 204 205 /* Error-handling wrapper around sqlite3_bind_blob. */ 206 svn_error_t * 207 svn_sqlite__bind_blob(svn_sqlite__stmt_t *stmt, 208 int slot, 209 const void *val, 210 apr_size_t len); 211 212 /* Look up VALUE in MAP, and bind the resulting token word at SLOT. */ 213 svn_error_t * 214 svn_sqlite__bind_token(svn_sqlite__stmt_t *stmt, 215 int slot, 216 const svn_token_map_t *map, 217 int value); 218 219 /* Bind the value to SLOT, unless SVN_IS_VALID_REVNUM(value) is false, 220 in which case it binds NULL. */ 221 svn_error_t * 222 svn_sqlite__bind_revnum(svn_sqlite__stmt_t *stmt, int slot, 223 svn_revnum_t value); 224 225 /* Bind a set of properties to the given slot. If PROPS is NULL, then no 226 binding will occur. PROPS will be stored as a serialized skel. */ 227 svn_error_t * 228 svn_sqlite__bind_properties(svn_sqlite__stmt_t *stmt, 229 int slot, 230 const apr_hash_t *props, 231 apr_pool_t *scratch_pool); 232 233 /* Bind a set of inherited properties to the given slot. If INHERITED_PROPS 234 is NULL, then no binding will occur. INHERITED_PROPS will be stored as a 235 serialized skel. */ 236 svn_error_t * 237 svn_sqlite__bind_iprops(svn_sqlite__stmt_t *stmt, 238 int slot, 239 const apr_array_header_t *inherited_props, 240 apr_pool_t *scratch_pool); 241 242 /* Bind a checksum's value to the given slot. If CHECKSUM is NULL, then no 243 binding will occur. */ 244 svn_error_t * 245 svn_sqlite__bind_checksum(svn_sqlite__stmt_t *stmt, 246 int slot, 247 const svn_checksum_t *checksum, 248 apr_pool_t *scratch_pool); 249 250 251 /* --------------------------------------------------------------------- 252 253 FETCHING VALUES 254 255 */ 256 257 /* Wrapper around sqlite3_column_blob and sqlite3_column_bytes. The return 258 value will be NULL if the column is null. 259 260 If RESULT_POOL is not NULL, allocate the return value (if any) in it. 261 If RESULT_POOL is NULL, the return value will be valid until an 262 invocation of svn_sqlite__column_* performs a data type conversion (as 263 described in the SQLite documentation) or the statement is stepped or 264 reset or finalized. */ 265 const void * 266 svn_sqlite__column_blob(svn_sqlite__stmt_t *stmt, int column, 267 apr_size_t *len, apr_pool_t *result_pool); 268 269 /* Wrapper around sqlite3_column_text. If the column is null, then the 270 return value will be NULL. 271 272 If RESULT_POOL is not NULL, allocate the return value (if any) in it. 273 If RESULT_POOL is NULL, the return value will be valid until an 274 invocation of svn_sqlite__column_* performs a data type conversion (as 275 described in the SQLite documentation) or the statement is stepped or 276 reset or finalized. */ 277 const char * 278 svn_sqlite__column_text(svn_sqlite__stmt_t *stmt, int column, 279 apr_pool_t *result_pool); 280 281 /* Wrapper around sqlite3_column_int64. If the column is null, then the 282 return value will be SVN_INVALID_REVNUM. */ 283 svn_revnum_t 284 svn_sqlite__column_revnum(svn_sqlite__stmt_t *stmt, int column); 285 286 /* Wrapper around sqlite3_column_int64. If the column is null, then the 287 return value will be FALSE. */ 288 svn_boolean_t 289 svn_sqlite__column_boolean(svn_sqlite__stmt_t *stmt, int column); 290 291 /* Wrapper around sqlite3_column_int. If the column is null, then the 292 return value will be 0. */ 293 int 294 svn_sqlite__column_int(svn_sqlite__stmt_t *stmt, int column); 295 296 /* Wrapper around sqlite3_column_int64. If the column is null, then the 297 return value will be 0. */ 298 apr_int64_t 299 svn_sqlite__column_int64(svn_sqlite__stmt_t *stmt, int column); 300 301 /* Fetch the word at COLUMN, look it up in the MAP, and return its value. 302 MALFUNCTION is thrown if the column is null or contains an unknown word. */ 303 int 304 svn_sqlite__column_token(svn_sqlite__stmt_t *stmt, 305 int column, 306 const svn_token_map_t *map); 307 308 /* Fetch the word at COLUMN, look it up in the MAP, and return its value. 309 Returns NULL_VAL if the column is null. MALFUNCTION is thrown if the 310 column contains an unknown word. */ 311 int 312 svn_sqlite__column_token_null(svn_sqlite__stmt_t *stmt, 313 int column, 314 const svn_token_map_t *map, 315 int null_val); 316 317 /* Return the column as a hash of const char * => const svn_string_t *. 318 If the column is null, then set *PROPS to NULL. The 319 results will be allocated in RESULT_POOL, and any temporary allocations 320 will be made in SCRATCH_POOL. */ 321 svn_error_t * 322 svn_sqlite__column_properties(apr_hash_t **props, 323 svn_sqlite__stmt_t *stmt, 324 int column, 325 apr_pool_t *result_pool, 326 apr_pool_t *scratch_pool); 327 328 /* Return the column as an array of depth-first ordered array of 329 svn_prop_inherited_item_t * structures. If the column is null, then 330 set *IPROPS to NULL. The results will be allocated in RESULT_POOL, 331 and any temporary allocations will be made in SCRATCH_POOL. */ 332 svn_error_t * 333 svn_sqlite__column_iprops(apr_array_header_t **iprops, 334 svn_sqlite__stmt_t *stmt, 335 int column, 336 apr_pool_t *result_pool, 337 apr_pool_t *scratch_pool); 338 339 /* Return the column as a checksum. If the column is null, then NULL will 340 be stored into *CHECKSUM. The result will be allocated in RESULT_POOL. */ 341 svn_error_t * 342 svn_sqlite__column_checksum(const svn_checksum_t **checksum, 343 svn_sqlite__stmt_t *stmt, 344 int column, 345 apr_pool_t *result_pool); 346 347 /* Return TRUE if the result of selecting the column is null, 348 FALSE otherwise */ 349 svn_boolean_t 350 svn_sqlite__column_is_null(svn_sqlite__stmt_t *stmt, int column); 351 352 /* Return the number of bytes the column uses in a text or blob representation. 353 0 for NULL columns. */ 354 int 355 svn_sqlite__column_bytes(svn_sqlite__stmt_t *stmt, int column); 356 357 /* When Subversion is compiled in maintainer mode: enables the sqlite error 358 logging to SVN_DBG_OUTPUT. */ 359 void 360 svn_sqlite__dbg_enable_errorlog(void); 361 362 363 /* --------------------------------------------------------------------- */ 364 365 #define SVN_SQLITE__INTEGER 1 366 #define SVN_SQLITE__FLOAT 2 367 #define SVN_SQLITE__TEXT 3 368 #define SVN_SQLITE__BLOB 4 369 #define SVN_SQLITE__NULL 5 370 371 /* */ 372 int 373 svn_sqlite__value_type(svn_sqlite__value_t *val); 374 375 /* */ 376 const char * 377 svn_sqlite__value_text(svn_sqlite__value_t *val); 378 379 380 /* --------------------------------------------------------------------- */ 381 382 /* */ 383 void 384 svn_sqlite__result_null(svn_sqlite__context_t *sctx); 385 386 void 387 svn_sqlite__result_int64(svn_sqlite__context_t *sctx, apr_int64_t val); 388 389 void 390 svn_sqlite__result_error(svn_sqlite__context_t *sctx, const char *msg, int num); 391 392 393 /* --------------------------------------------------------------------- */ 394 395 396 /* Error-handling wrapper around sqlite3_finalize. */ 397 svn_error_t * 398 svn_sqlite__finalize(svn_sqlite__stmt_t *stmt); 399 400 /* Reset STMT by calling sqlite3_reset(), and also clear any bindings to it. 401 402 Note: svn_sqlite__get_statement() calls this function automatically if 403 the requested statement has been used and has not yet been reset. */ 404 svn_error_t * 405 svn_sqlite__reset(svn_sqlite__stmt_t *stmt); 406 407 408 /* Begin a transaction in DB. */ 409 svn_error_t * 410 svn_sqlite__begin_transaction(svn_sqlite__db_t *db); 411 412 /* Like svn_sqlite__begin_transaction(), but takes out a 'RESERVED' lock 413 immediately, instead of using the default deferred locking scheme. */ 414 svn_error_t * 415 svn_sqlite__begin_immediate_transaction(svn_sqlite__db_t *db); 416 417 /* Begin a savepoint in DB. */ 418 svn_error_t * 419 svn_sqlite__begin_savepoint(svn_sqlite__db_t *db); 420 421 /* Commit the current transaction in DB if ERR is SVN_NO_ERROR, otherwise 422 * roll back the transaction. Return a composition of ERR and any error 423 * that may occur during the commit or roll-back. */ 424 svn_error_t * 425 svn_sqlite__finish_transaction(svn_sqlite__db_t *db, 426 svn_error_t *err); 427 428 /* Release the current savepoint in DB if EXPR is SVN_NO_ERROR, otherwise 429 * roll back to the savepoint and then release it. Return a composition of 430 * ERR and any error that may occur during the release or roll-back. */ 431 svn_error_t * 432 svn_sqlite__finish_savepoint(svn_sqlite__db_t *db, 433 svn_error_t *err); 434 435 /* Evaluate the expression EXPR within a transaction. 436 * 437 * Begin a transaction in DB; evaluate the expression EXPR, which would 438 * typically be a function call that does some work in DB; finally commit 439 * the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back 440 * the transaction. 441 */ 442 #define SVN_SQLITE__WITH_TXN(expr, db) \ 443 do { \ 444 svn_sqlite__db_t *svn_sqlite__db = (db); \ 445 svn_error_t *svn_sqlite__err; \ 446 \ 447 SVN_ERR(svn_sqlite__begin_transaction(svn_sqlite__db)); \ 448 svn_sqlite__err = (expr); \ 449 SVN_ERR(svn_sqlite__finish_transaction(svn_sqlite__db, svn_sqlite__err)); \ 450 } while (0) 451 452 /* Callback function to for use with svn_sqlite__with_transaction(). */ 453 typedef svn_error_t *(*svn_sqlite__transaction_callback_t)( 454 void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool); 455 456 /* Helper function to handle SQLite transactions. All the work done inside 457 CB_FUNC will be wrapped in an SQLite transaction, which will be committed 458 if CB_FUNC does not return an error. If any error is returned from CB_FUNC, 459 the transaction will be rolled back. DB and CB_BATON will be passed to 460 CB_FUNC. SCRATCH_POOL will be passed to the callback (NULL is valid). */ 461 svn_error_t * 462 svn_sqlite__with_transaction(svn_sqlite__db_t *db, 463 svn_sqlite__transaction_callback_t cb_func, 464 void *cb_baton, apr_pool_t *scratch_pool); 465 466 /* Like SVN_SQLITE__WITH_TXN(), but takes out a 'RESERVED' lock 467 immediately, instead of using the default deferred locking scheme. */ 468 #define SVN_SQLITE__WITH_IMMEDIATE_TXN(expr, db) \ 469 do { \ 470 svn_sqlite__db_t *svn_sqlite__db = (db); \ 471 svn_error_t *svn_sqlite__err; \ 472 \ 473 SVN_ERR(svn_sqlite__begin_immediate_transaction(svn_sqlite__db)); \ 474 svn_sqlite__err = (expr); \ 475 SVN_ERR(svn_sqlite__finish_transaction(svn_sqlite__db, svn_sqlite__err)); \ 476 } while (0) 477 478 /* Like svn_sqlite__with_transaction(), but takes out a 'RESERVED' lock 479 immediately, instead of using the default deferred locking scheme. */ 480 svn_error_t * 481 svn_sqlite__with_immediate_transaction(svn_sqlite__db_t *db, 482 svn_sqlite__transaction_callback_t cb_func, 483 void *cb_baton, 484 apr_pool_t *scratch_pool); 485 486 /* Evaluate the expression EXPR within a 'savepoint'. Savepoints can be 487 * nested. 488 * 489 * Begin a savepoint in DB; evaluate the expression EXPR, which would 490 * typically be a function call that does some work in DB; finally release 491 * the savepoint if EXPR evaluated to SVN_NO_ERROR, otherwise roll back 492 * to the savepoint and then release it. 493 */ 494 #define SVN_SQLITE__WITH_LOCK(expr, db) \ 495 do { \ 496 svn_sqlite__db_t *svn_sqlite__db = (db); \ 497 svn_error_t *svn_sqlite__err; \ 498 \ 499 SVN_ERR(svn_sqlite__begin_savepoint(svn_sqlite__db)); \ 500 svn_sqlite__err = (expr); \ 501 SVN_ERR(svn_sqlite__finish_savepoint(svn_sqlite__db, svn_sqlite__err)); \ 502 } while (0) 503 504 /* Evaluate the expression EXPR1..EXPR4 within a 'savepoint'. Savepoints can 505 * be nested. 506 * 507 * Begin a savepoint in DB; evaluate the expression EXPR1, which would 508 * typically be a function call that does some work in DB; if no error occurred, 509 * run EXPR2; if no error occurred EXPR3; ... and finally release 510 * the savepoint if EXPR evaluated to SVN_NO_ERROR, otherwise roll back 511 * to the savepoint and then release it. 512 */ 513 #define SVN_SQLITE__WITH_LOCK4(expr1, expr2, expr3, expr4, db) \ 514 do { \ 515 svn_sqlite__db_t *svn_sqlite__db = (db); \ 516 svn_error_t *svn_sqlite__err; \ 517 \ 518 SVN_ERR(svn_sqlite__begin_savepoint(svn_sqlite__db)); \ 519 svn_sqlite__err = (expr1); \ 520 if (!svn_sqlite__err) \ 521 svn_sqlite__err = (expr2); \ 522 if (!svn_sqlite__err) \ 523 svn_sqlite__err = (expr3); \ 524 if (!svn_sqlite__err) \ 525 svn_sqlite__err = (expr4); \ 526 SVN_ERR(svn_sqlite__finish_savepoint(svn_sqlite__db, svn_sqlite__err)); \ 527 } while (0) 528 529 530 /* Helper function to handle several SQLite operations inside a shared lock. 531 This callback is similar to svn_sqlite__with_transaction(), but can be 532 nested (even with a transaction). 533 534 Using this function as a wrapper around a group of operations can give a 535 *huge* performance boost as the shared-read lock will be shared over 536 multiple statements, instead of being reobtained every time, which may 537 require disk and/or network io, depending on SQLite's locking strategy. 538 539 SCRATCH_POOL will be passed to the callback (NULL is valid). 540 541 ### Since we now require SQLite >= 3.6.18, this function has the effect of 542 always behaving like a deferred transaction. Can it be combined with 543 svn_sqlite__with_transaction()? 544 */ 545 svn_error_t * 546 svn_sqlite__with_lock(svn_sqlite__db_t *db, 547 svn_sqlite__transaction_callback_t cb_func, 548 void *cb_baton, 549 apr_pool_t *scratch_pool); 550 551 552 /* Hotcopy an SQLite database from SRC_PATH to DST_PATH. */ 553 svn_error_t * 554 svn_sqlite__hotcopy(const char *src_path, 555 const char *dst_path, 556 apr_pool_t *scratch_pool); 557 558 /* Evaluate the expression EXPR. If any error is returned, close 559 * the connection in DB. */ 560 #define SVN_SQLITE__ERR_CLOSE(expr, db) do \ 561 { \ 562 svn_error_t *svn__err = (expr); \ 563 if (svn__err) \ 564 return svn_error_compose_create(svn__err, svn_sqlite__close(db)); \ 565 } while (0) 566 567 #ifdef __cplusplus 568 } 569 #endif /* __cplusplus */ 570 571 #endif /* SVN_SQLITE_H */ 572