You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2013/02/22 15:56:54 UTC

svn commit: r1449068 - in /subversion/trunk: build/transform_sql.py subversion/libsvn_wc/wc-queries.sql subversion/libsvn_wc/wc_db.c subversion/tests/libsvn_wc/wc-queries-test.c

Author: rhuijben
Date: Fri Feb 22 14:56:54 2013
New Revision: 1449068

URL: http://svn.apache.org/r1449068
Log:
Make the switch detection code much easier to understand by introducing a few
more preprocessor sql functions.

This is partly a showcase of how we can reduce some c code complexity using
these functions.

* build/transform_sql.py
  (process_file): Add RELPATH_JOIN(x, y), RELPATH_SKIP_ANCESTOR(x, y) and
                  RELPATH_SKIP_JOIN(x, y, z) which is a combination of the
                  other two.

* subversion/libsvn_wc/wc-queries.sql
  (STMT_HAS_SWITCHED): Simplify query. Use additional argument instead of
    join.

  (STMT_HAS_SWITCHED_REPOS_ROOT,
   STMT_HAS_SWITCHED_WCROOT,
   STMT_HAS_SWITCHED_WCROOT_REPOS_ROOT): Remove queries that can now be
     handled by STMT_HAS_SWITCHED.

* subversion/libsvn_wc/wc_db.c
  (has_switched_subtrees): Use single query. Pass repository relative path.

* subversion/tests/libsvn_wc/wc-queries-test.c
  (slow_statements): Remove specialized selects on the entire wc.

Modified:
    subversion/trunk/build/transform_sql.py
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/tests/libsvn_wc/wc-queries-test.c

Modified: subversion/trunk/build/transform_sql.py
URL: http://svn.apache.org/viewvc/subversion/trunk/build/transform_sql.py?rev=1449068&r1=1449067&r2=1449068&view=diff
==============================================================================
--- subversion/trunk/build/transform_sql.py (original)
+++ subversion/trunk/build/transform_sql.py Fri Feb 22 14:56:54 2013
@@ -137,10 +137,6 @@ class Processor(object):
       # So for the root we can compare with > '' and < x'FFFF'. (This skips the
       # root itself and selects all descendants)
       #
-      ### RH: I implemented this first with a user defined Sqlite function. But
-      ### when I wrote the documentation for it, I found out I could just
-      ### define it this way, without losing the option of just dropping the
-      ### query in a plain sqlite3.
 
       # '/'+1 == '0'
       line = re.sub(
@@ -149,6 +145,48 @@ class Processor(object):
             r" AND ((\1) < CASE (\2) WHEN '' THEN X'FFFF' ELSE (\2) || '0' END))",
             line)
 
