1251881Speter/*
2251881Speter * wc_db_util.c :  Various util functions for wc_db(_pdh)
3251881Speter *
4251881Speter * ====================================================================
5251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
6251881Speter *    or more contributor license agreements.  See the NOTICE file
7251881Speter *    distributed with this work for additional information
8251881Speter *    regarding copyright ownership.  The ASF licenses this file
9251881Speter *    to you under the Apache License, Version 2.0 (the
10251881Speter *    "License"); you may not use this file except in compliance
11251881Speter *    with the License.  You may obtain a copy of the License at
12251881Speter *
13251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
14251881Speter *
15251881Speter *    Unless required by applicable law or agreed to in writing,
16251881Speter *    software distributed under the License is distributed on an
17251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18251881Speter *    KIND, either express or implied.  See the License for the
19251881Speter *    specific language governing permissions and limitations
20251881Speter *    under the License.
21251881Speter * ====================================================================
22251881Speter */
23251881Speter
24251881Speter/* About this file:
25251881Speter   This file is meant to be a stash of fairly low-level functions used by both
26251881Speter   wc_db.c and wc_db_pdh.c.  In breaking stuff out of the monolithic wc_db.c,
27251881Speter   I have discovered that some utility functions are used by bits in both
28251881Speter   files.  Rather than shoehorn those functions into one file or the other, or
29251881Speter   create circular dependencies between the files, I felt a third file, with
30251881Speter   a well-defined scope, would be sensible.  History will judge its effect.
31251881Speter
32251881Speter   The goal of it file is simple: just execute SQLite statements.  That is,
33251881Speter   functions in this file should have no knowledge of pdh's or db's, and
34251881Speter   should just operate on the raw sdb object.  If a function requires more
35251881Speter   information than that, it shouldn't be in here.  -hkw
36251881Speter */
37251881Speter
38251881Speter#define SVN_WC__I_AM_WC_DB
39251881Speter
40251881Speter#include "svn_dirent_uri.h"
41251881Speter#include "private/svn_sqlite.h"
42251881Speter
43251881Speter#include "wc.h"
44251881Speter#include "adm_files.h"
45251881Speter#include "wc_db_private.h"
46251881Speter#include "wc-queries.h"
47251881Speter
48251881Speter#include "svn_private_config.h"
49251881Speter
50251881SpeterWC_QUERIES_SQL_DECLARE_STATEMENTS(statements);
51251881Speter
52251881Speter
53251881Speter
54251881Speter/* */
55251881Spetersvn_error_t *
56251881Spetersvn_wc__db_util_fetch_wc_id(apr_int64_t *wc_id,
57251881Speter                            svn_sqlite__db_t *sdb,
58251881Speter                            apr_pool_t *scratch_pool)
59251881Speter{
60251881Speter  svn_sqlite__stmt_t *stmt;
61251881Speter  svn_boolean_t have_row;
62251881Speter
63251881Speter  /* ### cheat. we know there is just one WORKING_COPY row, and it has a
64251881Speter     ### NULL value for local_abspath. */
65251881Speter  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_WCROOT_NULL));
66251881Speter  SVN_ERR(svn_sqlite__step(&have_row, stmt));
67251881Speter  if (!have_row)
68251881Speter    return svn_error_createf(SVN_ERR_WC_CORRUPT, svn_sqlite__reset(stmt),
69251881Speter                             _("Missing a row in WCROOT."));
70251881Speter
71251881Speter  SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 0));
72251881Speter  *wc_id = svn_sqlite__column_int64(stmt, 0);
73251881Speter
74251881Speter  return svn_error_trace(svn_sqlite__reset(stmt));
75251881Speter}
76251881Speter
77251881Speter
78251881Speter
79251881Speter
80251881Speter/* An SQLite application defined function that allows SQL queries to
81251881Speter   use "relpath_depth(local_relpath)".  */
82251881Speterstatic svn_error_t *
83251881Speterrelpath_depth_sqlite(svn_sqlite__context_t *sctx,
84251881Speter                     int argc,
85251881Speter                     svn_sqlite__value_t *values[],
86299742Sdim                     void *baton)
87251881Speter{
88251881Speter  const char *path = NULL;
89251881Speter  apr_int64_t depth;
90251881Speter
91251881Speter  if (argc == 1 && svn_sqlite__value_type(values[0]) == SVN_SQLITE__TEXT)
92251881Speter    path = svn_sqlite__value_text(values[0]);
93251881Speter  if (!path)
94251881Speter    {
95251881Speter      svn_sqlite__result_null(sctx);
96251881Speter      return SVN_NO_ERROR;
97251881Speter    }
98251881Speter
99251881Speter  depth = *path ? 1 : 0;
100251881Speter  while (*path)
101251881Speter    {
102251881Speter      if (*path == '/')
103251881Speter        ++depth;
104251881Speter      ++path;
105251881Speter    }
106251881Speter  svn_sqlite__result_int64(sctx, depth);
107251881Speter
108251881Speter  return SVN_NO_ERROR;
109251881Speter}
110251881Speter
111251881Speter
112251881Spetersvn_error_t *
113251881Spetersvn_wc__db_util_open_db(svn_sqlite__db_t **sdb,
114251881Speter                        const char *dir_abspath,
115251881Speter                        const char *sdb_fname,
116251881Speter                        svn_sqlite__mode_t smode,
117251881Speter                        svn_boolean_t exclusive,
118299742Sdim                        apr_int32_t timeout,
119251881Speter                        const char *const *my_statements,
120251881Speter                        apr_pool_t *result_pool,
121251881Speter                        apr_pool_t *scratch_pool)
122251881Speter{
123251881Speter  const char *sdb_abspath = svn_wc__adm_child(dir_abspath, sdb_fname,
124251881Speter                                              scratch_pool);
125251881Speter
126251881Speter  if (smode != svn_sqlite__mode_rwcreate)
127251881Speter    {
128251881Speter      svn_node_kind_t kind;
129251881Speter
130251881Speter      /* A file stat is much cheaper then a failed database open handled
131251881Speter         by SQLite. */
132251881Speter      SVN_ERR(svn_io_check_path(sdb_abspath, &kind, scratch_pool));
133251881Speter
134251881Speter      if (kind != svn_node_file)
135251881Speter        return svn_error_createf(APR_ENOENT, NULL,
136251881Speter                                 _("Working copy database '%s' not found"),
137251881Speter                                 svn_dirent_local_style(sdb_abspath,
138251881Speter                                                        scratch_pool));
139251881Speter    }
140251881Speter
141251881Speter  SVN_ERR(svn_sqlite__open(sdb, sdb_abspath, smode,
142251881Speter                           my_statements ? my_statements : statements,
143299742Sdim                           0, NULL, timeout, result_pool, scratch_pool));
144251881Speter
145251881Speter  if (exclusive)
146251881Speter    SVN_ERR(svn_sqlite__exec_statements(*sdb, STMT_PRAGMA_LOCKING_MODE));
147251881Speter
148251881Speter  SVN_ERR(svn_sqlite__create_scalar_function(*sdb, "relpath_depth", 1,
149299742Sdim                                             TRUE /* deterministic */,
150251881Speter                                             relpath_depth_sqlite, NULL));
151251881Speter
152251881Speter  return SVN_NO_ERROR;
153251881Speter}
154251881Speter
155