*** ../DBD-Pg/Pg.pm	Tue Oct 15 15:20:09 2002
--- Pg.pm	Sat Aug 24 16:12:16 2002
***************
*** 142,180 ****
          return $ret;
      }
  
  
!     sub table_info {         # DBI spec: TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE, REMARKS
!         my($dbh) = @_;
  
!         my $sth = $dbh->prepare(qq{
!             SELECT NULL::text    AS "TABLE_CAT"
!                  , u.usename     AS "TABLE_SCHEM"
!                  , c.relname     AS "TABLE_NAME"
!                  , 'TABLE'       AS "TABLE_TYPE"
!                  , d.description AS "REMARKS"
!             FROM pg_user  u
!                , pg_class c LEFT OUTER JOIN pg_description AS d ON c.relfilenode = d.objoid and d.objsubid = 0
!             WHERE c.relkind     =  'r'
!               AND c.relhasrules =  FALSE
!               AND c.relname     !~ '^pg_'
!               AND c.relname     !~ '^xin[vx][0-9]+'
!               AND c.relowner    =  u.usesysid
!             UNION
!             SELECT NULL::text
! 	             , u.usename
! 	             , c.relname
! 	             , 'VIEW'
! 	             , d.description 
!             FROM pg_user u
!                , pg_class c LEFT OUTER JOIN pg_description AS d ON c.relfilenode = d.objoid and d.objsubid = 0
!             WHERE c.relkind = 'v' 
!             AND   c.relhasrules = TRUE
!             AND   c.relname !~ '^pg_' 
!             AND   c.relname !~ '^xin[vx][0-9]+' 
!             AND   c.relowner = u.usesysid 
!             ORDER BY 2, 3, 4
!         }) or return undef;
  
          $sth->execute();
  
          return $sth;
--- 142,517 ----
          return $ret;
      }
  
+ 	# Column expected in statement handle returned.
+ 	# table_cat, table_schem, table_name, column_name, data_type, type_name,
+ 	# column_size, buffer_length, DECIMAL_DIGITS, NUM_PREC_RADIX, NULLABLE,
+ 	# REMARKS, COLUMN_DEF, SQL_DATA_TYPE, SQL_DATETIME_SUB, CHAR_OCTET_LENGTH,
+ 	# ORDINAL_POSITION, IS_NULLABLE
+ 	# The result set is ordered by TABLE_CAT, TABLE_SCHEM, 
+ 	# TABLE_NAME and ORDINAL_POSITION.
+ 
+ 	sub column_info {
+ 		my ($dbh) = shift;
+ 		my @attrs = @_;
+ 		# my ($dbh, $catalog, $schema, $table, $column) = @_;
+ 
+ 		my @wh = ();
+ 		my @flds = qw/catname u.usename c.relname a.attname/;
+ 
+ 		for my $idx (0 .. $#attrs) {
+ 			next if ($flds[$idx] eq 'catname'); # Skip catalog
+ 			if(defined $attrs[$idx]) {
+ 				if ($attrs[$idx] =~ m/[,%]/) {
+ 					# contains a meta character.
+ 					push( @wh, q{( } . join ( " OR "
+ 						, map { m/\%/ 
+ 							? qq{$flds[$idx] LIKE $_ }
+ 							: qq{$flds[$idx]    = $_ }
+ 							} (split /,/, $attrs[$idx]) )
+ 							. q{ )}
+ 						);
+ 				}
+ 				else {
+ 					push( @wh, qq{$flds[$idx] = $attrs[$idx]} );
+ 				}
+ 			}
+ 		}
+ 
+ 		my $wh = ();
+ 		$wh = join( " and ", ,'', @wh ) if (@wh);
+ 		my $col_info_sql = qq{
+ 			select
+ 				  NULL::text    AS "TABLE_CAT"
+ 				, u.usename     AS "TABLE_SCHEM"
+ 				, c.relname		AS "TABLE_NAME"
+ 				, a.attname		AS "COLUMN_NAME"
+ 				, t.typname		AS "DATA_TYPE"
+ 				, NULL::text	AS "TYPE_NAME"
+ 				, a.attlen		AS "COLUMN_SIZE"
+ 				, NULL::text	AS "BUFFER_LENGTH"
+ 				, NULL::text	AS "DECIMAL_DIGITS"
+ 				, NULL::text	AS "NUM_PREC_RADIX"
+ 				, a.attnotnull	AS "NULLABLE"
+ 				, NULL::text	AS "REMARKS"
+ 				, a.atthasdef	AS "COLUMN_DEF"
+ 				, NULL::text	AS "SQL_DATA_TYPE"
+ 				, NULL::text	AS "SQL_DATETIME_SUB"
+ 				, NULL::text	AS "CHAR_OCTET_LENGTH"
+ 				, a.attnum		AS "ORDINAL_POSITION"
+ 				, a.attnotnull  AS "IS_NULLABLE"
+ 				, a.atttypmod	as atttypmod
+ 				, a.attnotnull	as attnotnull
+ 				, a.atthasdef	as atthasdef
+ 				, a.attnum		as attnum
+ 			from 
+ 				  pg_attribute	a
+ 				, pg_class		c
+ 				, pg_type		t
+ 				, pg_user		u
+ 			where
+ 					a.attrelid = c.oid
+ 				and a.attnum  >= 0
+ 				and t.oid      = a.atttypid
+ 				and c.relkind  = 'r'
+ 				and c.relname !~ '^pg_'
+ 				and c.relowner = u.usesysid 
+ 				$wh
+ 			order by u.usename, c.relname, a.attnum
+ 		};
  
! 		my $sth = $dbh->prepare( $col_info_sql ) or
! 			return undef;
!         $sth->execute();
! 
!         return $sth;
! 	}
  
