On Sat, Sep 4, 2010 at 12:45 PM, Justin Erenkrantz
<jus...@erenkrantz.com> wrote:
> I'm going to see what a quick check to retrieve just the kind and
> status will do for the query volume.  I think it's unlikely we have to
> pull everything out of sqlite to answer that basic question.  --
> justin

We can reduce the query volume by one (per file) as we can skip the
active table query - see quick & dirty patch below.

It does replace 2 larger queries with 2 smaller ones, but I think our
bottleneck is likely more around query volume than query complexity...

Anyway, I'll stop replying to myself and enjoy the long weekend.  =)  -- justin

Index: status.c
===================================================================
--- status.c    (revision 992534)
+++ status.c    (working copy)
@@ -1263,10 +1270,7 @@ get_dir_status(const struct walk_status_baton *wb,
           svn_wc__db_status_t node_status;
           svn_wc__db_kind_t node_kind;

-          SVN_ERR(svn_wc__db_read_info(&node_status, &node_kind, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL,
+          SVN_ERR(svn_wc__db_read_info_exist(&node_status, &node_kind,
                                    wb->db, node_abspath, iterpool, iterpool));

           if (node_status != svn_wc__db_status_not_present
Index: wc_db.c
===================================================================
--- wc_db.c     (revision 992534)
+++ wc_db.c     (working copy)
@@ -51,7 +51,6 @@
 #include "private/svn_wc_private.h"
 #include "private/svn_token.h"

-
 #define NOT_IMPLEMENTED() SVN__NOT_IMPLEMENTED()


@@ -5051,6 +5050,161 @@ svn_wc__db_temp_op_delete(svn_wc__db_t *db,


 svn_error_t *
+svn_wc__db_read_info_exist(svn_wc__db_status_t *status,
+                     svn_wc__db_kind_t *kind,
+                     svn_wc__db_t *db,
+                     const char *local_abspath,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
+{
+  svn_wc__db_pdh_t *pdh;
+  const char *local_relpath;
+  svn_sqlite__stmt_t *stmt_base;
+  svn_sqlite__stmt_t *stmt_work;
+  svn_boolean_t have_base;
+  svn_boolean_t have_work;
+  svn_error_t *err = NULL;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              local_abspath, svn_sqlite__mode_readonly,
+                              scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(pdh);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt_base, pdh->wcroot->sdb,
+                                    STMT_SELECT_BASE_NODE_EXIST));
+  SVN_ERR(svn_sqlite__bindf(stmt_base, "is",
+                            pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_base, stmt_base));
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt_work, pdh->wcroot->sdb,
+                                    STMT_SELECT_WORKING_NODE_EXIST));
+  SVN_ERR(svn_sqlite__bindf(stmt_work, "is",
+                            pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_work, stmt_work));
+
+  if (have_base || have_work)
+    {
+      svn_wc__db_kind_t node_kind;
+
+      if (have_work)
+        node_kind = svn_sqlite__column_token(stmt_work, 1, kind_map);
+      else
+        node_kind = svn_sqlite__column_token(stmt_base, 1, kind_map);
+
+      if (status)
+        {
+          if (have_base)
+            {
+              *status = svn_sqlite__column_token(stmt_base, 0, presence_map);
+
+              /* We have a presence that allows a WORKING_NODE override
+                 (normal or not-present), or we don't have an override.  */
+              /* ### for now, allow an override of an incomplete BASE_NODE
+                 ### row. it appears possible to get rows in BASE/WORKING
+                 ### both set to 'incomplete'.  */
+              SVN_ERR_ASSERT((*status != svn_wc__db_status_absent
+                              && *status != svn_wc__db_status_excluded
+                              /* && *status != svn_wc__db_status_incomplete */)
+                             || !have_work);
+
+#ifndef SVN_WC__SINGLE_DB
+              if (node_kind == svn_wc__db_kind_subdir
+                  && *status == svn_wc__db_status_normal)
+                {
+                  /* We should have read a row from the subdir wc.db. It
+                     must be obstructed in some way.
+
+                     It is also possible that a WORKING node will override
+                     this value with a proper status.  */
+                  *status = svn_wc__db_status_obstructed;
+                }
+#endif
+            }
+
+          if (have_work)
+            {
+              svn_wc__db_status_t work_status;
+
+              work_status = svn_sqlite__column_token(stmt_work, 0,
+                                                     presence_map);
+              SVN_ERR_ASSERT(work_status == svn_wc__db_status_normal
+                             || work_status == svn_wc__db_status_not_present
+                             || work_status == svn_wc__db_status_base_deleted
+                             || work_status == svn_wc__db_status_incomplete
+                             || work_status == svn_wc__db_status_excluded);
+
+              if (work_status == svn_wc__db_status_incomplete)
+                {
+                  *status = svn_wc__db_status_incomplete;
+                }
+              else if (work_status == svn_wc__db_status_excluded)
+                {
+                  *status = svn_wc__db_status_excluded;
+                }
+              else if (work_status == svn_wc__db_status_not_present
+                       || work_status == svn_wc__db_status_base_deleted)
+                {
+                  /* The caller should scan upwards to detect whether this
+                     deletion has occurred because this node has been moved
+                     away, or it is a regular deletion. Also note that the
+                     deletion could be of the BASE tree, or a child of
+                     something that has been copied/moved here. */
+
+#ifndef SVN_WC__SINGLE_DB
+                  /* If we're looking at the data in the parent, then
+                     something has obstructed the child data. Inform
+                     the caller.  */
+                  if (node_kind == svn_wc__db_kind_subdir)
+                    *status = svn_wc__db_status_obstructed_delete;
+                  else
+#endif
+                    *status = svn_wc__db_status_deleted;
+                }
+              else /* normal */
+                {
+                  /* The caller should scan upwards to detect whether this
+                     addition has occurred because of a simple addition,
+                     a copy, or is the destination of a move. */
+
+#ifndef SVN_WC__SINGLE_DB
+                  /* If we're looking at the data in the parent, then
+                     something has obstructed the child data. Inform
+                     the caller.  */
+                  if (node_kind == svn_wc__db_kind_subdir)
+                    *status = svn_wc__db_status_obstructed_add;
+                  else
+#endif
+                    *status = svn_wc__db_status_added;
+                }
+            }
+        }
+      if (kind)
+        {
+#ifndef SVN_WC__SINGLE_DB
+          if (node_kind == svn_wc__db_kind_subdir)
+            *kind = svn_wc__db_kind_dir;
+          else
+#endif
+            *kind = node_kind;
+        }
+    }
+  else
+    {
+      err = svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+                              _("The node '%s' was not found."),
+                              svn_dirent_local_style(local_abspath,
+                                                     scratch_pool));
+    }
+
+  err = svn_error_compose_create(err, svn_sqlite__reset(stmt_base));
+  SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt_work)));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_wc__db_read_info(svn_wc__db_status_t *status,
                      svn_wc__db_kind_t *kind,
                      svn_revnum_t *revision,
Index: wc_db.h
===================================================================
--- wc_db.h     (revision 992534)
+++ wc_db.h     (working copy)
@@ -1523,7 +1523,16 @@ svn_wc__db_read_info(svn_wc__db_status_t *status,
                      apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool);

+svn_error_t *
+svn_wc__db_read_info_exist(svn_wc__db_status_t *status,  /* ### derived */
+                     svn_wc__db_kind_t *kind,

+                     svn_wc__db_t *db,
+                     const char *local_abspath,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool);
+
+
 /* Set *PROPVAL to the value of the property named PROPNAME of the node
    LOCAL_ABSPATH in the ACTUAL tree (looking through to the WORKING or BASE
    tree as required).
Index: wc-queries.sql
===================================================================
--- wc-queries.sql      (revision 992534)
+++ wc-queries.sql      (working copy)
@@ -43,6 +43,11 @@ left outer join lock on base_node.repos_id = lock.
   and base_node.repos_relpath = lock.repos_relpath
 where wc_id = ?1 and local_relpath = ?2;

+-- STMT_SELECT_BASE_NODE_EXIST
+select presence, kind
+from base_node
+where wc_id = ?1 and local_relpath = ?2;
+
 -- STMT_SELECT_WORKING_NODE
 select presence, kind, checksum, translated_size,
   changed_rev, changed_date, changed_author, depth, symlink_target,
@@ -51,6 +56,11 @@ select presence, kind, checksum, translated_size,
 from working_node
 where wc_id = ?1 and local_relpath = ?2;

+-- STMT_SELECT_WORKING_NODE_EXIST
+select presence, kind
+from working_node
+where wc_id = ?1 and local_relpath = ?2;
+
 -- STMT_SELECT_ACTUAL_NODE
 select prop_reject, changelist, conflict_old, conflict_new,
 conflict_working, tree_conflict_data, properties

Reply via email to