From 62b2ec349b01a454420eaadd22caad929521a76e Mon Sep 17 00:00:00 2001 From: "mkanat%kerio.com" <> Date: Thu, 17 Feb 2005 02:11:06 +0000 Subject: Bug 237862: New database layer for cross-database compatibility Patch By Tomas Kopal r=mkanat, a=myk --- Bugzilla/DB/Mysql.pm | 162 ++++++++++++++++++++++++++++++++++++++++++++++ Bugzilla/DB/Pg.pm | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 342 insertions(+) create mode 100644 Bugzilla/DB/Mysql.pm create mode 100644 Bugzilla/DB/Pg.pm (limited to 'Bugzilla/DB') diff --git a/Bugzilla/DB/Mysql.pm b/Bugzilla/DB/Mysql.pm new file mode 100644 index 000000000..d2204433b --- /dev/null +++ b/Bugzilla/DB/Mysql.pm @@ -0,0 +1,162 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Netscape Communications +# Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): Dave Miller +# Gayathri Swaminath +# Jeroen Ruigrok van der Werven +# Dave Lawrence +# Tomas Kopal + +=head1 NAME + +Bugzilla::DB::Mysql - Bugzilla database compatibility layer for MySQL + +=head1 DESCRIPTION + +This module overrides methods of the Bugzilla::DB module with MySQL specific +implementation. It is instantiated by the Bugzilla::DB module and should never +be used directly. + +For interface details see L and L. + +=cut + +package Bugzilla::DB::Mysql; + +use strict; + +use Bugzilla::Error; +use Carp; + +# This module extends the DB interface via inheritance +use base qw(Bugzilla::DB); + +sub new { + my ($class, $user, $pass, $host, $dbname, $port, $sock) = @_; + + # construct the DSN from the parameters we got + my $dsn = "DBI:mysql:host=$host;database=$dbname;port=$port"; + $dsn .= ";mysql_socket=$sock" if $sock; + + my $self = $class->db_new($dsn, $user, $pass); + + # all class local variables stored in DBI derived class needs to have + # a prefix 'private_'. See DBI documentation. + $self->{private_bz_tables_locked} = 0; + + bless ($self, $class); + + return $self; +} + +# when last_insert_id() is supported on MySQL by lowest DBI/DBD version +# required by Bugzilla, this implementation can be removed. +sub bz_last_key { + my ($self) = @_; + + my ($last_insert_id) = $self->selectrow_array('SELECT LAST_INSERT_ID()'); + + return $last_insert_id; +} + +sub sql_regexp { + return "REGEXP"; +} + +sub sql_not_regexp { + return "NOT REGEXP"; +} + +sub sql_limit { + my ($self, $limit,$offset) = @_; + + if (defined($offset)) { + return "LIMIT $offset, $limit"; + } else { + return "LIMIT $limit"; + } +} + +sub sql_to_days { + my ($self, $date) = @_; + + return "TO_DAYS($date)"; +} + +sub sql_date_format { + my ($self, $date, $format) = @_; + + $format = "%Y.%m.%d %H:%i:%s" if !$format; + + return "DATE_FORMAT($date, " . $self->quote($format) . ")"; +} + +sub sql_interval { + my ($self, $interval) = @_; + + return "INTERVAL $interval"; +} + +sub bz_lock_tables { + my ($self, @tables) = @_; + + # Check first if there was no lock before + if ($self->{private_bz_tables_locked}) { + carp("Tables already locked"); + ThrowCodeError("already_locked"); + } else { + $self->do('LOCK TABLE ' . join(', ', @tables)); + + $self->{private_bz_tables_locked} = 1; + } +} + +sub bz_unlock_tables { + my ($self, $abort) = @_; + + # Check first if there was previous matching lock + if (!$self->{private_bz_tables_locked}) { + # Abort is allowed even without previous lock for error handling + return if $abort; + carp("No matching lock"); + ThrowCodeError("no_matching_lock"); + } else { + $self->do("UNLOCK TABLES"); + + $self->{private_bz_tables_locked} = 0; + } +} + +# As Bugzilla currently runs on MyISAM storage, which does not supprt +# transactions, these functions die when called. +# Maybe we should just ignore these calls for now, but as we are not +# using transactions in MySQL yet, this just hints the developers. +sub bz_start_transaction { + die("Attempt to start transaction on DB without transaction support"); +} + +sub bz_commit_transaction { + die("Attempt to commit transaction on DB without transaction support"); +} + +sub bz_rollback_transaction { + die("Attempt to rollback transaction on DB without transaction support"); +} + +1; diff --git a/Bugzilla/DB/Pg.pm b/Bugzilla/DB/Pg.pm new file mode 100644 index 000000000..a23c38666 --- /dev/null +++ b/Bugzilla/DB/Pg.pm @@ -0,0 +1,180 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Netscape Communications +# Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): Dave Miller +# Gayathri Swaminath +# Jeroen Ruigrok van der Werven +# Dave Lawrence +# Tomas Kopal + +=head1 NAME + +Bugzilla::DB::Pg - Bugzilla database compatibility layer for PostgreSQL + +=head1 DESCRIPTION + +This module overrides methods of the Bugzilla::DB module with PostgreSQL +specific implementation. It is instantiated by the Bugzilla::DB module +and should never be used directly. + +For interface details see L and L. + +=cut + +package Bugzilla::DB::Pg; + +use strict; + +use Bugzilla::Error; +use Carp; + +# This module extends the DB interface via inheritance +use base qw(Bugzilla::DB); + +sub new { + my ($class, $user, $pass, $host, $dbname, $port) = @_; + + # construct the DSN from the parameters we got + my $dsn = "DBI:Pg:host=$host;dbname=$dbname;port=$port"; + + my $self = $class->db_new($dsn, $user, $pass); + + # all class local variables stored in DBI derived class needs to have + # a prefix 'private_'. See DBI documentation. + $self->{private_bz_tables_locked} = 0; + + bless ($self, $class); + + return $self; +} + +# if last_insert_id is supported on PostgreSQL by lowest DBI/DBD version +# supported by Bugzilla, this implementation can be removed. +sub bz_last_key { + my ($self, $table, $column) = @_; + + my $seq = $table . "_" . $column . "_seq"; + my ($last_insert_id) = $self->selectrow_array("SELECT CURRVAL('$seq')"); + + return $last_insert_id; +} + +sub sql_regexp { + return "~"; +} + +sub sql_not_regexp { + return "!~" +} + +sub sql_limit { + my ($self, $limit,$offset) = @_; + + if (defined($offset)) { + return "LIMIT $limit OFFSET $offset"; + } else { + return "LIMIT $limit"; + } +} + +sub sql_to_days { + my ($self, $date) = @_; + + return "TO_CHAR($date, 'J')::int"; +} + +sub sql_date_format { + my ($self, $date, $format) = @_; + + $format = "%Y.%m.%d %H:%i:%s" if !$format; + + $format =~ s/\%Y/YYYY/g; + $format =~ s/\%y/YY/g; + $format =~ s/\%m/MM/g; + $format =~ s/\%d/DD/g; + $format =~ s/\%a/Dy/g; + $format =~ s/\%H/HH24/g; + $format =~ s/\%i/MI/g; + $format =~ s/\%s/SS/g; + + return "TO_CHAR($date, " . $self->quote($format) . ")"; +} + +sub sql_interval { + my ($self, $interval) = @_; + + return "INTERVAL '$interval'"; +} + +sub bz_lock_tables { + my ($self, @tables) = @_; + + # Check first if there was no lock before + if ($self->{private_bz_tables_locked}) { + carp("Tables already locked"); + ThrowCodeError("already_locked"); + } else { + my %read_tables; + my %write_tables; + foreach my $table (@tables) { + $table =~ /^([\d\w]+)([\s]+AS[\s]+[\d\w]+)?[\s]+(WRITE|READ)$/i; + my $table_name = $1; + if ($3 =~ /READ/i) { + if (!exists $read_tables{$table_name}) { + $read_tables{$table_name} = undef; + } + } + else { + if (!exists $write_tables{$table_name}) { + $write_tables{$table_name} = undef; + } + } + } + + # Begin Transaction + $self->bz_start_transaction(); + + Bugzilla->dbh->do('LOCK TABLE ' . join(', ', keys %read_tables) . + ' IN ROW SHARE MODE') if keys %read_tables; + Bugzilla->dbh->do('LOCK TABLE ' . join(', ', keys %write_tables) . + ' IN ROW EXCLUSIVE MODE') if keys %write_tables; + } +} + +sub bz_unlock_tables { + my ($self, $abort) = @_; + + # Check first if there was previous matching lock + if (!$self->{private_bz_tables_locked}) { + # Abort is allowed even without previous lock for error handling + return if $abort; + + carp("No matching lock"); + ThrowCodeError("no_matching_lock"); + } else { + # End transaction, tables will be unlocked automatically + if ($abort) { + $self->bz_rollback_transaction(); + } else { + $self->bz_commit_transaction(); + } + } +} + +1; -- cgit v1.2.3-24-g4f1b