home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-perl-addon-1.4.9-installer.exe / Oracle.pm < prev    next >
Encoding:
Perl POD Document  |  2003-07-15  |  4.9 KB  |  176 lines

  1. package Class::DBI::Oracle;
  2.  
  3. =head1 NAME
  4.  
  5. Class::DBI::Oracle - Extensions to Class::DBI for Oracle
  6.  
  7. =head1 SYNOPSIS
  8.  
  9.   package Music::DBI;
  10.   use base 'Class::DBI::Oracle';
  11.   Music::DBI->set_db('Main', 'dbi:Oracle:tnsname', 'username', 'password');
  12.  
  13.   package Artist;
  14.   use base 'Music::DBI';
  15.   __PACKAGE__->set_up_table('Artist');
  16.   
  17.   # ... see the Class::DBI documentation for details on Class::DBI usage
  18.  
  19. =head1 DESCRIPTION
  20.  
  21. This is an extension to Class::DBI that currently implements:
  22.  
  23.     * A sequence fix for Oracle databases.
  24.     
  25.     * Automatic column name discovery.
  26.     
  27.     * Automatic primary key detection.
  28.  
  29.     * Sequence name guessing.
  30.  
  31.     * Proper aliasing of reserved words.
  32.  
  33. Instead of setting Class::DBI as your base class, use this.
  34.  
  35. =head1 BUGS
  36.  
  37. The sequence guessing is just that. If your naming convention follows the
  38. defacto standard of TABLENAME_SEQ, and you only use one sequence per table,
  39. this will work.
  40.  
  41. The primary and column name detection lowercases all names found. This is
  42. probably what you want. If it's not, don't use set_up_table.
  43.  
  44. =head1 AUTHOR
  45.  
  46. Teodor Zlatanov
  47.  
  48. Dan Sully E<lt>daniel-cpan@electricrain.comE<gt> added initial column, primary key and sequence finding.
  49.  
  50. Jay Strauss E<lt>classdbi@heyjay.comE<gt> updated column, primary key, and sequence finding. Added aliasing reserved words
  51.  
  52. =head1 SEE ALSO
  53.  
  54. L<Class::DBI> L<Class::DBI::mysql> L<Class::DBI::Pg>
  55.  
  56. =cut
  57.  
  58. use strict;
  59. use base 'Class::DBI';
  60.  
  61. use vars qw($VERSION);
  62. $VERSION = '0.51';
  63.  
  64. # Setup an alias if the tablename is an Oracle reserved word - 
  65. # for example if the class name is: user
  66. # make the table_alias q["user"]
  67. #
  68. # Note: actually not all oracle reserved words (v$reserved_words) seem
  69. # to be a problem, but these have been identified
  70.  
  71. my @problemWords = qw{
  72.     ACCESS ADD ALL ALTER AND ANY AS ASC AUDIT BETWEEN BY CHAR CHECK CLUSTER 
  73.     COLUMN COMMENT COMPRESS CONNECT CREATE CROSS CURRENT CURRENT_DATE 
  74.     CURRENT_TIMESTAMP CURSOR_SPECIFIC_SEGMENT DATE DBTIMEZONE DECIMAL 
  75.     DEFAULT DELETE DESC DISTINCT DROP ELSE ESCAPE EXCLUSIVE EXISTS FALSE 
  76.     FILE FLOAT FOR FROM GRANT GROUP HAVING IDENTIFIED IMMEDIATE IN INCREMENT
  77.     INDEX INITIAL INSERT INTEGER INTERSECT INTO IS JOIN LDAP_REG_SYNC_INTERVAL
  78.     LEVEL LIKE LOCALTIMESTAMP LOCK LOGICAL_READS_PER_SESSION LONG MAXEXTENTS
  79.     MINUS MLSLABEL MODE MODIFY NLS_SORT NOAUDIT NOCOMPRESS NOT NOWAIT NULL 
  80.     NUMBER OF OFFLINE ON ONLINE OPTION OR ORDER PASSWORD_VERIFY_FUNCTION 
  81.     PRIOR PRIVILEGES PUBLIC RAW RENAME RESOURCE REVOKE ROW ROWID ROWNUM ROWS
  82.     SELECT SESSION SESSIONTIMEZONE SET SHARE SIZE SMALLINT START SUCCESSFUL
  83.     SYNONYM SYSDATE SYSTIMESTAMP SYS_OP_BITVEC SYS_OP_ENFORCE_NOT_NULL$ TABLE
  84.     THEN TO TRIGGER UID UNION UNIQUE UPDATE USER VALIDATE VALUES VARCHAR 
  85.     VARCHAR2 VIEW WHENEVER WHERE WITH
  86. };
  87.  
  88. sub _die { require Carp; Carp::croak(@_); } 
  89.  
  90. sub set_up_table {
  91.     my($class, $table) = @_;
  92.     my $dbh = $class->db_Main();
  93.  
  94.     $class->table($table);
  95.  
  96.     $table = uc $table;
  97.  
  98.     # alias the table if needed.
  99.     (my $alias = $class) =~ s/.*:://g;
  100.     $class->table_alias(qq["$alias"]) if grep /$alias/i, @problemWords;
  101.  
  102.     # find the primary key and column names.
  103.     my $sql = qq[
  104.         select     lower(a.column_name), b.position
  105.         from     user_tab_columns a,
  106.                 (
  107.                 select     column_name, position
  108.                 from       user_constraints a, user_cons_columns b
  109.                 where     a.constraint_name = b.constraint_name
  110.                 and    a.constraint_type = 'P'
  111.                 and    a.table_name = ?
  112.                 ) b
  113.         where     a.column_name = b.column_name (+)
  114.         and    a.table_name = ?
  115.         order by position, a.column_name];
  116.  
  117.     my $sth = $dbh->prepare($sql);
  118.     $sth->execute($table,$table);
  119.     
  120.     my $col = $sth->fetchall_arrayref;
  121.     
  122.     $sth->finish();
  123.  
  124.     # deal with old revisions
  125.     my $msg;
  126.     my @primary = ();
  127.  
  128.     $msg = qq{has no primary key} unless $col->[0][1];
  129.  
  130.     # Class::DBI >= 0.93 can use multiple-primary-column keys.
  131.     if ($Class::DBI::VERSION >= 0.93) {
  132.  
  133.         map { push @primary, $_->[0] if $_->[1] } @$col;
  134.  
  135.     } else {
  136.  
  137.         $msg = qq{has a composite primary key} if $col->[1][1];
  138.  
  139.         push @primary, $col->[0][0];
  140.     }
  141.  
  142.     _die('The "',$class->table,qq{" table $msg}) if $msg;
  143.  
  144.     $class->columns(All => map {$_->[0]} @$col);
  145.     $class->columns(Primary => @primary);
  146.  
  147.     # attempt to guess the sequence from the table name.
  148.     # this won't work if there is inconsistent naming.
  149.     #
  150.     # This is potentially very dangerous code, there could be many
  151.     # sequences with the same table name embedded, probably should 
  152.     # only use the sequence if it's the only one that is found with the
  153.     # same tablename
  154.  
  155.     # Go and get all the sequences where the table name is within the
  156.     # name of the sequence
  157.     $sql = qq[
  158.         select    sequence_name
  159.         from    user_sequences
  160.         where    sequence_name like (?)
  161.     ];
  162.     
  163.     $sth = $dbh->prepare($sql);
  164.     $sth->execute("\%$table\%");
  165.     my @sequence = map {$_->[0]} @{$sth->fetchall_arrayref};
  166.     $sth->finish();
  167.  
  168.     $class->sequence($sequence[0]) unless $#sequence;
  169.  
  170. }
  171.  
  172.      __PACKAGE__->set_sql('Nextval', <<'');
  173. SELECT %s.NEXTVAL from DUAL
  174.  
  175. 1;
  176.