Bryan Encina's new patch for view wizard: 7.3 support and bug fixes
authorsoranzo <soranzo>
Fri, 14 May 2004 01:16:13 +0000 (01:16 +0000)
committersoranzo <soranzo>
Fri, 14 May 2004 01:16:13 +0000 (01:16 +0000)
classes/database/Postgres.php
classes/database/Postgres71.php
classes/database/Postgres73.php
classes/database/Postgres74.php
lang/english.php
lang/recoded/english.php
views.php

index 93f91471e15c7545242870082624517e43f45f50..052211e7d7bd7d73306d77ea24e438bbdfbd75ac 100755 (executable)
@@ -4,7 +4,7 @@
  * A class that implements the DB interface for Postgres
  * Note: This class uses ADODB and returns RecordSets.
  *
- * $Id: Postgres.php,v 1.201 2004/05/12 15:30:00 chriskl Exp $
+ * $Id: Postgres.php,v 1.202 2004/05/14 01:16:14 soranzo Exp $
  */
 
 // @@@ THOUGHT: What about inherits? ie. use of ONLY???
@@ -127,6 +127,8 @@ class Postgres extends BaseDB {
                                                                        '~' => 'i', '!~' => 'i', '~*' => 'i', '!~*' => 'i', 'IS NULL' => 'p', 'IS NOT NULL' => 'p', 
                                                                        'IN' => 'x', 'NOT IN' => 'x');
 
+       //Supported join operations for use with view wizard
+       var $joinOps = array('INNER JOIN' => 'INNER JOIN');
        /**
         * Constructor
         * @param $conn The database connection
index 5f2843d8723dd2a13b22d3a4ac68d923786ebf75..81e1d856085d3ab82dcf9976a892a4b31d9fcb8f 100644 (file)
@@ -4,7 +4,7 @@
  * A class that implements the DB interface for Postgres
  * Note: This class uses ADODB and returns RecordSets.
  *
- * $Id: Postgres71.php,v 1.55 2004/05/09 09:10:04 chriskl Exp $
+ * $Id: Postgres71.php,v 1.56 2004/05/14 01:16:14 soranzo Exp $
  */
 
 // @@@ THOUGHT: What about inherits? ie. use of ONLY???
@@ -48,6 +48,8 @@ class Postgres71 extends Postgres {
        var $selectOps = array('=' => 'i', '!=' => 'i', '<' => 'i', '>' => 'i', '<=' => 'i', '>=' => 'i', 'LIKE' => 'i', 'NOT LIKE' => 'i', 
                                                                        'ILIKE' => 'i', 'NOT ILIKE' => 'i', '~' => 'i', '!~' => 'i', '~*' => 'i', '!~*' => 'i', 
                                                                        'IS NULL' => 'p', 'IS NOT NULL' => 'p', 'IN' => 'x', 'NOT IN' => 'x');
+       //Supported join operations for use with view wizard                                                            
+       var $joinOps = array('INNER JOIN' => 'INNER JOIN', 'LEFT JOIN' => 'LEFT JOIN', 'RIGHT JOIN' => 'RIGHT JOIN', 'FULL JOIN' => 'FULL JOIN');
 
        /**
         * Constructor
index 805d3a4c2fec1762974e316afdedd6f97bdf4b79..45a636511476565dfad859306bed651e7f5a7557 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.102 2004/05/12 22:40:49 soranzo Exp $
+ * $Id: Postgres73.php,v 1.103 2004/05/14 01:16:14 soranzo Exp $
  */
 
 // @@@ THOUGHT: What about inherits? ie. use of ONLY???
@@ -938,6 +938,75 @@ class Postgres73 extends Postgres72 {
        }
 
        // Constraint functions
+       /**
+        * A function for getting all linking fields on the foreign keys based on the table names        
+        * @param $table array of table names            
+        * @return an array of linked tables and fields
+        */
+        function &getLinkingKeys($arrTables) {         
+               $this->arrayClean($arrTables);
+               $maxDimension = 1;
+                       
+               // Properly quote the tables    
+               $tables = "'" . implode("', '", $arrTables) . "'";
+               
+               //7.3 requires some workarounds since ANY doesn't support arrays 
+               $sql = "
+                       SELECT DISTINCT
+                               array_dims(pc.conkey) AS arr_dim,
+                               pgc1.relname AS p_table 
+                       FROM 
+                               pg_catalog.pg_constraint AS pc,
+                               pg_catalog.pg_class AS pgc1                             
+                       WHERE 
+                               pc.contype = 'f'
+                               AND (pc.conrelid = pgc1.relfilenode OR pc.confrelid = pgc1.relfilenode)
+                               AND pgc1.relname IN ($tables)                                   
+                       ";
+               
+               //parse our output for 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']);
+                       $tmpDimension = intval(substr($arrData[1], 0, strlen($arrData[1] - 1)));
+                       $maxDimension = $tmpDimension > $maxDimension ? $tmpDimension : $maxDimension;
+                       $rs->MoveNext();
+               }
+                       
+               //we know the highest index for foreign keys thaat conkey goes up to, expand for us in an IN query                              
+               $cons_str = '( (pfield.attnum = conkey[1] AND cfield.attnum = confkey[1]) ';            
+               for ($i = 2; $i <= $maxDimension; $i++) {
+                       $cons_str .= "OR (pfield.attnum = conkey[{$i}] AND cfield.attnum = confkey[{$i}]) ";            
+               }
+               $cons_str .= ') ';
+                       
+               $sql = "
+                       SELECT                                                                          
+                               pgc1.relname AS p_table,        
+                               pgc2.relname AS f_table,
+                               pfield.attname AS p_field,
+                               cfield.attname AS f_field       
+                       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
+                       WHERE
+                               pc.contype = 'f'                                
+                               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)   
+                               AND pgc2.relname IN ($tables)
+                               AND pgc1.relnamespace = (SELECT oid FROM pg_catalog.pg_namespace
+                                       WHERE nspname='{$this->_schema}')
+               ";
+               
+               return $this->selectSet($sql);                  
+        }
 
        /**
         * A helper function for getConstraints that translates
index 45e450298abb88c696bc9608e63d6b97673c911d..a9e1f9eccf70110530bae4ab0a2b32a94f4ffdea 100644 (file)
@@ -4,7 +4,7 @@
  * A class that implements the DB interface for Postgres
  * Note: This class uses ADODB and returns RecordSets.
  *
- * $Id: Postgres74.php,v 1.29 2004/05/12 22:40:49 soranzo Exp $
+ * $Id: Postgres74.php,v 1.30 2004/05/14 01:16:14 soranzo Exp $
  */
 
 include_once('./classes/database/Postgres73.php');
