| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Class::DBI::DB2; | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | =head1 NAME | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | Class::DBI::DB2 - Extensions to Class::DBI for DB2 | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | package Music::DBI; | 
| 10 |  |  |  |  |  |  | use base 'Class::DBI::DB2'; | 
| 11 |  |  |  |  |  |  | __PACKAGE__->set_db( 'Main', 'dbi:DB2:dbname', 'user', 'password', ); | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | package Artist; | 
| 14 |  |  |  |  |  |  | use base 'Music::DBI'; | 
| 15 |  |  |  |  |  |  | __PACKAGE__->set_up_table('Artist'); | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | __PACKAGE__->autoinflate(dates => 'Time::Piece'); | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | # Somewhere else ... | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | my $type = $class->column_type('column_name'); | 
| 22 |  |  |  |  |  |  | my $colno = $class->column_no('column_name'); | 
| 23 |  |  |  |  |  |  | my $nulls = $class->column_nulls('column_name'); | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | # ... see the Class::DBI documentation for details on Class::DBI usage | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | Class::DBI::DB2 automates the setup of Class::DBI columns and primary key | 
| 30 |  |  |  |  |  |  | for IBM DB2. | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | This is an extension to Class::DBI that currently implements: | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | * Automatic column name discovery. | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | * Automatic primary key(s) detection. | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | * Automatic column type detection (for use with autoinflate). | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | * Automatic column number detection (where column order is needed). | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | Instead of setting Class::DBI as your base class, use this. | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | =cut | 
| 45 |  |  |  |  |  |  |  | 
| 46 | 2 |  |  | 2 |  | 160065 | use strict; | 
|  | 2 |  |  |  |  | 6 |  | 
|  | 2 |  |  |  |  | 109 |  | 
| 47 |  |  |  |  |  |  | require Class::DBI; | 
| 48 | 2 |  |  | 2 |  | 11 | use base 'Class::DBI'; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 7749 |  | 
| 49 |  |  |  |  |  |  |  | 
| 50 | 2 |  |  | 2 |  | 369718 | use vars qw($VERSION); | 
|  | 2 |  |  |  |  | 13 |  | 
|  | 2 |  |  |  |  | 4724 |  | 
| 51 |  |  |  |  |  |  | $VERSION = '0.16'; | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | =head1 OBJECT METHODS | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | =head2 set_up_table | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | __PACKAGE__->set_up_table("table_name"); | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | An optional second argument can supply your own alias for your table name. | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | __PACKAGE__->set_up_table("table_name", "table_alias"); | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | Traditionally, to use Class::DBI, you have to set up the columns: | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | __PACKAGE__->columns(All => qw/list of columns/); | 
| 66 |  |  |  |  |  |  | __PACKAGE__->columns(Primary => 'column_name'); | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | While this allows for more flexibility if you're going to arrange your | 
| 69 |  |  |  |  |  |  | columns into a variety of groupings, sometimes you just want to create the | 
| 70 |  |  |  |  |  |  | 'all columns' list. | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | The columns call will extract the list of all the columns, and the primary key | 
| 73 |  |  |  |  |  |  | and set them up for you. It will die horribly if the table contains | 
| 74 |  |  |  |  |  |  | no primary key(s). | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | =cut | 
| 77 |  |  |  |  |  |  |  | 
| 78 | 0 |  |  | 0 |  | 0 | sub _croak { require Carp; Carp::croak(@_); } | 
|  | 0 |  |  |  |  | 0 |  | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | __PACKAGE__->set_sql( | 
| 81 |  |  |  |  |  |  | create_table => 'CREATE TABLE __TABLE__ (%s)'); | 
| 82 |  |  |  |  |  |  | __PACKAGE__->set_sql(drop_table => 'DROP TABLE __TABLE__'); | 
| 83 |  |  |  |  |  |  | __PACKAGE__->set_sql( | 
| 84 |  |  |  |  |  |  | desc_table => "SELECT COLNAME, COLNO, TYPENAME, NULLS FROM SYSCAT.COLUMNS WHERE TABSCHEMA = ? and TABNAME = ? order by colno"); | 
| 85 |  |  |  |  |  |  | __PACKAGE__->set_sql( | 
| 86 |  |  |  |  |  |  | exists => 'SELECT count(*) FROM SYSCAT.TABLES WHERE TABSCHEMA = ? and TABNAME = ?'); | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | sub desc_table { | 
| 89 | 0 |  |  | 0 | 0 | 0 | my $class = shift; | 
| 90 | 0 |  |  |  |  | 0 | my ($tabschema,$table) = split '\.', $class->table; | 
| 91 | 0 |  |  |  |  | 0 | return $class->search_desc_table(uc($tabschema),uc($table)); | 
| 92 |  |  |  |  |  |  | } | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | sub set_up_table | 
| 95 |  |  |  |  |  |  | { | 
| 96 | 0 |  |  | 0 | 1 | 0 | my $class = shift; | 
| 97 | 0 |  | 0 |  |  | 0 | $class->table( my $tabname = shift || $class->table, shift ); | 
| 98 | 0 |  |  |  |  | 0 | my $dbh = $class->db_Main; | 
| 99 | 0 |  |  |  |  | 0 | my ($tabschema,$table) = split '\.', $class->table; | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | # find primary key(s) | 
| 102 | 0 |  |  |  |  | 0 | my ( @primary ); | 
| 103 | 0 |  |  |  |  | 0 | my $sth = $dbh->prepare(<<"SQL"); | 
| 104 |  |  |  |  |  |  | SELECT c.COLNAME FROM SYSCAT.KEYCOLUSE kc, SYSCAT.TABCONST tc,  SYSCAT.COLUMNS c | 
| 105 |  |  |  |  |  |  | WHERE kc.CONSTNAME=tc.CONSTNAME AND kc.TABSCHEMA=tc.TABSCHEMA | 
| 106 |  |  |  |  |  |  | AND kc.TABNAME=tc.TABNAME AND kc.TABSCHEMA=c.TABSCHEMA AND | 
| 107 |  |  |  |  |  |  | kc.TABNAME=c.TABNAME AND kc.COLNAME=c.COLNAME AND kc.TABSCHEMA = ? AND | 
| 108 |  |  |  |  |  |  | kc.TABNAME = ? AND tc.TYPE = 'P' ORDER BY kc.COLSEQ | 
| 109 |  |  |  |  |  |  | SQL | 
| 110 | 0 |  |  |  |  | 0 | $sth->execute( uc($tabschema), uc($table) ); | 
| 111 | 0 |  |  |  |  | 0 | my $primaries = $sth->fetchall_arrayref; $sth->finish; | 
|  | 0 |  |  |  |  | 0 |  | 
| 112 | 0 |  |  |  |  | 0 | map {push @primary, $_->[0]} @$primaries; | 
|  | 0 |  |  |  |  | 0 |  | 
| 113 | 0 | 0 |  |  |  | 0 | $class->_croak("$table has no primary key") unless @primary; | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | # find all columns | 
| 116 | 0 |  |  |  |  | 0 | my ( @cols ); | 
| 117 | 0 |  |  |  |  | 0 | $sth = $dbh->prepare(<<"SQL"); | 
| 118 |  |  |  |  |  |  | SELECT COLNAME, COLNO, TYPENAME, NULLS FROM SYSCAT.COLUMNS | 
| 119 |  |  |  |  |  |  | WHERE TABSCHEMA = ? and TABNAME = ? order by colno | 
| 120 |  |  |  |  |  |  | SQL | 
| 121 | 0 |  |  |  |  | 0 | $sth->execute( uc($tabschema), uc($table) ); | 
| 122 | 0 |  |  |  |  | 0 | my $columns = $sth->fetchall_arrayref; $sth->finish; | 
|  | 0 |  |  |  |  | 0 |  | 
| 123 | 0 |  |  |  |  | 0 | map {push @cols, $_->[0]} @$columns; | 
|  | 0 |  |  |  |  | 0 |  | 
| 124 |  |  |  |  |  |  |  | 
| 125 | 0 |  |  |  |  | 0 | $class->columns( All     => @cols ); | 
| 126 | 0 |  |  |  |  | 0 | $class->columns( Primary => @primary ); | 
| 127 |  |  |  |  |  |  | } | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | =head2 autoinflate | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | __PACKAGE__->autoinflate(column_type => 'Inflation::Class'); | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | __PACKAGE__->autoinflate(timestamp => 'Time::Piece'); | 
| 134 |  |  |  |  |  |  | __PACKAGE__->autoinflate(dates => 'Time::Piece'); | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | This will automatically set up has_a() relationships for all columns of | 
| 137 |  |  |  |  |  |  | the specified type to the given class. | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | It is assumed that all classes passed will be able to inflate | 
| 140 |  |  |  |  |  |  | and deflate without needing extra has_a arguments, with the example of | 
| 141 |  |  |  |  |  |  | Time::Piece objects, that uses Time::Piece::DB2 (which you'll have to | 
| 142 |  |  |  |  |  |  | have installed!). | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | The special type 'dates' will autoinflate all columns of type date, | 
| 145 |  |  |  |  |  |  | time or timestamp. | 
| 146 |  |  |  |  |  |  |  | 
| 147 |  |  |  |  |  |  | =cut | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  | sub autoinflate { | 
| 150 | 0 |  |  | 0 | 1 | 0 | my ($class, %how) = @_; | 
| 151 | 0 |  | 0 |  |  | 0 | $how{$_} ||= $how{dates} for qw/DATE TIME TIMESTAMP/; | 
| 152 | 0 |  |  |  |  | 0 | my $info = $class->_column_info; | 
| 153 | 0 |  |  |  |  | 0 | foreach my $col (keys %$info) { | 
| 154 | 0 |  |  |  |  | 0 | (my $type = $info->{$col}->{typename}) =~ s/\W.*//; | 
| 155 | 0 | 0 |  |  |  | 0 | next unless $how{$type}; | 
| 156 | 0 |  |  |  |  | 0 | my %args; | 
| 157 | 0 | 0 |  |  |  | 0 | if ($how{$type} eq "Time::Piece") { | 
| 158 | 0 |  |  |  |  | 0 | eval "use Time::Piece::DB2"; | 
| 159 | 0 | 0 |  |  |  | 0 | $class->_croak($@) if $@; | 
| 160 | 0 |  |  |  |  | 0 | $args{inflate} = "from_db2_" . lc($type); | 
| 161 | 0 |  |  |  |  | 0 | $args{deflate} = "db2_" . lc($type); | 
| 162 |  |  |  |  |  |  | } | 
| 163 | 0 |  |  |  |  | 0 | $class->has_a(lc($col) => $how{$type}, %args); | 
| 164 |  |  |  |  |  |  | } | 
| 165 |  |  |  |  |  |  | } | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | sub exists { | 
| 168 | 2 |  |  | 2 | 0 | 3 | my $class = shift; | 
| 169 | 2 |  |  |  |  | 9 | my ($tabschema,$table) = split '\.', $class->table; | 
| 170 | 2 |  |  |  |  | 39 | return $class->sql_exists->select_val(uc($tabschema),uc($table)); | 
| 171 |  |  |  |  |  |  | } | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | =head2 create_table | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | $class->create_table(q{ | 
| 176 |  |  |  |  |  |  | name    VARCHAR(40)     NOT NULL, | 
| 177 |  |  |  |  |  |  | rank    VARCHAR(20)     NOT NULL, | 
| 178 |  |  |  |  |  |  | serial  INTEGER         NOT NULL | 
| 179 |  |  |  |  |  |  | PRIMARY KEY(name) | 
| 180 |  |  |  |  |  |  | }); | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | This creates the table for the class, with the given schema. If the | 
| 183 |  |  |  |  |  |  | table already exists we do nothing. | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  | A typical use would be: | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | Music::CD->table('cd'); | 
| 188 |  |  |  |  |  |  | Music::CD->create_table(q{ | 
| 189 |  |  |  |  |  |  | cdid   INTEGER NOT NULL, | 
| 190 |  |  |  |  |  |  | artist INTEGER NOT NULL, | 
| 191 |  |  |  |  |  |  | title  VARCHAR(255) NOT NULL, | 
| 192 |  |  |  |  |  |  | year   DATE, | 
| 193 |  |  |  |  |  |  | PRIMARY KEY(cdid), | 
| 194 |  |  |  |  |  |  | CONSTRAINT TITLE_UNIQ UNIQUE (artist,title) | 
| 195 |  |  |  |  |  |  | }); | 
| 196 |  |  |  |  |  |  | Music::CD->set_up_table; | 
| 197 |  |  |  |  |  |  |  | 
| 198 |  |  |  |  |  |  | =cut | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | sub create_table { | 
| 201 | 0 |  |  | 0 | 1 | 0 | my ($class, $schema) = @_; | 
| 202 | 0 | 0 |  |  |  | 0 | if ($class->exists == 0) { | 
| 203 | 0 |  |  |  |  | 0 | $class->sql_create_table(uc($schema))->execute; | 
| 204 |  |  |  |  |  |  | } | 
| 205 |  |  |  |  |  |  | } | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | =head2 drop_table | 
| 208 |  |  |  |  |  |  |  | 
| 209 |  |  |  |  |  |  | $class->drop_table; | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | Drops the table for this class, if it exists. | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | =cut | 
| 214 |  |  |  |  |  |  |  | 
| 215 |  |  |  |  |  |  | sub drop_table { | 
| 216 | 2 |  |  | 2 | 1 | 3983 | my $class = shift; | 
| 217 | 2 |  |  |  |  | 10 | my ($tabschema,$table) = split '\.', $class->table; | 
| 218 | 2 | 0 |  |  |  | 44 | if ($class->exists == 1) { | 
| 219 | 0 |  |  |  |  |  | $class->sql_drop_table->execute; | 
| 220 |  |  |  |  |  |  | } | 
| 221 |  |  |  |  |  |  | } | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  | =head2 column_type | 
| 224 |  |  |  |  |  |  |  | 
| 225 |  |  |  |  |  |  | my $type = $class->column_type('column_name'); | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  | This returns the 'typename' of this table's 'column_name' (VARCHAR(20), INTEGER, etc.) | 
| 228 |  |  |  |  |  |  |  | 
| 229 |  |  |  |  |  |  | =head2 column_no | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | my $colno = $class->column_no('column_name'); | 
| 232 |  |  |  |  |  |  |  | 
| 233 |  |  |  |  |  |  | This returns the 'colno' of this table's 'column_name' (0..n)  Useful when a column order | 
| 234 |  |  |  |  |  |  | is needed, for example, when loading a table from a flat-file. | 
| 235 |  |  |  |  |  |  |  | 
| 236 |  |  |  |  |  |  | =head2 column_nulls | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | my $null = $class->column_nulls('column_name'); | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | This returns the 'nulls' of this table's 'column_name' (Y,N) | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | =cut | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | sub _column_info { | 
| 245 | 0 |  |  | 0 |  |  | my $class = shift; | 
| 246 | 0 |  |  |  |  |  | my ($tabschema,$table) = split '\.', $class->table; | 
| 247 | 0 |  |  |  |  |  | my @columns = $class->desc_table(); | 
| 248 | 0 |  |  |  |  |  | return { map { $_->{colname} => $_ } @columns }; | 
|  | 0 |  |  |  |  |  |  | 
| 249 |  |  |  |  |  |  | } | 
| 250 |  |  |  |  |  |  |  | 
| 251 |  |  |  |  |  |  | sub column_no { | 
| 252 | 0 |  |  | 0 | 1 |  | my $class = shift; | 
| 253 | 0 | 0 |  |  |  |  | my $col = shift or die "Need a column for column_no"; | 
| 254 | 0 |  |  |  |  |  | return $class->_column_info->{uc($col)}->{colno}; | 
| 255 |  |  |  |  |  |  | } | 
| 256 |  |  |  |  |  |  |  | 
| 257 |  |  |  |  |  |  | sub column_nulls { | 
| 258 | 0 |  |  | 0 | 1 |  | my $class = shift; | 
| 259 | 0 | 0 |  |  |  |  | my $col = shift or die "Need a column for column_nulls"; | 
| 260 | 0 |  |  |  |  |  | return $class->_column_info->{uc($col)}->{nulls}; | 
| 261 |  |  |  |  |  |  | } | 
| 262 |  |  |  |  |  |  |  | 
| 263 |  |  |  |  |  |  | sub column_type { | 
| 264 | 0 |  |  | 0 | 1 |  | my $class = shift; | 
| 265 | 0 | 0 |  |  |  |  | my $col = shift or die "Need a column for column_type"; | 
| 266 | 0 |  |  |  |  |  | return $class->_column_info->{uc($col)}->{typename}; | 
| 267 |  |  |  |  |  |  | } | 
| 268 |  |  |  |  |  |  |  | 
| 269 |  |  |  |  |  |  | =head1 AUTHOR | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | Mark Ferris, Emark.ferris@geac.comE. | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | =head1 COPYRIGHT | 
| 274 |  |  |  |  |  |  |  | 
| 275 |  |  |  |  |  |  | Copyright (C) 2004 Mark Ferris. All rights reserved. | 
| 276 |  |  |  |  |  |  |  | 
| 277 |  |  |  |  |  |  | This library is free software; you can redistribute it and/or modify | 
| 278 |  |  |  |  |  |  | it under the same terms as Perl itself. | 
| 279 |  |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | L. IBM DB2 (http://www-4.ibm.com/software/data/db2/) | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | =cut | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | 1; |