You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2011/05/14 20:19:12 UTC

svn commit: r1103177 - in /subversion/trunk/subversion/libsvn_wc: wc-queries.sql wc_db.c

Author: hwright
Date: Sat May 14 18:19:11 2011
New Revision: 1103177

URL: http://svn.apache.org/viewvc?rev=1103177&view=rev
Log:
Implement some ideas I've had regarding target selection and performing
various operations.  When setting the changelist, populate a temporary table
with the list of targets we are setting, and then do the operation using
that list.

This segregates the target selection from the operation, making the former
generalizable for more operations.  It's all done in a transaction for speed,
and eliminates a number of shortcuts and optimizations which were not
very straightforward.

* subversion/libsvn_wc/wc-queries.sql
  (STMT_SELECT_ACTUAL_CHANGELIST,
   STMT_UPDATE_ACTUAL_CHANGELISTS,
   STMT_CREATE_TARGETS_LIST,
   STMT_DROP_TARGETS_LIST,
   STMT_INSERT_TARGETS_LIST,
   STMT_SELECT_TARGETS,
   STMT_INSERT_ACTUAL_EMPTIES,
   STMT_DELETE_ACTUAL_EMPTIES): New.
  (STMT_UPDATE_ACTUAL_CHANGELIST_FILTER_CHANGELIST,
   STMT_UPDATE_ACTUAL_CHANGELIST,
   STMT_INSERT_ACTUAL_CHANGELIST): Remove.

* subversion/libsvn_wc/wc_db.c
  (run_final_query): Run multiple final queries.
  (populate_targets_tree): New.
  (dump_targets): New, commented out.
  (set_changelist_baton_t): Add depth member.
  (set_changelist_txn): Use the new paradigm to select our changelist targets
    and set them.
  (svn_wc__db_op_set_changelist): Run the extra finalization query.
  (svn_wc__db_op_delete): Update finalization step.

Modified:
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc_db.c

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1103177&r1=1103176&r2=1103177&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Sat May 14 18:19:11 2011
@@ -106,6 +106,11 @@ SELECT tree_conflict_data
 FROM actual_node
 WHERE wc_id = ?1 AND local_relpath = ?2 AND tree_conflict_data IS NOT NULL
 
