From 5b9b183a71de9b9e30368073347c74f148110b9e Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Wed, 26 Aug 2015 11:10:48 -0400 Subject: [PATCH] Support for Firebird as a target database. Still a little rough around the edges, but should mostly work for simple cases. --- Bucardo.pm | 45 +++++- MANIFEST | 1 + bucardo | 7 + bucardo.schema | 18 ++- t/20-firebird.t | 380 ++++++++++++++++++++++++++++++++++++++++++++ t/20-mysql.t | 8 +- t/BucardoTesting.pm | 17 +- 7 files changed, 465 insertions(+), 11 deletions(-) create mode 100644 t/20-firebird.t diff --git a/Bucardo.pm b/Bucardo.pm index 4fe64e495..f368076a7 100644 --- a/Bucardo.pm +++ b/Bucardo.pm @@ -2465,7 +2465,7 @@ sub start_kid { ## Also setup common attributes my (@dbs, @dbs_source, @dbs_target, @dbs_delta, @dbs_fullcopy, @dbs_connectable, @dbs_dbi, @dbs_write, @dbs_non_fullcopy, - @dbs_postgres, @dbs_drizzle, @dbs_mongo, @dbs_mysql, @dbs_oracle, + @dbs_postgres, @dbs_drizzle, @dbs_firebird, @dbs_mongo, @dbs_mysql, @dbs_oracle, @dbs_redis, @dbs_sqlite); ## Used to weed out all but one source if in onetimecopy mode @@ -2572,6 +2572,16 @@ sub start_kid { $d->{has_mysql_timestamp_issue} = 1; } + ## Firebird + if ('firebird' eq $d->{dbtype}) { + push @dbs_firebird => $dbname; + $d->{does_sql} = 1; + $d->{does_truncate} = 1; + $d->{does_savepoints} = 1; + $d->{does_limit} = 1; + $d->{has_mysql_timestamp_issue} = 1; + } + ## Oracle if ('oracle' eq $d->{dbtype}) { push @dbs_oracle => $dbname; @@ -2639,6 +2649,7 @@ sub start_kid { ## Databases with Perl DBI support if ($d->{dbtype} eq 'postgres' or $d->{dbtype} eq 'drizzle' + or $d->{dbtype} eq 'firebird' or $d->{dbtype} eq 'mariadb' or $d->{dbtype} eq 'mysql' or $d->{dbtype} eq 'oracle' @@ -5663,6 +5674,9 @@ sub connect_database { return $backend, $dbh; } + elsif ('firebird' eq $dbtype) { + $dsn = "dbi:Firebird:db=$dbname"; + } elsif ('mysql' eq $dbtype or 'mariadb' eq $dbtype) { $dsn = "dbi:mysql:database=$dbname"; } @@ -9217,6 +9231,12 @@ sub delete_rows { ## The actual target table name: may differ from the source! my $tname = $newname->{$t->{name}}; + if ('firebird' eq $type) { + $goat->{pklist} =~ s/\"//g; ## not ideal: fix someday + $goat->{pklist} = uc $goat->{pklist}; + $tname = qq{"$tname"} if $tname !~ /"/; + } + ## Internal counters to help us break queries into chunks if needed my ($round, $roundtotal) = (0,0); @@ -9385,6 +9405,12 @@ sub delete_rows { ## The actual target name my $tname = $newname->{$t->{name}}; + $self->glog("Deleting from target $tname (type=$type)", LOG_DEBUG); + + if ('firebird' eq $type) { + $tname = qq{"$tname"} if $tname !~ /"/; + } + if ('mongo' eq $type) { ## Grab the collection name and store it @@ -9499,7 +9525,7 @@ sub delete_rows { $self->glog("Mongo objects removed from $tname: $t->{deleted_rows}", LOG_VERBOSE); } elsif ('mysql' eq $type or 'drizzle' eq $type or 'mariadb' eq $type - or 'oracle' eq $type or 'sqlite' eq $type) { + or 'oracle' eq $type or 'sqlite' eq $type or 'firebird' eq $type) { my $tdbh = $t->{dbh}; for (@{ $SQL{IN}{$tname} }) { $t->{deleted_rows} += $tdbh->do($_); @@ -9713,6 +9739,14 @@ sub push_rows { $tgtcmd =~ s/,$/)/o; $target->{sth} = $target->{dbh}->prepare($tgtcmd); } + elsif ('firebird' eq $type) { + $columnlist =~ s/\"//g; + $target_tablename = qq{"$target_tablename"} if $target_tablename !~ /"/; + my $tgtcmd = "INSERT INTO $target_tablename$columnlist VALUES ("; + $tgtcmd .= '?,' x @$cols; + $tgtcmd =~ s/,$/)/o; + $target->{sth} = $target->{dbh}->prepare($tgtcmd); + } elsif ('oracle' eq $type) { my $tgtcmd = "INSERT INTO $target_tablename$columnlist VALUES ("; $tgtcmd .= '?,' x @$cols; @@ -9836,15 +9870,16 @@ sub push_rows { } } elsif ($Table->{columnhash}{$key}{ftype} =~ /real|double|numeric/o) { - $object->{$key} = strtod($object->{$key}); + $object->{$key} = strtod($object->{$key}); } } $self->{collection}->insert($object, { safe => 1 }); } - ## For MySQL, MariaDB, Drizzle, Oracle, and SQLite, do some basic INSERTs + ## For MySQL, MariaDB, Firebird, Drizzle, Oracle, and SQLite, do some basic INSERTs elsif ('mysql' eq $type or 'mariadb' eq $type or 'drizzle' eq $type + or 'firebird' eq $type or 'oracle' eq $type or 'sqlite' eq $type) { chomp $buffer; @@ -9974,7 +10009,7 @@ sub push_rows { $self->glog(qq{Rows copied to Redis $target->{name}.$tname:: $total_source_rows}, LOG_VERBOSE); } else { - ## Nothing to be done for mongo, mysql, mariadb, sqlite, oracle + ## Nothing to be done for mongo, mysql, mariadb, sqlite, oracle, firebird } } diff --git a/MANIFEST b/MANIFEST index 5c07c13ce..6b24a4508 100644 --- a/MANIFEST +++ b/MANIFEST @@ -36,6 +36,7 @@ t/02-bctl-table.t t/10-fullcopy.t t/10-object-names.t t/20-drizzle.t +t/20-firebird.t t/10-makedelta.t t/20-mariadb.t t/20-mongo.t diff --git a/bucardo b/bucardo index d53b3116e..3de8c4347 100755 --- a/bucardo +++ b/bucardo @@ -1863,6 +1863,7 @@ sub add_database { ## This also makes sure we have a valid type my %dbtypeinfo = ( drizzle => ['DBD::drizzle', 'Drizzle database'], + firebird => ['DBD::Firebird', 'Firebird database'], mongo => ['MongoDB', 'MongoDB'], mysql => ['DBD::mysql', 'MySQL database'], mariadb => ['DBD::mysql', 'MariaDB database'], @@ -2451,6 +2452,11 @@ sub list_databases { $showhost, $showport; } + if ($dbtype eq 'firebird') { + printf 'Conn: isql-fb -u %s %s', + $info->{dbuser}, + $info->{dbname}; + } if ($dbtype eq 'oracle') { printf 'Conn: sqlplus %s%s', $info->{dbuser}, @@ -9780,6 +9786,7 @@ sub standardize_rdbms_name { $name =~ s/postgres.*/postgres/io; $name =~ s/pg.*/postgres/io; $name =~ s/driz?zle.*/drizzle/io; + $name =~ s/firebird/firebird/io; $name =~ s/mongo.*/mongo/io; $name =~ s/mysql.*/mysql/io; $name =~ s/maria.*/mariadb/io; diff --git a/bucardo.schema b/bucardo.schema index 5b12bc957..6e7567ac6 100644 --- a/bucardo.schema +++ b/bucardo.schema @@ -678,6 +678,7 @@ AS $bc$ ## Given the name of a db, return the type, plus type-specific connection information ## Postgres: a connection string, username, password, and attribs ## Drizzle: a connection string, username, and password +## Firebird: a connection string, username, and password ## Mongo: "foo: bar" style connection information, one per line ## MariaDB: a connection string, username, and password ## MySQL: a connection string, username, and password @@ -793,6 +794,21 @@ if ($dbtype eq 'mysql' or $dbtype eq 'mariadb') { } ## end mysql/mariadb +if ($dbtype eq 'firebird') { + + length $db{name} or elog(ERROR, qq{Database name is mandatory\n}); + length $db{user} or elog(ERROR, qq{Database username is mandatory\n}); + + my $connstring = "dbi:Firebird:db=$db{name}"; + $db{host} ||= ''; $db{port} ||= ''; $db{pass} ||= ''; + length $db{host} and $connstring .= ";host=$db{host}"; + length $db{port} and $connstring .= ";port=$db{port}"; + length $db{conn} and $connstring .= ";$db{conn}"; + + return "$dbtype\n$connstring\n$db{user}\n$db{pass}"; + +} ## end firebird + if ($dbtype eq 'oracle') { ## We should loosen this up somewhere @@ -1302,7 +1318,7 @@ for my $dbname (sort { ($db{$b}{role} eq 'source') <=> ($db{$a}{role} eq 'source next if $db{$dbname}{dbtype} =~ /flat/; ## Skip if this is a non-supported database - next if $db{$dbname}{dbtype} =~ /drizzle|mariadb|mongo|mysql|oracle|redis|sqlite/; + next if $db{$dbname}{dbtype} =~ /drizzle|mariadb|mongo|mysql|oracle|redis|sqlite|firebird/; ## Figure out how to connect to this database my $rv = spi_exec_query("SELECT bucardo.db_getconn('$dbname') AS conn"); diff --git a/t/20-firebird.t b/t/20-firebird.t new file mode 100644 index 000000000..83f809951 --- /dev/null +++ b/t/20-firebird.t @@ -0,0 +1,380 @@ +#!/usr/bin/env perl +# -*-mode:cperl; indent-tabs-mode: nil-*- + +## Test using Firebird as a database target + +use 5.008003; +use strict; +use warnings; +use Data::Dumper; +use lib 't','.'; +use DBD::Pg; +use Test::More; +use MIME::Base64; + +use vars qw/ $bct $dbhX $dbhA $dbhB $dbhC $dbhD $res $command $t %pkey $SQL %sth %sql/; + +## Must have the DBD::firebird module +my $evalok = 0; +eval { + require DBD::Firebird; + $evalok = 1; +}; +if (!$evalok) { + plan (skip_all => 'Cannot test Firebird unless the Perl module DBD::Firebird is installed'); +} + +## Firebird must be up and running +$evalok = 0; +my $dbh; +my $dbuser = 'testuser'; +my $dbpass = 'foo'; +my $dbname = '/tmp/test'; +eval { + $dbh = DBI->connect("dbi:Firebird:database=$dbname", $dbuser, $dbpass, + {AutoCommit=>1, PrintError=>0, RaiseError=>1}); + $evalok = 1; +}; +if (!$evalok) { + plan (skip_all => "Cannot test Firebird as we cannot connect to a running Firebird database: $@"); +} + +use BucardoTesting; + +## For now, remove a few test tables +for my $x (2,5,6,8,9,10) { + delete $tabletypefirebird{"bucardo_test$x"}; +} + +my $numtabletypes = keys %tabletypefirebird; +plan tests => 151; + +## Drop the test database if it exists +$dbname = q{/tmp/bucardo_test}; + +eval { + $dbh->do("DROP DATABASE $dbname"); +}; +## Create the test database +#$dbh->do("CREATE DATABASE $dbname"); + +## Reconnect to the new database +$dbh = DBI->connect("dbi:Firebird:database=$dbname", $dbuser, $dbpass, + {AutoCommit=>1, PrintError=>0, RaiseError=>1}); + +## Create one table for each table type +for my $table (sort keys %tabletypefirebird) { + + my $pkeyname = $table =~ /test5/ ? q{"id space"} : 'id'; + my $pkindex = $table =~ /test2/ ? '' : 'PRIMARY KEY'; + $SQL = qq{ + CREATE TABLE "$table" ( + $pkeyname $tabletypefirebird{$table} NOT NULL $pkindex}; + $SQL .= $table =~ /X/ ? "\n)" : qq{, + data1 VARCHAR(100) NOT NULL , + inty SMALLINT , + booly SMALLINT, + bite1 VARCHAR(100) , + bite2 VARCHAR(100) , + email VARCHAR(100) UNIQUE + ) + }; + + eval { $dbh->do(qq{DROP TABLE "$table"});}; + eval { $dbh->do($SQL);}; + + diag "Created $table"; + if ($table =~ /test2/) { + $dbh->do(qq{ALTER TABLE "$table" ADD CONSTRAINT multipk PRIMARY KEY ($pkeyname,data1)}); + } + +} + +$bct = BucardoTesting->new() or BAIL_OUT "Creation of BucardoTesting object failed\n"; +$location = 'firebird'; + +pass("*** Beginning Firebird tests"); + +END { + $bct and $bct->stop_bucardo($dbhX); + $dbhX and $dbhX->disconnect(); + $dbhA and $dbhA->disconnect(); + $dbhB and $dbhB->disconnect(); + $dbhC and $dbhC->disconnect(); + $dbhD and $dbhD->disconnect(); +} + +## Get Postgres database A and B and C created +$dbhA = $bct->repopulate_cluster('A'); +$dbhB = $bct->repopulate_cluster('B'); +$dbhC = $bct->repopulate_cluster('C'); + +## Create a bucardo database, and install Bucardo into it +$dbhX = $bct->setup_bucardo('A'); + +## Tell Bucardo about these databases + +## Three Postgres databases will be source, source, and target +for my $name (qw/ A B C /) { + $t = "Adding database from cluster $name works"; + my ($dbuser,$dbport,$dbhost) = $bct->add_db_args($name); + $command = "bucardo add db $name dbname=bucardo_test user=$dbuser port=$dbport host=$dbhost"; + $res = $bct->ctl($command); + like ($res, qr/Added database "$name"/, $t); +} + +$t = 'Adding firebird database Q works'; +$command = +"bucardo add db Q dbname=$dbname type=firebird dbuser=$dbuser password=$dbpass"; +$res = $bct->ctl($command); +like ($res, qr/Added database "Q"/, $t); + +## Teach Bucardo about all pushable tables, adding them to a new relgroup named "therd" +$t = q{Adding all tables on the master works}; +$command = +"bucardo add tables all db=A relgroup=therd pkonly"; +$res = $bct->ctl($command); +like ($res, qr/Creating relgroup: therd.*New tables added: \d/s, $t); + +## Add all sequences, and add them to the newly created relgroup +$t = q{Adding all sequences on the master works}; +$command = +"bucardo add sequences all db=A relgroup=therd"; +$res = $bct->ctl($command); +like ($res, qr/New sequences added: \d/, $t); + +## Create a new dbgroup +$t = q{Created a new dbgroup}; +$command = +"bucardo add dbgroup qx A:source B:source C Q"; +$res = $bct->ctl($command); +like ($res, qr/Created dbgroup "qx"/, $t); + +## Create a new sync +$t = q{Created a new sync}; +$command = +"bucardo add sync firebird relgroup=therd dbs=qx autokick=false"; +$res = $bct->ctl($command); +like ($res, qr/Added sync "firebird"/, $t); + +## Create a second sync, solely for multi-sync interaction issues +$bct->ctl('bucardo add dbgroup t1 A:source B C'); +$bct->ctl('bucardo add sync tsync1 relgroup=therd dbs=t1 autokick=false status=inactive'); + +## Start up Bucardo with these new syncs +$bct->restart_bucardo($dbhX); + +## Boolean values +my (@boolys) = qw( xxx true false null false true null ); + +## Get the statement handles ready for each table type +for my $table (sort keys %tabletypefirebird) { + + $pkey{$table} = $table =~ /test5/ ? q{"id space"} : 'id'; + + ## INSERT + for my $x (1..6) { + $SQL = $table =~ /X/ + ? qq{INSERT INTO "$table"($pkey{$table}) VALUES (?)} + : qq{INSERT INTO "$table"($pkey{$table},data1,inty,booly) VALUES (?,'foo',$x,$boolys[$x])}; + $sth{insert}{$x}{$table}{A} = $dbhA->prepare($SQL); + if ('BYTEA' eq $tabletypefirebird{$table}) { + $sth{insert}{$x}{$table}{A}->bind_param(1, undef, {pg_type => PG_BYTEA}); + } + } + + ## SELECT + $sql{select}{$table} = qq{SELECT inty, booly FROM "$table" ORDER BY $pkey{$table}}; + $table =~ /X/ and $sql{select}{$table} =~ s/inty/$pkey{$table}/; + + ## DELETE ALL + $SQL = qq{DELETE FROM "$table"}; + $sth{deleteall}{$table}{A} = $dbhA->prepare($SQL); + + ## DELETE ONE + $SQL = qq{DELETE FROM "$table" WHERE inty = ?}; + $sth{deleteone}{$table}{A} = $dbhA->prepare($SQL); + + ## TRUNCATE + $SQL = qq{TRUNCATE TABLE "$table"}; + $sth{truncate}{$table}{A} = $dbhA->prepare($SQL); + ## UPDATE + $SQL = qq{UPDATE "$table" SET inty = ?}; + $sth{update}{$table}{A} = $dbhA->prepare($SQL); +} + +## Add one row per table type to A +for my $table (keys %tabletypefirebird) { + my $type = $tabletypefirebird{$table}; + my $val1 = $val{$type}{1}; + $sth{insert}{1}{$table}{A}->execute($val1); +} + +## Before the commit on A, B, C, and Q should be empty +for my $table (sort keys %tabletypefirebird) { + my $type = $tabletypefirebird{$table}; + $t = qq{B has not received rows for table $table before A commits}; + $res = []; + bc_deeply($res, $dbhB, $sql{select}{$table}, $t); + bc_deeply($res, $dbhC, $sql{select}{$table}, $t); + bc_deeply($res, $dbh, $sql{select}{$table}, $t); +} + +## Commit, then kick off the sync +$dbhA->commit(); +$bct->ctl('bucardo kick firebird 0'); +$bct->ctl('bucardo kick firebird 0'); + +## Check B and C for the new rows +for my $table (sort keys %tabletypefirebird) { + + my $type = $tabletypefirebird{$table}; + $t = qq{Row with pkey of type $type gets copied to B}; + + $res = [[1,1]]; + bc_deeply($res, $dbhB, $sql{select}{$table}, $t); + bc_deeply($res, $dbhC, $sql{select}{$table}, $t); +} + +## Check that Firebird has the new rows +for my $table (sort keys %tabletypefirebird) { + $t = "Firebird table $table has correct number of rows after insert"; + $SQL = qq{SELECT * FROM "$table"}; + my $sth = $dbh->prepare($SQL); + my $count = $sth->execute(); + is ($count, 1, $t); + + $t = "Firebird table $table has correct entries"; + my $info = $sth->fetchall_arrayref({})->[0]; + my $type = $tabletypefirebird{$table}; + my $id = $val{$type}{1}; + my $pkeyname = $table =~ /test5/ ? 'id space' : 'id'; + + ## For now, binary is stored in escaped form, so we skip this one + next if $table =~ /test8/; + + ## Datetime has no time zone thingy at the end + $tabletypefirebird{$table} =~ /DATETIME/ and $id =~ s/\+.*//; + + is_deeply( + $info, + { + $pkeyname => $id, + inty => 1, + booly => 1, + email => undef, + bite1 => undef, + bite2 => undef, + data1 => 'foo', + }, + + $t); +} + +## Update each row +for my $table (keys %tabletypefirebird) { + $sth{update}{$table}{A}->execute(42); +} +$dbhA->commit(); +$bct->ctl('bucardo kick firebird 0'); + +for my $table (keys %tabletypefirebird) { + $t = "Firebird table $table has correct number of rows after update"; + $SQL = qq{SELECT * FROM "$table"}; + my $sth = $dbh->prepare($SQL); + my $count = $sth->execute(); + is ($count, 1, $t); + + $t = "Firebird table $table has updated value"; + my $info = $sth->fetchall_arrayref({})->[0]; + is ($info->{inty}, 42, $t); +} + +## Delete each row +for my $table (keys %tabletypefirebird) { + $sth{deleteall}{$table}{A}->execute(); +} +$dbhA->commit(); +$bct->ctl('bucardo kick firebird 0'); + +for my $table (keys %tabletypefirebird) { + $t = "Firebird table $table has correct number of rows after delete"; + $SQL = qq{SELECT * FROM "$table"}; + my $sth = $dbh->prepare($SQL); + (my $count = $sth->execute()) =~ s/0E0/0/; + $sth->finish(); + is ($count, 0, $t); +} + +## Insert two rows, then delete one of them +## Add one row per table type to A +for my $table (keys %tabletypefirebird) { + my $type = $tabletypefirebird{$table}; + my $val1 = $val{$type}{1}; + $sth{insert}{1}{$table}{A}->execute($val1); + my $val2 = $val{$type}{2}; + $sth{insert}{2}{$table}{A}->execute($val2); +} +$dbhA->commit(); +$bct->ctl('bucardo kick firebird 0'); + +for my $table (keys %tabletypefirebird) { + $t = "Firebird table $table has correct number of rows after double insert"; + $SQL = qq{SELECT * FROM "$table"}; + my $sth = $dbh->prepare($SQL); + my $count = $sth->execute(); + $sth->finish(); + is ($count, 2, $t); +} + +## Delete one of the rows +for my $table (keys %tabletypefirebird) { + $sth{deleteone}{$table}{A}->execute(2); ## inty = 2 +} +$dbhA->commit(); +$bct->ctl('bucardo kick firebird 0'); + +for my $table (keys %tabletypefirebird) { + $t = "Firebird table $table has correct number of rows after single deletion"; + $SQL = qq{SELECT * FROM "$table"}; + my $sth = $dbh->prepare($SQL); + my $count = $sth->execute(); + $sth->finish(); + is ($count, 1, $t); +} + +## Insert two more rows +for my $table (keys %tabletypefirebird) { + my $type = $tabletypefirebird{$table}; + my $val3 = $val{$type}{3}; + $sth{insert}{3}{$table}{A}->execute($val3); + my $val4 = $val{$type}{4}; + $sth{insert}{4}{$table}{A}->execute($val4); +} +$dbhA->commit(); +$bct->ctl('bucardo kick firebird 0'); + +for my $table (keys %tabletypefirebird) { + $t = "Firebird table $table has correct number of rows after more inserts"; + $SQL = qq{SELECT * FROM "$table"}; + my $sth = $dbh->prepare($SQL); + my $count = $sth->execute(); + is ($count, 3, $t); + + $t = "Firebird table $table has updated values"; + my $info = $sth->fetchall_arrayref({}); + $info = [ sort { $a->{inty} <=> $b->{inty} } @$info ]; + my ($val1, $val3, $val4) = @{$val{$tabletypefirebird{$table}}}{1, 3, 4}; + + my $pkeyname = $table =~ /test5/ ? 'id space' : 'id'; + my(@invar) = ( data1 => 'foo', 'email' => undef, bite1 => undef, bite2 => undef ); + is_deeply ($info, [{ $pkeyname=>$val1, inty=>1, booly=>1, @invar }, + { $pkeyname=>$val3, inty=>3, booly=>undef, @invar }, + { $pkeyname=>$val4, inty=>4, booly=>0, @invar }], $t) || diag explain $info; + + $sth->finish(); + +} + + +exit; diff --git a/t/20-mysql.t b/t/20-mysql.t index 4ee62cc88..88aff7b10 100644 --- a/t/20-mysql.t +++ b/t/20-mysql.t @@ -29,18 +29,18 @@ $evalok = 0; my $dbh; my $dbuser = 'root'; eval { - $dbh = DBI->connect('dbi:mysql:database=test', $dbuser, '', + $dbh = DBI->connect('dbi:mysql:database=test', $dbuser, 'fred', {AutoCommit=>1, PrintError=>0, RaiseError=>1}); $evalok = 1; }; if (!$evalok) { - plan (skip_all => "Cannot test MySQL as we cannot connect to a running MySQL database"); + plan (skip_all => "Cannot test MySQL as we cannot connect to a running MySQL database: $@"); } ## Need to ensure this is really MySQL, not MariaDB my $ver = $dbh->selectall_arrayref('SELECT version()')->[0][0]; if ($ver =~ /MariaDB/) { - plan (skip_all => "Cannot test MySQL: MySQL port is being used by MariaDB"); +# plan (skip_all => "Cannot test MySQL: MySQL port is being used by MariaDB"); } use BucardoTesting; @@ -61,7 +61,7 @@ eval { $dbh->do("CREATE DATABASE $dbname"); ## Reconnect to the new database -$dbh = DBI->connect("dbi:mysql:database=$dbname", $dbuser, '', +$dbh = DBI->connect("dbi:mysql:database=$dbname", $dbuser, 'fred', {AutoCommit=>1, PrintError=>0, RaiseError=>1}); ## Yes, this must be turned on manually! diff --git a/t/BucardoTesting.pm b/t/BucardoTesting.pm index ed81623e0..cc43902fc 100644 --- a/t/BucardoTesting.pm +++ b/t/BucardoTesting.pm @@ -25,7 +25,7 @@ my $DEBUG = $ENV{BUCARDO_DEBUG} || 0; $ENV{BUCARDO_CONFIRM} = 0 if exists $ENV{BUCARDO_CONFIRM}; use base 'Exporter'; -our @EXPORT = qw/%tabletype %tabletypemysql %tabletypemariadb %tabletypeoracle %tabletypesqlite +our @EXPORT = qw/%tabletype %tabletypemysql %tabletypemariadb %tabletypeoracle %tabletypesqlite %tabletypefirebird %sequences %val compare_tables bc_deeply clear_notices wait_for_notice $location $oldherd_msg $newherd_msg $addtable_msg $deltable_msg $nomatch_msg/; @@ -120,6 +120,21 @@ our %tabletypemariadb = 'bucardo space test' => 'INT', ); +our %tabletypefirebird = + ( + 'bucardo_test1' => 'SMALLINT', + 'bucardo_test2' => 'INT', + 'Bucardo_test3' => 'BIGINT', + 'bucardo_test4' => 'VARCHAR(700)', + 'bucardo_test5' => 'DATE', + 'bucardo_test6' => 'DATETIME', + 'bucardo_test7' => 'NUMERIC(5,1)', + 'bucardo_test8' => 'VARBINARY(1000)', + 'bucardo_test9' => 'INTEGER UNSIGNED', + 'bucardo_test10' => 'TIMESTAMP', + 'bucardo space test' => 'INT', + ); + our %tabletypeoracle = ( 'bucardo_test1' => 'SMALLINT', -- 2.39.5