Rev 1295 | Blame | Compare with Previous | Last modification | View Log | RSS feed
################################################################################ Codestriker: Copyright (c) 2001, 2002 David Sitsky. All rights reserved.# sits@users.sourceforge.net## This program is free software; you can redistribute it and modify it under# the terms of the GPL.package Codestriker::DB::Oracle;use strict;use DBI;use Codestriker;use Codestriker::DB::Database;# Module for handling an Oracle database.@Codestriker::DB::Oracle::ISA = ("Codestriker::DB::Database");# Type mappings.my $_TYPE = {$Codestriker::DB::Column::TYPE->{TEXT} => "clob",$Codestriker::DB::Column::TYPE->{VARCHAR} => "varchar2",$Codestriker::DB::Column::TYPE->{INT32} => "number(10)",$Codestriker::DB::Column::TYPE->{INT16} => "number(4)",$Codestriker::DB::Column::TYPE->{DATETIME} => "date",$Codestriker::DB::Column::TYPE->{FLOAT} => "float"};# Create a new Oracle database object.sub new {my $type = shift;# Database is parent class.my $self = Codestriker::DB::Database->new();$self->{sequence_created} = 0;return bless $self, $type;}# Return the DBD module this is dependent on.sub get_module_dependencies {return { name => 'DBD::Oracle', version => '0' };}# Retrieve a database connection.sub get_connection {my $self = shift;# Oracle support transactions, don't enable auto_commit.my $dbh = $self->_get_connection(0, 1);# Make sure the default date type is set to something used consistently# in Codestriker.$dbh->do("ALTER session SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'");return $dbh;}# Method for retrieving the list of current tables attached to the database.# For oracle, $dbh->tables doesn't work, need to retrieve data from the# user_tables table.sub get_tables() {my $self = shift;my @tables = ();my $table_select =$self->{dbh}->prepare_cached("SELECT table_name FROM user_tables");$table_select->execute();while (my ($table_name) = $table_select->fetchrow_array()) {push @tables, $table_name;}$table_select->finish();return @tables;}# Return the mapping for a specific type.sub _map_type {my ($self, $type) = @_;return $_TYPE->{$type};}# Oracle implements autoincrements with triggers.sub _get_autoincrement_type {return "";}# Create the table in the database for the specified table, and with the# provided type mappings.sub create_table {my ($self, $table) = @_;# Let the base class actually do the work in creating the table.$self->SUPER::create_table($table);# Create the necessary triggers for any autoincrement fields.foreach my $column (@{$table->get_columns()}) {if ($column->is_autoincrement()) {print "Creating autoincrement trigger for table: " .$table->get_name() . " field: " . $column->get_name() . "\n";$self->_oracle_handle_auto_increment($table->get_name(),$column->get_name());}}}# Oracle-specific routine for creating a trigger on a new row insert to# automatically assign a value to the specified fieldname from a sequence.# This is used since Oracle doesn't support auto-increment or default values# for fields.sub _oracle_handle_auto_increment{my ($self, $tablename, $fieldname) = @_;my $dbh = $self->{dbh};# Make sure the sequence is present in the database for the trigger to# work.eval {if ($self->{sequence_created} == 0) {$dbh->do("CREATE SEQUENCE sequence");print "Created sequence\n";$self->{sequence_created} = 1;}# Now create the actual trigger on the table.$dbh->do("CREATE TRIGGER ${tablename}_${fieldname}_ins_row " ."BEFORE INSERT ON ${tablename} FOR EACH ROW " ."DECLARE newid integer; " ."BEGIN " ."IF (:NEW.${fieldname} IS NULL) " ."THEN " ."SELECT sequence.NextVal INTO newid FROM DUAL; " .":NEW.${fieldname} := newid; " ."END IF; " ."END;");print "Created trigger\n";$dbh->commit();};if ($@) {eval { $self->rollback() };die "Unable to create sequence/trigger.\n";}}# Add a field to a specific table. If the field already exists, then catch# the error and continue silently. The SYNTAX for SQL Server is slightly# different to standard SQL, there is no "COLUMN" keyword after "ADD".sub add_field {my ($self, $table, $field, $definition) = @_;my $dbh = $self->{dbh};my $rc = 0;eval {$dbh->{PrintError} = 0;my $field_type = $self->_map_type($definition);$dbh->do("ALTER TABLE $table ADD $field $field_type");print "Added new field $field to table $table.\n";$rc = 1;$self->commit();};if ($@) {eval { $self->rollback() };}$dbh->{PrintError} = 1;return $rc;}# Indicate if the LIKE operator can be applied on a "text" field.# For Oracle, this is false.sub has_like_operator_for_text_field {my $self = shift;return 0;}# Function for generating an SQL subexpression for a case insensitive LIKE# operation.sub case_insensitive_like {my ($self, $field, $expression) = @_;# Convert the field and expression to lower case to get case insensitivity.my $field_lower = "lower($field)";my $expression_lower = $expression;$expression_lower =~ tr/[A-Z]/[a-z]/;$expression_lower = $self->{dbh}->quote($expression_lower);return "$field_lower LIKE $expression_lower";}1;