+-- STMT_SELECT_ACTUAL_CHANGELIST
+SELECT changelist
+FROM actual_node
+WHERE wc_id = ?1 AND local_relpath = ?2 AND changelist IS NOT NULL
+
 -- STMT_SELECT_NODE_CHILDREN_INFO
 /* Getting rows in an advantageous order using
      ORDER BY local_relpath, op_depth DESC
@@ -339,19 +344,10 @@ INSERT INTO actual_node (
   wc_id, local_relpath, prop_reject, parent_relpath)
 VALUES (?1, ?2, ?3, ?4)
 
--- STMT_UPDATE_ACTUAL_CHANGELIST_FILTER_CHANGELIST
-UPDATE actual_node SET changelist = ?3
-WHERE wc_id = ?1 AND local_relpath = ?2
-  AND changelist=?4
-
--- STMT_UPDATE_ACTUAL_CHANGELIST
-UPDATE actual_node SET changelist = ?3
-WHERE wc_id = ?1 AND local_relpath = ?2
-
--- STMT_INSERT_ACTUAL_CHANGELIST
-INSERT INTO actual_node (
-  wc_id, local_relpath, changelist, parent_relpath)
-VALUES (?1, ?2, ?3, ?4)
+-- STMT_UPDATE_ACTUAL_CHANGELISTS
+UPDATE actual_node SET changelist = ?2
+WHERE wc_id = ?1 AND local_relpath IN
+(SELECT local_relpath from targets_list)
 
 -- STMT_RESET_ACTUAL_WITH_CHANGELIST
 REPLACE INTO actual_node (
@@ -427,6 +423,31 @@ SELECT wc_id, local_relpath, notify, cha
 FROM changelist_list
 ORDER BY wc_id, local_relpath
 
+-- STMT_CREATE_TARGETS_LIST
+DROP TABLE IF EXISTS targets_list;
+CREATE TEMPORARY TABLE targets_list (
+  local_relpath TEXT NOT NULL,
+  parent_relpath TEXT NOT NULL
+  );
+
+-- STMT_DROP_TARGETS_LIST
+DROP TABLE targets_list;
+
+-- STMT_INSERT_TARGET
+INSERT INTO targets_list(local_relpath, parent_relpath) VALUES (?1, ?2)
+
+-- STMT_SELECT_TARGETS
+SELECT local_relpath, parent_relpath from targets_list
+
+-- STMT_INSERT_ACTUAL_EMPTIES
+INSERT OR IGNORE INTO actual_node (
+     wc_id, local_relpath, parent_relpath, properties,
+     conflict_old, conflict_new, conflict_working,
+     prop_reject, changelist, text_mod, tree_conflict_data )
+SELECT ?1, local_relpath, parent_relpath, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL
+FROM targets_list
+
 -- STMT_DELETE_ACTUAL_EMPTY
 DELETE FROM actual_node
 WHERE wc_id = ?1 AND local_relpath = ?2
@@ -441,6 +462,20 @@ WHERE wc_id = ?1 AND local_relpath = ?2
   AND right_checksum IS NULL
   AND left_checksum IS NULL
 
+-- STMT_DELETE_ACTUAL_EMPTIES
+DELETE FROM actual_node
+WHERE wc_id = ?1
+  AND properties IS NULL
+  AND conflict_old IS NULL
+  AND conflict_new IS NULL
+  AND prop_reject IS NULL
+  AND changelist IS NULL
+  AND text_mod IS NULL
+  AND tree_conflict_data IS NULL
+  AND older_checksum IS NULL
+  AND right_checksum IS NULL
+  AND left_checksum IS NULL
+
 -- STMT_DELETE_BASE_NODE
 DELETE FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1103177&r1=1103176&r2=1103177&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Sat May 14 18:19:11 2011
@@ -2466,10 +2466,18 @@ run_final_query(void *baton,
                 svn_wc__db_wcroot_t *wcroot,
                 apr_pool_t *scratch_pool)
 {
-  int *finalize_idx = baton;
+  int *final_queries = baton;
+  int *query_idx = final_queries;
+  svn_error_t *err = SVN_NO_ERROR;
 
-  return svn_error_return(svn_sqlite__exec_statements(wcroot->sdb,
-                                                      *finalize_idx));
+  while (*query_idx >= 0)
+    {
+      err = svn_error_compose_create(err, svn_sqlite__exec_statements(
+                                                 wcroot->sdb, *query_idx));
+      query_idx++;
+    }
+
+  return err;
 }
 
 static svn_error_t *
@@ -4944,11 +4952,105 @@ svn_wc__db_op_modified(svn_wc__db_t *db,
   NOT_IMPLEMENTED();
 }
 
+/* */
+static svn_error_t *
+populate_targets_tree(svn_wc__db_wcroot_t *wcroot,
+                      const char *local_relpath,
+                      svn_depth_t depth,
+                      const apr_array_header_t *changelist_filter,
+                      apr_pool_t *scratch_pool)
+{
+  apr_hash_t *changelist_hash = NULL;
+  svn_boolean_t have_row;
+  svn_sqlite__stmt_t *stmt;
+  const char *parent_relpath;
+
+  parent_relpath = svn_relpath_dirname(local_relpath, scratch_pool);
+
+  if (changelist_filter && changelist_filter->nelts)
+    SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
+                                       scratch_pool));
+
+  SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
+                                      STMT_CREATE_TARGETS_LIST));
+
+  switch (depth)
+    {
+      case svn_depth_empty:
+        if (changelist_hash)
+          {
+            const char *changelist;
+
+            SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                              STMT_SELECT_ACTUAL_CHANGELIST));
+            SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
+                                      local_relpath));
+            SVN_ERR(svn_sqlite__step(&have_row, stmt));
+            changelist = svn_sqlite__column_text(stmt, 0, scratch_pool);
+            SVN_ERR(svn_sqlite__reset(stmt));
+
+            if (changelist == NULL)
+              {
+                /* No changelist, so return. */
+                return SVN_NO_ERROR;
+              }
+
+            if (apr_hash_get(changelist_hash, changelist,
+                             APR_HASH_KEY_STRING) == NULL)
+              {
+                /* Changelist exists, but doesn't match. */
+                return SVN_NO_ERROR;
+              }
+          }
+
+        /* Insert this single path. */
+        SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                          STMT_INSERT_TARGET));
+        SVN_ERR(svn_sqlite__bindf(stmt, "ss", local_relpath, parent_relpath));
+        SVN_ERR(svn_sqlite__step_done(stmt));
+
+        break;
+
+      default:
+        /* Currently only defined for depth == empty */
+        SVN_ERR_MALFUNCTION();
+        break;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+#if 0
+static svn_error_t *
+dump_targets(svn_wc__db_wcroot_t *wcroot,
+             apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_TARGETS));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  while (have_row)
+    {
+      const char *target = svn_sqlite__column_text(stmt, 0, NULL);
+      SVN_DBG(("Target: '%s'\n", target));
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  return SVN_NO_ERROR;
+}
+#endif
+
 
 struct set_changelist_baton_t
 {
   const char *new_changelist;
   const apr_array_header_t *changelist_filter;
+  svn_depth_t depth;
 };
 
 
