xref: /trueos/contrib/subversion/subversion/libsvn_subr/sqlite.c (revision 7cfbe47f2542407346168136f8e33b5015eda94f)
1 /* sqlite.c
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 #include <apr_pools.h>
24 
25 #include "svn_types.h"
26 #include "svn_error.h"
27 #include "svn_pools.h"
28 #include "svn_io.h"
29 #include "svn_dirent_uri.h"
30 #include "svn_checksum.h"
31 
32 #include "internal_statements.h"
33 
34 #include "private/svn_sqlite.h"
35 #include "svn_private_config.h"
36 #include "private/svn_dep_compat.h"
37 #include "private/svn_atomic.h"
38 #include "private/svn_skel.h"
39 #include "private/svn_token.h"
40 
41 #ifdef SQLITE3_DEBUG
42 #include "private/svn_debug.h"
43 #endif
44 
45 #ifdef SVN_SQLITE_INLINE
46 /* Import the sqlite3 API vtable from sqlite3wrapper.c */
47 #  define SQLITE_OMIT_DEPRECATED
48 #  include <sqlite3ext.h>
49 extern const sqlite3_api_routines *const svn_sqlite3__api_funcs;
50 extern int (*const svn_sqlite3__api_initialize)(void);
51 extern int (*const svn_sqlite3__api_config)(int, ...);
52 #  define sqlite3_api svn_sqlite3__api_funcs
53 #  define sqlite3_initialize svn_sqlite3__api_initialize
54 #  define sqlite3_config svn_sqlite3__api_config
55 #else
56 #  include <sqlite3.h>
57 #endif
58 
59 #if !SQLITE_VERSION_AT_LEAST(3,7,12)
60 #error SQLite is too old -- version 3.7.12 is the minimum required version
61 #endif
62 
63 const char *
svn_sqlite__compiled_version(void)64 svn_sqlite__compiled_version(void)
65 {
66   static const char sqlite_version[] = SQLITE_VERSION;
67   return sqlite_version;
68 }
69 
70 const char *
svn_sqlite__runtime_version(void)71 svn_sqlite__runtime_version(void)
72 {
73   return sqlite3_libversion();
74 }
75 
76 
77 INTERNAL_STATEMENTS_SQL_DECLARE_STATEMENTS(internal_statements);
78 
79 
80 #ifdef SQLITE3_DEBUG
81 /* An sqlite query execution callback. */
82 static void
sqlite_tracer(void * data,const char * sql)83 sqlite_tracer(void *data, const char *sql)
84 {
85   /*  sqlite3 *db3 = data; */
86   SVN_DBG(("sql=\"%s\"\n", sql));
87 }
88 #endif
89 
90 #ifdef SQLITE3_PROFILE
91 /* An sqlite execution timing callback. */
92 static void
sqlite_profiler(void * data,const char * sql,sqlite3_uint64 duration)93 sqlite_profiler(void *data, const char *sql, sqlite3_uint64 duration)
94 {
95   /*  sqlite3 *db3 = data; */
96   SVN_DBG(("[%.3f] sql=\"%s\"\n", 1e-9 * duration, sql));
97 }
98 #endif
99 
100 struct svn_sqlite__db_t
101 {
102   sqlite3 *db3;
103   const char * const *statement_strings;
104   int nbr_statements;
105   svn_sqlite__stmt_t **prepared_stmts;
106   apr_pool_t *state_pool;
107 };
108 
109 struct svn_sqlite__stmt_t
110 {
111   sqlite3_stmt *s3stmt;
112   svn_sqlite__db_t *db;
113   svn_boolean_t needs_reset;
114 };
115 
116 struct svn_sqlite__context_t
117 {
118   sqlite3_context *context;
119 };
120 
121 struct svn_sqlite__value_t
122 {
123   sqlite3_value *value;
124 };
125 
126 
127 /* Convert SQLite error codes to SVN. Evaluates X multiple times */
128 #define SQLITE_ERROR_CODE(x) ((x) == SQLITE_READONLY            \
129                               ? SVN_ERR_SQLITE_READONLY         \
130                               : ((x) == SQLITE_BUSY             \
131                                  ? SVN_ERR_SQLITE_BUSY          \
132                                  : ((x) == SQLITE_CONSTRAINT    \
133                                     ? SVN_ERR_SQLITE_CONSTRAINT \
134                                     : SVN_ERR_SQLITE_ERROR)))
135 
136 
137 /* SQLITE->SVN quick error wrap, much like SVN_ERR. */
138 #define SQLITE_ERR(x, db) do                                     \
139 {                                                                \
140   int sqlite_err__temp = (x);                                    \
141   if (sqlite_err__temp != SQLITE_OK)                             \
142     return svn_error_createf(SQLITE_ERROR_CODE(sqlite_err__temp), \
143                              NULL, "sqlite[S%d]: %s",             \
144                              sqlite_err__temp,                    \
145                              sqlite3_errmsg((db)->db3));          \
146 } while (0)
147 
148 #define SQLITE_ERR_MSG(x, msg) do                                \
149 {                                                                \
150   int sqlite_err__temp = (x);                                    \
151   if (sqlite_err__temp != SQLITE_OK)                             \
152     return svn_error_createf(SQLITE_ERROR_CODE(sqlite_err__temp), \
153                              NULL, "sqlite[S%d]: %s",            \
154                              sqlite_err__temp, msg);             \
155 } while (0)
156 
157 
158 /* Time (in milliseconds) to wait for sqlite locks before giving up. */
159 #define BUSY_TIMEOUT 10000
160 
161 
162 /* Convenience wrapper around exec_sql2(). */
163 #define exec_sql(db, sql) exec_sql2((db), (sql), SQLITE_OK)
164 
165 /* Run the statement SQL on DB, ignoring SQLITE_OK and IGNORED_ERR.
166    (Note: the IGNORED_ERR parameter itself is not ignored.) */
167 static svn_error_t *
exec_sql2(svn_sqlite__db_t * db,const char * sql,int ignored_err)168 exec_sql2(svn_sqlite__db_t *db, const char *sql, int ignored_err)
169 {
170   char *err_msg;
171   int sqlite_err = sqlite3_exec(db->db3, sql, NULL, NULL, &err_msg);
172 
173   if (sqlite_err != SQLITE_OK && sqlite_err != ignored_err)
174     {
175       svn_error_t *err = svn_error_createf(SQLITE_ERROR_CODE(sqlite_err), NULL,
176                                            _("sqlite[S%d]: %s,"
177                                              " executing statement '%s'"),
178                                            sqlite_err, err_msg, sql);
179       sqlite3_free(err_msg);
180       return err;
181     }
182 
183   return SVN_NO_ERROR;
184 }
185 
186 
187 static svn_error_t *
prepare_statement(svn_sqlite__stmt_t ** stmt,svn_sqlite__db_t * db,const char * text,apr_pool_t * result_pool)188 prepare_statement(svn_sqlite__stmt_t **stmt, svn_sqlite__db_t *db,
189                   const char *text, apr_pool_t *result_pool)
190 {
191   *stmt = apr_palloc(result_pool, sizeof(**stmt));
192   (*stmt)->db = db;
193   (*stmt)->needs_reset = FALSE;
194 
195   SQLITE_ERR(sqlite3_prepare_v2(db->db3, text, -1, &(*stmt)->s3stmt, NULL), db);
196 
197   return SVN_NO_ERROR;
198 }
199 
200 
201 svn_error_t *
svn_sqlite__exec_statements(svn_sqlite__db_t * db,int stmt_idx)202 svn_sqlite__exec_statements(svn_sqlite__db_t *db, int stmt_idx)
203 {
204   SVN_ERR_ASSERT(stmt_idx < db->nbr_statements);
205 
206   return svn_error_trace(exec_sql(db, db->statement_strings[stmt_idx]));
207 }
208 
209 
210 svn_error_t *
svn_sqlite__get_statement(svn_sqlite__stmt_t ** stmt,svn_sqlite__db_t * db,int stmt_idx)211 svn_sqlite__get_statement(svn_sqlite__stmt_t **stmt, svn_sqlite__db_t *db,
212                           int stmt_idx)
213 {
214   SVN_ERR_ASSERT(stmt_idx < db->nbr_statements);
215 
216   if (db->prepared_stmts[stmt_idx] == NULL)
217     SVN_ERR(prepare_statement(&db->prepared_stmts[stmt_idx], db,
218                               db->statement_strings[stmt_idx],
219                               db->state_pool));
220 
221   *stmt = db->prepared_stmts[stmt_idx];
222 
223   if ((*stmt)->needs_reset)
224     return svn_error_trace(svn_sqlite__reset(*stmt));
225 
226   return SVN_NO_ERROR;
227 }
228 
229 /* Like svn_sqlite__get_statement but gets an internal statement.
230 
231    All internal statements that use this api are executed with step_done(),
232    so we don't need the fallback reset handling here or in the pool cleanup */
233 static svn_error_t *
get_internal_statement(svn_sqlite__stmt_t ** stmt,svn_sqlite__db_t * db,int stmt_idx)234 get_internal_statement(svn_sqlite__stmt_t **stmt, svn_sqlite__db_t *db,
235                        int stmt_idx)
236 {
237   /* The internal statements are stored after the registered statements */
238   int prep_idx = db->nbr_statements + stmt_idx;
239   SVN_ERR_ASSERT(stmt_idx < STMT_INTERNAL_LAST);
240 
241   if (db->prepared_stmts[prep_idx] == NULL)
242     SVN_ERR(prepare_statement(&db->prepared_stmts[prep_idx], db,
243                               internal_statements[stmt_idx],
244                               db->state_pool));
245 
246   *stmt = db->prepared_stmts[prep_idx];
247 
248   return SVN_NO_ERROR;
249 }
250 
251 
252 static svn_error_t *
step_with_expectation(svn_sqlite__stmt_t * stmt,svn_boolean_t expecting_row)253 step_with_expectation(svn_sqlite__stmt_t* stmt,
254                       svn_boolean_t expecting_row)
255 {
256   svn_boolean_t got_row;
257 
258   SVN_ERR(svn_sqlite__step(&got_row, stmt));
259   if ((got_row && !expecting_row)
260       ||
261       (!got_row && expecting_row))
262     return svn_error_create(SVN_ERR_SQLITE_ERROR,
263                             svn_sqlite__reset(stmt),
264                             expecting_row
265                               ? _("sqlite: Expected database row missing")
266                               : _("sqlite: Extra database row found"));
267 
268   return SVN_NO_ERROR;
269 }
270 
271 svn_error_t *
svn_sqlite__step_done(svn_sqlite__stmt_t * stmt)272 svn_sqlite__step_done(svn_sqlite__stmt_t *stmt)
273 {
274   SVN_ERR(step_with_expectation(stmt, FALSE));
275   return svn_error_trace(svn_sqlite__reset(stmt));
276 }
277 
278 svn_error_t *
svn_sqlite__step_row(svn_sqlite__stmt_t * stmt)279 svn_sqlite__step_row(svn_sqlite__stmt_t *stmt)
280 {
281   return svn_error_trace(step_with_expectation(stmt, TRUE));
282 }
283 
284 
285 svn_error_t *
svn_sqlite__step(svn_boolean_t * got_row,svn_sqlite__stmt_t * stmt)286 svn_sqlite__step(svn_boolean_t *got_row, svn_sqlite__stmt_t *stmt)
287 {
288   int sqlite_result = sqlite3_step(stmt->s3stmt);
289 
290   if (sqlite_result != SQLITE_DONE && sqlite_result != SQLITE_ROW)
291     {
292       svn_error_t *err1, *err2;
293 
294       err1 = svn_error_createf(SQLITE_ERROR_CODE(sqlite_result), NULL,
295                                "sqlite[S%d]: %s",
296                                sqlite_result, sqlite3_errmsg(stmt->db->db3));
297       err2 = svn_sqlite__reset(stmt);
298       return svn_error_compose_create(err1, err2);
299     }
300 
301   *got_row = (sqlite_result == SQLITE_ROW);
302   stmt->needs_reset = TRUE;
303 
304   return SVN_NO_ERROR;
305 }
306 
307 svn_error_t *
svn_sqlite__insert(apr_int64_t * row_id,svn_sqlite__stmt_t * stmt)308 svn_sqlite__insert(apr_int64_t *row_id, svn_sqlite__stmt_t *stmt)
309 {
310   svn_boolean_t got_row;
311 
312   SVN_ERR(svn_sqlite__step(&got_row, stmt));
313   if (row_id)
314     *row_id = sqlite3_last_insert_rowid(stmt->db->db3);
315 
316   return svn_error_trace(svn_sqlite__reset(stmt));
317 }
318 
319 svn_error_t *
svn_sqlite__update(int * affected_rows,svn_sqlite__stmt_t * stmt)320 svn_sqlite__update(int *affected_rows, svn_sqlite__stmt_t *stmt)
321 {
322   SVN_ERR(step_with_expectation(stmt, FALSE));
323 
324   if (affected_rows)
325     *affected_rows = sqlite3_changes(stmt->db->db3);
326 
327   return svn_error_trace(svn_sqlite__reset(stmt));
328 }
329 
330 
331 static svn_error_t *
vbindf(svn_sqlite__stmt_t * stmt,const char * fmt,va_list ap)332 vbindf(svn_sqlite__stmt_t *stmt, const char *fmt, va_list ap)
333 {
334   int count;
335 
336   for (count = 1; *fmt; fmt++, count++)
337     {
338       const void *blob;
339       apr_size_t blob_size;
340       const svn_token_map_t *map;
341 
342       switch (*fmt)
343         {
344           case 's':
345             SVN_ERR(svn_sqlite__bind_text(stmt, count,
346                                           va_arg(ap, const char *)));
347             break;
348 
349           case 'd':
350             SVN_ERR(svn_sqlite__bind_int(stmt, count,
351                                          va_arg(ap, int)));
352             break;
353 
354           case 'i':
355           case 'L':
356             SVN_ERR(svn_sqlite__bind_int64(stmt, count,
357                                            va_arg(ap, apr_int64_t)));
358             break;
359 
360           case 'b':
361             blob = va_arg(ap, const void *);
362             blob_size = va_arg(ap, apr_size_t);
363             SVN_ERR(svn_sqlite__bind_blob(stmt, count, blob, blob_size));
364             break;
365 
366           case 'r':
367             SVN_ERR(svn_sqlite__bind_revnum(stmt, count,
368                                             va_arg(ap, svn_revnum_t)));
369             break;
370 
371           case 't':
372             map = va_arg(ap, const svn_token_map_t *);
373             SVN_ERR(svn_sqlite__bind_token(stmt, count, map, va_arg(ap, int)));
374             break;
375 
376           case 'n':
377             /* Skip this column: no binding */
378             break;
379 
380           default:
381             SVN_ERR_MALFUNCTION();
382         }
383     }
384 
385   return SVN_NO_ERROR;
386 }
387 
388 svn_error_t *
svn_sqlite__bindf(svn_sqlite__stmt_t * stmt,const char * fmt,...)389 svn_sqlite__bindf(svn_sqlite__stmt_t *stmt, const char *fmt, ...)
390 {
391   svn_error_t *err;
392   va_list ap;
393 
394   va_start(ap, fmt);
395   err = vbindf(stmt, fmt, ap);
396   va_end(ap);
397   return svn_error_trace(err);
398 }
399 
400 svn_error_t *
svn_sqlite__bind_int(svn_sqlite__stmt_t * stmt,int slot,int val)401 svn_sqlite__bind_int(svn_sqlite__stmt_t *stmt,
402                      int slot,
403                      int val)
404 {
405   SQLITE_ERR(sqlite3_bind_int(stmt->s3stmt, slot, val), stmt->db);
406   return SVN_NO_ERROR;
407 }
408 
409 svn_error_t *
svn_sqlite__bind_int64(svn_sqlite__stmt_t * stmt,int slot,apr_int64_t val)410 svn_sqlite__bind_int64(svn_sqlite__stmt_t *stmt,
411                        int slot,
412                        apr_int64_t val)
413 {
414   SQLITE_ERR(sqlite3_bind_int64(stmt->s3stmt, slot, val), stmt->db);
415   return SVN_NO_ERROR;
416 }
417 
418 svn_error_t *
svn_sqlite__bind_text(svn_sqlite__stmt_t * stmt,int slot,const char * val)419 svn_sqlite__bind_text(svn_sqlite__stmt_t *stmt,
420                       int slot,
421                       const char *val)
422 {
423   SQLITE_ERR(sqlite3_bind_text(stmt->s3stmt, slot, val, -1, SQLITE_TRANSIENT),
424              stmt->db);
425   return SVN_NO_ERROR;
426 }
427 
428 svn_error_t *
svn_sqlite__bind_blob(svn_sqlite__stmt_t * stmt,int slot,const void * val,apr_size_t len)429 svn_sqlite__bind_blob(svn_sqlite__stmt_t *stmt,
430                       int slot,
431                       const void *val,
432                       apr_size_t len)
433 {
434   SQLITE_ERR(sqlite3_bind_blob(stmt->s3stmt, slot, val, (int) len,
435                                SQLITE_TRANSIENT),
436              stmt->db);
437   return SVN_NO_ERROR;
438 }
439 
440 svn_error_t *
svn_sqlite__bind_token(svn_sqlite__stmt_t * stmt,int slot,const svn_token_map_t * map,int value)441 svn_sqlite__bind_token(svn_sqlite__stmt_t *stmt,
442                        int slot,
443                        const svn_token_map_t *map,
444                        int value)
445 {
446   const char *word = svn_token__to_word(map, value);
447 
448   SQLITE_ERR(sqlite3_bind_text(stmt->s3stmt, slot, word, -1, SQLITE_STATIC),
449              stmt->db);
450   return SVN_NO_ERROR;
451 }
452 
453 svn_error_t *
svn_sqlite__bind_revnum(svn_sqlite__stmt_t * stmt,int slot,svn_revnum_t value)454 svn_sqlite__bind_revnum(svn_sqlite__stmt_t *stmt,
455                         int slot,
456                         svn_revnum_t value)
457 {
458   if (SVN_IS_VALID_REVNUM(value))
459     SQLITE_ERR(sqlite3_bind_int64(stmt->s3stmt, slot,
460                                   (sqlite_int64)value), stmt->db);
461   else
462     SQLITE_ERR(sqlite3_bind_null(stmt->s3stmt, slot), stmt->db);
463 
464   return SVN_NO_ERROR;
465 }
466 
467 svn_error_t *
svn_sqlite__bind_properties(svn_sqlite__stmt_t * stmt,int slot,const apr_hash_t * props,apr_pool_t * scratch_pool)468 svn_sqlite__bind_properties(svn_sqlite__stmt_t *stmt,
469                             int slot,
470                             const apr_hash_t *props,
471                             apr_pool_t *scratch_pool)
472 {
473   svn_skel_t *skel;
474   svn_stringbuf_t *properties;
475 
476   if (props == NULL)
477     return svn_error_trace(svn_sqlite__bind_blob(stmt, slot, NULL, 0));
478 
479   SVN_ERR(svn_skel__unparse_proplist(&skel, props, scratch_pool));
480   properties = svn_skel__unparse(skel, scratch_pool);
481   return svn_error_trace(svn_sqlite__bind_blob(stmt,
482                                                slot,
483                                                properties->data,
484                                                properties->len));
485 }
486 
487 svn_error_t *
svn_sqlite__bind_iprops(svn_sqlite__stmt_t * stmt,int slot,const apr_array_header_t * inherited_props,apr_pool_t * scratch_pool)488 svn_sqlite__bind_iprops(svn_sqlite__stmt_t *stmt,
489                         int slot,
490                         const apr_array_header_t *inherited_props,
491                         apr_pool_t *scratch_pool)
492 {
493   svn_skel_t *skel;
494   svn_stringbuf_t *properties;
495 
496   if (inherited_props == NULL)
497     return svn_error_trace(svn_sqlite__bind_blob(stmt, slot, NULL, 0));
498 
499   SVN_ERR(svn_skel__unparse_iproplist(&skel, inherited_props,
500                                       scratch_pool, scratch_pool));
501   properties = svn_skel__unparse(skel, scratch_pool);
502   return svn_error_trace(svn_sqlite__bind_blob(stmt,
503                                                slot,
504                                                properties->data,
505                                                properties->len));
506 }
507 
508 svn_error_t *
svn_sqlite__bind_checksum(svn_sqlite__stmt_t * stmt,int slot,const svn_checksum_t * checksum,apr_pool_t * scratch_pool)509 svn_sqlite__bind_checksum(svn_sqlite__stmt_t *stmt,
510                           int slot,
511                           const svn_checksum_t *checksum,
512                           apr_pool_t *scratch_pool)
513 {
514   const char *csum_str;
515 
516   if (checksum == NULL)
517     csum_str = NULL;
518   else
519     csum_str = svn_checksum_serialize(checksum, scratch_pool, scratch_pool);
520 
521   return svn_error_trace(svn_sqlite__bind_text(stmt, slot, csum_str));
522 }
523 
524 
525 const void *
svn_sqlite__column_blob(svn_sqlite__stmt_t * stmt,int column,apr_size_t * len,apr_pool_t * result_pool)526 svn_sqlite__column_blob(svn_sqlite__stmt_t *stmt, int column,
527                         apr_size_t *len, apr_pool_t *result_pool)
528 {
529   const void *val = sqlite3_column_blob(stmt->s3stmt, column);
530   *len = sqlite3_column_bytes(stmt->s3stmt, column);
531 
532   if (result_pool && val != NULL)
533     val = apr_pmemdup(result_pool, val, *len);
534 
535   return val;
536 }
537 
538 const char *
svn_sqlite__column_text(svn_sqlite__stmt_t * stmt,int column,apr_pool_t * result_pool)539 svn_sqlite__column_text(svn_sqlite__stmt_t *stmt, int column,
540                         apr_pool_t *result_pool)
541 {
542   /* cast from 'unsigned char' to regular 'char'  */
543   const char *result = (const char *)sqlite3_column_text(stmt->s3stmt, column);
544 
545   if (result_pool && result != NULL)
546     result = apr_pstrdup(result_pool, result);
547 
548   return result;
549 }
550 
551 svn_revnum_t
svn_sqlite__column_revnum(svn_sqlite__stmt_t * stmt,int column)552 svn_sqlite__column_revnum(svn_sqlite__stmt_t *stmt, int column)
553 {
554   if (svn_sqlite__column_is_null(stmt, column))
555     return SVN_INVALID_REVNUM;
556   return (svn_revnum_t) sqlite3_column_int64(stmt->s3stmt, column);
557 }
558 
559 svn_boolean_t
svn_sqlite__column_boolean(svn_sqlite__stmt_t * stmt,int column)560 svn_sqlite__column_boolean(svn_sqlite__stmt_t *stmt, int column)
561 {
562   return sqlite3_column_int64(stmt->s3stmt, column) != 0;
563 }
564 
565 int
svn_sqlite__column_int(svn_sqlite__stmt_t * stmt,int column)566 svn_sqlite__column_int(svn_sqlite__stmt_t *stmt, int column)
567 {
568   return sqlite3_column_int(stmt->s3stmt, column);
569 }
570 
571 apr_int64_t
svn_sqlite__column_int64(svn_sqlite__stmt_t * stmt,int column)572 svn_sqlite__column_int64(svn_sqlite__stmt_t *stmt, int column)
573 {
574   return sqlite3_column_int64(stmt->s3stmt, column);
575 }
576 
577 int
svn_sqlite__column_token(svn_sqlite__stmt_t * stmt,int column,const svn_token_map_t * map)578 svn_sqlite__column_token(svn_sqlite__stmt_t *stmt,
579                          int column,
580                          const svn_token_map_t *map)
581 {
582   /* cast from 'unsigned char' to regular 'char'  */
583   const char *word = (const char *)sqlite3_column_text(stmt->s3stmt, column);
584 
585   return svn_token__from_word_strict(map, word);
586 }
587 
588 int
svn_sqlite__column_token_null(svn_sqlite__stmt_t * stmt,int column,const svn_token_map_t * map,int null_val)589 svn_sqlite__column_token_null(svn_sqlite__stmt_t *stmt,
590                               int column,
591                               const svn_token_map_t *map,
592                               int null_val)
593 {
594   /* cast from 'unsigned char' to regular 'char'  */
595   const char *word = (const char *)sqlite3_column_text(stmt->s3stmt, column);
596 
597   if (!word)
598     return null_val;
599 
600   return svn_token__from_word_strict(map, word);
601 }
602 
603 svn_error_t *
svn_sqlite__column_properties(apr_hash_t ** props,svn_sqlite__stmt_t * stmt,int column,apr_pool_t * result_pool,apr_pool_t * scratch_pool)604 svn_sqlite__column_properties(apr_hash_t **props,
605                               svn_sqlite__stmt_t *stmt,
606                               int column,
607                               apr_pool_t *result_pool,
608                               apr_pool_t *scratch_pool)
609 {
610   apr_size_t len;
611   const void *val;
612 
613   /* svn_skel__parse_proplist copies everything needed to result_pool */
614   val = svn_sqlite__column_blob(stmt, column, &len, NULL);
615   if (val == NULL)
616     {
617       *props = NULL;
618       return SVN_NO_ERROR;
619     }
620 
621   SVN_ERR(svn_skel__parse_proplist(props,
622                                    svn_skel__parse(val, len, scratch_pool),
623                                    result_pool));
624 
625   return SVN_NO_ERROR;
626 }
627 
628 svn_error_t *
svn_sqlite__column_iprops(apr_array_header_t ** iprops,svn_sqlite__stmt_t * stmt,int column,apr_pool_t * result_pool,apr_pool_t * scratch_pool)629 svn_sqlite__column_iprops(apr_array_header_t **iprops,
630                           svn_sqlite__stmt_t *stmt,
631                           int column,
632                           apr_pool_t *result_pool,
633                           apr_pool_t *scratch_pool)
634 {
635   apr_size_t len;
636   const void *val;
637 
638   /* svn_skel__parse_iprops copies everything needed to result_pool */
639   val = svn_sqlite__column_blob(stmt, column, &len, NULL);
640   if (val == NULL)
641     {
642       *iprops = NULL;
643       return SVN_NO_ERROR;
644     }
645 
646   SVN_ERR(svn_skel__parse_iprops(iprops,
647                                  svn_skel__parse(val, len, scratch_pool),
648                                  result_pool));
649 
650   return SVN_NO_ERROR;
651 }
652 
653 svn_error_t *
svn_sqlite__column_checksum(const svn_checksum_t ** checksum,svn_sqlite__stmt_t * stmt,int column,apr_pool_t * result_pool)654 svn_sqlite__column_checksum(const svn_checksum_t **checksum,
655                             svn_sqlite__stmt_t *stmt, int column,
656                             apr_pool_t *result_pool)
657 {
658   const char *digest = svn_sqlite__column_text(stmt, column, NULL);
659 
660   if (digest == NULL)
661     *checksum = NULL;
662   else
663     SVN_ERR(svn_checksum_deserialize(checksum, digest,
664                                      result_pool, result_pool));
665 
666   return SVN_NO_ERROR;
667 }
668 
669 svn_boolean_t
svn_sqlite__column_is_null(svn_sqlite__stmt_t * stmt,int column)670 svn_sqlite__column_is_null(svn_sqlite__stmt_t *stmt, int column)
671 {
672   return sqlite3_column_type(stmt->s3stmt, column) == SQLITE_NULL;
673 }
674 
675 int
svn_sqlite__column_bytes(svn_sqlite__stmt_t * stmt,int column)676 svn_sqlite__column_bytes(svn_sqlite__stmt_t *stmt, int column)
677 {
678   return sqlite3_column_bytes(stmt->s3stmt, column);
679 }
680 
681 svn_error_t *
svn_sqlite__finalize(svn_sqlite__stmt_t * stmt)682 svn_sqlite__finalize(svn_sqlite__stmt_t *stmt)
683 {
684   SQLITE_ERR(sqlite3_finalize(stmt->s3stmt), stmt->db);
685   return SVN_NO_ERROR;
686 }
687 
688 svn_error_t *
svn_sqlite__reset(svn_sqlite__stmt_t * stmt)689 svn_sqlite__reset(svn_sqlite__stmt_t *stmt)
690 {
691   SQLITE_ERR(sqlite3_reset(stmt->s3stmt), stmt->db);
692   SQLITE_ERR(sqlite3_clear_bindings(stmt->s3stmt), stmt->db);
693   stmt->needs_reset = FALSE;
694   return SVN_NO_ERROR;
695 }
696 
697 
698 svn_error_t *
svn_sqlite__read_schema_version(int * version,svn_sqlite__db_t * db,apr_pool_t * scratch_pool)699 svn_sqlite__read_schema_version(int *version,
700                                 svn_sqlite__db_t *db,
701                                 apr_pool_t *scratch_pool)
702 {
703   svn_sqlite__stmt_t *stmt;
704 
705   SVN_ERR(prepare_statement(&stmt, db, "PRAGMA user_version;", scratch_pool));
706   SVN_ERR(svn_sqlite__step_row(stmt));
707 
708   *version = svn_sqlite__column_int(stmt, 0);
709 
710   return svn_error_trace(svn_sqlite__finalize(stmt));
711 }
712 
713 
714 static volatile svn_atomic_t sqlite_init_state = 0;
715 
716 /* If possible, verify that SQLite was compiled in a thread-safe
717    manner. */
718 /* Don't call this function directly!  Use svn_atomic__init_once(). */
719 static svn_error_t *
init_sqlite(void * baton,apr_pool_t * pool)720 init_sqlite(void *baton, apr_pool_t *pool)
721 {
722   if (sqlite3_libversion_number() < SVN_SQLITE_MIN_VERSION_NUMBER)
723     {
724       return svn_error_createf(
725                     SVN_ERR_SQLITE_ERROR, NULL,
726                     _("SQLite compiled for %s, but running with %s"),
727                     SVN_SQLITE_MIN_VERSION, sqlite3_libversion());
728     }
729 
730 #if APR_HAS_THREADS
731 
732   /* SQLite 3.5 allows verification of its thread-safety at runtime.
733      Older versions are simply expected to have been configured with
734      --enable-threadsafe, which compiles with -DSQLITE_THREADSAFE=1
735      (or -DTHREADSAFE, for older versions). */
736   if (! sqlite3_threadsafe())
737     return svn_error_create(SVN_ERR_SQLITE_ERROR, NULL,
738                             _("SQLite is required to be compiled and run in "
739                               "thread-safe mode"));
740 
741   /* If SQLite has been already initialized, sqlite3_config() returns
742      SQLITE_MISUSE. */
743   {
744     int err = sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
745     if (err != SQLITE_OK && err != SQLITE_MISUSE)
746       return svn_error_createf(SQLITE_ERROR_CODE(err), NULL,
747                                _("Could not configure SQLite [S%d]"), err);
748   }
749   SQLITE_ERR_MSG(sqlite3_initialize(), _("Could not initialize SQLite"));
750 
751 #endif /* APR_HAS_THRADS */
752 
753   return SVN_NO_ERROR;
754 }
755 
756 static svn_error_t *
internal_open(sqlite3 ** db3,const char * path,svn_sqlite__mode_t mode,apr_pool_t * scratch_pool)757 internal_open(sqlite3 **db3, const char *path, svn_sqlite__mode_t mode,
758               apr_pool_t *scratch_pool)
759 {
760   {
761     int flags;
762 
763     if (mode == svn_sqlite__mode_readonly)
764       flags = SQLITE_OPEN_READONLY;
765     else if (mode == svn_sqlite__mode_readwrite)
766       flags = SQLITE_OPEN_READWRITE;
767     else if (mode == svn_sqlite__mode_rwcreate)
768       flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
769     else
770       SVN_ERR_MALFUNCTION();
771 
772     /* Turn off SQLite's mutexes. All svn objects are single-threaded,
773        so we can already guarantee that our use of the SQLite handle
774        will be serialized properly.
775 
776        Note: in 3.6.x, we've already config'd SQLite into MULTITHREAD mode,
777        so this is probably redundant, but if we are running in a process where
778        somebody initialized SQLite before us it is needed anyway.  */
779     flags |= SQLITE_OPEN_NOMUTEX;
780 
781 #if !defined(WIN32) && !defined(SVN_SQLITE_INLINE)
782     if (mode == svn_sqlite__mode_rwcreate)
783       {
784         svn_node_kind_t kind;
785 
786         /* Create the file before SQLite to avoid any permissions
787            problems with an SQLite build that uses the default
788            SQLITE_DEFAULT_FILE_PERMISSIONS of 644 modified by umask.
789            We simply want umask permissions. */
790         SVN_ERR(svn_io_check_path(path, &kind, scratch_pool));
791         if (kind == svn_node_none)
792           SVN_ERR(svn_io_file_create(path, "", scratch_pool));
793       }
794 #endif
795 
796     /* Open the database. Note that a handle is returned, even when an error
797        occurs (except for out-of-memory); thus, we can safely use it to
798        extract an error message and construct an svn_error_t. */
799     {
800       /* We'd like to use SQLITE_ERR here, but we can't since it would
801          just return an error and leave the database open.  So, we need to
802          do this manually. */
803       /* ### SQLITE_CANTOPEN */
804       int err_code = sqlite3_open_v2(path, db3, flags, NULL);
805       if (err_code != SQLITE_OK)
806         {
807           /* Save the error message before closing the SQLite handle. */
808           char *msg = apr_pstrdup(scratch_pool, sqlite3_errmsg(*db3));
809 
810           /* We don't catch the error here, since we care more about the open
811              error than the close error at this point. */
812           sqlite3_close(*db3);
813 
814           SQLITE_ERR_MSG(err_code, msg);
815         }
816     }
817   }
818 
819   /* Retry until timeout when database is busy. */
820   SQLITE_ERR_MSG(sqlite3_busy_timeout(*db3, BUSY_TIMEOUT),
821                  sqlite3_errmsg(*db3));
822 
823   return SVN_NO_ERROR;
824 }
825 
826 
827 /* APR cleanup function used to close the database when its pool is destroyed.
828    DATA should be the svn_sqlite__db_t handle for the database. */
829 static apr_status_t
close_apr(void * data)830 close_apr(void *data)
831 {
832   svn_sqlite__db_t *db = data;
833   svn_error_t *err = SVN_NO_ERROR;
834   apr_status_t result;
835   int i;
836 
837   /* Check to see if we've already closed this database. */
838   if (db->db3 == NULL)
839     return APR_SUCCESS;
840 
841   /* Finalize any existing prepared statements. */
842   for (i = 0; i < db->nbr_statements; i++)
843     {
844       if (db->prepared_stmts[i])
845         {
846           if (db->prepared_stmts[i]->needs_reset)
847             {
848 #ifdef SVN_DEBUG
849               const char *stmt_text = db->statement_strings[i];
850               stmt_text = stmt_text; /* Provide value for debugger */
851 
852               SVN_ERR_MALFUNCTION_NO_RETURN();
853 #else
854               err = svn_error_compose_create(
855                             err,
856                             svn_sqlite__reset(db->prepared_stmts[i]));
857 #endif
858             }
859           err = svn_error_compose_create(
860                         svn_sqlite__finalize(db->prepared_stmts[i]), err);
861         }
862     }
863   /* And finalize any used internal statements */
864   for (; i < db->nbr_statements + STMT_INTERNAL_LAST; i++)
865     {
866       if (db->prepared_stmts[i])
867         {
868           err = svn_error_compose_create(
869                         svn_sqlite__finalize(db->prepared_stmts[i]), err);
870         }
871     }
872 
873   result = sqlite3_close(db->db3);
874 
875   /* If there's a pre-existing error, return it. */
876   if (err)
877     {
878       result = err->apr_err;
879       svn_error_clear(err);
880       return result;
881     }
882 
883   if (result != SQLITE_OK)
884     return SQLITE_ERROR_CODE(result); /* ### lossy */
885 
886   db->db3 = NULL;
887 
888   return APR_SUCCESS;
889 }
890 
891 
892 svn_error_t *
svn_sqlite__open(svn_sqlite__db_t ** db,const char * path,svn_sqlite__mode_t mode,const char * const statements[],int unused1,const char * const * unused2,apr_pool_t * result_pool,apr_pool_t * scratch_pool)893 svn_sqlite__open(svn_sqlite__db_t **db, const char *path,
894                  svn_sqlite__mode_t mode, const char * const statements[],
895                  int unused1, const char * const *unused2,
896                  apr_pool_t *result_pool, apr_pool_t *scratch_pool)
897 {
898   SVN_ERR(svn_atomic__init_once(&sqlite_init_state,
899                                 init_sqlite, NULL, scratch_pool));
900 
901   *db = apr_pcalloc(result_pool, sizeof(**db));
902 
903   SVN_ERR(internal_open(&(*db)->db3, path, mode, scratch_pool));
904 
905 #if SQLITE_VERSION_NUMBER >= 3008000 && SQLITE_VERSION_NUMBER < 3009000
906   /* disable SQLITE_ENABLE_STAT3/4 from 3.8.1 - 3.8.3 (but not 3.8.3.1+)
907    * to prevent using it when it's buggy.
908    * See: https://www.sqlite.org/src/info/4c86b126f2 */
909   if (sqlite3_libversion_number() > 3008000 &&
910       sqlite3_libversion_number() < 3008004 &&
911       strcmp(sqlite3_sourceid(),"2014-02-11")<0)
912     {
913       sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, (*db)->db3, 0x800);
914     }
915 #endif
916 
917 #ifdef SQLITE3_DEBUG
918   sqlite3_trace((*db)->db3, sqlite_tracer, (*db)->db3);
919 #endif
920 #ifdef SQLITE3_PROFILE
921   sqlite3_profile((*db)->db3, sqlite_profiler, (*db)->db3);
922 #endif
923 
924   /* ### simplify this. remnants of some old SQLite compat code.  */
925   {
926     int ignored_err = SQLITE_OK;
927 
928     SVN_ERR(exec_sql2(*db, "PRAGMA case_sensitive_like=1;", ignored_err));
929   }
930 
931   SVN_ERR(exec_sql(*db,
932               /* Disable synchronization to disable the explicit disk flushes
933                  that make Sqlite up to 50 times slower; especially on small
934                  transactions.
935 
936                  This removes some stability guarantees on specific hardware
937                  and power failures, but still guarantees atomic commits on
938                  application crashes. With our dependency on external data
939                  like pristine files (Wc) and revision files (repository),
940                  we can't keep up these additional guarantees anyway.
941 
942                  ### Maybe switch to NORMAL(1) when we use larger transaction
943                      scopes */
944               "PRAGMA synchronous=OFF;"
945               /* Enable recursive triggers so that a user trigger will fire
946                  in the deletion phase of an INSERT OR REPLACE statement.
947                  Requires SQLite >= 3.6.18  */
948               "PRAGMA recursive_triggers=ON;"
949               /* Enforce current Sqlite default behavior. Some distributions
950                  might change the Sqlite defaults without realizing how this
951                  affects application(read: Subversion) performance/behavior. */
952               "PRAGMA foreign_keys=OFF;"      /* SQLITE_DEFAULT_FOREIGN_KEYS*/
953               "PRAGMA locking_mode = NORMAL;" /* SQLITE_DEFAULT_LOCKING_MODE */
954               ));
955 
956 #if defined(SVN_DEBUG)
957   /* When running in debug mode, enable the checking of foreign key
958      constraints.  This has possible performance implications, so we don't
959      bother to do it for production...for now. */
960   SVN_ERR(exec_sql(*db, "PRAGMA foreign_keys=ON;"));
961 #endif
962 
963 #ifdef SVN_SQLITE_REVERSE_UNORDERED_SELECTS
964   /* When enabled, this PRAGMA causes SELECT statements without an ORDER BY
965      clause to emit their results in the reverse order of what they normally
966      would.  This can help detecting invalid assumptions about the result
967      order.*/
968   SVN_ERR(exec_sql(*db, "PRAGMA reverse_unordered_selects=ON;"));
969 #endif
970 
971   /* Store temporary tables in RAM instead of in temporary files, but don't
972      fail on this if this option is disabled in the sqlite compilation by
973      setting SQLITE_TEMP_STORE to 0 (always to disk) */
974   svn_error_clear(exec_sql(*db, "PRAGMA temp_store = MEMORY;"));
975 
976   /* Store the provided statements. */
977   if (statements)
978     {
979       (*db)->statement_strings = statements;
980       (*db)->nbr_statements = 0;
981       while (*statements != NULL)
982         {
983           statements++;
984           (*db)->nbr_statements++;
985         }
986 
987       (*db)->prepared_stmts = apr_pcalloc(
988                                   result_pool,
989                                   ((*db)->nbr_statements + STMT_INTERNAL_LAST)
990                                                 * sizeof(svn_sqlite__stmt_t *));
991     }
992   else
993     {
994       (*db)->nbr_statements = 0;
995       (*db)->prepared_stmts = apr_pcalloc(result_pool,
996                                           (0 + STMT_INTERNAL_LAST)
997                                                 * sizeof(svn_sqlite__stmt_t *));
998     }
999 
1000   (*db)->state_pool = result_pool;
1001   apr_pool_cleanup_register(result_pool, *db, close_apr, apr_pool_cleanup_null);
1002 
1003   return SVN_NO_ERROR;
1004 }
1005 
1006 svn_error_t *
svn_sqlite__close(svn_sqlite__db_t * db)1007 svn_sqlite__close(svn_sqlite__db_t *db)
1008 {
1009   apr_status_t result = apr_pool_cleanup_run(db->state_pool, db, close_apr);
1010 
1011   if (result == APR_SUCCESS)
1012     return SVN_NO_ERROR;
1013 
1014   return svn_error_wrap_apr(result, NULL);
1015 }
1016 
1017 static svn_error_t *
reset_all_statements(svn_sqlite__db_t * db,svn_error_t * error_to_wrap)1018 reset_all_statements(svn_sqlite__db_t *db,
1019                      svn_error_t *error_to_wrap)
1020 {
1021   int i;
1022   svn_error_t *err;
1023 
1024   /* ### Should we reorder the errors in this specific case
1025      ### to avoid returning the normal error as top level error? */
1026 
1027   err = svn_error_compose_create(error_to_wrap,
1028                    svn_error_create(SVN_ERR_SQLITE_RESETTING_FOR_ROLLBACK,
1029                                     NULL, NULL));
1030 
1031   for (i = 0; i < db->nbr_statements; i++)
1032     if (db->prepared_stmts[i] && db->prepared_stmts[i]->needs_reset)
1033       err = svn_error_compose_create(err,
1034                                 svn_sqlite__reset(db->prepared_stmts[i]));
1035 
1036   return err;
1037 }
1038 
1039 svn_error_t *
svn_sqlite__begin_transaction(svn_sqlite__db_t * db)1040 svn_sqlite__begin_transaction(svn_sqlite__db_t *db)
1041 {
1042   svn_sqlite__stmt_t *stmt;
1043 
1044   SVN_ERR(get_internal_statement(&stmt, db,
1045                                  STMT_INTERNAL_BEGIN_TRANSACTION));
1046   SVN_ERR(svn_sqlite__step_done(stmt));
1047   return SVN_NO_ERROR;
1048 }
1049 
1050 svn_error_t *
svn_sqlite__begin_immediate_transaction(svn_sqlite__db_t * db)1051 svn_sqlite__begin_immediate_transaction(svn_sqlite__db_t *db)
1052 {
1053   svn_sqlite__stmt_t *stmt;
1054 
1055   SVN_ERR(get_internal_statement(&stmt, db,
1056                                  STMT_INTERNAL_BEGIN_IMMEDIATE_TRANSACTION));
1057   SVN_ERR(svn_sqlite__step_done(stmt));
1058   return SVN_NO_ERROR;
1059 }
1060 
1061 svn_error_t *
svn_sqlite__begin_savepoint(svn_sqlite__db_t * db)1062 svn_sqlite__begin_savepoint(svn_sqlite__db_t *db)
1063 {
1064   svn_sqlite__stmt_t *stmt;
1065 
1066   SVN_ERR(get_internal_statement(&stmt, db,
1067                                  STMT_INTERNAL_SAVEPOINT_SVN));
1068   SVN_ERR(svn_sqlite__step_done(stmt));
1069   return SVN_NO_ERROR;
1070 }
1071 
1072 svn_error_t *
svn_sqlite__finish_transaction(svn_sqlite__db_t * db,svn_error_t * err)1073 svn_sqlite__finish_transaction(svn_sqlite__db_t *db,
1074                                svn_error_t *err)
1075 {
1076   svn_sqlite__stmt_t *stmt;
1077 
1078   /* Commit or rollback the sqlite transaction. */
1079   if (err)
1080     {
1081       svn_error_t *err2;
1082 
1083       err2 = get_internal_statement(&stmt, db,
1084                                     STMT_INTERNAL_ROLLBACK_TRANSACTION);
1085       if (!err2)
1086         err2 = svn_sqlite__step_done(stmt);
1087 
1088       if (err2 && err2->apr_err == SVN_ERR_SQLITE_BUSY)
1089         {
1090           /* ### Houston, we have a problem!
1091 
1092              We are trying to rollback but we can't because some
1093              statements are still busy. This leaves the database
1094              unusable for future transactions as the current transaction
1095              is still open.
1096 
1097              As we are returning the actual error as the most relevant
1098              error in the chain, our caller might assume that it can
1099              retry/compensate on this error (e.g. SVN_WC_LOCKED), while
1100              in fact the SQLite database is unusable until the statements
1101              started within this transaction are reset and the transaction
1102              aborted.
1103 
1104              We try to compensate by resetting all prepared but unreset
1105              statements; but we leave the busy error in the chain anyway to
1106              help diagnosing the original error and help in finding where
1107              a reset statement is missing. */
1108 
1109           err2 = reset_all_statements(db, err2);
1110           err2 = svn_error_compose_create(
1111                       svn_sqlite__step_done(stmt),
1112                       err2);
1113         }
1114 
1115       return svn_error_compose_create(err,
1116                                       err2);
1117     }
1118 
1119   SVN_ERR(get_internal_statement(&stmt, db, STMT_INTERNAL_COMMIT_TRANSACTION));
1120   return svn_error_trace(svn_sqlite__step_done(stmt));
1121 }
1122 
1123 svn_error_t *
svn_sqlite__finish_savepoint(svn_sqlite__db_t * db,svn_error_t * err)1124 svn_sqlite__finish_savepoint(svn_sqlite__db_t *db,
1125                              svn_error_t *err)
1126 {
1127   svn_sqlite__stmt_t *stmt;
1128 
1129   if (err)
1130     {
1131       svn_error_t *err2;
1132 
1133       err2 = get_internal_statement(&stmt, db,
1134                                     STMT_INTERNAL_ROLLBACK_TO_SAVEPOINT_SVN);
1135 
1136       if (!err2)
1137         err2 = svn_sqlite__step_done(stmt);
1138 
1139       if (err2 && err2->apr_err == SVN_ERR_SQLITE_BUSY)
1140         {
1141           /* Ok, we have a major problem. Some statement is still open, which
1142              makes it impossible to release this savepoint.
1143 
1144              ### See huge comment in svn_sqlite__finish_transaction for
1145                  further details */
1146 
1147           err2 = reset_all_statements(db, err2);
1148           err2 = svn_error_compose_create(svn_sqlite__step_done(stmt), err2);
1149         }
1150 
1151       err = svn_error_compose_create(err, err2);
1152       err2 = get_internal_statement(&stmt, db,
1153                                     STMT_INTERNAL_RELEASE_SAVEPOINT_SVN);
1154 
1155       if (!err2)
1156         err2 = svn_sqlite__step_done(stmt);
1157 
1158       return svn_error_trace(svn_error_compose_create(err, err2));
1159     }
1160 
1161   SVN_ERR(get_internal_statement(&stmt, db,
1162                                  STMT_INTERNAL_RELEASE_SAVEPOINT_SVN));
1163 
1164   return svn_error_trace(svn_sqlite__step_done(stmt));
1165 }
1166 
1167 svn_error_t *
svn_sqlite__with_transaction(svn_sqlite__db_t * db,svn_sqlite__transaction_callback_t cb_func,void * cb_baton,apr_pool_t * scratch_pool)1168 svn_sqlite__with_transaction(svn_sqlite__db_t *db,
1169                              svn_sqlite__transaction_callback_t cb_func,
1170                              void *cb_baton,
1171                              apr_pool_t *scratch_pool /* NULL allowed */)
1172 {
1173   SVN_SQLITE__WITH_TXN(cb_func(cb_baton, db, scratch_pool), db);
1174   return SVN_NO_ERROR;
1175 }
1176 
1177 svn_error_t *
svn_sqlite__with_immediate_transaction(svn_sqlite__db_t * db,svn_sqlite__transaction_callback_t cb_func,void * cb_baton,apr_pool_t * scratch_pool)1178 svn_sqlite__with_immediate_transaction(
1179   svn_sqlite__db_t *db,
1180   svn_sqlite__transaction_callback_t cb_func,
1181   void *cb_baton,
1182   apr_pool_t *scratch_pool /* NULL allowed */)
1183 {
1184   SVN_SQLITE__WITH_IMMEDIATE_TXN(cb_func(cb_baton, db, scratch_pool), db);
1185   return SVN_NO_ERROR;
1186 }
1187 
1188 svn_error_t *
svn_sqlite__with_lock(svn_sqlite__db_t * db,svn_sqlite__transaction_callback_t cb_func,void * cb_baton,apr_pool_t * scratch_pool)1189 svn_sqlite__with_lock(svn_sqlite__db_t *db,
1190                       svn_sqlite__transaction_callback_t cb_func,
1191                       void *cb_baton,
1192                       apr_pool_t *scratch_pool /* NULL allowed */)
1193 {
1194   SVN_SQLITE__WITH_LOCK(cb_func(cb_baton, db, scratch_pool), db);
1195   return SVN_NO_ERROR;
1196 }
1197 
1198 svn_error_t *
svn_sqlite__hotcopy(const char * src_path,const char * dst_path,apr_pool_t * scratch_pool)1199 svn_sqlite__hotcopy(const char *src_path,
1200                     const char *dst_path,
1201                     apr_pool_t *scratch_pool)
1202 {
1203   svn_sqlite__db_t *src_db;
1204 
1205   SVN_ERR(svn_sqlite__open(&src_db, src_path, svn_sqlite__mode_readonly,
1206                            NULL, 0, NULL,
1207                            scratch_pool, scratch_pool));
1208 
1209   {
1210     svn_sqlite__db_t *dst_db;
1211     sqlite3_backup *backup;
1212     int rc1, rc2;
1213 
1214     SVN_ERR(svn_sqlite__open(&dst_db, dst_path, svn_sqlite__mode_rwcreate,
1215                              NULL, 0, NULL, scratch_pool, scratch_pool));
1216     backup = sqlite3_backup_init(dst_db->db3, "main", src_db->db3, "main");
1217     if (!backup)
1218       return svn_error_createf(SVN_ERR_SQLITE_ERROR, NULL,
1219                                _("SQLite hotcopy failed for %s"), src_path);
1220     do
1221       {
1222         /* Pages are usually 1024 byte (SQLite docs). On my laptop
1223            copying gets faster as the number of pages is increased up
1224            to about 64, beyond that speed levels off.  Lets put the
1225            number of pages an order of magnitude higher, this is still
1226            likely to be a fraction of large databases. */
1227         rc1 = sqlite3_backup_step(backup, 1024);
1228 
1229         /* Should we sleep on SQLITE_OK?  That would make copying a
1230            large database take much longer.  When we do sleep how,
1231            long should we sleep?  Should the sleep get longer if we
1232            keep getting BUSY/LOCKED?  I have no real reason for
1233            choosing 25. */
1234         if (rc1 == SQLITE_BUSY || rc1 == SQLITE_LOCKED)
1235           sqlite3_sleep(25);
1236       }
1237     while (rc1 == SQLITE_OK || rc1 == SQLITE_BUSY || rc1 == SQLITE_LOCKED);
1238     rc2 = sqlite3_backup_finish(backup);
1239     if (rc1 != SQLITE_DONE)
1240       SQLITE_ERR(rc1, dst_db);
1241     SQLITE_ERR(rc2, dst_db);
1242     SVN_ERR(svn_sqlite__close(dst_db));
1243   }
1244 
1245   SVN_ERR(svn_sqlite__close(src_db));
1246 
1247   return SVN_NO_ERROR;
1248 }
1249 
1250 struct function_wrapper_baton_t
1251 {
1252   svn_sqlite__func_t func;
1253   void *baton;
1254 
1255   apr_pool_t *scratch_pool;
1256 };
1257 
1258 static void
wrapped_func(sqlite3_context * context,int argc,sqlite3_value * values[])1259 wrapped_func(sqlite3_context *context,
1260              int argc,
1261              sqlite3_value *values[])
1262 {
1263   struct function_wrapper_baton_t *fwb = sqlite3_user_data(context);
1264   svn_sqlite__context_t sctx;
1265   svn_sqlite__value_t **local_vals =
1266                             apr_palloc(fwb->scratch_pool,
1267                                        sizeof(svn_sqlite__value_t *) * argc);
1268   svn_error_t *err;
1269   int i;
1270 
1271   sctx.context = context;
1272 
1273   for (i = 0; i < argc; i++)
1274     {
1275       local_vals[i] = apr_palloc(fwb->scratch_pool, sizeof(*local_vals[i]));
1276       local_vals[i]->value = values[i];
1277     }
1278 
1279   err = fwb->func(&sctx, argc, local_vals, fwb->scratch_pool);
1280   svn_pool_clear(fwb->scratch_pool);
1281 
1282   if (err)
1283     {
1284       char buf[256];
1285       sqlite3_result_error(context,
1286                            svn_err_best_message(err, buf, sizeof(buf)),
1287                            -1);
1288       svn_error_clear(err);
1289     }
1290 }
1291 
1292 svn_error_t *
svn_sqlite__create_scalar_function(svn_sqlite__db_t * db,const char * func_name,int argc,svn_sqlite__func_t func,void * baton)1293 svn_sqlite__create_scalar_function(svn_sqlite__db_t *db,
1294                                    const char *func_name,
1295                                    int argc,
1296                                    svn_sqlite__func_t func,
1297                                    void *baton)
1298 {
1299   struct function_wrapper_baton_t *fwb = apr_pcalloc(db->state_pool,
1300                                                      sizeof(*fwb));
1301 
1302   fwb->scratch_pool = svn_pool_create(db->state_pool);
1303   fwb->func = func;
1304   fwb->baton = baton;
1305 
1306   SQLITE_ERR(sqlite3_create_function(db->db3, func_name, argc, SQLITE_ANY,
1307                                      fwb, wrapped_func, NULL, NULL),
1308              db);
1309 
1310   return SVN_NO_ERROR;
1311 }
1312 
1313 int
svn_sqlite__value_type(svn_sqlite__value_t * val)1314 svn_sqlite__value_type(svn_sqlite__value_t *val)
1315 {
1316   return sqlite3_value_type(val->value);
1317 }
1318 
1319 const char *
svn_sqlite__value_text(svn_sqlite__value_t * val)1320 svn_sqlite__value_text(svn_sqlite__value_t *val)
1321 {
1322   return (const char *) sqlite3_value_text(val->value);
1323 }
1324 
1325 void
svn_sqlite__result_null(svn_sqlite__context_t * sctx)1326 svn_sqlite__result_null(svn_sqlite__context_t *sctx)
1327 {
1328   sqlite3_result_null(sctx->context);
1329 }
1330 
1331 void
svn_sqlite__result_int64(svn_sqlite__context_t * sctx,apr_int64_t val)1332 svn_sqlite__result_int64(svn_sqlite__context_t *sctx, apr_int64_t val)
1333 {
1334   sqlite3_result_int64(sctx->context, val);
1335 }
1336