[DBD::Pg 13/14] Add back in MATERIALIZED VIEWS work - too hard to do so inside the previous merger. Also changed tabs to spaces, minor POD tweaks.
dbdpg-commits-gENoVmVU/[email protected] Sun, 27 Jul 2014 05:14:14 +0000
| Newsgroups | gmane.comp.db.postgresql.dbdpg.cvs |
|---|---|
| Message-ID | <[email protected]> |
Committed by Greg Sabino Mullane <greg-O9fzpki4YnJWk0Htik3J/[email protected]> Subject: [DBD::Pg 13/14] Add back in MATERIALIZED VIEWS work - too hard to do so inside the previous merger. Also changed tabs to spaces, minor POD tweaks. --- Pg.pm | 586 +++++++++++++++++++++++++++++---------------------------- t/03dbmethod.t | 2 + 2 files changed, 302 insertions(+), 286 deletions(-) diff --git a/Pg.pm b/Pg.pm index ed261c5..3a9379d 100644 --- a/Pg.pm +++ b/Pg.pm @@ -1067,35 +1067,41 @@ use 5.008001; SELECT 'SYSTEM VIEW' , 'relkind: v; nspname ~ ^pg_(catalog|toast)$' UNION + SELECT 'MATERIALIZED VIEW' + , 'relkind: m' + UNION + SELECT 'SYSTEM MATERIALIZED VIEW' + , 'relkind: m; nspname ~ ^pg_(catalog|toast)$' + UNION SELECT 'LOCAL TEMPORARY' , 'relkind: r; nspname ~ ^pg_(toast_)?temp') type_info ORDER BY "TABLE_TYPE" ASC }; - } - else { - # Default SQL - $extracols = q{,n.nspname AS pg_schema, c.relname AS pg_table}; - my @search = (q|c.relkind IN ('r', 'v')|, # No sequences, etc. for now - q|NOT (quote_ident(n.nspname) ~ '^pg_(toast_)?temp_' AND NOT has_schema_privilege(n.nspname, 'USAGE'))|); # No others' temp objects - my $showtablespace = ', quote_ident(t.spcname) AS "pg_tablespace_name", quote_ident(t.spclocation) AS "pg_tablespace_location"'; - if ($dbh->{private_dbdpg}{version} >= 90200) { - $showtablespace = ', quote_ident(t.spcname) AS "pg_tablespace_name", quote_ident(pg_tablespace_location(t.oid)) AS "pg_tablespace_location"'; - } - - ## If the schema or table has an underscore or a %, use a LIKE comparison - if (defined $schema and length $schema) { - push @search, 'n.nspname ' . ($schema =~ /[_%]/ ? 'LIKE ' : '= ') . $dbh->quote($schema); - } - if (defined $table and length $table) { - push @search, 'c.relname ' . ($table =~ /[_%]/ ? 'LIKE ' : '= ') . $dbh->quote($table); - } - - my $TSJOIN = 'pg_catalog.pg_tablespace t ON (t.oid = c.reltablespace)'; - if ($dbh->{private_dbdpg}{version} < 80000) { - $TSJOIN = '(SELECT 0 AS oid, 0 AS spcname, 0 AS spclocation LIMIT 0) AS t ON (t.oid=1)'; - } - my $whereclause = join "\n\t\t\t\t\t AND " => @search; - $tbl_sql = qq{ + } + else { + # Default SQL + $extracols = q{,n.nspname AS pg_schema, c.relname AS pg_table}; + my @search = (q|c.relkind IN ('r', 'v', 'm')|, # No sequences, etc. for now + q|NOT (quote_ident(n.nspname) ~ '^pg_(toast_)?temp_' AND NOT has_schema_privilege(n.nspname, 'USAGE'))|); # No others' temp objects + my $showtablespace = ', quote_ident(t.spcname) AS "pg_tablespace_name", quote_ident(t.spclocation) AS "pg_tablespace_location"'; + if ($dbh->{private_dbdpg}{version} >= 90200) { + $showtablespace = ', quote_ident(t.spcname) AS "pg_tablespace_name", quote_ident(pg_tablespace_location(t.oid)) AS "pg_tablespace_location"'; + } + + ## If the schema or table has an underscore or a %, use a LIKE comparison + if (defined $schema and length $schema) { + push @search, 'n.nspname ' . ($schema =~ /[_%]/ ? 'LIKE ' : '= ') . $dbh->quote($schema); + } + if (defined $table and length $table) { + push @search, 'c.relname ' . ($table =~ /[_%]/ ? 'LIKE ' : '= ') . $dbh->quote($table); + } + + my $TSJOIN = 'pg_catalog.pg_tablespace t ON (t.oid = c.reltablespace)'; + if ($dbh->{private_dbdpg}{version} < 80000) { + $TSJOIN = '(SELECT 0 AS oid, 0 AS spcname, 0 AS spclocation LIMIT 0) AS t ON (t.oid=1)'; + } + my $whereclause = join "\n\t\t\t\t\t AND " => @search; + $tbl_sql = qq{ SELECT NULL::text AS "TABLE_CAT" , quote_ident(n.nspname) AS "TABLE_SCHEM" , quote_ident(c.relname) AS "TABLE_NAME" @@ -1107,10 +1113,17 @@ use 5.008001; 'SYSTEM TABLE' ELSE 'TABLE' END - ELSE CASE WHEN quote_ident(n.nspname) ~ '^pg_' THEN + WHEN c.relkind = 'v' THEN + CASE WHEN quote_ident(n.nspname) ~ '^pg_' THEN 'SYSTEM VIEW' ELSE 'VIEW' END + WHEN c.relkind = 'm' THEN + CASE WHEN quote_ident(n.nspname) ~ '^pg_' THEN + 'SYSTEM MATERIALIZED VIEW' + ELSE 'MATERIALIZED VIEW' + END + ELSE 'UNKNOWN' END AS "TABLE_TYPE" , d.description AS "REMARKS" $showtablespace $extracols FROM pg_catalog.pg_class AS c @@ -1122,129 +1135,129 @@ use 5.008001; ORDER BY "TABLE_TYPE", "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME" }; - if (defined($type) and length($type)) { - my $type_restrict = join ', ' => - map { $dbh->quote($_) unless /^'/ } - grep {length} - split(',', $type); - $tbl_sql = qq{SELECT * FROM ($tbl_sql) ti WHERE "TABLE_TYPE" IN ($type_restrict)}; - } - } - my $sth = $dbh->prepare( $tbl_sql ) or return undef; - $sth->execute(); - - return $sth; - } + if (defined($type) and length($type)) { + my $type_restrict = join ', ' => + map { $dbh->quote($_) unless /^'/ } + grep {length} + split(',', $type); + $tbl_sql = qq{SELECT * FROM ($tbl_sql) ti WHERE "TABLE_TYPE" IN ($type_restrict)}; + } + } + my $sth = $dbh->prepare( $tbl_sql ) or return undef; + $sth->execute(); + + return $sth; + } - sub tables { - my ($dbh, @args) = @_; - my $attr = $args[4]; - my $sth = $dbh->table_info(@args) or return; - my $tables = $sth->fetchall_arrayref() or return; - my @tables = map { (! (ref $attr eq 'HASH' and $attr->{pg_noprefix})) ? - "$_->[1].$_->[2]" : $_->[2] } @$tables; - return @tables; - } + sub tables { + my ($dbh, @args) = @_; + my $attr = $args[4]; + my $sth = $dbh->table_info(@args) or return; + my $tables = $sth->fetchall_arrayref() or return; + my @tables = map { (! (ref $attr eq 'HASH' and $attr->{pg_noprefix})) ? + "$_->[1].$_->[2]" : $_->[2] } @$tables; + return @tables; + } - sub table_attributes { - my ($dbh, $table) = @_; + sub table_attributes { + my ($dbh, $table) = @_; - my $sth = $dbh->column_info(undef,undef,$table,undef); + my $sth = $dbh->column_info(undef,undef,$table,undef); - my %convert = ( - COLUMN_NAME => 'NAME', - DATA_TYPE => 'TYPE', - COLUMN_SIZE => 'SIZE', - NULLABLE => 'NOTNULL', - REMARKS => 'REMARKS', - COLUMN_DEF => 'DEFAULT', - pg_constraint => 'CONSTRAINT', - ); + my %convert = ( + COLUMN_NAME => 'NAME', + DATA_TYPE => 'TYPE', + COLUMN_SIZE => 'SIZE', + NULLABLE => 'NOTNULL', + REMARKS => 'REMARKS', + COLUMN_DEF => 'DEFAULT', + pg_constraint => 'CONSTRAINT', + ); - my $attrs = $sth->fetchall_arrayref(\%convert); + my $attrs = $sth->fetchall_arrayref(\%convert); - for my $row (@$attrs) { - # switch the column names - for my $name (keys %$row) { - $row->{ $convert{$name} } = $row->{$name}; + for my $row (@$attrs) { + # switch the column names + for my $name (keys %$row) { + $row->{ $convert{$name} } = $row->{$name}; - ## Keep some original columns - delete $row->{$name} unless ($name eq 'REMARKS' or $name eq 'NULLABLE'); + ## Keep some original columns + delete $row->{$name} unless ($name eq 'REMARKS' or $name eq 'NULLABLE'); - } - # Moved check outside of loop as it was inverting the NOTNULL value for - # attribute. - # NOTNULL inverts the sense of NULLABLE - $row->{NOTNULL} = ($row->{NOTNULL} ? 0 : 1); + } + # Moved check outside of loop as it was inverting the NOTNULL value for + # attribute. + # NOTNULL inverts the sense of NULLABLE + $row->{NOTNULL} = ($row->{NOTNULL} ? 0 : 1); - my @pri_keys = $dbh->primary_key( undef, undef, $table ); - $row->{PRIMARY_KEY} = scalar(grep { /^$row->{NAME}$/i } @pri_keys) ? 1 : 0; - } + my @pri_keys = $dbh->primary_key( undef, undef, $table ); + $row->{PRIMARY_KEY} = scalar(grep { /^$row->{NAME}$/i } @pri_keys) ? 1 : 0; + } - return $attrs; + return $attrs; - } + } - sub _calc_col_size { + sub _calc_col_size { - my $mod = shift; - my $size = shift; + my $mod = shift; + my $size = shift; - if ((defined $size) and ($size > 0)) { - return $size; - } elsif ($mod > 0xffff) { - my $prec = ($mod & 0xffff) - 4; - $mod >>= 16; - my $dig = $mod; - return "$prec,$dig"; - } elsif ($mod >= 4) { - return $mod - 4; - } # else { - # $rtn = $mod; - # $rtn = undef; - # } + if ((defined $size) and ($size > 0)) { + return $size; + } elsif ($mod > 0xffff) { + my $prec = ($mod & 0xffff) - 4; + $mod >>= 16; + my $dig = $mod; + return "$prec,$dig"; + } elsif ($mod >= 4) { + return $mod - 4; + } # else { + # $rtn = $mod; + # $rtn = undef; + # } - return; - } + return; + } - sub type_info_all { - my ($dbh) = @_; - - my $names = - { - TYPE_NAME => 0, - DATA_TYPE => 1, - COLUMN_SIZE => 2, - LITERAL_PREFIX => 3, - LITERAL_SUFFIX => 4, - CREATE_PARAMS => 5, - NULLABLE => 6, - CASE_SENSITIVE => 7, - SEARCHABLE => 8, - UNSIGNED_ATTRIBUTE => 9, - FIXED_PREC_SCALE => 10, - AUTO_UNIQUE_VALUE => 11, - LOCAL_TYPE_NAME => 12, - MINIMUM_SCALE => 13, - MAXIMUM_SCALE => 14, - SQL_DATA_TYPE => 15, - SQL_DATETIME_SUB => 16, - NUM_PREC_RADIX => 17, - INTERVAL_PRECISION => 18, - }; - - ## This list is derived from dbi_sql.h in DBI, from types.c and types.h, and from the PG docs - - ## Aids to make the list more readable: - my $GIG = 1073741824; - my $PS = 'precision/scale'; - my $LEN = 'length'; - my $UN; - my $ti = - [ - $names, + sub type_info_all { + my ($dbh) = @_; + + my $names = + { + TYPE_NAME => 0, + DATA_TYPE => 1, + COLUMN_SIZE => 2, + LITERAL_PREFIX => 3, + LITERAL_SUFFIX => 4, + CREATE_PARAMS => 5, + NULLABLE => 6, + CASE_SENSITIVE => 7, + SEARCHABLE => 8, + UNSIGNED_ATTRIBUTE => 9, + FIXED_PREC_SCALE => 10, + AUTO_UNIQUE_VALUE => 11, + LOCAL_TYPE_NAME => 12, + MINIMUM_SCALE => 13, + MAXIMUM_SCALE => 14, + SQL_DATA_TYPE => 15, + SQL_DATETIME_SUB => 16, + NUM_PREC_RADIX => 17, + INTERVAL_PRECISION => 18, + }; + + ## This list is derived from dbi_sql.h in DBI, from types.c and types.h, and from the PG docs + + ## Aids to make the list more readable: + my $GIG = 1073741824; + my $PS = 'precision/scale'; + my $LEN = 'length'; + my $UN; + my $ti = + [ + $names, # name sql_type size pfx/sfx crt n/c/s +-/P/I local min max sub rdx itvl ['unknown', SQL_UNKNOWN_TYPE, 0, $UN,$UN, $UN, 1,0,0, $UN,0,0, 'UNKNOWN', $UN,$UN, @@ -1291,31 +1304,31 @@ use 5.008001; ['timestamptz',SQL_TYPE_TIMESTAMP_WITH_TIMEZONE, 29, q{'},q{'}, $UN, 1,0,2, $UN,0,0, 'TIMESTAMPTZ',0,6, SQL_TYPE_TIMESTAMP_WITH_TIMEZONE, $UN, $UN, $UN ], - # - # intentionally omitted: char, all geometric types, internal types - ]; - return $ti; - } + # + # intentionally omitted: char, all geometric types, internal types + ]; + return $ti; + } - # Characters that need to be escaped by quote(). - my %esc = ( - q{'} => '\\047', # '\\' . sprintf("%03o", ord("'")), # ISO SQL 2 - '\\' => '\\134', # '\\' . sprintf("%03o", ord("\\")), - ); + # Characters that need to be escaped by quote(). + my %esc = ( + q{'} => '\\047', # '\\' . sprintf("%03o", ord("'")), # ISO SQL 2 + '\\' => '\\134', # '\\' . sprintf("%03o", ord("\\")), + ); - # Set up lookup for SQL types we don't want to escape. - my %no_escape = map { $_ => 1 } - DBI::SQL_INTEGER, DBI::SQL_SMALLINT, DBI::SQL_BIGINT, DBI::SQL_DECIMAL, - DBI::SQL_FLOAT, DBI::SQL_REAL, DBI::SQL_DOUBLE, DBI::SQL_NUMERIC; + # Set up lookup for SQL types we don't want to escape. + my %no_escape = map { $_ => 1 } + DBI::SQL_INTEGER, DBI::SQL_SMALLINT, DBI::SQL_BIGINT, DBI::SQL_DECIMAL, + DBI::SQL_FLOAT, DBI::SQL_REAL, DBI::SQL_DOUBLE, DBI::SQL_NUMERIC; - sub get_info { + sub get_info { - my ($dbh,$type) = @_; + my ($dbh,$type) = @_; - return undef unless defined $type and length $type; + return undef unless defined $type and length $type; - my %type = ( + my %type = ( ## Driver information: @@ -1329,7 +1342,7 @@ use 5.008001; 4 => ['SQL_DRIVER_HENV', 0 ], ## not applicable 76 => ['SQL_DRIVER_HLIB', 0 ], ## not applicable 5 => ['SQL_DRIVER_HSTMT', 0 ], ## not applicable - ## Not clear what should go here. Some things suggest 'Pg', others 'Pg.pm'. We'll use DBD::Pg for now + ## Not clear what should go here. Some things suggest 'Pg', others 'Pg.pm'. We'll use DBD::Pg for now 6 => ['SQL_DRIVER_NAME', 'DBD::Pg' ], 77 => ['SQL_DRIVER_ODBC_VERSION', '03.00' ], 7 => ['SQL_DRIVER_VER', 'DBDVERSION' ], ## magic word @@ -1497,146 +1510,146 @@ use 5.008001; 125 => ['SQL_CONVERT_WLONGVARCHAR', 0 ], 126 => ['SQL_CONVERT_WVARCHAR', 0 ], - ); ## end of %type - - ## Put both numbers and names into a hash - my %t; - for (keys %type) { - $t{$_} = $type{$_}->[1]; - $t{$type{$_}->[0]} = $type{$_}->[1]; - } - - return undef unless exists $t{$type}; - - my $ans = $t{$type}; - - if ($ans eq 'NAMEDATALEN') { - return $dbh->selectall_arrayref('SHOW max_identifier_length')->[0][0]; - } - elsif ($ans eq 'ODBCVERSION') { - my $version = $dbh->{private_dbdpg}{version}; - return '00.00.0000' unless $version =~ /^(\d\d?)(\d\d)(\d\d)$/o; - return sprintf '%02d.%02d.%.2d00', $1,$2,$3; - } - elsif ($ans eq 'DBDVERSION') { - my $simpleversion = $DBD::Pg::VERSION; - $simpleversion =~ s/_/./g; - return sprintf '%02d.%02d.%1d%1d%1d%1d', split (/\./, "$simpleversion.0.0.0.0.0.0"); - } - elsif ($ans eq 'MAXCONNECTIONS') { - return $dbh->selectall_arrayref('SHOW max_connections')->[0][0]; - } - elsif ($ans eq 'ENCODING') { - return $dbh->selectall_arrayref('SHOW server_encoding')->[0][0]; - } - elsif ($ans eq 'KEYWORDS') { - ## http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html - ## Basically, we want ones that are 'reserved' for PostgreSQL but not 'reserved' in SQL:2003 - ## - return join ',' => (qw(ANALYSE ANALYZE ASC DEFERRABLE DESC DO FREEZE ILIKE INITIALLY ISNULL LIMIT NOTNULL OFF OFFSET PLACING RETURNING VERBOSE)); - } - elsif ($ans eq 'CURRENTDB') { - return $dbh->selectall_arrayref('SELECT pg_catalog.current_database()')->[0][0]; - } - elsif ($ans eq 'READONLY') { - my $SQL = q{SELECT CASE WHEN setting = 'on' THEN 'Y' ELSE 'N' END FROM pg_settings WHERE name = 'transaction_read_only'}; - my $info = $dbh->selectall_arrayref($SQL); - return defined $info->[0] ? $info->[0][0] : 'N'; - } - elsif ($ans eq 'DEFAULTTXN') { - my $SQL = q{SELECT CASE WHEN setting = 'read committed' THEN 2 ELSE 8 END FROM pg_settings WHERE name = 'default_transaction_isolation'}; - my $info = $dbh->selectall_arrayref($SQL); - return defined $info->[0] ? $info->[0][0] : 2; - } - - return $ans; - } # end of get_info - - sub private_attribute_info { - return { - pg_async_status => undef, - pg_bool_tf => undef, - pg_db => undef, - pg_default_port => undef, - pg_enable_utf8 => undef, - pg_utf8_flag => undef, - pg_errorlevel => undef, - pg_expand_array => undef, - pg_host => undef, - pg_INV_READ => undef, - pg_INV_WRITE => undef, - pg_lib_version => undef, - pg_options => undef, - pg_pass => undef, - pg_pid => undef, - pg_placeholder_dollaronly => undef, - pg_placeholder_nocolons => undef, - pg_port => undef, - pg_prepare_now => undef, - pg_protocol => undef, - pg_server_prepare => undef, - pg_server_version => undef, - pg_socket => undef, - pg_standard_conforming_strings => undef, - pg_switch_prepared => undef, - pg_user => undef, - }; - } + ); ## end of %type + + ## Put both numbers and names into a hash + my %t; + for (keys %type) { + $t{$_} = $type{$_}->[1]; + $t{$type{$_}->[0]} = $type{$_}->[1]; + } + + return undef unless exists $t{$type}; + + my $ans = $t{$type}; + + if ($ans eq 'NAMEDATALEN') { + return $dbh->selectall_arrayref('SHOW max_identifier_length')->[0][0]; + } + elsif ($ans eq 'ODBCVERSION') { + my $version = $dbh->{private_dbdpg}{version}; + return '00.00.0000' unless $version =~ /^(\d\d?)(\d\d)(\d\d)$/o; + return sprintf '%02d.%02d.%.2d00', $1,$2,$3; + } + elsif ($ans eq 'DBDVERSION') { + my $simpleversion = $DBD::Pg::VERSION; + $simpleversion =~ s/_/./g; + return sprintf '%02d.%02d.%1d%1d%1d%1d', split (/\./, "$simpleversion.0.0.0.0.0.0"); + } + elsif ($ans eq 'MAXCONNECTIONS') { + return $dbh->selectall_arrayref('SHOW max_connections')->[0][0]; + } + elsif ($ans eq 'ENCODING') { + return $dbh->selectall_arrayref('SHOW server_encoding')->[0][0]; + } + elsif ($ans eq 'KEYWORDS') { + ## http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html + ## Basically, we want ones that are 'reserved' for PostgreSQL but not 'reserved' in SQL:2003 + ## + return join ',' => (qw(ANALYSE ANALYZE ASC DEFERRABLE DESC DO FREEZE ILIKE INITIALLY ISNULL LIMIT NOTNULL OFF OFFSET PLACING RETURNING VERBOSE)); + } + elsif ($ans eq 'CURRENTDB') { + return $dbh->selectall_arrayref('SELECT pg_catalog.current_database()')->[0][0]; + } + elsif ($ans eq 'READONLY') { + my $SQL = q{SELECT CASE WHEN setting = 'on' THEN 'Y' ELSE 'N' END FROM pg_settings WHERE name = 'transaction_read_only'}; + my $info = $dbh->selectall_arrayref($SQL); + return defined $info->[0] ? $info->[0][0] : 'N'; + } + elsif ($ans eq 'DEFAULTTXN') { + my $SQL = q{SELECT CASE WHEN setting = 'read committed' THEN 2 ELSE 8 END FROM pg_settings WHERE name = 'default_transaction_isolation'}; + my $info = $dbh->selectall_arrayref($SQL); + return defined $info->[0] ? $info->[0][0] : 2; + } + + return $ans; + } # end of get_info + + sub private_attribute_info { + return { + pg_async_status => undef, + pg_bool_tf => undef, + pg_db => undef, + pg_default_port => undef, + pg_enable_utf8 => undef, + pg_utf8_flag => undef, + pg_errorlevel => undef, + pg_expand_array => undef, + pg_host => undef, + pg_INV_READ => undef, + pg_INV_WRITE => undef, + pg_lib_version => undef, + pg_options => undef, + pg_pass => undef, + pg_pid => undef, + pg_placeholder_dollaronly => undef, + pg_placeholder_nocolons => undef, + pg_port => undef, + pg_prepare_now => undef, + pg_protocol => undef, + pg_server_prepare => undef, + pg_server_version => undef, + pg_socket => undef, + pg_standard_conforming_strings => undef, + pg_switch_prepared => undef, + pg_user => undef, + }; + } } { - package DBD::Pg::st; + package DBD::Pg::st; - sub parse_trace_flag { - my ($h, $flag) = @_; - return DBD::Pg->parse_trace_flag($flag); - } - - sub bind_param_array { - - ## Binds an array of data to a specific placeholder in a statement - ## The DBI version is broken, so we implement a near-copy here - - my $sth = shift; - my ($p_id, $value_array, $attr) = @_; - - ## Bail if the second arg is not undef or an arrayref - return $sth->set_err(1, "Value for parameter $p_id must be a scalar or an arrayref, not a ".ref($value_array)) - if defined $value_array and ref $value_array and ref $value_array ne 'ARRAY'; - - ## Bail if the first arg is not a number - return $sth->set_err(1, q{Can't use named placeholders for non-driver supported bind_param_array}) - unless DBI::looks_like_number($p_id); # because we rely on execute(@ary) here - - ## Store the list of items in the hash (will be undef or an arrayref) - $sth->{ParamArrays}{$p_id} = $value_array; - - ## If any attribs were passed in, we need to call bind_param - return $sth->bind_param($p_id, '', $attr) if $attr; ## This is the big change so -w does not complain - - return 1; - } ## end bind_param_array + sub parse_trace_flag { + my ($h, $flag) = @_; + return DBD::Pg->parse_trace_flag($flag); + } - sub private_attribute_info { - return { - pg_async => undef, - pg_bound => undef, - pg_current_row => undef, - pg_direct => undef, - pg_numbound => undef, - pg_cmd_status => undef, - pg_oid_status => undef, - pg_placeholder_dollaronly => undef, - pg_placeholder_nocolons => undef, - pg_prepare_name => undef, - pg_prepare_now => undef, - pg_segments => undef, - pg_server_prepare => undef, - pg_size => undef, - pg_switch_prepared => undef, - pg_type => undef, - }; + sub bind_param_array { + + ## Binds an array of data to a specific placeholder in a statement + ## The DBI version is broken, so we implement a near-copy here + + my $sth = shift; + my ($p_id, $value_array, $attr) = @_; + + ## Bail if the second arg is not undef or an arrayref + return $sth->set_err(1, "Value for parameter $p_id must be a scalar or an arrayref, not a ".ref($value_array)) + if defined $value_array and ref $value_array and ref $value_array ne 'ARRAY'; + + ## Bail if the first arg is not a number + return $sth->set_err(1, q{Can't use named placeholders for non-driver supported bind_param_array}) + unless DBI::looks_like_number($p_id); # because we rely on execute(@ary) here + + ## Store the list of items in the hash (will be undef or an arrayref) + $sth->{ParamArrays}{$p_id} = $value_array; + + ## If any attribs were passed in, we need to call bind_param + return $sth->bind_param($p_id, '', $attr) if $attr; ## This is the big change so -w does not complain + + return 1; + } ## end bind_param_array + + sub private_attribute_info { + return { + pg_async => undef, + pg_bound => undef, + pg_current_row => undef, + pg_direct => undef, + pg_numbound => undef, + pg_cmd_status => undef, + pg_oid_status => undef, + pg_placeholder_dollaronly => undef, + pg_placeholder_nocolons => undef, + pg_prepare_name => undef, + pg_prepare_now => undef, + pg_segments => undef, + pg_server_prepare => undef, + pg_size => undef, + pg_switch_prepared => undef, + pg_type => undef, + }; } } ## end st section @@ -2772,7 +2785,7 @@ Returns all tables and views visible to the current user. The schema and table arguments will do a C<LIKE> search if a percent sign (C<%>) or an underscore (C<_>) is detected in the argument. The C<$type> argument accepts any comma-separated combination of "TABLE", "VIEW", "SYSTEM TABLE", "SYSTEM VIEW", -or "LOCAL TEMPORARY". (Using all is the default action.) +"MATERIALIZED VIEW", "SYSTEM MATERIALIZED VIEW", or "LOCAL TEMPORARY". (Using all is the default action.) Note that a statement handle is returned, and not a direct list of tables. See the examples below for ways to handle this. @@ -2786,7 +2799,8 @@ B<TABLE_SCHEM>: The name of the schema that the table or view is in. B<TABLE_NAME>: The name of the table or view. B<TABLE_TYPE>: The type of object returned. Will be one of "TABLE", "VIEW", -"MATERIALIZED VIEW", "SYSTEM VIEW", "SYSTEM MATERIALIZED VIEW", or "SYSTEM TABLE". +"MATERIALIZED VIEW", "SYSTEM VIEW", "SYSTEM MATERIALIZED VIEW", "SYSTEM TABLE", +or "LOCAL TEMPORARY". The TABLE_SCHEM and TABLE_NAME will be quoted via C<quote_ident()>. diff --git a/t/03dbmethod.t b/t/03dbmethod.t index 2eb536f..108e0c5 100644 --- a/t/03dbmethod.t +++ b/t/03dbmethod.t @@ -554,6 +554,8 @@ ok ($sth, $t); my @expected = ('LOCAL TEMPORARY', 'SYSTEM TABLE', 'SYSTEM VIEW', + 'MATERIALIZED VIEW', + 'SYSTEM MATERIALIZED VIEW', 'TABLE', 'VIEW',); -- 1.8.4