@@ -4961,91 +5063,34 @@ set_changelist_txn(void *baton,
 {
   struct set_changelist_baton_t *scb = baton;
   svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-
-  SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
-                                      STMT_CREATE_CHANGELIST_LIST));
 
-  /* If we are filtering based on changelist_filter, we *must* already have
-     nodes, so we can skip this check. */
-  if (scb->changelist_filter && scb->changelist_filter->nelts > 0)
-    have_row = TRUE;
-  else
-    {
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_SELECT_ACTUAL_NODE));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-      SVN_ERR(svn_sqlite__reset(stmt));
-    }
-
-  if (!have_row)
-    {
-      /* We need to insert an ACTUAL node, but only if we're not attempting
-         to remove a (non-existent) changelist. */
-      if (scb->new_changelist == NULL)
-        return SVN_NO_ERROR;
-
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_INSERT_ACTUAL_CHANGELIST));
-
-      /* The parent of relpath=="" is null, so we simply skip binding the
-         column. Otherwise, bind the proper value to 'parent_relpath'.  */
-      if (*local_relpath != '\0')
-        SVN_ERR(svn_sqlite__bind_text(stmt, 4,
-                                      svn_relpath_dirname(local_relpath,
-                                                          scratch_pool)));
-    }
-  else if (!scb->changelist_filter || scb->changelist_filter->nelts == 0)
-    {
-      /* No filtering going on: we can just use the simple statement. */
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_UPDATE_ACTUAL_CHANGELIST));
-    }
-  else
-    {
-      /* We need to execute (potentially) multiple changelist-filtered
-         queries, one for each changelist.  */
-      int i;
+  SVN_ERR(populate_targets_tree(wcroot, local_relpath, scb->depth,
+                                scb->changelist_filter, scratch_pool));
 
-      /* Start with the second changelist in the list of changelist filters.
-         In the case where we only have one changelist filter, this loop is
-         skipped, and we get simple single-query execution. */
-      for (i = 1; i < scb->changelist_filter->nelts; i++)
-        {
-          const char *cl = APR_ARRAY_IDX(scb->changelist_filter, i,
-                                         const char *);
+  /* Ensure we have actual nodes for our targets. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_INSERT_ACTUAL_EMPTIES));
+  SVN_ERR(svn_sqlite__bind_int64(stmt, 1, wcroot->wc_id));
+  SVN_ERR(svn_sqlite__step_done(stmt));
 
-          SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                           STMT_UPDATE_ACTUAL_CHANGELIST_FILTER_CHANGELIST));
-          SVN_ERR(svn_sqlite__bindf(stmt, "isss", wcroot->wc_id,
-                                    local_relpath, scb->new_changelist, cl));
-          SVN_ERR(svn_sqlite__step_done(stmt));
-        }
+  /* Now create our notification table. */
+  SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
+                                      STMT_CREATE_CHANGELIST_LIST));
 
-      /* Finally, we do the first changelist, and let the actual execution
-         fall through below. */
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                           STMT_UPDATE_ACTUAL_CHANGELIST_FILTER_CHANGELIST));
-      SVN_ERR(svn_sqlite__bind_text(stmt, 4,
-                                   APR_ARRAY_IDX(scb->changelist_filter, 0,
-                                                 const char *)));
-    }
+  /* Update our changelists. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_UPDATE_ACTUAL_CHANGELISTS));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, scb->new_changelist));
+  SVN_ERR(svn_sqlite__step_done(stmt));
 
-  /* Run the update or insert query */
-  SVN_ERR(svn_sqlite__bindf(stmt, "iss", wcroot->wc_id, local_relpath,
-                            scb->new_changelist));
+  /* We may have left empty ACTUAL nodes, so remove it.  */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_DELETE_ACTUAL_EMPTIES));
+  SVN_ERR(svn_sqlite__bind_int64(stmt, 1, wcroot->wc_id));
   SVN_ERR(svn_sqlite__step_done(stmt));
 
