Split contact query into subqueries

One can't fetch host and service contacts with a reasonable single
query.

refs #3088
This commit is contained in:
Eric Lippmann 2018-07-05 14:06:52 +02:00
parent aa25bb4be4
commit e684c6d18e
7 changed files with 529 additions and 214 deletions

View File

@ -3,233 +3,104 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
/**
* Query for contacts
*/
class ContactQuery extends IdoQuery
{
/**
* {@inheritdoc}
*/
protected $allowCustomVars = true;
/**
* {@inheritdoc}
*/
protected $groupBase = array('contacts' => array('co.object_id', 'c.contact_id'));
/**
* {@inheritdoc}
*/
protected $groupOrigin = array('contactgroups', 'hosts', 'services');
/**
* {@inheritdoc}
*/
protected $columnMap = array(
'contactgroups' => array(
'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci',
'contactgroup_name' => 'cgo.name1',
'contactgroup_alias' => 'cg.alias COLLATE latin1_general_ci'
),
'contacts' => array(
protected $columnMap = [
'contacts' => [
'contact_id' => 'c.contact_id',
'contact' => 'co.name1 COLLATE latin1_general_ci',
'contact_name' => 'co.name1',
'contact_alias' => 'c.alias COLLATE latin1_general_ci',
'contact_email' => 'c.email_address COLLATE latin1_general_ci',
'contact_pager' => 'c.pager_address',
'contact' => 'c.contact',
'contact_name' => 'c.contact_name',
'contact_alias' => 'c.contact_alias',
'contact_email' => 'c.contact_email',
'contact_pager' => 'c.contact_pager',
'contact_object_id' => 'c.contact_object_id',
'contact_has_host_notfications' => 'c.host_notifications_enabled',
'contact_has_service_notfications' => 'c.service_notifications_enabled',
'contact_can_submit_commands' => 'c.can_submit_commands',
'contact_notify_service_recovery' => 'c.notify_service_recovery',
'contact_notify_service_warning' => 'c.notify_service_warning',
'contact_notify_service_critical' => 'c.notify_service_critical',
'contact_notify_service_unknown' => 'c.notify_service_unknown',
'contact_notify_service_flapping' => 'c.notify_service_flapping',
'contact_notify_service_downtime' => 'c.notify_service_downtime',
'contact_notify_host_recovery' => 'c.notify_host_recovery',
'contact_notify_host_down' => 'c.notify_host_down',
'contact_notify_host_unreachable' => 'c.notify_host_unreachable',
'contact_notify_host_flapping' => 'c.notify_host_flapping',
'contact_notify_host_downtime' => 'c.notify_host_downtime'
),
'hostgroups' => array(
'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
'hostgroup_name' => 'hgo.name1'
),
'hosts' => array(
'host' => 'ho.name1 COLLATE latin1_general_ci',
'host_name' => 'ho.name1',
'host_alias' => 'h.alias',
'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
),
'instances' => array(
'instance_name' => 'i.instance_name'
),
'servicegroups' => array(
'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
'servicegroup_name' => 'sgo.name1',
'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
),
'services' => array(
'service' => 'so.name2 COLLATE latin1_general_ci',
'service_description' => 'so.name2',
'service_display_name' => 's.display_name COLLATE latin1_general_ci',
'service_host_name' => 'so.name1'
),
'timeperiods' => array(
'contact_notify_host_timeperiod' => 'ht.alias COLLATE latin1_general_ci',
'contact_notify_service_timeperiod' => 'st.alias COLLATE latin1_general_ci'
)
);
'contact_has_host_notfications' => 'c.contact_has_host_notfications',
'contact_has_service_notfications' => 'c.contact_has_service_notfications',
'contact_can_submit_commands' => 'c.contact_can_submit_commands',
'contact_notify_service_recovery' => 'c.contact_notify_service_recovery',
'contact_notify_service_warning' => 'c.contact_notify_service_warning',
'contact_notify_service_critical' => 'c.contact_notify_service_critical',
'contact_notify_service_unknown' => 'c.contact_notify_service_unknown',
'contact_notify_service_flapping' => 'c.contact_notify_service_flapping',
'contact_notify_service_downtime' => 'c.contact_notify_service_downtime',
'contact_notify_host_recovery' => 'c.contact_notify_host_recovery',
'contact_notify_host_down' => 'c.contact_notify_host_down',
'contact_notify_host_unreachable' => 'c.contact_notify_host_unreachable',
'contact_notify_host_flapping' => 'c.contact_notify_host_flapping',
'contact_notify_host_downtime' => 'c.contact_notify_host_downtime',
'contact_notify_host_timeperiod' => 'c.contact_notify_host_timeperiod',
'contact_notify_service_timeperiod' => 'c.contact_notify_service_timeperiod'
]
];
/** @var Zend_Db_Select The union */
protected $contactQuery;
/** @var IdoQuery[] Subqueries used for the contact query */
protected $subQueries = [];
public function allowsCustomVars()
{
foreach ($this->subQueries as $query) {
if (! $query->allowsCustomVars()) {
return false;
}
}
return true;
}
public function addFilter(Filter $filter)
{
foreach ($this->subQueries as $sub) {
$sub->applyFilter(clone $filter);
}
return $this;
}
/**
* {@inheritdoc}
*/
protected function joinBaseTables()
{
$this->select->from(
array('c' => $this->prefix . 'contacts'),
array()
)->join(
array('co' => $this->prefix . 'objects'),
'co.object_id = c.contact_object_id AND co.is_active = 1',
array()
$this->contactQuery = $this->db->select();
$this->select->distinct()->from(
['c' => $this->contactQuery],
[]
);
$hosts = $this->createSubQuery('hostcontact', array_keys($this->columnMap['contacts']));
$this->subQueries[] = $hosts;
$this->contactQuery->union([$hosts], Zend_Db_Select::SQL_UNION_ALL);
$services = $this->createSubQuery('servicecontact', array_keys($this->columnMap['contacts']));
$this->subQueries[] = $services;
$this->contactQuery->union([$services], Zend_Db_Select::SQL_UNION_ALL);
$this->joinedVirtualTables['contacts'] = true;
}
/**
* Join contact groups
*/
protected function joinContactgroups()
public function order($columnOrAlias, $dir = null)
{
$this->select->joinLeft(
array('cgm' => $this->prefix . 'contactgroup_members'),
'co.object_id = cgm.contact_object_id',
array()
)->joinLeft(
array('cg' => $this->prefix . 'contactgroups'),
'cgm.contactgroup_id = cg.contactgroup_id',
array()
)->joinLeft(
array('cgo' => $this->prefix . 'objects'),
'cg.contactgroup_object_id = cgo.object_id AND cgo.is_active = 1 AND cgo.objecttype_id = 11',
array()
);
foreach ($this->subQueries as $sub) {
$sub->requireColumn($columnOrAlias);
}
return parent::order($columnOrAlias, $dir);
}
/**
* Join host groups
*/
protected function joinHostgroups()
public function where($condition, $value = null)
{
$this->requireVirtualTable('hosts');
$this->select->joinLeft(
array('hgm' => $this->prefix . 'hostgroup_members'),
'hgm.host_object_id = ho.object_id',
array()
)->joinLeft(
array('hg' => $this->prefix . 'hostgroups'),
'hg.hostgroup_id = hgm.hostgroup_id',
array()
)->joinLeft(
array('hgo' => $this->prefix . 'objects'),
'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
array()
);
}
$this->requireColumn($condition);
foreach ($this->subQueries as $sub) {
$sub->where($condition, $value);
}
/**
* Join hosts
*/
protected function joinHosts()
{
$this->select->joinLeft(
array('hc' => $this->prefix . 'host_contacts'),
'hc.contact_object_id = c.contact_object_id',
array()
)->joinLeft(
array('h' => $this->prefix . 'hosts'),
'h.host_id = hc.host_id',
array()
)->joinLeft(
array('ho' => $this->prefix . 'objects'),
'ho.object_id = h.host_object_id AND ho.is_active = 1',
array()
);
}
/**
* Join instances
*/
protected function joinInstances()
{
$this->select->join(
array('i' => $this->prefix . 'instances'),
'i.instance_id = c.instance_id',
array()
);
}
/**
* Join service groups
*/
protected function joinServicegroups()
{
$this->requireVirtualTable('services');
$this->select->joinLeft(
array('sgm' => $this->prefix . 'servicegroup_members'),
'sgm.service_object_id = s.service_object_id',
array()
)->joinLeft(
array('sg' => $this->prefix . 'servicegroups'),
'sg.servicegroup_id = sgm.servicegroup_id',
array()
)->joinLeft(
array('sgo' => $this->prefix . 'objects'),
'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
array()
);
}
/**
* Join services
*/
protected function joinServices()
{
$this->select->joinLeft(
array('sc' => $this->prefix . 'service_contacts'),
'sc.contact_object_id = c.contact_object_id',
array()
)->joinLeft(
array('s' => $this->prefix . 'services'),
's.service_id = sc.service_id',
array()
)->joinLeft(
array('so' => $this->prefix . 'objects'),
'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
array()
);
}
/**
* Join time periods
*/
protected function joinTimeperiods()
{
$this->select->joinLeft(
array('ht' => $this->prefix . 'timeperiods'),
'ht.timeperiod_object_id = c.host_timeperiod_object_id',
array()
);
$this->select->joinLeft(
array('st' => $this->prefix . 'timeperiods'),
'st.timeperiod_object_id = c.service_timeperiod_object_id',
array()
);
return $this;
}
}

View File

@ -0,0 +1,211 @@
<?php
/* Icinga Web 2 | (c) 2018 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
/**
* Query for host contacts
*/
class HostcontactQuery extends IdoQuery
{
protected $allowCustomVars = true;
protected $groupBase = ['contacts' => ['co.object_id', 'c.contact_id'], 'timeperiods' => ['ht.timeperiod_id']];
protected $groupOrigin = ['contactgroups', 'hosts', 'services'];
protected $columnMap = [
'contactgroups' => [
'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci',
'contactgroup_name' => 'cgo.name1',
'contactgroup_alias' => 'cg.alias COLLATE latin1_general_ci'
],
'contacts' => [
'contact_id' => 'c.contact_id',
'contact' => 'co.name1 COLLATE latin1_general_ci',
'contact_name' => 'co.name1',
'contact_alias' => 'c.alias COLLATE latin1_general_ci',
'contact_email' => 'c.email_address COLLATE latin1_general_ci',
'contact_pager' => 'c.pager_address',
'contact_object_id' => 'c.contact_object_id',
'contact_has_host_notfications' => 'c.host_notifications_enabled',
'contact_has_service_notfications' => 'c.service_notifications_enabled',
'contact_can_submit_commands' => 'c.can_submit_commands',
'contact_notify_service_recovery' => 'c.notify_service_recovery',
'contact_notify_service_warning' => 'c.notify_service_warning',
'contact_notify_service_critical' => 'c.notify_service_critical',
'contact_notify_service_unknown' => 'c.notify_service_unknown',
'contact_notify_service_flapping' => 'c.notify_service_flapping',
'contact_notify_service_downtime' => 'c.notify_service_downtime',
'contact_notify_host_recovery' => 'c.notify_host_recovery',
'contact_notify_host_down' => 'c.notify_host_down',
'contact_notify_host_unreachable' => 'c.notify_host_unreachable',
'contact_notify_host_flapping' => 'c.notify_host_flapping',
'contact_notify_host_downtime' => 'c.notify_host_downtime'
],
'hostgroups' => [
'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
'hostgroup_name' => 'hgo.name1'
],
'hosts' => [
'host' => 'ho.name1 COLLATE latin1_general_ci',
'host_name' => 'ho.name1',
'host_alias' => 'h.alias',
'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
],
'instances' => [
'instance_name' => 'i.instance_name'
],
'servicegroups' => [
'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
'servicegroup_name' => 'sgo.name1',
'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
],
'services' => [
'service' => 'so.name2 COLLATE latin1_general_ci',
'service_description' => 'so.name2',
'service_display_name' => 's.display_name COLLATE latin1_general_ci',
'service_host_name' => 'so.name1'
],
'timeperiods' => [
'contact_notify_host_timeperiod' => 'ht.alias COLLATE latin1_general_ci',
'contact_notify_service_timeperiod' => 'st.alias COLLATE latin1_general_ci'
]
];
protected function joinBaseTables()
{
$this->select->from(
['c' => $this->prefix . 'contacts'],
[]
)->join(
['co' => $this->prefix . 'objects'],
'co.object_id = c.contact_object_id AND co.is_active = 1',
[]
);
$this->select->joinLeft(
['hc' => $this->prefix . 'host_contacts'],
'hc.contact_object_id = c.contact_object_id',
[]
)->joinLeft(
['h' => $this->prefix . 'hosts'],
'h.host_id = hc.host_id',
[]
)->joinLeft(
['ho' => $this->prefix . 'objects'],
'ho.object_id = h.host_object_id AND ho.is_active = 1',
[]
);
$this->joinedVirtualTables['contacts'] = true;
$this->joinedVirtualTables['hosts'] = true;
}
/**
* Join contact groups
*/
protected function joinContactgroups()
{
$this->select->joinLeft(
['cgm' => $this->prefix . 'contactgroup_members'],
'co.object_id = cgm.contact_object_id',
[]
)->joinLeft(
['cg' => $this->prefix . 'contactgroups'],
'cgm.contactgroup_id = cg.contactgroup_id',
[]
)->joinLeft(
['cgo' => $this->prefix . 'objects'],
'cg.contactgroup_object_id = cgo.object_id AND cgo.is_active = 1 AND cgo.objecttype_id = 11',
[]
);
}
/**
* Join host groups
*/
protected function joinHostgroups()
{
$this->select->joinLeft(
['hgm' => $this->prefix . 'hostgroup_members'],
'hgm.host_object_id = ho.object_id',
[]
)->joinLeft(
['hg' => $this->prefix . 'hostgroups'],
'hg.hostgroup_id = hgm.hostgroup_id',
[]
)->joinLeft(
['hgo' => $this->prefix . 'objects'],
'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
[]
);
}
/**
* Join instances
*/
protected function joinInstances()
{
$this->select->join(
['i' => $this->prefix . 'instances'],
'i.instance_id = c.instance_id',
[]
);
}
/**
* Join service groups
*/
protected function joinServicegroups()
{
$this->requireVirtualTable('services');
$this->select->joinLeft(
['sgm' => $this->prefix . 'servicegroup_members'],
'sgm.service_object_id = s.service_object_id',
[]
)->joinLeft(
['sg' => $this->prefix . 'servicegroups'],
'sg.servicegroup_id = sgm.servicegroup_id',
[]
)->joinLeft(
['sgo' => $this->prefix . 'objects'],
'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
[]
);
}
/**
* Join services
*/
protected function joinServices()
{
$this->select->joinLeft(
['s' => $this->prefix . 'services'],
's.host_object_id = ho.object_id',
[]
)->joinLeft(
['so' => $this->prefix . 'objects'],
'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
[]
);
}
/**
* Join time periods
*/
protected function joinTimeperiods()
{
$this->select->joinLeft(
['ht' => $this->prefix . 'timeperiods'],
'ht.timeperiod_object_id = c.host_timeperiod_object_id',
[]
);
$this->select->joinLeft(
['st' => $this->prefix . 'timeperiods'],
'st.timeperiod_object_id = c.service_timeperiod_object_id',
[]
);
}
}

View File

@ -1132,10 +1132,6 @@ abstract class IdoQuery extends DbQuery
case 'servicestatus':
$groupedColumns[] = 'ss.servicestatus_id';
break;
case 'timeperiods':
$groupedColumns[] = 'ht.timeperiod_id';
$groupedColumns[] = 'st.timeperiod_id';
break;
default:
return;
}

