automatic joints from Relation table

This commit is contained in:
Marc Delisle
2002-04-26 10:48:23 +00:00
parent 481793d104
commit 3393185cbb
2 changed files with 215 additions and 11 deletions

View File

@@ -5,6 +5,11 @@ phpMyAdmin - Changelog
$Id$
$Source$
2002-04-26 Marc Delisle <lem9@users.sourceforge.net>
* tbl_qbe.php3: automatic joints from Relation table, thanks
to Mike Beck (mike.beck at ibmiller.de)
(experimental: some things remain to be tested)
2002-04-26 Alexander M. Turek <rabus@users.sourceforge.net>
* libraries/common.lib.php3: fixed a controluser bug.

View File

@@ -689,18 +689,217 @@ if (!empty($qry_select)) {
}
// 2. FROM
if (!isset($TableList)) {
$TableList = array();
}
if (!isset($qry_from)) {
$qry_from = '';
}
for ($x = 0; $x < sizeof($TableList); $x++) {
if ($x) {
$qry_from .= ', ';
// Create LEFT JOINS out of Relations
// Code originally by Mike Beck<mike.beck@ibmiller.de>
// If we can use Relations we could make some left joins
// First find out if relations are available in this database
// First we need the really needed Tables - those in TableList might
// still be all Tables.
if(count($Field)>0){
// we only start this if we have fields, otherwise it would be dumb
while (list(, $value) = each ($Field)) {
$parts = explode('.',$value);
if(urldecode($parts[0])!=''){
$alltabs_b[] = urldecode($parts[0]);
$alltabs[] =substr(urldecode($parts[0]),1,strlen(urldecode($parts[0]))-2);
}
}
$qry_from .= PMA_backquote(urldecode($TableList[$x]));
} // end for
$rel_work=FALSE;
$rel_query = 'SHOW TABLES';
$tables = @mysql_query($rel_query) or PMA_mysqlDie('', $rel_query, '', $err_url);
while($ctable = @mysql_fetch_array($tables)){
if($ctable[0] == $cfg['Server']['relation']){
$rel_work=TRUE;
}
}
if($rel_work && count($alltabs)>0){
// now we need all tables that we have in the whereclause
for ($x = 0; $x < $col; $x++) {
$wtable=explode('.',$curField[$x]);
$ctable= str_replace('`', '',$wtable[0]);
if (!empty($curField[$x]) && !empty($curCriteria[$x])) {
if($where[$ctable]!='='){
$where[$ctable]=substr($curCriteria[$x],0,1);
}
}
}
if(count($where)>1){
// if we have enough whereclauses then we want those that have
// a '=' (not for example 'like'
while (list($key,$value) = each ($where)){
if($value=='='){
$wheretabs[]=$key;
}
}
}
// if there was nothing starting with '=' we have to use all we got in the
// first place (in this case we can use & here - if it works with old versions
// of php ??
if(count($wheretabs)==0){
$wheretabs=$where;
}
// i expect it will make sense to have the table which is most often
// found as dest_table as the one to start our FROM...
// but we have to make sure that if there is a WHERE clause then we have
// a master out of those that are used there
// We will need this a few times:
$incrit = '(\''. str_replace(',', "','", implode(',',$alltabs)) . '\')';
$rel_query = 'SELECT src_table as wer,count(dest_table) as hits from '.PMA_backquote($cfg['Server']['relation']);
$rel_query .= ' WHERE src_table IN '.$incrit.' AND dest_table in '.$incrit;
$rel_query .= ' GROUP by src_table ORDER by hits desc ';
$rel_id = @mysql_query($rel_query) or PMA_mysqlDie('', $rel_query, '', $err_url);
// if we don't find anything we try the other way round
if(mysql_num_rows($rel_id)==0){
$rel_query = 'SELECT dest_table as wer,count(src_table) as hits from '.PMA_backquote($cfg['Server']['relation']);
$rel_query .= ' WHERE src_table IN '.$incrit.' AND dest_table in '.$incrit;
$rel_query .= ' GROUP by dest_table ORDER by hits desc ';
$rel_id = @mysql_query($rel_query) or PMA_mysqlDie('', $rel_query, '', $err_url);
}
while ($row = mysql_fetch_array($rel_id)){
// we want the first one (highest number of hits) or
// the first one that is in the WHERE clause
if(!isset($master)){
$master = $row['wer'];
}else{
// remember that we found more than one because
// this means we need to refine more
$hit=2;
}
if(is_array($wheretabs)){
while (list($key, $value) = each ($wheretabs)){
if($row['src_table']==$key){
$master = $row['wer'];
$ex=1;
break;
}
}
}
if ($ex==1){break;}
}
if($ex ==1||$hit!=2){
// if $ex is not 1 then obviously none of the tables
// that are used in the whereclause could be found -
// that means that using left joins doesn't make much sense anyway
if($master != ''){
$qry_from = PMA_backquote($master);
}
// now we want one Array that has all tablenames but master
while (list(, $value) = each ($alltabs)) {
if($value != $master){
$reltabs[] = $value;
$rel[$value]['mcon']=0;
}
}
// now we only use everything but the first table
$incrit_s = '(\''. str_replace(',', "','", implode(',',$reltabs)) . '\')';
$rel_query = 'SELECT * from '.PMA_backquote($cfg['Server']['relation']);
$rel_query .= ' WHERE src_table IN '.$incrit.' AND dest_table in '.$incrit_s;
$rel_query .= ' ORDER by dest_table,src_table ';
$rel_id = @mysql_query($rel_query) or PMA_mysqlDie('', $rel_query, '', $err_url);
while ($row = mysql_fetch_array($rel_id)){
$dest_table = $row['dest_table'];
if($rel[$dest_table]['mcon']==0){
// if we allready found a link to the mastertable we don't want another
// otherwise we take whatever we get
$rel[$dest_table]['link'] = ' LEFT JOIN '.PMA_backquote($dest_table);
$rel[$dest_table]['link'] .= ' ON '.PMA_backquote($row['src_table']).'.'.PMA_backquote($row['src_column']);
$rel[$dest_table]['link'] .= ' = '.PMA_backquote($row['dest_table']).'.'.PMA_backquote($row['dest_column']) .' ';
}
if($row['src_table'] == $master){
$rel[$dest_table]['mcon']=1;
}
}
// possibly we still don't have all - there might be some that are
// only found as a dest_table in relation to one of those that we allready have
if($master!=''){
$found[] = $master;
$qry_from = PMA_backquote($master);
}
while (list($key, $varr) = each ($rel)) {
if($varr['link'] == ''){
$rest[] = $key;
}else{
$found[] = $key;
}
}
if(is_array($rest) && is_array($found) && count($rest)>0){
$incrit_d = '(\''. str_replace(',', "','", implode(',',$found)) . '\')';
$incrit_s = '(\''. str_replace(',', "','", implode(',',$rest)) . '\')';
$rel_query = 'SELECT * from '.$cfg['Server']['relation'];
$rel_query .= ' WHERE src_table IN '.$incrit_s.' AND dest_table in '.$incrit_d;
$rel_query .= ' ORDER by src_table,dest_table ';
$rel_id = @mysql_query($rel_query) or PMA_mysqlDie('', $rel_query, '', $err_url);
while ($row = mysql_fetch_array($rel_id)){
$dest_table = $row['dest_table'];
// echo 'pr<70>fe '.$src_table;
if($rel[$dest_table]['mcon']==0){
// if we allready found a link to the mastertable we don't want another
// otherwise we take whatever we get
$rel[$dest_table]['link'] = ' LEFT JOIN '.$dest_table;
$rel[$dest_table]['link'] .= ' ON '.PMA_backquote($row['dest_table']).'.'.PMA_backquote($row['dest_column']);
$rel[$dest_table]['link'] .= ' = '.PMA_backquote($row['src_table']).'.'.PMA_backquote($row['src_column']) .' ';
// in extreme cases we hadn't found a master yet, so let's use
// the one we found now
$master = $row['dest_table'];
}
if($row['src_table'] == $master){
$rel[$dest_table]['mcon']=1;
}
}
}
// now let's see what we found - every table that doesn't have a link gets
// added directly to the FROM the links go to a second variable $lj which is added afterwards
reset ($rel);
while (list($key, $varr) = each ($rel)) {
if($varr['link'] == ''){
if($qry_from != ''){
$qry_from .= ',';
}
$qry_from .= PMA_backquote($key);
// echo 'add '.$key;
}else{
if($varr['mcon']==0){
// those that have no link with the mastertable we will show at the end
$lj .= $varr['link'];
}else{
$ljm .= $varr['link'];
}
}
}
// on one occasion i had qry_from at this point end with a ,
// as i can't find why this happened i check this now:
if(substr($qry_from, strlen($qry_from)-1,1)==','){
$qry_from =substr($qry_from,0,strlen($qry_from));
}
$qry_from .= $ljm.$lj;
} // End $ex==1 (testing if it is worth the pain
}// End rel work and $alltabs>0
if(empty($qry_from)) {
$qry_from=implode(',',$alltabs);
}
} // End count($Field)>0
if (!empty($qry_from)) {
$encoded_qry .= urlencode('FROM ' . $qry_from . "\n");
echo 'FROM ' . htmlspecialchars($qry_from) . "\n";