fix from Bryan so that view wizard can handle joining tables in different schemas
authorchriskl <chriskl>
Fri, 4 Jun 2004 05:26:35 +0000 (05:26 +0000)
committerchriskl <chriskl>
Fri, 4 Jun 2004 05:26:35 +0000 (05:26 +0000)
classes/database/Postgres73.php
views.php

index 9c7ef6f3eafbc7a520b9bc53f9f8adb4595c3d4b..cc5c652059555882d8616d4b215cb56b4b4407f0 100644 (file)
@@ -4,7 +4,7 @@
  * A class that implements the DB interface for Postgres
  * Note: This class uses ADODB and returns RecordSets.
  *
- * $Id: Postgres73.php,v 1.117 2004/06/03 07:34:56 chriskl Exp $
+ * $Id: Postgres73.php,v 1.118 2004/06/04 05:26:35 chriskl Exp $
  */
 
 // @@@ THOUGHT: What about inherits? ie. use of ONLY???
@@ -936,15 +936,21 @@ class Postgres73 extends Postgres72 {
 
        /**
         * A function for getting all columns linked by foreign keys given a group of tables
-        * @param $tables Array of table names           
+        * @param $tables multi dimensional assoc array that holds schema and table name
         * @return An array of linked tables and columns
-        * @return -1 $tables isn't an array\r
+        * @return -1 $tables isn't an array
         */
         function &getLinkingKeys($tables) {
                if (!is_array($tables)) return -1;
 
-               $this->arrayClean($tables);
-               $tables_list = "'" . implode("', '", $tables) . "'";
+               $tables_list = "'{$tables[0]['tablename']}'";
+               $schema_list = "'{$tables[0]['schemaname']}'";
+               $schema_tables_list = "'{$tables[0]['schemaname']}.{$tables[0]['tablename']}'";
+               for ($i = 1; $i < sizeof($tables); $i++) {
+                       $tables_list .= ", '{$tables[$i]['tablename']}'";
+                       $schema_list .= ", '{$tables[$i]['schemaname']}'";
+                       $schema_tables_list .= ", '{$tables[$i]['schemaname']}.{$tables[$i]['tablename']}'";
+               }
                $maxDimension = 1;
 
                $sql = "
@@ -960,7 +966,7 @@ class Postgres73 extends Postgres72 {
                                AND pgc1.relname IN ($tables_list)
                        ";
                
-               //parse our output for find the highest dimension of foreign keys since pc.conkey is stored in an array
+               //parse our output to find the highest dimension of foreign keys since pc.conkey is stored in an array
                $rs = $this->selectSet($sql);
                while (!$rs->EOF) {
                        $arrData = explode(':', $rs->fields['arr_dim']);
@@ -981,26 +987,29 @@ class Postgres73 extends Postgres72 {
                                pgc1.relname AS p_table,
                                pgc2.relname AS f_table,
                                pfield.attname AS p_field,
-                               cfield.attname AS f_field
+                               cfield.attname AS f_field,
+                               pgns1.nspname AS p_schema,
+                               pgns2.nspname AS f_schema
                        FROM
                                pg_catalog.pg_constraint AS pc,
                                pg_catalog.pg_class AS pgc1,
                                pg_catalog.pg_class AS pgc2,
                                pg_catalog.pg_attribute AS pfield,
-                               pg_catalog.pg_attribute AS cfield
+                               pg_catalog.pg_attribute AS cfield,
+                               (SELECT oid AS ns_id, nspname FROM pg_catalog.pg_namespace WHERE nspname IN ($schema_list) ) AS pgns1,
+                               (SELECT oid AS ns_id, nspname FROM pg_catalog.pg_namespace WHERE nspname IN ($schema_list) ) AS pgns2
                        WHERE
                                pc.contype = 'f'
+                               AND pgc1.relnamespace = pgns1.ns_id
+                               AND pgc2.relnamespace = pgns2.ns_id
                                AND pc.conrelid = pgc1.relfilenode
                                AND pc.confrelid = pgc2.relfilenode
                                AND pfield.attrelid = pc.conrelid
                                AND cfield.attrelid = pc.confrelid
                                AND $cons_str
-                               AND pgc1.relname IN ($tables_list)
-                               AND pgc2.relname IN ($tables_list)
-                               AND pgc1.relnamespace = (SELECT oid FROM pg_catalog.pg_namespace
-                                       WHERE nspname='{$this->_schema}')
-               ";
-               
+                               AND pgns1.nspname || '.' || pgc1.relname IN ($schema_tables_list)
+                               AND pgns2.nspname || '.' || pgc2.relname IN ($schema_tables_list)                               
+               ";              
                return $this->selectSet($sql);
         }
 
index cd114e7a551b4820cb39fecd9d2b33e624340449..c4ab459c25b3bbb57e9e1bb3d200f163b6584dc5 100644 (file)
--- a/views.php
+++ b/views.php
@@ -3,7 +3,7 @@
        /**
         * Manage views in a database
         *
-        * $Id: views.php,v 1.41 2004/06/03 06:42:20 chriskl Exp $
+        * $Id: views.php,v 1.42 2004/06/04 05:26:35 chriskl Exp $
         */
 
        // Include application functions
                        
                        echo "<h2>", $misc->printVal($_REQUEST['database']), ": {$lang['strviews']}: {$lang['strcreateviewwiz']}</h2>\n";               
                        $misc->printMsg($msg);
-                       $tblCount = sizeof($_POST['formTables']);
-                       // If we have a message that means an error occurred in doSaveCreate, which means POST['formTables'] has quotes
-                       // around the table names, but getTableAttributes doesn't accept quoted table names so we strip them here
-                       if (strlen($msg)) {
-                               for ($i = 0; $i < $tblCount; $i++) {
-                                       $_POST['formTables'][$i] = str_replace('"', '', $_POST['formTables'][$i]);
-                               }
-                       }
-                                               
-                       $arrFields = array(); //array that will hold all our table/field names
-
+                       
+                       $tblCount = sizeof($_POST['formTables']);                                               
+                       //unserialize our schema/table information and store in arrSelTables
+                       for ($i = 0; $i < $tblCount; $i++) {
+                               $arrSelTables[] = unserialize($_POST['formTables'][$i]);
+                       }                                                                       
+                       
+                       $linkCount = $tblCount;                                         
                        // If we can get foreign key info then get our linking keys
                        if ($data->hasForeignKeysInfo()) {
-                               $rsLinkKeys = $data->getLinkingKeys($_POST['formTables']);
-                       
+                               $rsLinkKeys = $data->getLinkingKeys($arrSelTables);
                                $linkCount = $rsLinkKeys->recordCount() > $tblCount ? $rsLinkKeys->recordCount() : $tblCount;
                        }
                        
-                       // Get fieldnames
-                       for ($i = 0; $i < $tblCount; $i++) {                            
-                               $attrs = &$data->getTableAttributes($_POST['formTables'][$i]);
-                               while (!$attrs->EOF) {
-                                       // Quote table/field name
-                                       $arrFields["\"{$_POST['formTables'][$i]}\"." . "\"{$attrs->f['attname']}\""] = "\"{$_POST['formTables'][$i]}\"." . "\"{$attrs->f['attname']}\"";
+                       $arrFields = array(); //array that will hold all our table/field names
+                       
+                       //if we have schemas we need to specify the correct schema for each table we're retrieiving
+                       //with getTableAttributes
+                       $curSchema = $data->hasSchemas() ? $data->_schema : NULL;
+                       for ($i = 0; $i < $tblCount; $i++) {
+                               if ($data->hasSchemas() && $data->_schema != $arrSelTables[$i]['schemaname']) {
+                                       $data->setSchema($arrSelTables[$i]['schemaname']);
+                               }
+                               
+                               $attrs = &$data->getTableAttributes($arrSelTables[$i]['tablename']);
+                               while (!$attrs->EOF) {                                          
+                                       if ($data->hasSchemas() ) {
+                                               $arrFields["{$arrSelTables[$i]['schemaname']}.{$arrSelTables[$i]['tablename']}.{$attrs->f['attname']}"] = serialize(array('schemaname' => $arrSelTables[$i]['schemaname'], 'tablename' => $arrSelTables[$i]['tablename'], 'fieldname' => $attrs->f['attname']) );
+                                       }
+                                       else {
+                                               $arrFields["{$arrSelTables[$i]['tablename']}.{$attrs->f['attname']}"] = serialize(array('schemaname' => NULL, 'tablename' => $arrSelTables[$i]['tablename'], 'fieldname' => $attrs->f['attname']) );
+                                       }
                                        $attrs->moveNext();
                                }
-                       }
+                               
+                               //reset back to our original schema in case we switched from it
+                               if ($data->hasSchemas() ) {                             
+                                       $data->setSchema($curSchema);
+                               }
+                       }                                               
                        asort($arrFields);                      
                        
                        echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
                        echo "<tr><th class=\"data\">{$lang['strcomment']}</th></tr>";
                        echo "<tr>\n<td class=\"data1\">\n";
                        // View comments                        
-                       echo "<input name=\"formComment\" id=\"formComment\" value=\"", htmlspecialchars($_REQUEST['formComment']), "\" style=\"width: 100%;\" />\n";
+                       echo "<textarea name=\"formComment\" rows=\"3\" cols=\"32\" wrap=\"virtual\">", 
+                               htmlspecialchars($_REQUEST['formComment']), "</textarea>\n";
                        echo "</td>\n</tr>\n";
                        echo "</table>\n";
                        
                        echo "<table>\n";
                        echo "<tr><th class=\"data\">{$lang['strfields']}</th></tr>";
                        echo "<tr>\n<td class=\"data1\">\n";                    
-                       echo GUI::printCombo($arrFields, 'formFields[]', false, '', true);                      
+                       echo GUI::printCombo($arrFields, 'formFields[]', false, '', true);
                        echo "</td>\n</tr>\n</table>\n<br />\n";                                                
-                                               
-                       if ($data->hasForeignKeysInfo()) {
-                               // Output the Linking keys combo boxes
-                               echo "<table>\n";
-                               echo "<tr><th class=\"data\">{$lang['strviewlink']}</th></tr>";                                 
-                               $rowClass = 'data1';
-                               for ($i = 0; $i < $linkCount; $i++) {
-                                       // Initialise variables
-                                       if (!isset($formLink[$i]['operator'])) $formLink[$i]['operator'] = 'INNER JOIN';
-                                       echo "<tr>\n<td class=\"$rowClass\">\n";
-                                                               
-                                       if (!$rsLinkKeys->EOF) {
-                                               $curLeftLink = htmlspecialchars("\"{$rsLinkKeys->f['p_table']}\".\"{$rsLinkKeys->f['p_field']}\"");
-                                               $curRightLink = htmlspecialchars("\"{$rsLinkKeys->f['f_table']}\".\"{$rsLinkKeys->f['f_field']}\"");
-                                               $rsLinkKeys->moveNext();
-                                       }
-                                       else {
-                                               $curLeftLink = '';
-                                               $curRightLink = '';
-                                       }
-                                       
-                                       echo GUI::printCombo($arrFields, "formLink[$i][leftlink]", true, $curLeftLink, false );
-                                       echo GUI::printCombo($data->joinOps, "formLink[$i][operator]", true, $formLink[$i]['operator']);
-                                       echo GUI::printCombo($arrFields, "formLink[$i][rightlink]", true, $curRightLink, false );
-                                       echo "</td>\n</tr>\n";
-                                       $rowClass = $rowClass == 'data1' ? 'data2' : 'data1';
-                               
+                                                                       
+                       // Output the Linking keys combo boxes only if we detect linking keys
+                       echo "<table>\n";
+                       echo "<tr><th class=\"data\">{$lang['strviewlink']}</th></tr>";                                 
+                       $rowClass = 'data1';
+                       for ($i = 0; $i < $linkCount; $i++) {
+                               // Initialise variables
+                               if (!isset($formLink[$i]['operator'])) $formLink[$i]['operator'] = 'INNER JOIN';
+                               echo "<tr>\n<td class=\"$rowClass\">\n";
+                                                       
+                               if ($data->hasForeignKeysInfo() && !$rsLinkKeys->EOF) {
+                                       $curLeftLink = htmlspecialchars(serialize(array('schemaname' => $rsLinkKeys->f['p_schema'], 'tablename' => $rsLinkKeys->f['p_table'], 'fieldname' => $rsLinkKeys->f['p_field']) ) );
+                                       $curRightLink = htmlspecialchars(serialize(array('schemaname' => $rsLinkKeys->f['f_schema'], 'tablename' => $rsLinkKeys->f['f_table'], 'fieldname' => $rsLinkKeys->f['f_field']) ) );                                           
+                                       $rsLinkKeys->moveNext();
                                }
-                               echo "</table>\n<br />\n";
-                       }                                               
-                                               
-                       // Output additional conditions
-                       
+                               else {
+                                       $curLeftLink = '';
+                                       $curRightLink = '';
+                               }
+                               
+                               echo GUI::printCombo($arrFields, "formLink[$i][leftlink]", true, $curLeftLink, false );
+                               echo GUI::printCombo($data->joinOps, "formLink[$i][operator]", true, $formLink[$i]['operator']);
+                               echo GUI::printCombo($arrFields, "formLink[$i][rightlink]", true, $curRightLink, false );
+                               echo "</td>\n</tr>\n";
+                               $rowClass = $rowClass == 'data1' ? 'data2' : 'data1';                   
+                       }
+                       echo "</table>\n<br />\n";
+                                                               
                        // Build list of available operators (infix only)
                        $arrOperators = array();
                        foreach ($data->selectOps as $k => $v) {
                                if ($v == 'i') $arrOperators[$k] = $k;
                        }
 
+                       // Output additional conditions, note that this portion of the wizard treats the right hand side as literal values 
+                       //(not as database objects) so field names will be treated as strings, use the above linking keys section to perform joins
                        echo "<table>\n";
                        echo "<tr><th class=\"data\">{$lang['strviewconditions']}</th></tr>";                                   
                        $rowClass = 'data1';
-                       for ($i = 0; $i < 3; $i++) {                            
+                       for ($i = 0; $i < $linkCount; $i++) {                           
                                echo "<tr>\n<td class=\"$rowClass\">\n";
                                echo GUI::printCombo($arrFields, "formCondition[$i][field]");
                                echo GUI::printCombo($arrOperators, "formCondition[$i][operator]", false, false);
                        echo "<input type=\"submit\" value=\"{$lang['strnext']}\" />\n";
                        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
                                                
-                       foreach ($_POST['formTables'] AS $curTable) {
-                               echo "<input type=\"hidden\" name=\"formTables[]\" id=\"formTables[]\" value=\"" . htmlspecialchars("\"$curTable\"") . "\" />\n";
+                       foreach ($arrSelTables AS $curTable) {                          
+                               echo "<input type=\"hidden\" name=\"formTables[]\" id=\"formTables[]\" value=\"" . htmlspecialchars(serialize($curTable) ) . "\" />\n";
                        }
                        
                        echo $misc->form;
        function doWizardCreate($msg = '') {
                global $data, $misc;
                global $PHP_SELF, $lang;
-               $tables = &$data->getTables();
-               
+               $tables = &$data->getTables(true);                              
                echo "<h2>", $misc->printVal($_REQUEST['database']), ": {$lang['strviews']}: {$lang['strcreateviewwiz']}</h2>\n";               
                $misc->printMsg($msg);
                echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
                echo "<tr>\n<td class=\"data1\">\n";            
                
                $arrTables = array();
-               while (!$tables->EOF) {                 
-                       $arrTables[$tables->f[$data->tbFields['tbname']]] = $tables->f[$data->tbFields['tbname']];                      
+               while (!$tables->EOF) {                                         
+                       $arrTmp = array();
+                       $arrTmp['schemaname'] = $tables->f['schemaname'];
+                       $arrTmp['tablename'] = $tables->f['tablename'];
+                       if ($data->hasSchemas() ) { //if schemas aren't available don't show them in the interface
+                               $arrTables[$tables->f['schemaname'] . '.' . $tables->f['tablename']] = serialize($arrTmp);
+                       }
+                       else {
+                               $arrTables[$tables->f['tablename']] = serialize($arrTmp);
+                       }
                        $tables->moveNext();
                }               
                echo GUI::printCombo($arrTables, 'formTables[]', false, '', true);                      
        
                if (!strlen($_POST['formView']) ) doSetParamsCreate($lang['strviewneedsname']);
                else if (!isset($_POST['formFields']) || !count($_POST['formFields']) ) doSetParamsCreate($lang['strviewneedsfields']);
-               else {           
-                       $selTables = implode(', ', $_POST['formTables']);               
-                       $selFields = implode(', ', $_POST['formFields']);               
+               else {                                          
+                       $selFields = '';                                                
+                       foreach ($_POST['formFields'] AS $curField) {
+                               $arrTmp = unserialize($curField);
+                               if ($data->hasSchemas() ) {                                     
+                                       $selFields .= strlen($selFields) ? ", \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\"" : "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\"";
+                               }
+                               else {
+                                       $selFields .= strlen($selFields) ? ", \"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\"" : "\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\"";
+                               }                               
+                       }                       
                        
                        $linkFields = '';
 
                                        while ($j < $count) {                                   
                                                foreach ($arrLinks AS $curLink) {
                                                        
-                                                       $tbl1 = substr($curLink['leftlink'], 0, strpos($curLink['leftlink'], '.') );
-                                                       $tbl2 = substr($curLink['rightlink'], 0, strpos($curLink['rightlink'], '.') );
+                                                       $arrLeftLink = unserialize($curLink['leftlink']);
+                                                       $arrRightLink = unserialize($curLink['rightlink']);
+                                                       
+                                                       $tbl1 = $data->hasSchemas() ? "\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\"" : $arrLeftLink['tablename'];
+                                                       $tbl2 = $data->hasSchemas() ? "\"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\"" : $arrLeftLink['tablename'];                                                                                         
                                                                                                        
                                                        if ( (!in_array($curLink, $arrJoined) && in_array($tbl1, $arrUsedTbls)) || !count($arrJoined) ) {
                                                                                                                        
                                                                // Make sure for multi-column foreign keys that we use a table alias tables joined to more than once
                                                                // This can (and should be) more optimized for multi-column foreign keys
                                                                $adj_tbl2 = in_array($tbl2, $arrUsedTbls) ? "$tbl2 AS alias_ppa_" . mktime() : $tbl2;
+                                                                                                                                                                               
+                                                               if ($data->hasSchemas() ) {     
+                                                                       $linkFields .= strlen($linkFields) ? "{$curLink['operator']} $adj_tbl2 ON (\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\".\"{$arrLeftLink['fieldname']}\" = \"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\".\"{$arrRightLink['fieldname']}\") " : "$tbl1 {$curLink['operator']} $adj_tbl2 ON (\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\".\"{$arrLeftLink['fieldname']}\" = \"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\".\"{$arrRightLink['fieldname']}\") ";
+                                                               }
+                                                               else {
+                                                                       $linkFields .= strlen($linkFields) ? "{$curLink['operator']} $adj_tbl2 ON (\"{$arrLeftLink['tablename']}\".\"{$arrLeftLink['fieldname']}\" = \"{$arrRightLink['tablename']}\".\"{$arrRightLink['fieldname']}\") " : "$tbl1 {$curLink['operator']} $adj_tbl2 ON (\"{$arrLeftLink['tablename']}\".\"{$arrLeftLink['fieldname']}\" = \"{$arrRightLink['tablename']}\".\"{$arrRightLink['fieldname']}\") ";
+                                                               }                                                               
                                                                
-                                                               $linkFields .= strlen($linkFields) ? "{$curLink['operator']} $adj_tbl2 ON ({$curLink['leftlink']} = {$curLink['rightlink']}) " : "$tbl1 {$curLink['operator']} $adj_tbl2 ON ({$curLink['leftlink']} = {$curLink['rightlink']}) ";
                                                                $arrJoined[] = $curLink;
                                                                if (!in_array($tbl1, $arrUsedTbls) )  $arrUsedTbls[] = $tbl1;
                                                                if (!in_array($tbl2, $arrUsedTbls) )  $arrUsedTbls[] = $tbl2;
                                                }
                                                $j++;                                   
                                        }
-                               }
-                               // Otherwise, just select from all seleted tables - a cartesian join
-                               else {
-                                       $linkFields = implode(', ', $_POST['formTables']);
-                               }
-                       }
-                       // Otherwise, just select from all seleted tables - a cartesian join
-                       else {
-                               $linkFields = implode(', ', $_POST['formTables']);
-                       }
+                               }                               
+                       }                       
+                       
+                       //if linkfields has no length then either _POST['formLink'] was not set, or there were no join conditions 
+                       //just select from all seleted tables - a cartesian join do a
+                       if (!strlen($linkFields) ) {
+                               foreach ($_POST['formTables'] AS $curTable) {
+                                       $arrTmp = unserialize($curTable);
+                                       if ($data->hasSchemas() ) {                                     
+                                               $linkFields .= strlen($linkFields) ? ", \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\"" : "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\"";
+                                       }
+                                       else {
+                                               $linkFields .= strlen($linkFields) ? ", \"{$arrTmp['tablename']}\"" : "\"{$arrTmp['tablename']}\"";
+                                       }                               
+                               }                               
+                       }                       
                        
                        $addConditions = '';
                        if (is_array($_POST['formCondition']) ) {
                                foreach ($_POST['formCondition'] AS $curCondition) {
-                                       if (strlen($curCondition['field']) && strlen($curCondition['txt']) ) {
-                                               $addConditions .= strlen($addConditions) ? ' AND ' . "{$curCondition['field']} {$curCondition['operator']} '{$curCondition['txt']}' " : " {$curCondition['field']} {$curCondition['operator']} '{$curCondition['txt']}' ";
+                                       if (strlen($curCondition['field']) && strlen($curCondition['txt']) ) {                                          
+                                               $arrTmp = unserialize($curCondition['field']);
+                                               if ($data->hasSchemas() ) {
+                                                       $addConditions .= strlen($addConditions) ? " AND \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" {$curCondition['operator']} '{$curCondition['txt']}' " : " \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" {$curCondition['operator']} '{$curCondition['txt']}' ";
+                                               }                                               
+                                               else {
+                                                       $addConditions .= strlen($addConditions) ? " AND \"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" {$curCondition['field']} {$curCondition['operator']} '{$curCondition['txt']}' " : " \"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" {$curCondition['operator']} '{$curCondition['txt']}' ";
+                                               }                                               
                                        }       
                                }               
                        }