! 	sub primary_key_info {
!         my $dbh = shift;
! 		my ($catalog, $schema, $table) = @_;
! 		my @attrs = @_;
! 
! 		# TABLE_CAT:, TABLE_SCHEM:, TABLE_NAME:, COLUMN_NAME:, KEY_SEQ:
! 		# , PK_NAME:
! 
! 		my @wh = (); my @dat = ();  # Used to hold data for the attributes.
! 		my @flds = qw/catname u.usename bc.relname/;
! 
! 		for my $idx (0 .. $#attrs) {
! 			next if ($flds[$idx] eq 'catname'); # Skip catalog
! 			if(defined $attrs[$idx]) {
! 				if ($attrs[$idx] =~ m/[,%_?]/) {
! 					# contains a meta character.
! 					push( @wh, q{( } . join ( " OR "
! 						, map { push(@dat, $_);
! 							m/[%_?]/ 
! 							? qq{$flds[$idx] iLIKE ? }
! 							: qq{$flds[$idx]    = ?  }
! 							} (split /,/, $attrs[$idx]) )
! 							. q{ )}
! 						);
! 				}
! 				else {
! 					push( @dat, $attrs[$idx] );
! 					push( @wh, qq{$flds[$idx] = ? } );
! 				}
! 			}
! 		}
! 
! 		my $wh = ();
! 		$wh = join( " and ", ,'', @wh ) if (@wh);
! 
! 		# Base primary key selection query borrowed from phpPgAdmin.
! 		my $pri_key_sql = qq{
! 			SELECT
! 				NULL::text		AS "TABLE_CAT"
! 				, u.usename		AS "TABLE_SCHEM"
! 				, bc.relname	AS "TABLE_NAME"
! 				, a.attname		AS "COLUMN_NAME"
! 				, a.attnum		AS "KEY_SEQ"
! 				, ic.relname	AS "PK_NAME"
! 			FROM
! 				  pg_class bc
! 				, pg_class ic
! 				, pg_index i
! 				, pg_attribute a
! 				, pg_user	u
! 			WHERE
! 				i.indrelid = bc.oid
! 			and i.indexrelid = ic.oid
! 			and
! 			(
! 				i.indkey[0] = a.attnum
! 				or
! 				i.indkey[1] = a.attnum
! 				or
! 				i.indkey[2] = a.attnum
! 				or
! 				i.indkey[3] = a.attnum
! 				or
! 				i.indkey[4] = a.attnum
! 				or
! 				i.indkey[5] = a.attnum
! 				or
! 				i.indkey[6] = a.attnum
! 				or
! 				i.indkey[7] = a.attnum
! 				or
! 				i.indkey[8] = a.attnum
! 				or
! 				i.indkey[9] = a.attnum
! 				or
! 				i.indkey[10] = a.attnum
! 				or
! 				i.indkey[11] = a.attnum
! 				or
! 				i.indkey[12] = a.attnum
! 			)
! 			and a.attrelid = bc.oid
! 			and i.indproc = '0'::oid
! 			and i.indisprimary = 't' 
! 			and bc.relowner    =  u.usesysid
! 			$wh
! 			order by
! 				u.usename, bc.relname, a.attnum
! 		};
! 
!         my $sth = $dbh->prepare( $pri_key_sql ) or
! 			return undef;
!         $sth->execute(@dat);
! 
!         return $sth;
! 	}
! 
! 
!     sub table_info {         # DBI spec: TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE, REMARKS
!         my $dbh = shift;
! 		my ($catalog, $schema, $table, $type) = @_;
! 		my @attrs = @_;
! 
! 		my $tbl_sql = ();
! 
! 		if ( # Rules 19a
! 			    (defined $catalog and $catalog eq '%')
! 			and (defined $schema  and $schema  eq  '')
! 			and (defined $table   and $table   eq  '')
! 			) {
! 				$tbl_sql = q{
! 					SELECT 
! 					   NULL::text    AS "TABLE_CAT"
! 					 , NULL::text    AS "TABLE_SCHEM"
! 					 , NULL::text    AS "TABLE_NAME"
! 					 , NULL::text    AS "TABLE_TYPE"
! 					 , NULL::text    AS "REMARKS"
! 					};
! 		}
! 		elsif (# Rules 19b
! 			    (defined $catalog and $catalog eq  '')
! 			and (defined $schema  and $schema  eq '%')
! 			and (defined $table   and $table   eq  '')
! 			) {
! 				$tbl_sql = q{
! 					SELECT 
! 					   NULL::text    AS "TABLE_CAT"
! 					 , u.usename     AS "TABLE_SCHEM"
! 					 , NULL::text    AS "TABLE_NAME"
! 					 , NULL::text    AS "TABLE_TYPE"
! 					 , NULL::text    AS "REMARKS"
! 					from pg_user u
! 					order by u.usename
! 				};
! 		}
! 		elsif (# Rules 19c
! 			    (defined $catalog and $catalog eq  '')
! 			and (defined $schema  and $schema  eq  '')
! 			and (defined $table   and $table   eq  '')
! 			and (defined $type    and $type    eq  '%')
! 			) {
! 				# From the postgresql 7.2.1 manual 3.5 pg_class
! 				#  'r' = ordinary table
! 				#, 'i' = index
! 				#, 'S' = sequence
! 				#, 'v' = view
! 				#, 's' = special
! 				#, 't' = secondary TOAST table 
! 				$tbl_sql = q{
! 					SELECT 
! 					   NULL::text    AS "TABLE_CAT"
! 					 , NULL::text    AS "TABLE_SCHEM"
! 					 , NULL::text    AS "TABLE_NAME"
! 					 , 'table'       AS "TABLE_TYPE"
! 					 , 'ordinary table - r'    AS "REMARKS"
! 					union
! 					SELECT 
! 					   NULL::text    AS "TABLE_CAT"
! 					 , NULL::text    AS "TABLE_SCHEM"
! 					 , NULL::text    AS "TABLE_NAME"
! 					 , 'index'       AS "TABLE_TYPE"
! 					 , 'index - i'    AS "REMARKS"
! 					union
! 					SELECT 
! 					   NULL::text    AS "TABLE_CAT"
! 					 , NULL::text    AS "TABLE_SCHEM"
! 					 , NULL::text    AS "TABLE_NAME"
! 					 , 'sequence'       AS "TABLE_TYPE"
! 					 , 'sequence - S'    AS "REMARKS"
! 					union
! 					SELECT 
! 					   NULL::text    AS "TABLE_CAT"
! 					 , NULL::text    AS "TABLE_SCHEM"
! 					 , NULL::text    AS "TABLE_NAME"
! 					 , 'view'       AS "TABLE_TYPE"
! 					 , 'view - v'    AS "REMARKS"
! 					union
! 					SELECT 
! 					   NULL::text    AS "TABLE_CAT"
! 					 , NULL::text    AS "TABLE_SCHEM"
! 					 , NULL::text    AS "TABLE_NAME"
! 					 , 'special'       AS "TABLE_TYPE"
! 					 , 'special - s'    AS "REMARKS"
! 					union
! 					SELECT 
! 					   NULL::text    AS "TABLE_CAT"
! 					 , NULL::text    AS "TABLE_SCHEM"
! 					 , NULL::text    AS "TABLE_NAME"
! 					 , 'secondary'   AS "TABLE_TYPE"
! 					 , 'secondary TOAST table - t'    AS "REMARKS"
! 				};
! 		}
! 		else {
! 				# Default SQL
! 				$tbl_sql = qq{
! 				SELECT NULL::text    AS "TABLE_CAT"
! 					 , u.usename     AS "TABLE_SCHEM"
! 					 , c.relname     AS "TABLE_NAME"
! 					 , CASE
! 					 	 WHEN c.relkind = 'v' THEN 'VIEW'
! 					  	 ELSE 'TABLE'
! 						END			 AS "TABLE_TYPE"
! 					 , d.description AS "REMARKS"
! 				FROM pg_user		AS u
! 				   , pg_class		AS c LEFT OUTER JOIN 
! 					 pg_description	AS d 
! 						ON c.relfilenode = d.objoid and d.objsubid = 0
! 				WHERE 
! 					  ((c.relkind     =  'r'
! 				  AND c.relhasrules =  FALSE) OR
! 					  (c.relkind     =  'v'
! 				  AND c.relhasrules =  TRUE))
! 				  AND c.relname     !~ '^pg_'
! 				  AND c.relname     !~ '^xin[vx][0-9]+'
! 				  AND c.relowner    =  u.usesysid
! 				ORDER BY 2, 3
! 				};
! 
! 			# Did we receive any arguments?
! 			if (@attrs) {
! 				my @wh = ();
! 				my @flds = qw/catname u.usename c.relname c.relkind/;
! 
! 				for my $idx (0 .. $#attrs) {
! 					next if ($flds[$idx] eq 'catname'); # Skip catalog
! 					if(defined $attrs[$idx]) {
! 						# Change the "name" of the types to the real value.
! 						if ($flds[$idx]  =~ m/relkind/) {
! 							$attrs[$idx] =~ s/^\'?table\'?/'r'/i;
! 							$attrs[$idx] =~ s/^\'?index\'?/'i'/i;
! 							$attrs[$idx] =~ s/^\'?sequence\'?/'S'/i;
! 							$attrs[$idx] =~ s/^\'?view\'?/'v'/i;
! 							$attrs[$idx] =~ s/^\'?special\'?/'s'/i;
! 							$attrs[$idx] =~ s/^\'?secondary\'?/'t'/i;
! 						}
! 						if ($attrs[$idx] =~ m/[,%]/) {
! 							# contains a meta character.
! 							push( @wh, q{( } . join ( " OR "
! 								, map { m/\%/ 
! 									? qq{$flds[$idx] LIKE $_ }
! 									: qq{$flds[$idx]    = $_ }
! 									} (split /,/, $attrs[$idx]) )
! 									. q{ )}
! 								);
! 						}
! 						else {
! 							push( @wh, qq{$flds[$idx] = $attrs[$idx]} );
! 						}
! 					}
! 				}
! 
! 				my $wh = ();
! 				if (@wh) {
! 					$wh = join( " and ", ,'', @wh );
! 
! 					$tbl_sql = qq{
! 					SELECT NULL::text    AS "TABLE_CAT"
! 						 , u.usename     AS "TABLE_SCHEM"
! 						 , c.relname     AS "TABLE_NAME"
! 						 , CASE
! 							 WHEN c.relkind = 'r' THEN 'TABLE'
! 							 WHEN c.relkind = 'v' THEN 'VIEW'
! 							 WHEN c.relkind = 'i' THEN 'INDEX'
! 							 WHEN c.relkind = 'S' THEN 'SEQUENCE'
! 							 WHEN c.relkind = 's' THEN 'SPECIAL'
! 							 WHEN c.relkind = 't' THEN 'SECONDARY'
! 							 ELSE 'UNKNOWN'
! 							END			 AS "TABLE_TYPE"
! 						 , d.description AS "REMARKS"
! 					FROM pg_user		AS u
! 					   , pg_class		AS c LEFT OUTER JOIN 
! 						 pg_description	AS d 
! 							ON c.relfilenode = d.objoid and d.objsubid = 0
! 					WHERE 
! 						  c.relname     !~ '^pg_'
! 					  AND c.relname     !~ '^xin[vx][0-9]+'
! 					  AND c.relowner    =  u.usesysid
! 					  $wh
! 					ORDER BY 2, 3
! 					};
! 				}
! 			}
! 		}
  
+         my $sth = $dbh->prepare( $tbl_sql ) or
+ 			return undef;
          $sth->execute();
  
          return $sth;
***************
*** 211,234 ****
                from pg_attribute a,
                     pg_class     c,
                     pg_type      t
!               where c.relname  = '$table'
                  and a.attrelid = c.oid
                  and a.attnum  >= 0
                  and t.oid      = a.atttypid
                  order by 1 
!              ");
      
          return $result unless scalar(@$attrs);
  
          # Get the primary key
!         my ($pri_key) = $dbh->selectrow_array("SELECT pg_attribute.attname
                                                 FROM   pg_class, pg_attribute, pg_index
                                                 WHERE  pg_class.oid          = pg_attribute.attrelid 
                                                 AND    pg_class.oid          = pg_index.indrelid 
!                                                AND    pg_index.indkey[0]    = pg_attribute.attnum
                                                 AND    pg_index.indisprimary = 't'
!                                                AND    pg_class.relname      = '$table'");
!         $pri_key = '' unless $pri_key;
  
          foreach my $attr (reverse @$attrs) {
              my ($col_name, $col_type, $size, $mod, $notnull, $hasdef, $attnum) = @$attr;
--- 548,592 ----
                from pg_attribute a,
                     pg_class     c,
                     pg_type      t
!               where c.relname  = ?
                  and a.attrelid = c.oid
                  and a.attnum  >= 0
                  and t.oid      = a.atttypid
                  order by 1 
!              ", undef, $table);
      
          return $result unless scalar(@$attrs);
  
+ 	# Select the array value for tables primary key.
+ 	my $pk_key_sql = qq{SELECT pg_index.indkey
+                             FROM   pg_class, pg_index
+                             WHERE
+                                    pg_class.oid          = pg_index.indrelid
+                             AND    pg_class.relname      = '$table'
+                             AND    pg_index.indisprimary = 't'
+ 			};
+ 	# Expand this (returned as a string) a real array.
+ 	my @pk;
+ 	foreach (split( /\s+/, $dbh->selectrow_array( $pk_key_sql)))
+ 	{
+ 		push @pk, $_;
+ 	}
+ 
+ 	my $pk_bt = 
+ 		(@pk)   ? "AND    pg_attribute.attnum in (" . join ( ", ", @pk ) . ")"
+ 			: "";
+ 		
          # Get the primary key
!         my $pri_key = $dbh->selectcol_arrayref("SELECT pg_attribute.attname
                                                 FROM   pg_class, pg_attribute, pg_index
                                                 WHERE  pg_class.oid          = pg_attribute.attrelid 
                                                 AND    pg_class.oid          = pg_index.indrelid 
! 					       $pk_bt
                                                 AND    pg_index.indisprimary = 't'
!                                                AND    pg_class.relname      = ?
! 					       order by pg_attribute.attnum
! 					       ", undef, $table );
!         $pri_key = [] unless $pri_key;
  
          foreach my $attr (reverse @$attrs) {
              my ($col_name, $col_type, $size, $mod, $notnull, $hasdef, $attnum) = @$attr;
***************
*** 256,262 ****
              $constraint = '' unless $constraint;
  
              # Check to see if this is the primary key
!             my $is_primary_key = (lc $pri_key eq lc $col_name) ? 1 : 0;
  
              push @$result,
                  { NAME        => $col_name,
--- 614,620 ----
              $constraint = '' unless $constraint;
  
              # Check to see if this is the primary key
!             my $is_primary_key = scalar(grep { /^$col_name$/i } @$pri_key) ? 1 : 0;
  
              push @$result,
                  { NAME        => $col_name,