-  if (scb->new_changelist == NULL)
-    {
-     /* When removing a changelist, we may have left an empty ACTUAL node, so
-        remove it.  */
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_DELETE_ACTUAL_EMPTY));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
-      SVN_ERR(svn_sqlite__step_done(stmt));
-    }
+  /* Drop the targets tree table. */
+  SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb, STMT_DROP_TARGETS_LIST));
 
   return SVN_NO_ERROR;
 }
@@ -5110,8 +5155,10 @@ svn_wc__db_op_set_changelist(svn_wc__db_
 {
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
-  struct set_changelist_baton_t scb = { new_changelist, changelist_filter };
-  int final_query = STMT_DROP_CHANGELIST_LIST;
+  struct set_changelist_baton_t scb = { new_changelist, changelist_filter,
+                                        depth };
+  int final_queries[] = { STMT_DROP_CHANGELIST_LIST, STMT_DROP_TARGETS_LIST,
+                          -1 };
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   SVN_ERR_ASSERT(depth == svn_depth_empty);
@@ -5136,7 +5183,7 @@ svn_wc__db_op_set_changelist(svn_wc__db_
                                             do_changelist_notify, NULL,
                                             cancel_func, cancel_baton,
                                             notify_func, notify_baton,
-                                            run_final_query, &final_query,
+                                            run_final_query, final_queries,
                                             scratch_pool));
 }
 
@@ -6297,7 +6344,7 @@ svn_wc__db_op_delete(svn_wc__db_t *db,
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
   struct op_delete_baton_t odb;
-  int final_query = STMT_DROP_DELETE_LIST;
+  int final_queries[] = { STMT_DROP_DELETE_LIST, -1 };
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
@@ -6320,7 +6367,7 @@ svn_wc__db_op_delete(svn_wc__db_t *db,
                                             do_delete_notify, NULL,
                                             cancel_func, cancel_baton,
                                             notify_func, notify_baton,
-                                            run_final_query, &final_query,
+                                            run_final_query, final_queries,
                                             scratch_pool));
 }
 



Re: svn commit: r1103177 - in /subversion/trunk/subversion/libsvn_wc: wc-queries.sql wc_db.c

Posted by Greg Stein <gs...@gmail.com>.
On Sat, May 14, 2011 at 14:19,  <hw...@apache.org> wrote:
>...

> +++ subversion/trunk/subversion/libsvn_wc/wc_db.c Sat May 14 18:19:11 2011
>...
> @@ -4944,11 +4952,105 @@ svn_wc__db_op_modified(svn_wc__db_t *db,
>   NOT_IMPLEMENTED();
>  }
>
> +/* */
> +static svn_error_t *
> +populate_targets_tree(svn_wc__db_wcroot_t *wcroot,
> +                      const char *local_relpath,
> +                      svn_depth_t depth,
> +                      const apr_array_header_t *changelist_filter,
> +                      apr_pool_t *scratch_pool)
> +{
> +  apr_hash_t *changelist_hash = NULL;
> +  svn_boolean_t have_row;
> +  svn_sqlite__stmt_t *stmt;
> +  const char *parent_relpath;
> +
> +  parent_relpath = svn_relpath_dirname(local_relpath, scratch_pool);
> +
> +  if (changelist_filter && changelist_filter->nelts)
> +    SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
> +                                       scratch_pool));
> +
> +  SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
> +                                      STMT_CREATE_TARGETS_LIST));
> +
> +  switch (depth)
> +    {
> +      case svn_depth_empty:
> +        if (changelist_hash)
> +          {
> +            const char *changelist;
> +
> +            SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
> +                                              STMT_SELECT_ACTUAL_CHANGELIST));
> +            SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
> +                                      local_relpath));
> +            SVN_ERR(svn_sqlite__step(&have_row, stmt));

have_row is not checked.

>...

Re: svn commit: r1103177 - in /subversion/trunk/subversion/libsvn_wc: wc-queries.sql wc_db.c

