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