+      # RELPATH_SKIP_JOIN(x, y, z) skips the x prefix from z and the joins the
+      # result after y. In other words it replaces x with y, but follows the
+      # relpath rules.
+      line = re.sub(
+             r'RELPATH_SKIP_JOIN[(]([?]?[A-Za-z0-9_.]+), ' +
+                                 r'([?]?[A-Za-z0-9_.]+), ' +
+                                 r'([?]?[A-Za-z0-9_.]+)[)]',
+             r"(CASE WHEN (\1) = '' THEN RELPATH_JOIN(\2, \3) " +
+             r"WHEN (\2) = '' THEN RELPATH_SKIP_ANCESTOR(\1, \3) " +
+             r"WHEN SUBSTR((\3), 1, LENGTH(\1)) = (\1) " +
+             r"THEN " +
+                   r"CASE WHEN LENGTH(\1) = LENGTH(\3) THEN (\2) " +
+                        r"WHEN SUBSTR((\3), LENGTH(\1)+1, 1) = '/' " +
+                        r"THEN (\2) || SUBSTR((\3), LENGTH(\1)+1) " +
+                   r"END " +
+             r"END)",
+             line)
+
+      # RELPATH_JOIN(x, y) joins x to y following the svn_relpath_join() rules
+      line = re.sub(
+            r'RELPATH_JOIN[(]([?]?[A-Za-z0-9_.]+), ([?]?[A-Za-z0-9_.]+)[)]',
+            r"(CASE WHEN (\1) = '' THEN (\2) " +
+                  r"WHEN (\2) = '' THEN (\1) " +
+                 r"ELSE (\1) || '/' || (\2) " +
+            r"END)",
+            line)
+
+      # RELPATH_SKIP_ANCESTOR(x, y) skips the x prefix from y following the
+      # svn_relpath_skip_ancestor() rules. Returns NULL when y is not below X.
+      line = re.sub(
+             r'RELPATH_SKIP_ANCESTOR[(]([?]?[A-Za-z0-9_.]+), ' +
+                                     r'([?]?[A-Za-z0-9_.]+)[)]',
+             r"(CASE WHEN (\1) = '' THEN (\2) " +
+             r" WHEN SUBSTR((\2), 1, LENGTH(\1)) = (\1) " +
+             r" THEN " +
+                   r"CASE WHEN LENGTH(\1) = LENGTH(\2) THEN '' " +
+                        r"WHEN SUBSTR((\2), LENGTH(\1)+1, 1) = '/' " +
+                        r"THEN SUBSTR((\2), LENGTH(\1)+2) " +
+                   r"END" +
+             r" END)",
+            line)
+
       # Another preprocessing.
       for symbol, string in self.token_map.iteritems():
         # ### This doesn't sql-escape 'string'

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1449068&r1=1449067&r2=1449068&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Fri Feb 22 14:56:54 2013
@@ -1442,73 +1442,15 @@ WHERE wc_id = ?1
   AND properties IS NOT NULL
 LIMIT 1
 
-/* Determine if there is some switched subtree in just SQL. This looks easy,
-   but it really isn't, because we don't have a simple (and optimizable)
-   path join operation in SQL.
-
-   To work around that we have 4 different cases:
-      * Check on a node that is neither wcroot nor repos root
-      * Check on a node that is repos_root, but not wcroot.
-      * Check on a node that is wcroot, but not repos root.
-      * Check on a node that is both wcroot and repos root.
-
-   To make things easier, our testsuite is usually in that last category,
-   while normal working copies are almost always in one of the others.
-*/
 -- STMT_HAS_SWITCHED
