From 23f5d80380c715fda0ca6421b5b7ffe65cbef88c Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Sun, 26 Mar 2006 22:09:02 +0000 Subject: [PATCH] enabled so_sql::search to use UNION --- etemplate/inc/class.so_sql.inc.php | 144 +++++++++++++++++++++-------- 1 file changed, 103 insertions(+), 41 deletions(-) diff --git a/etemplate/inc/class.so_sql.inc.php b/etemplate/inc/class.so_sql.inc.php index 06f93748fc..eabccaf5be 100644 --- a/etemplate/inc/class.so_sql.inc.php +++ b/etemplate/inc/class.so_sql.inc.php @@ -507,41 +507,113 @@ class so_sql } $query = $db_filter; } - $num_rows = 0; // as spec. in max_matches in the user-prefs - if (is_array($start)) list($start,$num_rows) = $start; - - if ($start !== false && $num_rows != 1) // need to get the total too, saved in $this->total - { - if ($this->db->Type == 'mysql' && $this->db->ServerInfo['version'] >= 4.0) - { - $mysql_calc_rows = 'SQL_CALC_FOUND_ROWS '; - } - elseif (!$need_full_no_count && (!$join || stristr($join,'LEFT JOIN'))) - { - $this->db->select($this->table_name,'COUNT(*)',$query,__LINE__,__FILE__); - $this->total = $this->db->next_record() ? (int) $this->db->f(0) : false; - } - else // cant do a count, have to run the query without limit - { - $this->db->select($this->table_name,($only_keys === true ? implode(',',$this->db_key_cols) : (!$only_keys ? '*' : $only_keys)). - ($extra_cols ? ','.(is_array($extra_cols) ? implode(',',$extra_cols) : $extra_cols) : ''), - $query,__LINE__,__FILE__,false,$order_by && !stristr($order_by,'ORDER BY') ? 'ORDER BY '.$order_by : $order_by,false,0,$join); - $this->total = $this->db->num_rows(); - } - } - $this->db->select($this->table_name,$mysql_calc_rows.($only_keys === true ? implode(',',$this->db_key_cols) : (!$only_keys ? '*' : $only_keys)). - ($extra_cols ? ','.(is_array($extra_cols) ? implode(',',$extra_cols) : $extra_cols) : ''), - $query,__LINE__,__FILE__,$start,$order_by && !stristr($order_by,'ORDER BY') ? 'ORDER BY '.$order_by : $order_by,false,$num_rows,$join); - - if ($mysql_calc_rows) - { - $this->total = $this->db->Link_ID->GetOne('SELECT FOUND_ROWS()'); - } if ((int) $this->debug >= 4) { echo "

so_sql::search(,only_keys=$only_keys,order_by='$order_by',wildcard='$wildcard',empty=$empty,$op,start='$start',".print_r($filter,true).") query=".print_r($query,true).", total='$this->total'

\n"; echo "
criteria = "; _debug_array($criteria); } + $colums = ($only_keys === true ? implode(',',$this->db_key_cols) : (!$only_keys ? '*' : $only_keys)). + ($extra_cols ? ','.(is_array($extra_cols) ? implode(',',$extra_cols) : $extra_cols) : ''); + + $num_rows = 0; // as spec. in max_matches in the user-prefs + if (is_array($start)) list($start,$num_rows) = $start; + + if (is_array($order_by)) + { + list($order_by,$union_order_by) = $order_by; + } + if ($order_by && !stristr($order_by,'ORDER BY')) + { + $order_by = 'ORDER BY '.$order_by; + } + static $union = array(); + static $union_cols = array(); + if ($start === 'UNION' || $union) + { + $union[] = array( + 'table' => $this->table_name, + 'cols' => $colums, + 'where' => $query, + 'append' => $order_by, + 'join' => $join, + ); + if ($start === 'UNION') + { + if (!$union_cols) // union used the colum-names of the first query + { + $union_cols = $this->_get_columns($only_keys,$extra_cols); + } + return true; // waiting for further calls, before running the union-query + } + // running the union query now + if ($start !== false && $num_rows != 1) // need to get the total too, saved in $this->total + { + if ($this->db->Type == 'mysql' && $this->db->ServerInfo['version'] >= 4.0) + { + $union[0]['cols'] = ($mysql_calc_rows = 'SQL_CALC_FOUND_ROWS ').$union[0]['cols']; + } + else // cant do a count, have to run the query without limit + { + $this->db->union($union,__LINE__,__FILE__); + $this->total = $this->db->num_rows(); + } + } + $this->db->union($union,__LINE__,__FILE__,$union_order_by,$start,$num_rows); + + $cols = $union_cols; + $union = $union_cols = array(); + } + else // no UNION + { + if ($start !== false && $num_rows != 1) // need to get the total too, saved in $this->total + { + if ($this->db->Type == 'mysql' && $this->db->ServerInfo['version'] >= 4.0) + { + $mysql_calc_rows = 'SQL_CALC_FOUND_ROWS '; + } + elseif (!$need_full_no_count && (!$join || stristr($join,'LEFT JOIN'))) + { + $this->db->select($this->table_name,'COUNT(*)',$query,__LINE__,__FILE__); + $this->total = $this->db->next_record() ? (int) $this->db->f(0) : false; + } + else // cant do a count, have to run the query without limit + { + $this->db->select($this->table_name,$colums,$query,__LINE__,__FILE__,false,$order_by,false,0,$join); + $this->total = $this->db->num_rows(); + } + } + $this->db->select($this->table_name,$mysql_calc_rows.$colums,$query,__LINE__,__FILE__, + $start,$order_by,false,$num_rows,$join); + + $cols = $this->_get_columns($only_keys,$extra_cols); + } + if ($mysql_calc_rows) + { + $this->total = $this->db->Link_ID->GetOne('SELECT FOUND_ROWS()'); + } + $arr = array(); + for ($n = 0; ($row = $this->db->row(true)); ++$n) + { + $data = array(); + foreach($cols as $db_col => $col) + { + $data[$col] = $row[$db_col]; + } + $arr[] = $this->db2data($data); + } + return $n ? $arr : False; + } + + /** + * extract the requested columns from $only_keys and $extra_cols param of a search + * + * @internal + * @param boolean/string $only_keys=true True returns only keys, False returns all cols. comma seperated list of keys to return + * @param string/array $extra_cols='' string or array of strings to be added to the SELECT, eg. "count(*) as num" + * @return array with columns as db-name => internal-name pairs + */ + function _get_columns($only_keys,$extra_cols) + { if ($only_keys === true) // only primary key { $cols = $this->db_key_cols; @@ -570,17 +642,7 @@ class so_sql $cols[$col] = $col; } } - $arr = array(); - for ($n = 0; ($row = $this->db->row(true)); ++$n) - { - $data = array(); - foreach($cols as $db_col => $col) - { - $data[$col] = $row[$db_col]; - } - $arr[] = $this->db2data($data); - } - return $n ? $arr : False; + return $cols; } /**