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