diff --git a/application/controllers/Dashboard.php b/application/controllers/Dashboard.php index 45b44c178..d2d01a1ac 100644 --- a/application/controllers/Dashboard.php +++ b/application/controllers/Dashboard.php @@ -2,8 +2,7 @@ class Dashboard extends CI_Controller { - public function index() - { + public function index() { // Check if users logged in $this->load->model('user_model'); if ($this->user_model->validate_session() == 0) { diff --git a/application/controllers/Logbook.php b/application/controllers/Logbook.php index f281a17ce..aa4c821d0 100644 --- a/application/controllers/Logbook.php +++ b/application/controllers/Logbook.php @@ -7,7 +7,6 @@ require_once APPPATH . '../src/Dxcc/Dxcc.php'; class Logbook extends CI_Controller { function index() { - // Check if users logged in $this->load->model('user_model'); if($this->user_model->validate_session() == 0) { @@ -707,29 +706,66 @@ class Logbook extends CI_Controller { $html = ""; - if(!empty($logbooks_locations_array)) { - $this->db->select(''.$this->config->item('table_name').'.COL_CALL, '.$this->config->item('table_name').'.COL_BAND, '.$this->config->item('table_name').'.COL_FREQ, '.$this->config->item('table_name').'.COL_TIME_ON, '.$this->config->item('table_name').'.COL_RST_RCVD, '.$this->config->item('table_name').'.COL_RST_SENT, '.$this->config->item('table_name').'.COL_MODE, '.$this->config->item('table_name').'.COL_SUBMODE, '.$this->config->item('table_name').'.COL_PRIMARY_KEY, '.$this->config->item('table_name').'.COL_SAT_NAME, '.$this->config->item('table_name').'.COL_GRIDSQUARE, '.$this->config->item('table_name').'.COL_QSL_RCVD, '.$this->config->item('table_name').'.COL_EQSL_QSL_RCVD, '.$this->config->item('table_name').'.COL_EQSL_QSL_SENT, '.$this->config->item('table_name').'.COL_QSL_SENT, '.$this->config->item('table_name').'.COL_STX, '.$this->config->item('table_name').'.COL_STX_STRING, '.$this->config->item('table_name').'.COL_SRX, '.$this->config->item('table_name').'.COL_SRX_STRING, '.$this->config->item('table_name').'.COL_LOTW_QSL_SENT, '.$this->config->item('table_name').'.COL_LOTW_QSL_RCVD, '.$this->config->item('table_name').'.COL_VUCC_GRIDS, '.$this->config->item('table_name').'.COL_MY_GRIDSQUARE, '.$this->config->item('table_name').'.COL_CONTEST_ID, '.$this->config->item('table_name').'.COL_STATE, '.$this->config->item('table_name').'.COL_QRZCOM_QSO_UPLOAD_STATUS, '.$this->config->item('table_name').'.COL_QRZCOM_QSO_DOWNLOAD_STATUS, '.$this->config->item('table_name').'.COL_CLUBLOG_QSO_UPLOAD_STATUS, '.$this->config->item('table_name').'.COL_CLUBLOG_QSO_DOWNLOAD_STATUS, '.$this->config->item('table_name').'.COL_POTA_REF, '.$this->config->item('table_name').'.COL_IOTA, '.$this->config->item('table_name').'.COL_SOTA_REF, '.$this->config->item('table_name').'.COL_WWFF_REF, '.$this->config->item('table_name').'.COL_OPERATOR, '.$this->config->item('table_name').'.COL_COUNTRY, station_profile.*, satellite.displayname AS sat_displayname'); - $this->db->from($this->config->item('table_name')); - - $this->db->join('station_profile', 'station_profile.station_id = '.$this->config->item('table_name').'.station_id'); - $this->db->join('satellite', 'satellite.name = '.$this->config->item('table_name').'.COL_SAT_NAME', 'left outer'); - $this->db->where_in('station_profile.station_id', $logbooks_locations_array); - - $this->db->group_start(); - $this->db->where($this->config->item('table_name').'.COL_CALL', $lookupcall); - $this->db->or_like($this->config->item('table_name').'.COL_CALL', '/'.$lookupcall,'before'); - $this->db->or_like($this->config->item('table_name').'.COL_CALL', $lookupcall.'/','after'); - $this->db->or_like($this->config->item('table_name').'.COL_CALL', '/'.$lookupcall.'/'); - $this->db->group_end(); - - $this->db->order_by($this->config->item('table_name').".COL_TIME_ON", "desc"); - $this->db->order_by($this->config->item('table_name').".COL_PRIMARY_KEY", "desc"); - $this->db->limit($count); - - $query = $this->db->get(); + // Load all satellites once for PHP-side join (much faster than SQL join) + $satellites = []; + $sat_query = $this->db->query('SELECT name, displayname FROM satellite'); + foreach ($sat_query->result() as $sat) { + $satellites[$sat->name] = $sat->displayname; } - if (!empty($logbooks_locations_array) && $query->num_rows() > 0) { + if(!empty($logbooks_locations_array)) { + $station_ids = implode(',', array_map(function($id) { return (int)$id; }, $logbooks_locations_array)); + + $bindings = [ + $lookupcall, // Exact match: COL_CALL = ? + '/' . $lookupcall, // Starts with /: COL_CALL LIKE '/ABC' + $lookupcall . '/', // Ends with /: COL_CALL LIKE 'ABC/' + '/' . $lookupcall . '/', // Both sides: COL_CALL LIKE '/ABC/' + (int)$count // LIMIT + ]; + + $sql = "SELECT + qsos.COL_CALL, qsos.COL_BAND, qsos.COL_FREQ, qsos.COL_TIME_ON, + qsos.COL_RST_RCVD, qsos.COL_RST_SENT, qsos.COL_MODE, qsos.COL_SUBMODE, + qsos.COL_PRIMARY_KEY, qsos.COL_SAT_NAME, qsos.COL_GRIDSQUARE, + qsos.COL_QSL_RCVD, qsos.COL_EQSL_QSL_RCVD, qsos.COL_EQSL_QSL_SENT, + qsos.COL_QSL_SENT, qsos.COL_STX, qsos.COL_STX_STRING, qsos.COL_SRX, + qsos.COL_SRX_STRING, qsos.COL_LOTW_QSL_SENT, qsos.COL_LOTW_QSL_RCVD, + qsos.COL_VUCC_GRIDS, qsos.COL_MY_GRIDSQUARE, qsos.COL_CONTEST_ID, + qsos.COL_STATE, qsos.COL_QRZCOM_QSO_UPLOAD_STATUS, + qsos.COL_QRZCOM_QSO_DOWNLOAD_STATUS, qsos.COL_CLUBLOG_QSO_UPLOAD_STATUS, + qsos.COL_CLUBLOG_QSO_DOWNLOAD_STATUS, qsos.COL_POTA_REF, qsos.COL_IOTA, + qsos.COL_SOTA_REF, qsos.COL_WWFF_REF, qsos.COL_OPERATOR, qsos.COL_COUNTRY, + station_profile.* + FROM " . $this->config->item('table_name') . " qsos + JOIN station_profile ON station_profile.station_id = qsos.station_id + WHERE station_profile.station_id IN ($station_ids) + AND ( + qsos.COL_CALL = ? + OR qsos.COL_CALL LIKE ? + OR qsos.COL_CALL LIKE ? + OR qsos.COL_CALL LIKE ? + ) + ORDER BY qsos.COL_TIME_ON DESC, qsos.COL_PRIMARY_KEY DESC + LIMIT ?"; + + $query = $this->db->query($sql, $bindings); + + // Add satellite data via PHP-side join + $results = $query->result(); + foreach ($results as &$row) { + $row->sat_name = $row->COL_SAT_NAME ?? null; + $row->sat_displayname = null; + if (!empty($row->COL_SAT_NAME) && isset($satellites[$row->COL_SAT_NAME])) { + $row->sat_displayname = $satellites[$row->COL_SAT_NAME]; + } + } + unset($row); + } else { + $results = []; + } + + if (!empty($results)) { $html .= "
| ".date($custom_date_format, $timestamp). date(' H:i',strtotime($row->COL_TIME_ON ?? '1970-01-01 00:00:00')) . " | "; diff --git a/application/models/Logbook_model.php b/application/models/Logbook_model.php index c65267ef1..19c25ff4e 100644 --- a/application/models/Logbook_model.php +++ b/application/models/Logbook_model.php @@ -2163,13 +2163,19 @@ class Logbook_model extends CI_Model { return array(); } + // Load all satellites once for PHP-side join (much faster than SQL COALESCE) + $satellites = []; + $sat_query = $this->db->select('name, displayname')->get('satellite'); + foreach ($sat_query->result() as $sat) { + $satellites[$sat->name] = $sat->displayname; + } + $binding = array(); - $sql = "SELECT qsos.*, station_profile.*, dxcc_entities.*, lotw_users.callsign, lotw_users.lastupload, satellite.displayname AS sat_displayname, satellite.name AS sat_name + $sql = "SELECT qsos.*, station_profile.*, dxcc_entities.*, lotw_users.callsign, lotw_users.lastupload FROM ".$this->config->item('table_name')." qsos JOIN `station_profile` ON `station_profile`.`station_id` = qsos.`station_id` LEFT JOIN `dxcc_entities` ON qsos.`col_dxcc` = `dxcc_entities`.`adif` LEFT OUTER JOIN `lotw_users` ON `lotw_users`.`callsign` = qsos.`col_call` - LEFT OUTER JOIN satellite ON qsos.col_prop_mode='SAT' and qsos.COL_SAT_NAME = COALESCE(NULLIF(satellite.name, ''), NULLIF(satellite.displayname, '')) WHERE 1=1"; if ($band != '') { if ($band == 'SAT') { @@ -2194,7 +2200,39 @@ class Logbook_model extends CI_Model { $binding[] = (int) $offset; } $sql .= ";"; - return $this->db->query($sql, $binding); + $query = $this->db->query($sql, $binding); + + // Add satellite data via PHP-side join (much faster than SQL COALESCE join) + $results = $query->result(); + foreach ($results as &$row) { + $row->sat_name = $row->COL_SAT_NAME ?? null; + $row->sat_displayname = null; + if (!empty($row->COL_SAT_NAME) && isset($satellites[$row->COL_SAT_NAME])) { + $row->sat_displayname = $satellites[$row->COL_SAT_NAME]; + } + } + unset($row); + + // Return a query-like object with result() method for compatibility + return new class($results) { + private $data; + + public function __construct($data) { + $this->data = $data; + } + + public function result() { + return $this->data; + } + + public function num_rows() { + return count($this->data); + } + + public function num_fields() { + return empty($this->data) ? 0 : count(get_object_vars($this->data[0])); + } + }; } function get_qso($id, $trusted = false) { diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php index 12e9b2d3e..8d1e1a941 100644 --- a/application/models/Logbookadvanced_model.php +++ b/application/models/Logbookadvanced_model.php @@ -94,6 +94,13 @@ class Logbookadvanced_model extends CI_Model { } public function searchDb($searchCriteria) { + // Load all satellites once for PHP-side join (much faster than SQL COALESCE) + $satellites = []; + $sat_query = $this->db->query('SELECT name, displayname FROM satellite'); + foreach ($sat_query->result() as $sat) { + $satellites[$sat->name] = $sat->displayname; + } + $conditions = []; $binding = [$searchCriteria['user_id']]; @@ -637,10 +644,9 @@ class Logbookadvanced_model extends CI_Model { } $sql = " - SELECT qsos.*, qsos.last_modified AS qso_last_modified, dxcc_entities.*, lotw_users.*, station_profile.*, satellite.*, dxcc_entities.name as dxccname, mydxcc.name AS station_country, exists(select 1 from qsl_images where qsoid = qsos.COL_PRIMARY_KEY) as qslcount, coalesce(contest.name, qsos.col_contest_id) as contestname + SELECT qsos.*, qsos.last_modified AS qso_last_modified, dxcc_entities.*, lotw_users.*, station_profile.*, dxcc_entities.name as dxccname, mydxcc.name AS station_country, exists(select 1 from qsl_images where qsoid = qsos.COL_PRIMARY_KEY) as qslcount, coalesce(contest.name, qsos.col_contest_id) as contestname FROM " . $this->config->item('table_name') . " qsos INNER JOIN station_profile ON qsos.station_id=station_profile.station_id - LEFT OUTER JOIN satellite ON qsos.col_prop_mode='SAT' and qsos.COL_SAT_NAME = COALESCE(NULLIF(satellite.name, ''), NULLIF(satellite.displayname, '')) LEFT OUTER JOIN dxcc_entities ON qsos.col_dxcc = dxcc_entities.adif left outer join dxcc_entities mydxcc on qsos.col_my_dxcc = mydxcc.adif LEFT OUTER JOIN lotw_users ON qsos.col_call = lotw_users.callsign @@ -651,7 +657,42 @@ class Logbookadvanced_model extends CI_Model { $sortorder $limit "; - return $this->db->query($sql, $binding); + $query = $this->db->query($sql, $binding); + + // Add satellite data via PHP-side join (much faster than SQL COALESCE) + $results = $query->result(); + foreach ($results as &$row) { + $row->sat_name = $row->COL_SAT_NAME ?? null; + $row->sat_displayname = null; + if (!empty($row->COL_SAT_NAME) && isset($satellites[$row->COL_SAT_NAME])) { + $row->sat_displayname = $satellites[$row->COL_SAT_NAME]; + } + } + unset($row); + + // Return a query-like object with result() method for compatibility + return new class($results) { + private $data; + + public function __construct($data) { + $this->data = $data; + } + + public function result($type = 'object') { + if ($type === 'array') { + return json_decode(json_encode($this->data), true); + } + return $this->data; + } + + public function num_rows() { + return count($this->data); + } + + public function row() { + return !empty($this->data) ? $this->data[0] : null; + } + }; }