View File

@ -0,0 +1,212 @@
<?php
/* Icinga Web 2 | (c) 2018 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
/**
* Query for service contacts
*/
class ServicecontactQuery extends IdoQuery
{
protected $allowCustomVars = true;
protected $groupBase = ['contacts' => ['co.object_id', 'c.contact_id'], 'timeperiods' => ['st.timeperiod_id']];
protected $groupOrigin = ['contactgroups', 'hosts', 'services'];
protected $columnMap = [
'contactgroups' => [
'contactgroup' => 'cgo.name1 COLLATE latin1_general_ci',
'contactgroup_name' => 'cgo.name1',
'contactgroup_alias' => 'cg.alias COLLATE latin1_general_ci'
],
'contacts' => [
'contact_id' => 'c.contact_id',
'contact' => 'co.name1 COLLATE latin1_general_ci',
'contact_name' => 'co.name1',
'contact_alias' => 'c.alias COLLATE latin1_general_ci',
'contact_email' => 'c.email_address COLLATE latin1_general_ci',
'contact_pager' => 'c.pager_address',
'contact_object_id' => 'c.contact_object_id',
'contact_has_host_notfications' => 'c.host_notifications_enabled',
'contact_has_service_notfications' => 'c.service_notifications_enabled',
'contact_can_submit_commands' => 'c.can_submit_commands',
'contact_notify_service_recovery' => 'c.notify_service_recovery',
'contact_notify_service_warning' => 'c.notify_service_warning',
'contact_notify_service_critical' => 'c.notify_service_critical',
'contact_notify_service_unknown' => 'c.notify_service_unknown',
'contact_notify_service_flapping' => 'c.notify_service_flapping',
'contact_notify_service_downtime' => 'c.notify_service_downtime',
'contact_notify_host_recovery' => 'c.notify_host_recovery',
'contact_notify_host_down' => 'c.notify_host_down',
'contact_notify_host_unreachable' => 'c.notify_host_unreachable',
'contact_notify_host_flapping' => 'c.notify_host_flapping',
'contact_notify_host_downtime' => 'c.notify_host_downtime'
],
'hostgroups' => [
'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
'hostgroup_alias' => 'hg.alias COLLATE latin1_general_ci',
'hostgroup_name' => 'hgo.name1'
],
'hosts' => [
'host' => 'ho.name1 COLLATE latin1_general_ci',
'host_name' => 'ho.name1',
'host_alias' => 'h.alias',
'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
],
'instances' => [
'instance_name' => 'i.instance_name'
],
'servicegroups' => [
'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci',
'servicegroup_name' => 'sgo.name1',
'servicegroup_alias' => 'sg.alias COLLATE latin1_general_ci'
],
'services' => [
'service' => 'so.name2 COLLATE latin1_general_ci',
'service_description' => 'so.name2',
'service_display_name' => 's.display_name COLLATE latin1_general_ci',
'service_host_name' => 'so.name1'
],
'timeperiods' => [
'contact_notify_host_timeperiod' => 'ht.alias COLLATE latin1_general_ci',
'contact_notify_service_timeperiod' => 'st.alias COLLATE latin1_general_ci'
]
];
protected function joinBaseTables()
{
$this->select->from(
['c' => $this->prefix . 'contacts'],
[]
)->join(
['co' => $this->prefix . 'objects'],
'co.object_id = c.contact_object_id AND co.is_active = 1',
[]
);
$this->select->joinLeft(
['sc' => $this->prefix . 'service_contacts'],
'sc.contact_object_id = c.contact_object_id',
[]
)->joinLeft(
['s' => $this->prefix . 'services'],
's.service_id = sc.service_id',
[]
)->joinLeft(
['so' => $this->prefix . 'objects'],
'so.object_id = s.service_object_id AND so.is_active = 1 AND so.objecttype_id = 2',
[]
);
$this->joinedVirtualTables['contacts'] = true;
$this->joinedVirtualTables['services'] = true;
}
/**
* Join contact groups
*/
protected function joinContactgroups()
{
$this->select->joinLeft(
['cgm' => $this->prefix . 'contactgroup_members'],
'co.object_id = cgm.contact_object_id',
[]
)->joinLeft(
['cg' => $this->prefix . 'contactgroups'],
'cgm.contactgroup_id = cg.contactgroup_id',
[]
)->joinLeft(
['cgo' => $this->prefix . 'objects'],
'cg.contactgroup_object_id = cgo.object_id AND cgo.is_active = 1 AND cgo.objecttype_id = 11',
[]
);
}
/**
* Join host groups
*/
protected function joinHostgroups()
{
$this->requireVirtualTable('hosts');
$this->select->joinLeft(
['hgm' => $this->prefix . 'hostgroup_members'],
'hgm.host_object_id = ho.object_id',
[]
)->joinLeft(
['hg' => $this->prefix . 'hostgroups'],
'hg.hostgroup_id = hgm.hostgroup_id',
[]
)->joinLeft(
['hgo' => $this->prefix . 'objects'],
'hgo.object_id = hg.hostgroup_object_id AND hgo.is_active = 1 AND hgo.objecttype_id = 3',
[]
);
}
/**
* Join hosts
*/
protected function joinHosts()
{
$this->select->joinLeft(
['h' => $this->prefix . 'hosts'],
'h.host_object_id = s.host_object_id',
[]
)->joinLeft(
['ho' => $this->prefix . 'objects'],
'ho.object_id = h.host_object_id AND ho.is_active = 1',
[]
);
}
/**
* Join instances
*/
protected function joinInstances()
{
$this->select->join(
['i' => $this->prefix . 'instances'],
'i.instance_id = c.instance_id',
[]
);
}
/**
* Join service groups
*/
protected function joinServicegroups()
{
$this->requireVirtualTable('services');
$this->select->joinLeft(
['sgm' => $this->prefix . 'servicegroup_members'],
'sgm.service_object_id = s.service_object_id',
[]
)->joinLeft(
['sg' => $this->prefix . 'servicegroups'],
'sg.servicegroup_id = sgm.servicegroup_id',
[]
)->joinLeft(
['sgo' => $this->prefix . 'objects'],
'sgo.object_id = sg.servicegroup_object_id AND sgo.is_active = 1 AND sgo.objecttype_id = 4',
[]
);
}
/**
* Join time periods
*/
protected function joinTimeperiods()
{
$this->select->joinLeft(
['ht' => $this->prefix . 'timeperiods'],
'ht.timeperiod_object_id = c.host_timeperiod_object_id',
[]
);
$this->select->joinLeft(
['st' => $this->prefix . 'timeperiods'],
'st.timeperiod_object_id = c.service_timeperiod_object_id',
[]
);
}
}

View File

@ -0,0 +1,17 @@
<?php
/* Icinga Web 2 | (c) 2018 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\DataView;
class Hostcontact extends Contact
{
public function getColumns()
{
return [
'contact_name',
'contact_alias',
'contact_email',
'contact_pager'
];
}
}

View File

@ -0,0 +1,8 @@
<?php
/* Icinga Web 2 | (c) 2018 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\DataView;
class Servicecontact extends Hostcontact
{
}

View File

@ -394,7 +394,7 @@ abstract class MonitoredObject implements Filterable
*/
public function fetchContacts()
{
$contacts = $this->backend->select()->from('contact', array(
$contacts = $this->backend->select()->from("{$this->type}contact", array(
'contact_name',
'contact_alias',
'contact_email',