mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-22 06:30:59 +01:00
Big performance improvment by:
- using egw_link::set_cache() for entries read or searched --> eliminates an excessive number of single entry reads, when the links need titles or file_access permissions - removing sub-query for number of sub-entries from search (Bug #1613) - method to query the number of sub-entries of all displayed entries in one go
This commit is contained in:
parent
25b3c3a1f8
commit
876649fe6f
@ -415,6 +415,9 @@ class infolog_bo
|
|||||||
{
|
{
|
||||||
if ($data[$time]) $data[$time] += $this->tz_offset_s;
|
if ($data[$time]) $data[$time] += $this->tz_offset_s;
|
||||||
}
|
}
|
||||||
|
// pre-cache title and file access
|
||||||
|
self::set_link_cache($data);
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -654,6 +657,9 @@ class infolog_bo
|
|||||||
// notify the link-class about the update, as other apps may be subscribt to it
|
// notify the link-class about the update, as other apps may be subscribt to it
|
||||||
egw_link::notify_update('infolog',$info_id,$values);
|
egw_link::notify_update('infolog',$info_id,$values);
|
||||||
|
|
||||||
|
// pre-cache the new values
|
||||||
|
self::set_link_cache($values);
|
||||||
|
|
||||||
// send email notifications and do the history logging
|
// send email notifications and do the history logging
|
||||||
if (!is_object($this->tracking))
|
if (!is_object($this->tracking))
|
||||||
{
|
{
|
||||||
@ -667,10 +673,10 @@ class infolog_bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query the number of children / subs
|
* Query the number of children / subs for one or more info_id's
|
||||||
*
|
*
|
||||||
* @param int $info_id id
|
* @param int|array $info_id id
|
||||||
* @return int number of subs
|
* @return int|array number of subs
|
||||||
*/
|
*/
|
||||||
function anzSubs( $info_id )
|
function anzSubs( $info_id )
|
||||||
{
|
{
|
||||||
@ -696,21 +702,25 @@ class infolog_bo
|
|||||||
$ret = $this->so->search($query);
|
$ret = $this->so->search($query);
|
||||||
|
|
||||||
// convert system- to user-time
|
// convert system- to user-time
|
||||||
if (is_array($ret) && $this->tz_offset_s)
|
if (is_array($ret))
|
||||||
{
|
{
|
||||||
foreach($ret as $id => $data)
|
foreach($ret as $id => &$data)
|
||||||
{
|
{
|
||||||
foreach($this->timestamps as $time)
|
if($this->tz_offset_s)
|
||||||
{
|
{
|
||||||
if ($data[$time]) $ret[$id][$time] += $this->tz_offset_s;
|
foreach($this->timestamps as $time)
|
||||||
|
{
|
||||||
|
if ($data[$time]) $data[$time] += $this->tz_offset_s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// pre-cache title and file access
|
||||||
|
self::set_link_cache($data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//echo "<p>boinfolog::search(".print_r($query,True).")=<pre>".print_r($ret,True)."</pre>\n";
|
//echo "<p>boinfolog::search(".print_r($query,True).")=<pre>".print_r($ret,True)."</pre>\n";
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* imports a mail identified by uid as infolog
|
* imports a mail identified by uid as infolog
|
||||||
*
|
*
|
||||||
@ -868,15 +878,28 @@ class infolog_bo
|
|||||||
/**
|
/**
|
||||||
* Check access to the projects file store
|
* Check access to the projects file store
|
||||||
*
|
*
|
||||||
* @param int $id id of entry
|
* @param int|array $id id of entry or entry array
|
||||||
* @param int $check EGW_ACL_READ for read and EGW_ACL_EDIT for write or delete access
|
* @param int $check EGW_ACL_READ for read and EGW_ACL_EDIT for write or delete access
|
||||||
* @return boolean true if access is granted or false otherwise
|
* @return boolean true if access is granted or false otherwise
|
||||||
*/
|
*/
|
||||||
function file_access($id,$check,$rel_path)
|
function file_access($id,$check,$rel_path=null)
|
||||||
{
|
{
|
||||||
return $this->check_access($id,$check);
|
return $this->check_access($id,$check);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the cache of the link class (title, file_access) for the given infolog entry
|
||||||
|
*
|
||||||
|
* @param array $info
|
||||||
|
*/
|
||||||
|
function set_link_cache(array $info)
|
||||||
|
{
|
||||||
|
egw_link::set_cache('infolog',$info['info_id'],
|
||||||
|
$this->link_title($info),
|
||||||
|
$this->file_access($info,EGW_ACL_EDIT) ? EGW_ACL_READ|EGW_ACL_EDIT :
|
||||||
|
($this->file_access($info,EGW_ACL_READ) ? EGW_ACL_READ : 0));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hook called be calendar to include events or todos in the cal-dayview
|
* hook called be calendar to include events or todos in the cal-dayview
|
||||||
*
|
*
|
||||||
|
@ -15,13 +15,8 @@
|
|||||||
*
|
*
|
||||||
* all values passed to this class are run either through intval or addslashes to prevent query-insertion
|
* all values passed to this class are run either through intval or addslashes to prevent query-insertion
|
||||||
* and for pgSql 7.3 compatibility
|
* and for pgSql 7.3 compatibility
|
||||||
*
|
|
||||||
* @package infolog
|
|
||||||
* @author Ralf Becker <RalfBecker@outdoor-training.de>
|
|
||||||
* @copyright (c) by Ralf Becker <RalfBecker@outdoor-training.de>
|
|
||||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
||||||
*/
|
*/
|
||||||
class infolog_so // DB-Layer
|
class infolog_so
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Instance of the db class
|
* Instance of the db class
|
||||||
@ -213,9 +208,10 @@ class infolog_so // DB-Layer
|
|||||||
}
|
}
|
||||||
if (count($private_user_list))
|
if (count($private_user_list))
|
||||||
{
|
{
|
||||||
$has_private_access = 'info_owner IN ('.implode(',',$private_user_list).')';
|
$has_private_access = $this->db->expression($this->info_table,array('info_owner' => $private_user_list));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$public_access = $this->db->expression($this->info_table,array('info_owner' => $public_user_list));
|
||||||
// implicit read-rights for responsible user
|
// implicit read-rights for responsible user
|
||||||
$filtermethod .= " OR (".$this->responsible_filter($this->user)." AND info_access='public')";
|
$filtermethod .= " OR (".$this->responsible_filter($this->user)." AND info_access='public')";
|
||||||
|
|
||||||
@ -224,7 +220,7 @@ class infolog_so // DB-Layer
|
|||||||
{
|
{
|
||||||
$filtermethod .= " OR (".$this->responsible_filter($this->user).
|
$filtermethod .= " OR (".$this->responsible_filter($this->user).
|
||||||
($filter == 'own' && count($public_user_list) ? // offer's should show up in own, eg. startpage, but need read-access
|
($filter == 'own' && count($public_user_list) ? // offer's should show up in own, eg. startpage, but need read-access
|
||||||
" OR info_status = 'offer' AND info_owner IN(" . implode(',',$public_user_list) . ')' : '').")".
|
" OR info_status = 'offer' AND $public_access" : '').")".
|
||||||
" AND (info_access='public'".($has_private_access?" OR $has_private_access":'').')';
|
" AND (info_access='public'".($has_private_access?" OR $has_private_access":'').')';
|
||||||
}
|
}
|
||||||
elseif ($filter != 'my' && $filter != 'responsible') // none --> all entrys user has rights to see
|
elseif ($filter != 'my' && $filter != 'responsible') // none --> all entrys user has rights to see
|
||||||
@ -235,7 +231,7 @@ class infolog_so // DB-Layer
|
|||||||
}
|
}
|
||||||
if (count($public_user_list))
|
if (count($public_user_list))
|
||||||
{
|
{
|
||||||
$filtermethod .= " OR (info_access='public' AND info_owner IN(" . implode(',',$public_user_list) . '))';
|
$filtermethod .= " OR (info_access='public' AND $public_access)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$filtermethod .= ') ';
|
$filtermethod .= ') ';
|
||||||
@ -348,6 +344,7 @@ class infolog_so // DB-Layer
|
|||||||
*/
|
*/
|
||||||
function read($info_id) // did _not_ ensure ACL
|
function read($info_id) // did _not_ ensure ACL
|
||||||
{
|
{
|
||||||
|
//echo "<p>read($info_id) ".function_backtrace()."</p>\n";
|
||||||
if ($info_id && ((int)$info_id == $this->data['info_id'] || $info_id == $this->data['info_uid']))
|
if ($info_id && ((int)$info_id == $this->data['info_id'] || $info_id == $this->data['info_uid']))
|
||||||
{
|
{
|
||||||
return $this->data; // return the already read entry
|
return $this->data; // return the already read entry
|
||||||
@ -587,30 +584,28 @@ class infolog_so // DB-Layer
|
|||||||
*
|
*
|
||||||
* This is done now be search too (in key info_anz_subs), if DB can use sub-queries
|
* This is done now be search too (in key info_anz_subs), if DB can use sub-queries
|
||||||
*
|
*
|
||||||
* @param $info_id id of log-entry
|
* @param int|array $info_id id(s) of log-entry
|
||||||
* @return int the number of sub-entries
|
* @return int|array the number of sub-entries or indexed by info_id, if array as param given
|
||||||
*/
|
*/
|
||||||
function anzSubs( $info_id )
|
function anzSubs( $info_id )
|
||||||
{
|
{
|
||||||
if (($info_id = intval($info_id)) <= 0)
|
if (!is_array($info_id) || !$info_id)
|
||||||
{
|
{
|
||||||
return 0;
|
if ((int)$info_id <= 0) return 0;
|
||||||
}
|
}
|
||||||
$this->db->select($this->info_table,'count(*)',array(
|
$counts = array();
|
||||||
'info_id_parent' => $info_id,
|
foreach($this->db->select($this->info_table,'info_id_parent,COUNT(*) AS info_anz_subs',array('info_id_parent' => $info_id),__LINE__,__FILE__,
|
||||||
$this->aclFilter()
|
false,'GROUP BY info_id_parent','infolog') as $row)
|
||||||
),__LINE__,__FILE__);
|
{
|
||||||
|
$counts[$row['info_id_parent']] = (int)$row['info_anz_subs'];
|
||||||
$this->db->next_record();
|
}
|
||||||
//echo "<p>anzSubs($info_id) = ".$this->db->f(0)." ($sql)</p>\n";
|
//echo '<p>'.__METHOD__."($info_id) = ".array2string($counts)."</p>\n";
|
||||||
return $this->db->f(0);
|
return is_array($info_id) ? $counts : (int)array_pop($counts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* searches InfoLog for a certain pattern in $query
|
* searches InfoLog for a certain pattern in $query
|
||||||
*
|
*
|
||||||
* If DB can use sub-queries, the number of subs are under the key info_anz_subs.
|
|
||||||
*
|
|
||||||
* @param $query[order] column-name to sort after
|
* @param $query[order] column-name to sort after
|
||||||
* @param $query[sort] sort-order DESC or ASC
|
* @param $query[sort] sort-order DESC or ASC
|
||||||
* @param $query[filter] string with combination of acl-, date- and status-filters, eg. 'own-open-today' or ''
|
* @param $query[filter] string with combination of acl-, date- and status-filters, eg. 'own-open-today' or ''
|
||||||
@ -716,7 +711,7 @@ class infolog_so // DB-Layer
|
|||||||
$cats = $GLOBALS['egw']->categories->return_all_children((int)$query['cat_id']);
|
$cats = $GLOBALS['egw']->categories->return_all_children((int)$query['cat_id']);
|
||||||
$filtermethod .= ' AND info_cat'.(count($cats)>1? ' IN ('.implode(',',$cats).') ' : '='.(int)$query['cat_id']);
|
$filtermethod .= ' AND info_cat'.(count($cats)>1? ' IN ('.implode(',',$cats).') ' : '='.(int)$query['cat_id']);
|
||||||
}
|
}
|
||||||
$join = $distinct = $count_subs = '';
|
$join = $distinct = '';
|
||||||
if ($query['query']) $query['search'] = $query['query']; // allow both names
|
if ($query['query']) $query['search'] = $query['query']; // allow both names
|
||||||
if ($query['search']) // we search in _from, _subject, _des and _extra_value for $query
|
if ($query['search']) // we search in _from, _subject, _des and _extra_value for $query
|
||||||
{
|
{
|
||||||
@ -771,23 +766,19 @@ class infolog_so // DB-Layer
|
|||||||
{
|
{
|
||||||
$query['total'] = $this->db->query($sql="SELECT $distinct main.info_id ".$sql_query,__LINE__,__FILE__)->NumRows();
|
$query['total'] = $this->db->query($sql="SELECT $distinct main.info_id ".$sql_query,__LINE__,__FILE__)->NumRows();
|
||||||
}
|
}
|
||||||
if ($this->db->capabilities['sub_queries'])
|
|
||||||
{
|
|
||||||
$count_subs = ",(SELECT COUNT(*) FROM $this->info_table sub WHERE sub.info_id_parent=main.info_id AND $acl_filter) AS info_anz_subs";
|
|
||||||
}
|
|
||||||
$info_customfield = '';
|
$info_customfield = '';
|
||||||
if ($sortbycf != '')
|
if ($sortbycf != '')
|
||||||
{
|
{
|
||||||
$info_customfield = ", (SELECT DISTINCT info_extra_value FROM $this->extra_table sub2 where sub2.info_id=main.info_id AND info_extra_name=".$this->db->quote($sortbycf).") AS cfsortcrit ";
|
$info_customfield = ", (SELECT DISTINCT info_extra_value FROM $this->extra_table sub2 where sub2.info_id=main.info_id AND info_extra_name=".$this->db->quote($sortbycf).") AS cfsortcrit ";
|
||||||
}
|
}
|
||||||
//echo "SELECT $distinct main.* $count_subs $info_customfield $sql_query $ordermethod"."<br>";
|
//echo "SELECT $distinct main.* $info_customfield $sql_query $ordermethod"."<br>";
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (isset($query['start']) && isset($query['total']) && $query['start'] > $query['total'])
|
if (isset($query['start']) && isset($query['total']) && $query['start'] > $query['total'])
|
||||||
{
|
{
|
||||||
$query['start'] = 0;
|
$query['start'] = 0;
|
||||||
}
|
}
|
||||||
$rs = $this->db->query($sql="SELECT $mysql_calc_rows $distinct main.* $count_subs $info_customfield $sql_query $ordermethod",__LINE__,__FILE__,
|
$rs = $this->db->query($sql="SELECT $mysql_calc_rows $distinct main.* $info_customfield $sql_query $ordermethod",__LINE__,__FILE__,
|
||||||
(int) $query['start'],isset($query['start']) ? (int) $query['num_rows'] : -1,false,egw_db::FETCH_ASSOC);
|
(int) $query['start'],isset($query['start']) ? (int) $query['num_rows'] : -1,false,egw_db::FETCH_ASSOC);
|
||||||
//echo "<p>db::query('$sql',,,".(int)$query['start'].','.(isset($query['start']) ? (int) $query['num_rows'] : -1).")</p>\n";
|
//echo "<p>db::query('$sql',,,".(int)$query['start'].','.(isset($query['start']) ? (int) $query['num_rows'] : -1).")</p>\n";
|
||||||
|
|
||||||
|
@ -355,10 +355,11 @@ class infolog_ui
|
|||||||
// set old show_times pref, that get_info calculates the cumulated time of the timesheets
|
// set old show_times pref, that get_info calculates the cumulated time of the timesheets
|
||||||
$this->prefs['show_times'] = strpos($this->prefs['nextmatch-'.$query['columnselection_pref']],'info_used_time_info_planned_time_info_replanned_time') !== false;
|
$this->prefs['show_times'] = strpos($this->prefs['nextmatch-'.$query['columnselection_pref']],'info_used_time_info_planned_time_info_replanned_time') !== false;
|
||||||
|
|
||||||
// query all links in one go
|
// query all links and sub counts in one go
|
||||||
if ($infos && !$query['csv_export'])
|
if ($infos && !$query['csv_export'])
|
||||||
{
|
{
|
||||||
$links = bolink::get_links_multiple('infolog',array_keys($infos));
|
$links = bolink::get_links_multiple('infolog',array_keys($infos));
|
||||||
|
$anzSubs = $this->bo->anzSubs(array_keys($infos));
|
||||||
}
|
}
|
||||||
$readonlys = $rows = array();
|
$readonlys = $rows = array();
|
||||||
foreach($infos as $id => $info)
|
foreach($infos as $id => $info)
|
||||||
@ -366,6 +367,7 @@ class infolog_ui
|
|||||||
if (!$query['csv_export'])
|
if (!$query['csv_export'])
|
||||||
{
|
{
|
||||||
$info['links'] =& $links[$id];
|
$info['links'] =& $links[$id];
|
||||||
|
$info['info_anz_subs'] = (int)$anzSubs[$id];
|
||||||
$info = $this->get_info($info,$readonlys,$query['action'],$query['action_id'],$query['filter2'],$details);
|
$info = $this->get_info($info,$readonlys,$query['action'],$query['action_id'],$query['filter2'],$details);
|
||||||
|
|
||||||
if (!$query['filter2'] && $this->prefs['show_links'] == 'no_describtion' ||
|
if (!$query['filter2'] && $this->prefs['show_links'] == 'no_describtion' ||
|
||||||
|
Loading…
Reference in New Issue
Block a user