@@ -195,49 +195,6 @@ class Postgres74 extends Postgres73 {
 
        // Constraint functions
 
-       /**\r
-        * A function for getting all linking columns on the foreign keys based on the table names\r
-        * @param $tables Array of table names\r
-        * @return A recordset of (constrained table, referenced table, constrained column, referenced column)
-        * @return -1 $tables isn't an array\r
-        */\r
-        function &getLinkingKeys($tables) {
-               if (!is_array($tables)) return -1;
-\r
-               $this->arrayClean($tables);\r
-               // Properly quote the tables list\r
-               $tables_list = "'" . implode("', '", $tables) . "'";
-\r
-               // ct = constrained table, rt = referenced table
-               // cc = constrained column, rc = referenced column\r
-               $sql = "SELECT\r
-                               ct.relname AS p_table,\r
-                               rt.relname AS f_table,\r
-                               cc.attname AS p_field,\r
-                               rc.attname AS f_field\r
-                       FROM\r
-                               pg_catalog.pg_constraint c,\r
-                               pg_catalog.pg_class ct,\r
-                               pg_catalog.pg_class rt,\r
-                               pg_catalog.pg_attribute cc,\r
-                               pg_catalog.pg_attribute rc\r
-                       WHERE\r
-                               c.contype = 'f'\r
-                               AND c.conrelid = ct.relfilenode\r
-                               AND c.confrelid = rt.relfilenode\r
-                               AND cc.attrelid = c.conrelid\r
-                               AND rc.attrelid = c.confrelid\r
-                               AND cc.attnum = ANY (c.conkey)\r
-                               AND rc.attnum = ANY (c.confkey)\r
-                               AND ct.relname IN ($tables_list)\r
-                               AND rt.relname IN ($tables_list)\r
-                               AND ct.relnamespace = (SELECT oid FROM pg_catalog.pg_namespace\r
-                                       WHERE nspname='{$this->_schema}')\r
-               ";
-               \r
-               return $this->selectSet($sql);\r
-        }
-
        /**
         * Returns a list of all constraints on a table
         * @param $table The table to find rules for
index 86f2d6e0009058dd7c079020db3909d23a6b8858..3b98cd7791d3300092be91ca3a73259973f15a07 100755 (executable)
@@ -4,7 +4,7 @@
         * English language file for phpPgAdmin.  Use this as a basis
         * for new translations.
         *
-        * $Id: english.php,v 1.141 2004/05/09 08:35:55 chriskl Exp $
+        * $Id: english.php,v 1.142 2004/05/14 01:16:14 soranzo Exp $
         */
 
        // Language and character set
        $lang['strviewname'] = 'View name';
        $lang['strviewneedsname'] = 'You must give a name for your view.';
        $lang['strviewneedsdef'] = 'You must give a definition for your view.';
+       $lang['strviewneedsfields'] = 'Please select the fields you want selected in your view.';
        $lang['strviewcreated'] = 'View created.';
        $lang['strviewcreatedbad'] = 'View creation failed.';
        $lang['strconfdropview'] = 'Are you sure you want to drop the view "%s"?';
index 4a1806a12b001fe95d5e938611b3c081c459e062..1d3d256779c290b4c666dd6eb8a3c39ccdcd22fb 100644 (file)
@@ -4,7 +4,7 @@
         * English language file for phpPgAdmin.  Use this as a basis
         * for new translations.
         *
-        * $Id: english.php,v 1.94 2004/05/09 08:35:55 chriskl Exp $
+        * $Id: english.php,v 1.95 2004/05/14 01:16:15 soranzo Exp $
         */
 
        // Language and character set
        $lang['strviewname'] = 'View name';
        $lang['strviewneedsname'] = 'You must give a name for your view.';
        $lang['strviewneedsdef'] = 'You must give a definition for your view.';
+       $lang['strviewneedsfields'] = 'Please select the fields you want selected in your view.';
        $lang['strviewcreated'] = 'View created.';
        $lang['strviewcreatedbad'] = 'View creation failed.';
        $lang['strconfdropview'] = 'Are you sure you want to drop the view &quot;%s&quot;?';
index 92a13d9fdb518c20117ebfbb493ec040d92d032e..99a8f06b89bc6441cb9405855af8fb1d45cbfa68 100644 (file)
--- a/views.php
+++ b/views.php
@@ -3,7 +3,7 @@
        /**
         * Manage views in a database
         *
-        * $Id: views.php,v 1.32 2004/05/12 22:40:49 soranzo Exp $
+        * $Id: views.php,v 1.33 2004/05/14 01:16:13 soranzo Exp $
         */
 
        // Include application functions
                        $rsLinkKeys = $data->getLinkingKeys($_POST['formTables']);
                        
                        // Update tblcount if we have more foreign keys than tables (perhaps in the case of composite foreign keys)
-                       $tblCount = $rsLinkKeys->recordCount() > $tblCount ? $rsLinkKeys->recordCount() : $tblCount;
+                       $linkCount = $rsLinkKeys->recordCount() > $tblCount ? $rsLinkKeys->recordCount() : $tblCount;
                        
                        // Get fieldnames
                        for ($i = 0; $i < $tblCount; $i++) {                            
                        echo "</td>\n</tr>\n</table>\n<br />\n";                                                
                        
                        // Output the Linking keys combo boxes
-                       $arrLinkOperators = array('INNER JOIN' => 'INNER JOIN', 'LEFT JOIN' => 'LEFT JOIN', 'RIGHT JOIN' => 'RIGHT JOIN');
                        echo "<table>\n";
                        echo "<tr><th class=\"data\">{$lang['strviewlink']}</th></tr>";                                 
                        $rowClass = 'data1';
-                       for ($i = 0; $i <= $tblCount; $i++) {
+                       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";
                                }
                                
                                echo GUI::printCombo($arrFields, "formLink[$i][leftlink]", true, $curLeftLink, false );
-                               echo GUI::printCombo($arrLinkOperators, "formLink[$i][operator]", true, $formLink[$i]['operator']);                                                             
+                               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';
                global $data, $lang;
                
                // Check that they've given a name and fields they want to select               
-               if (!strlen($_POST['formView']) || !isset($_POST['formFields']) || !count($_POST['formFields']) ) doSetParamsCreate($lang['strviewneedsdef']);
+       
+               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']);               
                                                                                                
                                                if ( (!in_array($curLink, $arrJoined) && in_array($tbl1, $arrUsedTbls)) || !count($arrJoined) ) {
                                                                                                                
-                                                       $linkFields .= strlen($linkFields) ? "{$curLink['operator']} $tbl2 ON ({$curLink['leftlink']} = {$curLink['rightlink']}) " : "$tbl1 {$curLink['operator']} $tbl2 ON ({$curLink['leftlink']} = {$curLink['rightlink']}) ";
+                                                       //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;
+                                                       
+                                                       $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;