Posted by Greg Stein <gs...@gmail.com>.
On Sat, May 14, 2011 at 16:26, Hyrum K Wright <hy...@hyrumwright.org> wrote:
> On Sat, May 14, 2011 at 7:29 PM, Greg Stein <gs...@gmail.com> wrote:
>...
>>>...
>>> +  struct set_changelist_baton_t scb = { new_changelist, changelist_filter,
>>> +                                        depth };
>>> +  int final_queries[] = { STMT_DROP_CHANGELIST_LIST, STMT_DROP_TARGETS_LIST,
>>> +                          -1 };
>>
>> It seems that it would be cleaner to just put the 'DROP TABLE
>> targets_list' into the STMT_DROP_CHANGELIST_LIST (maybe rename the
>> latter to something like STMT_FINALIZE_CHANGELIST). Then you could rip
>> out all this multiple statement stuff. I think one STMT would be
>> cleaner than all this code to support multiple.
>
> The goal is to use the target_list stuff for multiple operations, such
> as propset (and potentially things like info, too).  As a result, the
> 'DROP TABLE targets_list' will be used in combination with a number of
> other finalize statements.  I suppose we could duplicate that single
> drop statement wherever we need to finalize an operation (and maybe
> that's acceptable duplication), but I'd like to leave it separate, at
> least for now.

That was my thought: just put that DROP into the other finalize
statements. We already drop a bunch of triggers and the change_list
table. I see no reason not to throw a drop of the targets_list in
there, too.

It just seems easier to have multiple SQL operations in one STMT,
rather than simulate the same in C code.

Cheers,
-g

Re: svn commit: r1103177 - in /subversion/trunk/subversion/libsvn_wc: wc-queries.sql wc_db.c

Posted by Hyrum K Wright <hy...@hyrumwright.org>.
On Sat, May 14, 2011 at 7:29 PM, Greg Stein <gs...@gmail.com> wrote:
> On Sat, May 14, 2011 at 14:19,  <hw...@apache.org> wrote:
>>...
>> +++ subversion/trunk/subversion/libsvn_wc/wc_db.c Sat May 14 18:19:11 2011
>> @@ -2466,10 +2466,18 @@ run_final_query(void *baton,
>>                 svn_wc__db_wcroot_t *wcroot,
>>                 apr_pool_t *scratch_pool)
>>  {
>> -  int *finalize_idx = baton;
>> +  int *final_queries = baton;
>> +  int *query_idx = final_queries;
>
> Seems that 'final_queries' is not needed.

Ah, true.  r1103207.

>>...
>> +  struct set_changelist_baton_t scb = { new_changelist, changelist_filter,
>> +                                        depth };
>> +  int final_queries[] = { STMT_DROP_CHANGELIST_LIST, STMT_DROP_TARGETS_LIST,
>> +                          -1 };
>
> It seems that it would be cleaner to just put the 'DROP TABLE
> targets_list' into the STMT_DROP_CHANGELIST_LIST (maybe rename the
> latter to something like STMT_FINALIZE_CHANGELIST). Then you could rip
> out all this multiple statement stuff. I think one STMT would be
> cleaner than all this code to support multiple.

The goal is to use the target_list stuff for multiple operations, such
as propset (and potentially things like info, too).  As a result, the
'DROP TABLE targets_list' will be used in combination with a number of
other finalize statements.  I suppose we could duplicate that single
drop statement wherever we need to finalize an operation (and maybe
that's acceptable duplication), but I'd like to leave it separate, at
least for now.

-Hyrum

Re: svn commit: r1103177 - in /subversion/trunk/subversion/libsvn_wc: wc-queries.sql wc_db.c

Posted by Greg Stein <gs...@gmail.com>.
On Sat, May 14, 2011 at 14:19,  <hw...@apache.org> wrote:
>...
> +++ subversion/trunk/subversion/libsvn_wc/wc_db.c Sat May 14 18:19:11 2011
> @@ -2466,10 +2466,18 @@ run_final_query(void *baton,
>                 svn_wc__db_wcroot_t *wcroot,
>                 apr_pool_t *scratch_pool)
>  {
> -  int *finalize_idx = baton;
> +  int *final_queries = baton;
> +  int *query_idx = final_queries;

Seems that 'final_queries' is not needed.

>...
> +  struct set_changelist_baton_t scb = { new_changelist, changelist_filter,
> +                                        depth };
> +  int final_queries[] = { STMT_DROP_CHANGELIST_LIST, STMT_DROP_TARGETS_LIST,
> +                          -1 };

It seems that it would be cleaner to just put the 'DROP TABLE
targets_list' into the STMT_DROP_CHANGELIST_LIST (maybe rename the
latter to something like STMT_FINALIZE_CHANGELIST). Then you could rip
out all this multiple statement stuff. I think one STMT would be
cleaner than all this code to support multiple.

>...

Cheers,
-g