root/trunk/t/lib/db-common.pl @ 164

Revision 164, 5.8 kB (checked in by miyagawa, 7 months ago)

PostgreSQL patch from clkao

  • Property svn:executable set to *
  • Property svn:keywords set to Id Revision
Line 
1# $Id$
2
3use strict;
4use File::Spec;
5use Carp qw(croak);
6
7sub run_tests {
8    my ($n, $code) = @_;
9
10    run_tests_mysql($n, $code);
11    run_tests_pgsql($n, $code);
12    run_tests_sqlite($n, $code);
13}
14
15sub run_tests_innodb {
16    my ($n, $code) = @_;
17    run_tests_mysql($n, $code, 1);
18}
19
20sub run_tests_mysql {
21    my ($n, $code, $innodb) = @_;
22  SKIP: {
23      local $ENV{USE_MYSQL} = 1;
24      local $ENV{TS_DB_USER} ||= 'root';
25      my $dbh = eval { mysql_dbh() };
26      skip "MySQL not accessible as root on localhost", $n if $@;
27      skip "InnoDB not available on localhost's MySQL", $n if $innodb && ! has_innodb($dbh);
28      $code->();
29  }
30}
31
32sub run_tests_pgsql {
33    my ($n, $code) = @_;
34  SKIP: {
35      local $ENV{USE_PGSQL} = 1;
36      local $ENV{TS_DB_USER} ||= 'postgres';
37      my $dbh = eval { pgsql_dbh() };
38      skip "PgSQL not accessible as root on localhost", $n if $@;
39      $code->();
40  }
41}
42
43sub run_tests_sqlite {
44    my ($n, $code) = @_;
45
46    # SQLite
47  SKIP: {
48      my $rv = eval "use DBD::SQLite; 1";
49      $rv = 0 if $ENV{SKIP_SQLITE};
50      skip "SQLite not installed", $n if !$rv;
51      $code->();
52  }
53}
54
55sub test_client {
56    my %opts = @_;
57    my $dbs     = delete $opts{dbs};
58    my $init    = delete $opts{init};
59    my $pfx     = delete $opts{dbprefix};
60    croak "'dbs' not an ARRAY" unless ref $dbs eq "ARRAY";
61    croak "unknown opts" if %opts;
62    $init = 1 unless defined $init;
63
64    if ($init) {
65        setup_dbs({ prefix => $pfx }, $dbs);
66    }
67
68    if ($ENV{USE_DBH_FOR_TEST}) {
69        my @tmp;
70        for (@$dbs) { eval {
71            my $dsn    = dsn_for($_); 
72            my $dbh    = DBI->connect( $dsn, "root", "", {
73                RaiseError => 1,
74                PrintError => 0,
75                AutoCommit => 1,
76            } ) or die $DBI::errstr;
77            my $driver =  Data::ObjectDriver::Driver::DBI->new( dbh => $dbh); 
78            push @tmp, { driver => $driver, prefix => $pfx };
79        } }
80        return TheSchwartz->new(databases => [@tmp]); 
81    } else {
82        return TheSchwartz->new(databases => [
83                                          map { {
84                                              dsn  => dsn_for($_),
85                                              user => $ENV{TS_DB_USER},
86                                              pass => $ENV{TS_DB_PASS},
87                                              prefix => $pfx,
88                                          } } @$dbs
89                                          ]);
90    }
91}
92
93sub has_innodb {
94    my $dbh = shift;
95    my $tmpname = "test_to_see_if_innoavail";
96    $dbh->do("CREATE TABLE IF NOT EXISTS $tmpname (i int) ENGINE=INNODB")
97        or return 0;
98    my @row = $dbh->selectrow_array("SHOW CREATE TABLE $tmpname");
99    my $row = join(' ', @row);
100    my $has_it = ($row =~ /=InnoDB/i);
101    $dbh->do("DROP TABLE $tmpname");
102    return $has_it;
103}
104
105sub schema_file {
106    return "doc/schema.sql" if $ENV{USE_MYSQL};
107    return "doc/schema-postgres.sql" if $ENV{USE_PGSQL};
108    return "t/schema-sqlite.sql";
109}
110
111sub db_filename {
112    my($dbname) = @_;
113    return $dbname . '.db';
114}
115
116sub mysql_dbname {
117    my($dbname) = @_;
118    return 't_sch_' . $dbname;
119}
120
121sub dsn_for {
122    my $dbname = shift;
123    if ($ENV{USE_MYSQL}) {
124        return 'dbi:mysql:' . mysql_dbname($dbname);
125    }
126    elsif ($ENV{USE_PGSQL}) {
127        return 'dbi:Pg:dbname=' . mysql_dbname($dbname);
128    } else {
129        return 'dbi:SQLite:dbname=' . db_filename($dbname);
130    }
131}
132
133sub setup_dbs {
134    shift if $_[0] =~ /\.sql$/;  # skip filenames (old)
135
136    my $opts = ref $_[0] eq "HASH" ? shift : {};
137    my $pfx = delete $opts->{prefix} || "";
138    die "unknown opts" if %$opts;
139
140    my(@dbs) = @_;
141    my $dbs = ref $dbs[0] ? $dbs[0] : \@dbs;  # support array or arrayref (old)
142
143    my $schema = schema_file();
144    teardown_dbs(@$dbs);
145    for my $dbname (@$dbs) {
146        if ($ENV{USE_MYSQL}) {
147            create_mysql_db(mysql_dbname($dbname));
148        }
149        elsif ($ENV{USE_PGSQL}) {
150            create_pgsql_db(mysql_dbname($dbname));
151        }
152        my $dbh = DBI->connect(dsn_for($dbname),
153            $ENV{TS_DB_USER}, $ENV{TS_DB_PASS}, { RaiseError => 1, PrintError => 0 })
154            or die "Couldn't connect: $!\n";
155        my @sql = load_sql($schema);
156        for my $sql (@sql) {
157            $sql =~ s!^\s*create\s+table\s+(\w+)!CREATE TABLE ${pfx}$1!mi;
158            $sql =~ s!^\s*(create.*?index)\s+(\w+)\s+on\s+(\w+)!$1 $2 ON ${pfx}$3!i;
159            $sql .= " ENGINE=INNODB\n" if $ENV{USE_MYSQL};
160            $dbh->do($sql);
161        }
162        $dbh->disconnect;
163    }
164}
165
166sub mysql_dbh {
167    return DBI->connect("DBI:mysql:mysql", "root", "", { RaiseError => 1 })
168        or die "Couldn't connect to database";
169}
170
171my $pg_dbh;
172
173sub pgsql_dbh {
174    return $pg_dbh if $pg_dbh;
175    $pg_dbh ||=
176        DBI->connect("DBI:Pg:dbname=postgres", "postgres", "", { RaiseError => 1 })
177            or die "Couldn't connect to database";
178}
179
180sub create_mysql_db {
181    my $dbname = shift;
182    mysql_dbh()->do("CREATE DATABASE $dbname");
183}
184
185sub drop_mysql_db {
186    my $dbname = shift;
187    mysql_dbh()->do("DROP DATABASE IF EXISTS $dbname");
188}
189
190sub create_pgsql_db {
191    my $dbname = shift;
192    pgsql_dbh()->do("CREATE DATABASE $dbname");
193}
194
195sub drop_pgsql_db {
196    my $dbname = shift;
197    undef $pg_dbh;
198    eval { pgsql_dbh()->do("DROP DATABASE IF EXISTS $dbname") };
199}
200
201sub teardown_dbs {
202    my(@dbs) = @_;
203    for my $db (@dbs) {
204        if ($ENV{USE_MYSQL}) {
205            drop_mysql_db(mysql_dbname($db));
206        } elsif ($ENV{USE_PGSQL}) {
207            drop_pgsql_db(mysql_dbname($db));
208        } else {
209            my $file = db_filename($db);
210            next unless -e $file;
211            unlink $file or die "Can't teardown $db: $!";
212        }
213    }
214}
215
216sub load_sql {
217    my($file) = @_;
218    open my $fh, $file or die "Can't open $file: $!";
219    my $sql = do { local $/; <$fh> };
220    close $fh;
221    split /;\s*/, $sql;
222}
223
2241;
Note: See TracBrowser for help on using the browser.