[dev] datatree: getObject for nonexistent objects

Karsten Fourmont fourmont at gmx.de
Sun Jan 21 03:37:17 PST 2007


Hi,

I just realized that calling DataTree:getObject is extremly costly for 
nonexistent objects (with sql backend). If you do this:

$o = $_datatree->getObject("unknown_fake_object");

you'll end up with this sql query being executed:

SELECT [*] FROM horde_datatree c WHERE c.group_uid = 'syncml'

which means that the complete datatree is loaded!  Futile as the object 
is not there no matter how much you load. (see end of post for detailed 
horde.log)

The reason for that as far as I could figure it out:

_buildLoadQuery calls _buildParentIds in line 193 of sql.php:
$parent_where = $this->_buildParentIds($root, $loadTree, 'c.');
_buildParentIds' SQL query does not find anything and so returns '' in 
line 267.
Then _buildLoadQuery goes on like this in line 194:
if (!empty($parent_where) && !is_a($parent_where, 'PEAR_Error')) {
    $where = sprintf('%s AND (%s)', $where, $parent_where);
}
so the where part is not included and the query ends up being "get all".

I'm not an expert on the delicate internals of the datatree but imho 
_buildLoadQuery should do like this:
if (!empty($parent_where) && !is_a($parent_where, 'PEAR_Error')) {
     $where = sprintf('%s AND (%s)', $where, $parent_where);
} else {
    return $parent_where;
}
both invocations of _buildLoadQuery explicitly check for empty as well 
as PEAR_Error returns so all should be fine.

With this change in place the result if getObject is the same ("not 
found") but the complete datatree is not loaded.

The query
SQL Query by DataTree_sql::_buildParentIds(): SELECT datatree_id, 
datatree_parents FROM horde_datatree WHERE datatree_name = ? AND 
group_uid = ? ORDER BY datatree_id [on line 266 of 
"/home/httpd/html/horde/framework/DataTree/DataTree/sql.php"]

is still executed twice though.

Would some DataTree-expert review and commit this patch? Thanks!

Index: DataTree/DataTree/sql.php
===================================================================
RCS file: /repository/framework/DataTree/DataTree/sql.php,v
retrieving revision 1.224
diff -u -r1.224 sql.php
--- DataTree/DataTree/sql.php	4 Jan 2007 08:01:58 -0000	1.224
+++ DataTree/DataTree/sql.php	21 Jan 2007 11:42:12 -0000
@@ -193,6 +193,8 @@
              $parent_where = $this->_buildParentIds($root, $loadTree, 
'c.');
              if (!empty($parent_where) && !is_a($parent_where, 
'PEAR_Error')) {
                  $where = sprintf('%s AND (%s)', $where, $parent_where);
+            } else {
+                return $parent_where;
              }
          }
          if (!is_null($sortby_name)) {



--
1) here's the complete log of the unnecessary load for reference:

SQL Query by DataTree_sql::_buildParentIds(): SELECT datatree_id, 
datatree_parents FROM horde_datatree WHERE datatree_name = ? AND 
group_uid = ? ORDER BY datatree_id [on line 264 of DataTree/sql.php"]

SQL Query by DataTree_sql::_load(): SELECT c.datatree_id, 
c.datatree_name, c.datatree_parents, c.datatree_order FROM 
horde_datatree c WHERE c.group_uid = 'syncml'  [on line 133 of 
"DataTree/sql.php"]

SQL Query by DataTree_sql::_buildParentIds(): SELECT datatree_id, 
datatree_parents FROM horde_datatree WHERE datatree_name = ? AND 
group_uid = ? ORDER BY datatree_id [on line 264 of "DataTree/sql.php"]

SQL Query by DataTree_sql::_load(): SELECT c.datatree_id, 
c.datatree_name, c.datatree_parents, c.datatree_order FROM 
horde_datatree c WHERE c.group_uid = 'syncml'  [on line 133 of 
"DataTree/sql.php"]



More information about the dev mailing list