3 * ====================================================================
4 * Copyright (c) 2007 CollabNet. All rights reserved.
6 * This software is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at http://subversion.tigris.org/license-1.html.
9 * If newer versions of this license are posted there, you may use a
10 * newer version instead, at your option.
12 * This software consists of voluntary contributions made by many
13 * individuals. For exact contribution history, see the revision
14 * history and logs, available at http://subversion.tigris.org/.
15 * ====================================================================
24 #include <apr_general.h>
25 #include <apr_pools.h>
29 #include "svn_types.h"
32 #include "svn_mergeinfo.h"
33 #include "svn_pools.h"
35 #include "private/svn_fs_sqlite.h"
36 #include "../libsvn_fs/fs-loader.h"
37 #include "svn_private_config.h"
39 #include "sqlite-util.h"
42 /* An sqlite query execution callback. */
44 sqlite_tracer(void *data
, const char *sql
)
46 /* sqlite3 *db = data; */
47 fprintf(stderr
, "SQLITE SQL is \"%s\"\n", sql
);
51 struct svn_fs__sqlite_stmt_t
57 /* Convert SQLite error codes to SVN */
58 #define SQLITE_ERROR_CODE(x) ((x) == SQLITE_READONLY ? \
59 SVN_ERR_FS_SQLITE_READONLY \
60 : SVN_ERR_FS_SQLITE_ERROR )
62 /* SQLITE->SVN quick error wrap, much like SVN_ERR. */
63 #define SQLITE_ERR(x, db) do \
65 int sqlite_err__temp = (x); \
66 if (sqlite_err__temp != SQLITE_OK) \
67 return svn_error_create(SQLITE_ERROR_CODE(sqlite_err__temp), \
68 NULL, sqlite3_errmsg((db))); \
73 svn_fs__sqlite_exec(sqlite3
*db
, const char *sql
)
77 int sqlite_err
= sqlite3_exec(db
, sql
, NULL
, NULL
, &err_msg
);
78 if (sqlite_err
!= SQLITE_OK
)
80 err
= svn_error_create(SQLITE_ERROR_CODE(sqlite_err
), NULL
,
82 sqlite3_free(err_msg
);
89 svn_fs__sqlite_prepare(svn_fs__sqlite_stmt_t
**stmt
, sqlite3
*db
,
90 const char *text
, apr_pool_t
*pool
)
92 svn_fs__sqlite_stmt_t
*s
= apr_palloc(pool
, sizeof(*s
));
94 SQLITE_ERR(sqlite3_prepare(db
, text
, -1, &(s
->s3stmt
), NULL
), db
);
100 step_with_expectation(svn_fs__sqlite_stmt_t
* stmt
,
101 svn_boolean_t expecting_row
)
103 svn_boolean_t got_row
;
104 SVN_ERR(svn_fs__sqlite_step(&got_row
, stmt
));
105 if ((got_row
&& !expecting_row
)
107 (!got_row
&& expecting_row
))
108 return svn_error_create(SVN_ERR_FS_SQLITE_ERROR
, NULL
,
110 ? _("Expected database row missing")
111 : _("Extra database row found"));
117 svn_fs__sqlite_step_done(svn_fs__sqlite_stmt_t
*stmt
)
119 return step_with_expectation(stmt
, FALSE
);
123 svn_fs__sqlite_step_row(svn_fs__sqlite_stmt_t
*stmt
)
125 return step_with_expectation(stmt
, TRUE
);
129 svn_fs__sqlite_step(svn_boolean_t
*got_row
, svn_fs__sqlite_stmt_t
*stmt
)
131 int sqlite_result
= sqlite3_step(stmt
->s3stmt
);
132 if (sqlite_result
!= SQLITE_DONE
&& sqlite_result
!= SQLITE_ROW
)
134 /* Extract the real error value with finalize. */
135 SVN_ERR(svn_fs__sqlite_finalize(stmt
));
136 /* This really should have thrown an error! */
140 *got_row
= (sqlite_result
== SQLITE_ROW
);
146 svn_fs__sqlite_bind_int64(svn_fs__sqlite_stmt_t
*stmt
,
150 SQLITE_ERR(sqlite3_bind_int64(stmt
->s3stmt
, slot
, val
), stmt
->db
);
155 svn_fs__sqlite_bind_text(svn_fs__sqlite_stmt_t
*stmt
,
159 SQLITE_ERR(sqlite3_bind_text(stmt
->s3stmt
, slot
, val
, -1, SQLITE_TRANSIENT
),
165 svn_fs__sqlite_column_text(svn_fs__sqlite_stmt_t
*stmt
, int column
)
167 return (const char *) sqlite3_column_text(stmt
->s3stmt
, column
);
171 svn_fs__sqlite_column_revnum(svn_fs__sqlite_stmt_t
*stmt
, int column
)
173 return (svn_revnum_t
) sqlite3_column_int64(stmt
->s3stmt
, column
);
177 svn_fs__sqlite_column_boolean(svn_fs__sqlite_stmt_t
*stmt
, int column
)
179 return (sqlite3_column_int64(stmt
->s3stmt
, column
) == 0
184 svn_fs__sqlite_column_int(svn_fs__sqlite_stmt_t
*stmt
, int column
)
186 return sqlite3_column_int(stmt
->s3stmt
, column
);
190 svn_fs__sqlite_finalize(svn_fs__sqlite_stmt_t
*stmt
)
192 SQLITE_ERR(sqlite3_finalize(stmt
->s3stmt
), stmt
->db
);
197 svn_fs__sqlite_reset(svn_fs__sqlite_stmt_t
*stmt
)
199 SQLITE_ERR(sqlite3_reset(stmt
->s3stmt
), stmt
->db
);
203 /* Time (in milliseconds) to wait for sqlite locks before giving up. */
204 #define BUSY_TIMEOUT 10000
206 static const char *schema_create_sql
[] = {
207 NULL
, /* An empty database is format 0 */
210 "PRAGMA auto_vacuum = 1;"
212 "CREATE TABLE mergeinfo (revision INTEGER NOT NULL, mergedfrom TEXT NOT "
213 "NULL, mergedto TEXT NOT NULL, mergedrevstart INTEGER NOT NULL, "
214 "mergedrevend INTEGER NOT NULL, inheritable INTEGER NOT NULL);"
216 "CREATE INDEX mi_mergedfrom_idx ON mergeinfo (mergedfrom);"
218 "CREATE INDEX mi_mergedto_idx ON mergeinfo (mergedto);"
220 "CREATE INDEX mi_revision_idx ON mergeinfo (revision);"
222 "CREATE TABLE mergeinfo_changed (revision INTEGER NOT NULL, path TEXT "
225 "CREATE UNIQUE INDEX mi_c_revpath_idx ON mergeinfo_changed (revision, path);"
227 "CREATE INDEX mi_c_path_idx ON mergeinfo_changed (path);"
229 "CREATE INDEX mi_c_revision_idx ON mergeinfo_changed (revision);"
233 "CREATE TABLE node_origins (node_id TEXT NOT NULL, node_rev_id TEXT NOT "
236 "CREATE UNIQUE INDEX no_ni_idx ON node_origins (node_id);"
240 static const int latest_schema_format
=
241 sizeof(schema_create_sql
)/sizeof(schema_create_sql
[0]) - 1;
245 upgrade_format(sqlite3
*db
, int current_format
, apr_pool_t
*pool
)
247 apr_pool_t
*iterpool
= svn_pool_create(pool
);
249 while (current_format
< latest_schema_format
)
251 const char *pragma_cmd
;
253 svn_pool_clear(iterpool
);
255 /* Go to the next format */
258 /* Run the upgrade SQL */
259 SVN_ERR(svn_fs__sqlite_exec(db
, schema_create_sql
[current_format
]));
261 /* Update the user version pragma */
262 pragma_cmd
= apr_psprintf(iterpool
,
263 "PRAGMA user_version = %d;",
265 SVN_ERR(svn_fs__sqlite_exec(db
, pragma_cmd
));
268 svn_pool_destroy(iterpool
);
274 /* Check the schema format of the database, upgrading it if necessary.
275 Return SVN_ERR_FS_UNSUPPORTED_FORMAT if the schema format is too new, or
276 SVN_ERR_FS_SQLITE_ERROR if an sqlite error occurs during
277 validation. Return SVN_NO_ERROR if everything is okay. */
279 check_format(sqlite3
*db
, apr_pool_t
*pool
)
281 svn_fs__sqlite_stmt_t
*stmt
;
284 SVN_ERR(svn_fs__sqlite_prepare(&stmt
, db
, "PRAGMA user_version;", pool
));
285 SVN_ERR(svn_fs__sqlite_step_row(stmt
));
287 /* Validate that the schema exists as expected and that the
288 schema and repository versions match. */
289 schema_format
= svn_fs__sqlite_column_int(stmt
, 0);
291 SVN_ERR(svn_fs__sqlite_finalize(stmt
));
293 if (schema_format
== latest_schema_format
)
295 else if (schema_format
< latest_schema_format
)
296 return upgrade_format(db
, schema_format
, pool
);
298 return svn_error_createf(SVN_ERR_FS_UNSUPPORTED_FORMAT
, NULL
,
299 _("Index schema format %d not "
300 "recognized"), schema_format
);
303 /* If possible, verify that SQLite was compiled in a thread-safe
306 init_sqlite(apr_pool_t
*pool
)
308 svn_boolean_t is_threadsafe
= TRUE
;
310 /* SQLite 3.5 allows verification of its thread-safety at runtime.
311 Older versions are simply expected to have been configured with
312 --enable-threadsafe, which compiles with -DSQLITE_THREADSAFE=1
313 (or -DTHREADSAFE, for older versions). */
314 #ifdef SVN_HAVE_SQLITE_THREADSAFE_PREDICATE
315 /* sqlite3_threadsafe() was available at Subversion 'configure'-time. */
316 is_threadsafe
= sqlite3_threadsafe();
317 #endif /* SVN_HAVE_SQLITE_THREADSAFE_PREDICATE */
320 return svn_error_create(SVN_ERR_FS_SQLITE_ERROR
, NULL
,
321 _("SQLite is required to be compiled and run in "
322 "thread-safe mode"));
327 svn_fs__sqlite_open(sqlite3
**db
, const char *repos_path
, apr_pool_t
*pool
)
330 static svn_boolean_t sqlite_initialized
= FALSE
;
332 if (! sqlite_initialized
)
334 /* There is a potential initialization race condition here, but
335 it currently isn't worth guarding against (e.g. with a mutex). */
336 SVN_ERR(init_sqlite(pool
));
337 sqlite_initialized
= TRUE
;
340 db_path
= svn_path_join(repos_path
, SVN_FS__SQLITE_DB_NAME
, pool
);
342 /* Open the database. */
343 SQLITE_ERR(sqlite3_open(db_path
, db
), *db
);
344 /* Retry until timeout when database is busy. */
345 SQLITE_ERR(sqlite3_busy_timeout(*db
, BUSY_TIMEOUT
), *db
);
347 sqlite3_trace(*db
, sqlite_tracer
, *db
);
350 SVN_ERR(svn_fs__sqlite_exec(*db
, "PRAGMA case_sensitive_like=on;"));
352 /* Validate the schema, upgrading if necessary. */
353 return check_format(*db
, pool
);
357 svn_fs__sqlite_close(sqlite3
*db
, svn_error_t
*err
)
359 int result
= sqlite3_close(db
);
360 /* If there's a pre-existing error, return it. */
361 /* ### If the connection close also fails, say something about it as well? */
363 SQLITE_ERR(result
, db
);
368 /* Create an sqlite DB for our mergeinfo index under PATH. Use POOL
369 for temporary allocations. */
371 svn_fs__sqlite_create_index(const char *path
, apr_pool_t
*pool
)
374 /* Opening the database will create it + schema if it's not already there. */
375 SVN_ERR(svn_fs__sqlite_open(&db
, path
, pool
));
376 return svn_fs__sqlite_close(db
, SVN_NO_ERROR
);