Author: hwright
Date: Mon Apr 18 16:12:14 2011
New Revision: 1094636

URL: http://svn.apache.org/viewvc?rev=1094636&view=rev
Log:
Don't dynamically prepare an sql statement when setting changelists using a
changelist filter.

Suggested by: gstein

* subversion/libsvn_wc/wc-queries.sql
  (STMT_UPDATE_ACTUAL_CHANGELIST_FILTER_CHANGELIST): New.

* subversion/libsvn_wc/wc_db.c
  (construct_filter): Remove.
  (set_changelist_txn): Implement an interative multiple-changelist filter,
    rather than attempting to do it in one query.

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=1094636&r1=1094635&r2=1094636&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Mon Apr 18 16:12:14 
2011
@@ -326,6 +326,11 @@ 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

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1094636&r1=1094635&r2=1094636&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Mon Apr 18 16:12:14 2011
@@ -55,8 +55,6 @@
 
 #define NOT_IMPLEMENTED() SVN__NOT_IMPLEMENTED()
 
-WC_QUERIES_SQL_DECLARE_STATEMENTS(statements);
-
 
 /*
  * Some filename constants.
@@ -443,31 +441,6 @@ static const char *construct_like_arg(co
 }
 
 
-/* Construct a clause to be used as a filter, of the form:
- * COLUMN in (LIST[0], LIST[1], LIST[2], ..., LIST[N]).
- *
- * Allocate the result either statically or in RESULT_POOL.  */
-static const char *
-construct_filter(const char *column_name,
-                 const apr_array_header_t *list,
-                 apr_pool_t *result_pool)
-{
-  svn_stringbuf_t *clause;
-  int i;
-
-  if (!list || list->nelts == 0)
-    return "";
-
-  clause = svn_stringbuf_createf(result_pool, "%s IN (?", column_name);
-
-  for (i = 1; i < list->nelts; i++)
-    svn_stringbuf_appendcstr(clause, ", ?");
-  svn_stringbuf_appendcstr(clause, ")");
-
-  return clause->data;
-}
-
-
 /* Look up REPOS_ID in SDB and set *REPOS_ROOT_URL and/or *REPOS_UUID to
    its root URL and UUID respectively.  If REPOS_ID is INVALID_REPOS_ID,
    use NULL for both URL and UUID.  Either or both output parameters may be
@@ -3510,33 +3483,39 @@ set_changelist_txn(void *baton,
                                       svn_relpath_dirname(local_relpath,
                                                           scratch_pool)));
     }
-  else if (scb->changelists && scb->changelists->nelts)
+  else if (!scb->changelists || scb->changelists->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;
-      const char *stmt_text = apr_pstrcat(scratch_pool,
-                                   statements[STMT_UPDATE_ACTUAL_CHANGELIST],
-                                    " AND ",
-                                    construct_filter("changelist",
-                                                     scb->changelists,
-                                                     scratch_pool),
-                                    NULL);
 
-      SVN_ERR(svn_sqlite__prepare(&stmt, wcroot->sdb, stmt_text,
-                                  scratch_pool));
-
-      for (i = 0; i < scb->changelists->nelts; i++)
+      /* 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->changelists->nelts; i++)
         {
           const char *cl = APR_ARRAY_IDX(scb->changelists, i, const char *);
 
-          /* The magic number '4' here is the number of existing params,
-             plus 1, in the statement, which will be bound below. */
-          SVN_ERR(svn_sqlite__bind_text(stmt, i+4, cl));
+          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));
         }
-    }
-  else
-    {
+
+      /* 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));
+                           STMT_UPDATE_ACTUAL_CHANGELIST_FILTER_CHANGELIST));
+      SVN_ERR(svn_sqlite__bind_text(stmt, 4,
+                                   APR_ARRAY_IDX(scb->changelists, 0,
+                                                 const char *)));
     }
 
   /* Run the update or insert query */


Reply via email to