summaryrefslogtreecommitdiff
path: root/subversion/libsvn_wc/wc-metadata.sql
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_wc/wc-metadata.sql')
-rw-r--r--subversion/libsvn_wc/wc-metadata.sql292
1 files changed, 231 insertions, 61 deletions
diff --git a/subversion/libsvn_wc/wc-metadata.sql b/subversion/libsvn_wc/wc-metadata.sql
index 18f8fc6..e4b226e 100644
--- a/subversion/libsvn_wc/wc-metadata.sql
+++ b/subversion/libsvn_wc/wc-metadata.sql
@@ -23,17 +23,16 @@
/*
* the KIND column in these tables has one of the following values
- * (documented in the corresponding C type #svn_wc__db_kind_t):
+ * (documented in the corresponding C type #svn_kind_t):
* "file"
* "dir"
* "symlink"
* "unknown"
- * "subdir"
*
* the PRESENCE column in these tables has one of the following values
* (see also the C type #svn_wc__db_status_t):
* "normal"
- * "absent" -- server has declared it "absent" (ie. authz failure)
+ * "server-excluded" -- server has declared it excluded (ie. authz failure)
* "excluded" -- administratively excluded (ie. sparse WC)
* "not-present" -- node not present at this REV
* "incomplete" -- state hasn't been filled in
@@ -108,7 +107,8 @@ CREATE TABLE PRISTINE (
md5_checksum TEXT NOT NULL
);
-
+CREATE INDEX I_PRISTINE_MD5 ON PRISTINE (md5_checksum);
+
/* ------------------------------------------------------------------------- */
/* The ACTUAL_NODE table describes text changes and property changes
@@ -170,7 +170,10 @@ CREATE TABLE ACTUAL_NODE (
/* stsp: This is meant for text conflicts, right? What about property
conflicts? Why do we need these in a column to refer to the
pristine store? Can't we just parse the checksums from
- conflict_data as well? */
+ conflict_data as well?
+ rhuijben: Because that won't allow triggers to handle refcounts.
+ We would have to scan all conflict skels before cleaning up the
+ a single file from the pristine stor */
older_checksum TEXT REFERENCES PRISTINE (checksum),
left_checksum TEXT REFERENCES PRISTINE (checksum),
right_checksum TEXT REFERENCES PRISTINE (checksum),
@@ -178,8 +181,8 @@ CREATE TABLE ACTUAL_NODE (
PRIMARY KEY (wc_id, local_relpath)
);
-CREATE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath);
-CREATE INDEX I_ACTUAL_CHANGELIST ON ACTUAL_NODE (changelist);
+CREATE UNIQUE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath,
+ local_relpath);
/* ------------------------------------------------------------------------- */
@@ -250,19 +253,10 @@ PRAGMA user_version =
op_depth values are not normally visible to the user but may become
visible after reverting local changes.
- ### The following text needs revision
-
- Each row in BASE_NODE has an associated row NODE_DATA. Additionally, each
- row in WORKING_NODE has one or more associated rows in NODE_DATA.
-
This table contains full node descriptions for nodes in either the BASE
or WORKING trees as described in notes/wc-ng/design. Fields relate
both to BASE and WORKING trees, unless documented otherwise.
- ### This table is to be integrated into the SCHEMA statement as soon
- the experimental status of NODES is lifted.
- ### This table superseeds NODE_DATA
-
For illustration, with a scenario like this:
# (0)
@@ -272,12 +266,11 @@ PRAGMA user_version =
touch foo/bar
svn add foo/bar # (2)
- , these are the NODES for the path foo/bar (before single-db, the
- numbering of op_depth is still a bit different):
+ , these are the NODES table rows for the path foo/bar:
- (0) BASE_NODE -----> NODES (op_depth == 0)
- (1) NODES (op_depth == 1) ( <----_ )
- (2) NODES (op_depth == 2) <----- WORKING_NODE
+ (0) "BASE" ---> NODES (op_depth == 0)
+ (1) NODES (op_depth == 1)
+ (2) NODES (op_depth == 2)
0 is the original data for foo/bar before 'svn rm foo' (if it existed).
1 is the data for foo/bar copied in from ^/moo/bar.
@@ -316,8 +309,8 @@ CREATE TABLE NODES (
BASE node, the location of the initial checkout.
When op_depth != 0, they indicate where this node was copied/moved from.
- In this case, the fields are set only on the root of the operation,
- and are NULL for all children. */
+ In this case, the fields are set for the root of the operation and for all
+ children. */
repos_id INTEGER REFERENCES REPOSITORY (id),
repos_path TEXT,
revision INTEGER,
@@ -364,7 +357,7 @@ CREATE TABLE NODES (
current 'op_depth'. This state is badly named, it should be
something like 'deleted'.
- absent: in the 'BASE' tree this is a node that is excluded by
+ server-excluded: in the 'BASE' tree this is a node that is excluded by
authz. The name of the node is known from the parent, but no
other information is available. Not valid in the 'WORKING'
tree as there is no way to commit such a node.
@@ -384,16 +377,19 @@ CREATE TABLE NODES (
perhaps add a column called "moved_from". */
/* Boolean value, specifying if this node was moved here (rather than just
- copied). The source of the move is specified in copyfrom_*. */
+ copied). This is set on all the nodes in the moved tree. The source of
+ the move is implied by a different node with a moved_to column pointing
+ at the root node of the moved tree. */
moved_here INTEGER,
/* If the underlying node was moved away (rather than just deleted), this
- specifies the local_relpath of where the BASE node was moved to.
+ specifies the local_relpath of where the node was moved to.
This is set only on the root of a move, and is NULL for all children.
- Note that moved_to never refers to *this* node. It always refers
- to the "underlying" node, whether that is BASE or a child node
- implied from a parent's move/copy. */
+ The op-depth of the moved-to node is not recorded. A moved_to path
+ always points at a node within the highest op-depth layer at the
+ destination. This invariant must be maintained by operations which
+ change existing move information. */
moved_to TEXT,
@@ -402,8 +398,11 @@ CREATE TABLE NODES (
/* the kind of the new node. may be "unknown" if the node is not present. */
kind TEXT NOT NULL,
- /* serialized skel of this node's properties. NULL if we
- have no information about the properties (a non-present node). */
+ /* serialized skel of this node's properties (when presence is 'normal' or
+ 'incomplete'); an empty skel or NULL indicates no properties. NULL if
+ we have no information about the properties (any other presence).
+ TODO: Choose & require a single representation for 'no properties'.
+ */
properties BLOB,
/* NULL depth means "default" (typically svn_depth_infinity) */
@@ -460,24 +459,27 @@ CREATE TABLE NODES (
node does not have any dav-cache. */
dav_cache BLOB,
- /* The serialized file external information. */
- /* ### hack. hack. hack.
- ### This information is already stored in properties, but because the
- ### current working copy implementation is such a pain, we can't
- ### readily retrieve it, hence this temporary cache column.
- ### When it is removed, be sure to remove the extra column from
- ### the db-tests.
-
- ### Note: This is only here as a hack, and should *NOT* be added
- ### to any wc_db APIs. */
- file_external TEXT,
+ /* Is there a file external in this location. NULL if there
+ is no file external, otherwise '1' */
+ /* ### Originally we had a wc-1.0 like skel in this place, so we
+ ### check for NULL.
+ ### In Subversion 1.7 we defined this column as TEXT, but Sqlite
+ ### only uses this information for deciding how to optimize
+ ### anyway. */
+ file_external INTEGER,
+ /* serialized skel of this node's inherited properties. NULL if this
+ is not the BASE of a WC root node. */
+ inherited_props BLOB,
PRIMARY KEY (wc_id, local_relpath, op_depth)
);
-CREATE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath, op_depth);
+CREATE UNIQUE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath,
+ local_relpath, op_depth);
+/* I_NODES_MOVED is introduced in format 30 */
+CREATE UNIQUE INDEX I_NODES_MOVED ON NODES (wc_id, moved_to, op_depth);
/* Many queries have to filter the nodes table to pick only that version
of each node with the highest (most "current") op_depth. This view
@@ -495,7 +497,7 @@ CREATE VIEW NODES_CURRENT AS
AND n2.local_relpath = n.local_relpath);
/* Many queries have to filter the nodes table to pick only that version
- of each node with the base (least "current") op_depth. This view
+ of each node with the BASE ("as checked out") op_depth. This view
does the heavy lifting for such queries. */
CREATE VIEW NODES_BASE AS
SELECT * FROM nodes
@@ -539,13 +541,13 @@ CREATE TABLE EXTERNALS (
local_relpath TEXT NOT NULL,
/* The working copy root can't be recorded as an external in itself
- so this will never be NULL. */
+ so this will never be NULL. ### ATM only inserted, never queried */
parent_relpath TEXT NOT NULL,
/* Repository location fields */
repos_id INTEGER NOT NULL REFERENCES REPOSITORY (id),
- /* Either 'normal' or 'excluded' */
+ /* Either MAP_NORMAL or MAP_EXCLUDED */
presence TEXT NOT NULL,
/* the kind of the external. */
@@ -566,22 +568,75 @@ CREATE TABLE EXTERNALS (
PRIMARY KEY (wc_id, local_relpath)
);
-CREATE INDEX I_EXTERNALS_PARENT ON EXTERNALS (wc_id, parent_relpath);
CREATE UNIQUE INDEX I_EXTERNALS_DEFINED ON EXTERNALS (wc_id,
def_local_relpath,
local_relpath);
+/* ------------------------------------------------------------------------- */
+/* This statement provides SQLite with the necessary information about our
+ indexes to make better decisions in the query planner.
+
+ For every interesting index this contains a number of rows where the
+ statistics ar calculated for and then for every column in the index the
+ average number of rows with the same value in all columns left of this
+ column including the column itself.
+
+ See http://www.sqlite.org/fileformat2.html#stat1tab for more details.
+
+ The important thing here is that this tells Sqlite that the wc_id column
+ of the NODES and ACTUAL_NODE table is usually a single value, so queries
+ should use more than one column for index usage.
+
+ The current hints describe NODES+ACTUAL_NODE as a working copy with
+ 8000 nodes in 1 a single working copy(=wc_id), 10 nodes per directory
+ and an average of 2 op-depth layers per node.
+
+ The number of integers must be number of index columns + 1, which is
+ verified via the test_schema_statistics() test.
+ */
+-- STMT_INSTALL_SCHEMA_STATISTICS
+ANALYZE sqlite_master; /* Creates empty sqlite_stat1 if necessary */
+
+DELETE FROM sqlite_stat1
+WHERE tbl in ('NODES', 'ACTUAL_NODE', 'LOCK', 'WC_LOCK');
+
+INSERT OR REPLACE INTO sqlite_stat1(tbl, idx, stat) VALUES
+ ('NODES', 'sqlite_autoindex_NODES_1', '8000 8000 2 1');
+INSERT OR REPLACE INTO sqlite_stat1(tbl, idx, stat) VALUES
+ ('NODES', 'I_NODES_PARENT', '8000 8000 10 2 1');
+/* Tell a lie: We ignore that 99.9% of all moved_to values are NULL */
+INSERT OR REPLACE INTO sqlite_stat1(tbl, idx, stat) VALUES
+ ('NODES', 'I_NODES_MOVED', '8000 8000 1 1');
+
+INSERT OR REPLACE INTO sqlite_stat1(tbl, idx, stat) VALUES
+ ('ACTUAL_NODE', 'sqlite_autoindex_ACTUAL_NODE_1', '8000 8000 1');
+INSERT OR REPLACE INTO sqlite_stat1(tbl, idx, stat) VALUES
+ ('ACTUAL_NODE', 'I_ACTUAL_PARENT', '8000 8000 10 1');
+
+INSERT OR REPLACE INTO sqlite_stat1(tbl, idx, stat) VALUES
+ ('LOCK', 'sqlite_autoindex_LOCK_1', '100 100 1');
+
+INSERT OR REPLACE INTO sqlite_stat1(tbl, idx, stat) VALUES
+ ('WC_LOCK', 'sqlite_autoindex_WC_LOCK_1', '100 100 1');
+
+/* sqlite_autoindex_WORK_QUEUE_1 doesn't exist because WORK_QUEUE is
+ a INTEGER PRIMARY KEY AUTOINCREMENT table */
+
+ANALYZE sqlite_master; /* Loads sqlite_stat1 data for query optimizer */
+/* ------------------------------------------------------------------------- */
+
/* Format 20 introduces NODES and removes BASE_NODE and WORKING_NODE */
-- STMT_UPGRADE_TO_20
-UPDATE BASE_NODE SET checksum=(SELECT checksum FROM pristine
- WHERE md5_checksum=BASE_NODE.checksum)
-WHERE EXISTS(SELECT 1 FROM pristine WHERE md5_checksum=BASE_NODE.checksum);
+UPDATE BASE_NODE SET checksum = (SELECT checksum FROM pristine
+ WHERE md5_checksum = BASE_NODE.checksum)
+WHERE EXISTS (SELECT 1 FROM pristine WHERE md5_checksum = BASE_NODE.checksum);
-UPDATE WORKING_NODE SET checksum=(SELECT checksum FROM pristine
- WHERE md5_checksum=WORKING_NODE.checksum)
-WHERE EXISTS(SELECT 1 FROM pristine WHERE md5_checksum=WORKING_NODE.checksum);
+UPDATE WORKING_NODE SET checksum = (SELECT checksum FROM pristine
+ WHERE md5_checksum = WORKING_NODE.checksum)
+WHERE EXISTS (SELECT 1 FROM pristine
+ WHERE md5_checksum = WORKING_NODE.checksum);
INSERT INTO NODES (
wc_id, local_relpath, op_depth, parent_relpath,
@@ -626,6 +681,15 @@ PRAGMA user_version = 20;
-- STMT_UPGRADE_TO_21
PRAGMA user_version = 21;
+/* For format 21 bump code */
+-- STMT_UPGRADE_21_SELECT_OLD_TREE_CONFLICT
+SELECT wc_id, local_relpath, tree_conflict_data
+FROM actual_node
+WHERE tree_conflict_data IS NOT NULL
+
+/* For format 21 bump code */
+-- STMT_UPGRADE_21_ERASE_OLD_CONFLICTS
+UPDATE actual_node SET tree_conflict_data = NULL
/* ------------------------------------------------------------------------- */
@@ -647,6 +711,9 @@ PRAGMA user_version = 22;
-- STMT_UPGRADE_TO_23
PRAGMA user_version = 23;
+-- STMT_UPGRADE_23_HAS_WORKING_NODES
+SELECT 1 FROM nodes WHERE op_depth > 0
+LIMIT 1
/* ------------------------------------------------------------------------- */
@@ -696,6 +763,15 @@ PRAGMA user_version = 26;
-- STMT_UPGRADE_TO_27
PRAGMA user_version = 27;
+/* For format 27 bump code */
+-- STMT_UPGRADE_27_HAS_ACTUAL_NODES_CONFLICTS
+SELECT 1 FROM actual_node
+WHERE NOT ((prop_reject IS NULL) AND (conflict_old IS NULL)
+ AND (conflict_new IS NULL) AND (conflict_working IS NULL)
+ AND (tree_conflict_data IS NULL))
+LIMIT 1
+
+
/* ------------------------------------------------------------------------- */
/* Format 28 involves no schema changes, it only converts MD5 pristine
@@ -703,9 +779,9 @@ PRAGMA user_version = 27;
-- STMT_UPGRADE_TO_28
-UPDATE NODES SET checksum=(SELECT checksum FROM pristine
- WHERE md5_checksum=nodes.checksum)
-WHERE EXISTS(SELECT 1 FROM pristine WHERE md5_checksum=nodes.checksum);
+UPDATE NODES SET checksum = (SELECT checksum FROM pristine
+ WHERE md5_checksum = nodes.checksum)
+WHERE EXISTS (SELECT 1 FROM pristine WHERE md5_checksum = nodes.checksum);
PRAGMA user_version = 28;
@@ -751,6 +827,97 @@ PRAGMA user_version = 29;
/* ------------------------------------------------------------------------- */
+/* Format 30 creates a new NODES index for move information, and a new
+ PRISTINE index for the md5_checksum column. It also activates use of
+ skel-based conflict storage -- see notes/wc-ng/conflict-storage-2.0.
+ It also renames the "absent" presence to "server-excluded". */
+-- STMT_UPGRADE_TO_30
+CREATE UNIQUE INDEX IF NOT EXISTS I_NODES_MOVED
+ON NODES (wc_id, moved_to, op_depth);
+
+CREATE INDEX IF NOT EXISTS I_PRISTINE_MD5 ON PRISTINE (md5_checksum);
+
+UPDATE nodes SET presence = "server-excluded" WHERE presence = "absent";
+
+/* Just to be sure clear out file external skels from pre 1.7.0 development
+ working copies that were never updated by 1.7.0+ style clients */
+UPDATE nodes SET file_external=1 WHERE file_external IS NOT NULL;
+
+-- STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE
+SELECT wc_id, local_relpath,
+ conflict_old, conflict_working, conflict_new, prop_reject, tree_conflict_data
+FROM actual_node
+WHERE conflict_old IS NOT NULL
+ OR conflict_working IS NOT NULL
+ OR conflict_new IS NOT NULL
+ OR prop_reject IS NOT NULL
+ OR tree_conflict_data IS NOT NULL
+ORDER by wc_id, local_relpath
+
+-- STMT_UPGRADE_30_SET_CONFLICT
+UPDATE actual_node SET conflict_data = ?3, conflict_old = NULL,
+ conflict_working = NULL, conflict_new = NULL, prop_reject = NULL,
+ tree_conflict_data = NULL
+WHERE wc_id = ?1 and local_relpath = ?2
+
+/* ------------------------------------------------------------------------- */
+
+/* Format 31 adds the inherited_props column to the NODES table. C code then
+ initializes the update/switch roots to make sure future updates fetch the
+ inherited properties */
+-- STMT_UPGRADE_TO_31_ALTER_TABLE
+ALTER TABLE NODES ADD COLUMN inherited_props BLOB;
+-- STMT_UPGRADE_TO_31_FINALIZE
+DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST;
+DROP INDEX IF EXISTS I_EXTERNALS_PARENT;
+
+DROP INDEX I_NODES_PARENT;
+CREATE UNIQUE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath,
+ local_relpath, op_depth);
+
+DROP INDEX I_ACTUAL_PARENT;
+CREATE UNIQUE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath,
+ local_relpath);
+
+PRAGMA user_version = 31;
+
+-- STMT_UPGRADE_31_SELECT_WCROOT_NODES
+/* Select all base nodes which are the root of a WC, including
+ switched subtrees, but excluding those which map to the root
+ of the repos.
+
+ ### IPROPS: Is this query horribly inefficient? Quite likely,
+ ### but it only runs during an upgrade, so do we care? */
+SELECT l.wc_id, l.local_relpath FROM nodes as l
+LEFT OUTER JOIN nodes as r
+ON l.wc_id = r.wc_id
+ AND r.local_relpath = l.parent_relpath
+ AND r.op_depth = 0
+WHERE l.op_depth = 0
+ AND l.repos_path != ''
+ AND ((l.repos_id IS NOT r.repos_id)
+ OR (l.repos_path IS NOT RELPATH_SKIP_JOIN(r.local_relpath, r.repos_path, l.local_relpath)))
+
+
+/* ------------------------------------------------------------------------- */
+/* Format 32 .... */
+-- STMT_UPGRADE_TO_32
+
+/* Drop old index. ### Remove this part from the upgrade to 31 once bumped */
+DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST;
+DROP INDEX IF EXISTS I_EXTERNALS_PARENT;
+CREATE INDEX I_EXTERNALS_PARENT ON EXTERNALS (wc_id, parent_relpath);
+
+DROP INDEX I_NODES_PARENT;
+CREATE UNIQUE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath,
+ local_relpath, op_depth);
+
+DROP INDEX I_ACTUAL_PARENT;
+CREATE UNIQUE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath,
+ local_relpath);
+
+/* ------------------------------------------------------------------------- */
+
/* Format YYY introduces new handling for conflict information. */
-- format: YYY
@@ -763,9 +930,12 @@ PRAGMA user_version = 29;
number will be, however, so we're just marking it as 99 for now. */
-- format: 99
-/* TODO: Rename the "absent" presence value to "server-excluded" before
- the 1.7 release. wc_db.c and this file have references to "absent" which
- still need to be changed to "server-excluded". */
+/* TODO: Un-confuse *_revision column names in the EXTERNALS table to
+ "-r<operative> foo@<peg>", as suggested by the patch attached to
+ http://svn.haxx.se/dev/archive-2011-09/0478.shtml */
+/* TODO: Remove column parent_relpath from EXTERNALS. We're not using it and
+ never will. It's not interesting like in the NODES table: the external's
+ parent path may be *anything*: unversioned, "behind" a another WC... */
/* Now "drop" the tree_conflict_data column from actual_node. */
CREATE TABLE ACTUAL_NODE_BACKUP (
@@ -803,8 +973,8 @@ CREATE TABLE ACTUAL_NODE (
PRIMARY KEY (wc_id, local_relpath)
);
-CREATE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath);
-CREATE INDEX I_ACTUAL_CHANGELIST ON ACTUAL_NODE (changelist);
+CREATE UNIQUE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath,
+ local_relpath);
INSERT INTO ACTUAL_NODE SELECT
wc_id, local_relpath, parent_relpath, properties, conflict_old,