-SELECT o.repos_path || '/' || SUBSTR(s.local_relpath, LENGTH(?2)+2) AS expected
-       /*,s.local_relpath, s.repos_path, o.local_relpath, o.repos_path*/
-FROM nodes AS o
-LEFT JOIN nodes AS s
-ON o.wc_id = s.wc_id
-   AND IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2)
-   AND s.op_depth = 0
-   AND s.repos_id = o.repos_id
-   AND s.file_external IS NULL
-WHERE o.wc_id = ?1 AND o.local_relpath=?2 AND o.op_depth=0
-  AND s.repos_path != expected
-LIMIT 1
-
--- STMT_HAS_SWITCHED_REPOS_ROOT
-SELECT SUBSTR(s.local_relpath, LENGTH(?2)+2) AS expected
-       /*,s.local_relpath, s.repos_path, o.local_relpath, o.repos_path*/
-FROM nodes AS o
-LEFT JOIN nodes AS s
-ON o.wc_id = s.wc_id
-   AND IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2)
-   AND s.op_depth = 0
-   AND s.repos_id = o.repos_id
-   AND s.file_external IS NULL
-WHERE o.wc_id = ?1 AND o.local_relpath=?2 AND o.op_depth=0
-  AND s.repos_path != expected
-LIMIT 1
-
--- STMT_HAS_SWITCHED_WCROOT
-SELECT o.repos_path || '/' || s.local_relpath AS expected
-       /*,s.local_relpath, s.repos_path, o.local_relpath, o.repos_path*/
-FROM nodes AS o
-LEFT JOIN nodes AS s
-ON o.wc_id = s.wc_id
-   AND s.local_relpath != ''
-   AND s.op_depth = 0
-   AND s.repos_id = o.repos_id
-   AND s.file_external IS NULL
-WHERE o.wc_id = ?1 AND o.local_relpath=?2 AND o.op_depth=0
-  AND s.repos_path != expected
-LIMIT 1
-
--- STMT_HAS_SWITCHED_WCROOT_REPOS_ROOT
-SELECT s.local_relpath AS expected
-       /*,s.local_relpath, s.repos_path, o.local_relpath, o.repos_path*/
-FROM nodes AS o
-LEFT JOIN nodes AS s
-ON o.wc_id = s.wc_id
-   AND s.local_relpath != ''
-   AND s.op_depth = 0
-   AND s.repos_id = o.repos_id
-   AND s.file_external IS NULL
-WHERE o.wc_id = ?1 AND o.local_relpath=?2 AND o.op_depth=0
-  AND s.repos_path != expected
+SELECT 1
+FROM nodes
+WHERE wc_id = ?1
+  AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+  AND op_depth = 0
+  AND file_external IS NULL
+  AND presence IN (MAP_NORMAL, MAP_INCOMPLETE)
+  AND repos_path IS NOT RELPATH_SKIP_JOIN(?2, ?3, local_relpath)
 LIMIT 1
 
 -- STMT_SELECT_BASE_FILES_RECURSIVE

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1449068&r1=1449067&r2=1449068&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Fri Feb 22 14:56:54 2013
@@ -14271,36 +14271,9 @@ has_switched_subtrees(svn_boolean_t *is_
         }
     }
 
-  /* Select the right query based on whether the node is the wcroot, repos root
-     or neither. */
-  if (*local_relpath == '\0')
-    {
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                        (*repos_relpath == '\0')
-                            ? STMT_HAS_SWITCHED_WCROOT_REPOS_ROOT
-                            : STMT_HAS_SWITCHED_WCROOT));
-    }
-  else
-    {
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                        (*repos_relpath == '\0')
-                            ? STMT_HAS_SWITCHED_REPOS_ROOT
-                            : STMT_HAS_SWITCHED));
-    }
-
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
-
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_HAS_SWITCHED));
+  SVN_ERR(svn_sqlite__bindf(stmt, "iss", wcroot->wc_id, local_relpath, repos_relpath));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  /* ### Please keep this code for a little while or until the code has enough
-         test coverage. These columns are only available in the 4 queries
-         after their selection is uncommented. */
-/*if (have_row)
-    SVN_DBG(("Expected %s for %s, but got %s. Origin=%s with %s\n",
-             svn_sqlite__column_text(stmt, 0, scratch_pool),
-             svn_sqlite__column_text(stmt, 1, scratch_pool),
-             svn_sqlite__column_text(stmt, 2, scratch_pool),
-             svn_sqlite__column_text(stmt, 3, scratch_pool),
-             svn_sqlite__column_text(stmt, 4, scratch_pool)));*/
   if (have_row)
     *is_switched = TRUE;
   SVN_ERR(svn_sqlite__reset(stmt));

Modified: subversion/trunk/subversion/tests/libsvn_wc/wc-queries-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/wc-queries-test.c?rev=1449068&r1=1449067&r2=1449068&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/wc-queries-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/wc-queries-test.c Fri Feb 22 14:56:54 2013
@@ -82,8 +82,6 @@ static const int schema_statements[] =
 static const int slow_statements[] =
 {
   /* Operate on the entire WC */
-  STMT_HAS_SWITCHED_WCROOT,             /* wc scan op_depth 0 */
-  STMT_HAS_SWITCHED_WCROOT_REPOS_ROOT,  /* wc scan op_depth 0 */
   STMT_SELECT_ALL_NODES,                /* schema validation code */
 
   /* Is there a record? ### Can we somehow check for LIMIT 1? */