home *** CD-ROM | disk | FTP | other *** search
/ PC World 2002 July & August / PCWorld_2002-07-08_cd.bin / Komunik / MySQL / mysql / data1.cab / Development / bench / server-cfg < prev    next >
Text File  |  2002-02-21  |  97KB  |  3,367 lines

  1. #!/usr/bin/perl
  2. # Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  3. #
  4. # This library is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU Library General Public
  6. # License as published by the Free Software Foundation; either
  7. # version 2 of the License, or (at your option) any later version.
  8. #
  9. # This library is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. # Library General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU Library General Public
  15. # License along with this library; if not, write to the Free
  16. # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  17. # MA 02111-1307, USA
  18. #
  19. # The configuration file for the DBI/DBD tests on different databases ....
  20. # You will need the DBD module for the database you are running.
  21. # Monty made this bench script and I (Luuk de Boer) rewrote it to DBI/DBD.
  22. # Monty rewrote this again to use packages.
  23. #
  24. # Each database has a different package that has 3 functions:
  25. # new        Creates a object with some standard slot
  26. # version    Version number of the server
  27. # create    Generates commands to create a table
  28. #
  29.  
  30. #
  31. # First some global functions that help use the packages:
  32. #
  33.  
  34. sub get_server
  35. {
  36.   my ($name,$host,$database,$odbc,$machine)=@_;
  37.   my ($server);
  38.   if ($name =~ /mysql/i)
  39.   { $server=new db_MySQL($host, $database, $machine); }
  40.   elsif ($name =~ /pg/i)
  41.   { $server= new db_Pg($host,$database); }
  42.   elsif ($name =~ /msql/i)
  43.   { $server= new db_mSQL($host,$database); }
  44.   elsif ($name =~ /solid/i)
  45.   { $server= new db_Solid($host,$database); }
  46.   elsif ($name =~ /Empress/i)
  47.   { $server= new db_Empress($host,$database); }
  48.   elsif ($name =~ /FrontBase/i)
  49.   { $server= new db_FrontBase($host,$database); }
  50.   elsif ($name =~ /Oracle/i)
  51.   { $server= new db_Oracle($host,$database); }
  52.   elsif ($name =~ /Access/i)
  53.   { $server= new db_access($host,$database); }
  54.   elsif ($name =~ /Informix/i)
  55.   { $server= new db_Informix($host,$database); }
  56.   elsif ($name =~ /ms-sql/i)
  57.   { $server= new db_ms_sql($host,$database); }
  58.   elsif ($name =~ /sybase/i)
  59.   { $server= new db_sybase($host,$database); }
  60.   elsif ($name =~ /Adabas/i)            # Adabas has two drivers
  61.   {
  62.     $server= new db_Adabas($host,$database);
  63.     if ($name =~ /AdabasD/i)
  64.     {
  65.       $server->{'data_source'} =~ s/:Adabas:/:AdabasD:/;
  66.     }
  67.   }
  68.   elsif ($name =~ /DB2/i)
  69.   { $server= new db_db2($host,$database); }
  70.   elsif ($name =~ /Mimer/i)
  71.   { $server= new db_Mimer($host,$database); }
  72.   elsif ($name =~ /interBase/i)
  73.   { $server= new db_interbase($host,$database); }
  74.   else
  75.   {
  76.       die "Unknown sql server name used: $name\nUse one of: Access, Adabas, AdabasD, Empress, FrontBase, Oracle, Informix, DB2, mSQL, Mimer, MS-SQL, MySQL, Pg, Solid or Sybase.\nIf the connection is done trough ODBC the name must end with _ODBC\n";
  77.   }
  78.   if ($name =~ /_ODBC$/i || defined($odbc) && $odbc)
  79.   {
  80.     if (! ($server->{'data_source'} =~ /^([^:]*):([^:]+):([^:]*)/ ))
  81.     {
  82.       die "Can't find databasename in data_source: '" .
  83.       $server->{'data_source'}. "'\n";
  84.     }
  85.     if ($3) {
  86.       $server->{'data_source'} = "$1:ODBC:$3";
  87.     } else {
  88.       $server->{'data_source'} = "$1:ODBC:$database";
  89.     }
  90.   }
  91.   return $server;
  92. }
  93.  
  94. sub all_servers
  95. {
  96.   return ["Access", "Adabas", "DB2", "Empress", "FrontBase", "Oracle",
  97.       "Informix", "InterBase", "Mimer", "mSQL", "MS-SQL", "MySQL", "Pg",
  98.       "Solid", "Sybase"];
  99. }
  100.  
  101. #############################################################################
  102. #         First the configuration for MySQL off course :-)
  103. #############################################################################
  104.  
  105. package db_MySQL;
  106.  
  107. sub new
  108. {
  109.   my ($type,$host,$database,$machine)= @_;
  110.   my $self= {};
  111.   my %limits;
  112.   bless $self;
  113.  
  114.   $self->{'cmp_name'}        = "mysql";
  115.   $self->{'data_source'}    = "DBI:mysql:$database:$host";
  116.   $self->{'limits'}        = \%limits;
  117.   $self->{'smds'}        = \%smds;
  118.   $self->{'blob'}        = "blob";
  119.   $self->{'text'}        = "text";
  120.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  121.   $self->{'vacuum'}        = 1; # When using with --fast
  122.   $self->{'drop_attr'}        = "";
  123.  
  124.   $limits{'NEG'}        = 1; # Supports -id
  125.   $limits{'alter_add_multi_col'}= 1; #Have ALTER TABLE t add a int,add b int;
  126.   $limits{'alter_table'}    = 1; # Have ALTER TABLE
  127.   $limits{'alter_table_dropcol'}= 1; # Have ALTER TABLE DROP column
  128.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  129.   $limits{'func_extra_%'}    = 1; # Has % as alias for mod()
  130.   $limits{'func_extra_if'}    = 1; # Have function if.
  131.   $limits{'func_extra_in_num'}    = 1; # Has function in
  132.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  133.   $limits{'func_odbc_mod'}    = 1; # Have function mod.
  134.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  135.   $limits{'group_by_position'}  = 1; # Can use 'GROUP BY 1'
  136.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  137.   $limits{'group_func_extra_std'} = 1; # Have group function std().
  138.   $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
  139.   $limits{'group_functions'}    = 1; # Have group functions
  140.   $limits{'having_with_alias'}  = 1; # Can use aliases in HAVING
  141.   $limits{'having_with_group'}    = 1; # Can use group functions in HAVING
  142.   $limits{'insert_multi_value'} = 1; # Have INSERT ... values (1,2),(3,4)
  143.   $limits{'insert_select'}    = 1;
  144.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  145.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  146.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  147.   $limits{'limit'}        = 1;        # supports the limit attribute
  148.   $limits{'load_data_infile'}    = 1; # Has load data infile
  149.   $limits{'lock_tables'}    = 1; # Has lock tables
  150.   $limits{'max_column_name'}    = 64; # max table and column name
  151.   $limits{'max_columns'}    = 2000;    # Max number of columns in table
  152.   $limits{'max_conditions'}    = 9999; # (Actually not a limit)
  153.   $limits{'max_index'}        = 16; # Max number of keys
  154.   $limits{'max_index_parts'}    = 16; # Max segments/key
  155.   $limits{'max_tables'}        = (($machine || '') =~ "^win") ? 5000 : 65000;
  156.   $limits{'max_text_size'}    = 1000000; # Good enough for tests
  157.   $limits{'multi_drop'}        = 1; # Drop table can take many tables
  158.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  159.   $limits{'order_by_unused'}    = 1;
  160.   $limits{'query_size'}        = 1000000; # Max size with default buffers.
  161.   $limits{'select_without_from'}= 1; # Can do 'select 1';
  162.   $limits{'subqueries'}        = 0; # Doesn't support sub-queries.
  163.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  164.   $limits{'unique_index'}    = 1; # Unique index works or not
  165.   $limits{'working_all_fields'} = 1;
  166.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  167.  
  168.   $smds{'time'}            = 1;
  169.   $smds{'q1'}     = 'b';        # with time not supp by mysql ('')
  170.   $smds{'q2'}     = 'b';
  171.   $smds{'q3'}     = 'b';        # with time ('')
  172.   $smds{'q4'}     = 'c';        # with time not supp by mysql (d)
  173.   $smds{'q5'}     = 'b';        # with time not supp by mysql ('')
  174.   $smds{'q6'}     = 'c';        # with time not supp by mysql ('')
  175.   $smds{'q7'}     = 'c';
  176.   $smds{'q8'}     = 'f';
  177.   $smds{'q9'}     = 'c';
  178.   $smds{'q10'}     = 'b';
  179.   $smds{'q11'}     = 'b';
  180.   $smds{'q12'}     = 'd';
  181.   $smds{'q13'}     = 'c';
  182.   $smds{'q14'}     = 'd';
  183.   $smds{'q15'}     = 'd';
  184.   $smds{'q16'}     = 'a';
  185.   $smds{'q17'}     = 'c';
  186.  
  187.   # Some fixes that depends on the environment
  188.   if (defined($main::opt_create_options) &&
  189.       $main::opt_create_options =~ /type=heap/i)
  190.   {
  191.     $limits{'working_blobs'}    = 0; # HEAP tables can't handle BLOB's
  192.   }
  193.   if (defined($main::opt_create_options) &&
  194.       $main::opt_create_options =~ /type=innodb/i)
  195.   {
  196.     $limits{'max_text_size'}    = 8000; # Limit in Innobase
  197.   }
  198.   if (defined($main::opt_create_options) &&
  199.       $main::opt_create_options =~ /type=gemini/i)
  200.   {
  201.     $limits{'working_blobs'}    = 0; # Blobs not implemented yet
  202.     $limits{'max_tables'}    = 500;
  203.   }
  204.  
  205.   return $self;
  206. }
  207.  
  208. #
  209. # Get the version number of the database
  210. #
  211.  
  212. sub version
  213. {
  214.   my ($self)=@_;
  215.   my ($dbh,$sth,$version,@row);
  216.  
  217.   $dbh=$self->connect();
  218.   $sth = $dbh->prepare("select VERSION()") or die $DBI::errstr;
  219.   $version="MySQL 3.20.?";
  220.   if ($sth->execute && (@row = $sth->fetchrow_array))
  221.   {
  222.     $row[0] =~ s/-/ /g;            # To get better tables with long names
  223.     $version="MySQL $row[0]";
  224.   }
  225.   $sth->finish;
  226.   $dbh->disconnect;
  227.   return $version;
  228. }
  229.  
  230. #
  231. # Connection with optional disabling of logging
  232. #
  233.  
  234. sub connect
  235. {
  236.   my ($self)=@_;
  237.   my ($dbh);
  238.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  239.             $main::opt_password,{ PrintError => 0}) ||
  240.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  241.  
  242.   $dbh->do("SET OPTION LOG_OFF=1,UPDATE_LOG=0");
  243.   return $dbh;
  244. }
  245.  
  246. #
  247. # Returns a list of statements to create a table
  248. # The field types are in ANSI SQL format.
  249. #
  250. # If one uses $main::opt_fast then one is allowed to use
  251. # non standard types to get better speed.
  252. #
  253.  
  254. sub create
  255. {
  256.   my($self,$table_name,$fields,$index,$options) = @_;
  257.   my($query,@queries);
  258.  
  259.   $query="create table $table_name (";
  260.   foreach $field (@$fields)
  261.   {
  262.     $field =~ s/ decimal/ double(10,2)/i;
  263.     $field =~ s/ big_decimal/ double(10,2)/i;
  264.     $field =~ s/ date/ int/i;        # Because of tcp ?
  265.     $query.= $field . ',';
  266.   }
  267.   foreach $index (@$index)
  268.   {
  269.     $query.= $index . ',';
  270.   }
  271.   substr($query,-1)=")";        # Remove last ',';
  272.   $query.=" $options" if (defined($options));
  273.   $query.=" $main::opt_create_options" if (defined($main::opt_create_options));
  274.   push(@queries,$query);
  275.   return @queries;
  276. }
  277.  
  278. sub insert_file {
  279.   my ($self,$dbname, $file, $dbh) = @_;
  280.   my ($command, $sth);
  281.  
  282.   $file =~ s|\\|/|g;            # Change Win32 names to Unix syntax
  283.   $command = "load data infile '$file' into table $dbname columns optionally enclosed by '\\'' terminated by ','";
  284. #  print "$command\n";
  285.   $sth = $dbh->do($command) or die $DBI::errstr;
  286.   return $sth;            # Contains number of rows
  287. }
  288.  
  289. #
  290. # Do any conversions to the ANSI SQL query so that the database can handle it
  291. #
  292.  
  293. sub query {
  294.   my($self,$sql) = @_;
  295.   return $sql;
  296. }
  297.  
  298. sub drop_index {
  299.   my ($self,$table,$index) = @_;
  300.   return "DROP INDEX $index ON $table";
  301. }
  302.  
  303. #
  304. # Abort if the server has crashed
  305. # return: 0 if ok
  306. #      1 question should be retried
  307. #
  308.  
  309. sub abort_if_fatal_error
  310. {
  311.   return 0;
  312. }
  313.  
  314. #
  315. # This should return 1 if we to do disconnect / connect when doing
  316. # big batches
  317. #
  318.  
  319. sub small_rollback_segment
  320. {
  321.   return 0;
  322. }
  323.  
  324. #
  325. # reconnect on errors (needed mainly be crash-me)
  326. #
  327.  
  328. sub reconnect_on_errors
  329. {
  330.   return 0;
  331. }
  332.  
  333. #
  334. # Optimize tables for better performance
  335. #
  336.  
  337. sub vacuum
  338. {
  339.   my ($self,$full_vacuum,$dbh_ref,@tables)=@_;
  340.   my ($loop_time,$end_time,$dbh);
  341.   if ($#tables >= 0)
  342.   {
  343.     $dbh=$$dbh_ref;
  344.     $loop_time=new Benchmark;
  345.     $dbh->do("OPTIMIZE TABLE " . join(',',@tables)) || die "Got error: $DBI::errstr when executing 'OPTIMIZE TABLE'\n";
  346.     $end_time=new Benchmark;
  347.     print "Time for book-keeping (1): " .
  348.       Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"all") . "\n\n";
  349.   }
  350. }
  351.  
  352.  
  353. #############################################################################
  354. #             Definitions for mSQL
  355. #############################################################################
  356.  
  357. package db_mSQL;
  358.  
  359. sub new
  360. {
  361.   my ($type,$host,$database)= @_;
  362.   my $self= {};
  363.   my %limits;
  364.   bless $self;
  365.  
  366.   $self->{'cmp_name'}        = "msql";
  367.   $self->{'data_source'}    = "DBI:mSQL:$database:$host";
  368.   $self->{'limits'}        = \%limits;
  369.   $self->{'double_quotes'}    = 0;
  370.   $self->{'drop_attr'}        = "";
  371.   $self->{'blob'}        = "text(" . $limits{'max_text_size'} .")";
  372.   $self->{'text'}        = "text(" . $limits{'max_text_size'} .")";
  373.  
  374.   $limits{'max_conditions'}    = 74;
  375.   $limits{'max_columns'}    = 75;
  376.   $limits{'max_tables'}        = 65000;    # Should be big enough
  377.   $limits{'max_text_size'}    = 32000;
  378.   $limits{'query_size'}        = 65535;
  379.   $limits{'max_index'}        = 5;
  380.   $limits{'max_index_parts'}    = 10;
  381.   $limits{'max_column_name'} = 35;
  382.  
  383.   $limits{'join_optimizer'}    = 0;        # Can't optimize FROM tables
  384.   $limits{'load_data_infile'}    = 0;
  385.   $limits{'lock_tables'}    = 0;
  386.   $limits{'functions'}        = 0;
  387.   $limits{'group_functions'}    = 0;
  388.   $limits{'group_distinct_functions'}= 0;     # Have count(distinct)
  389.   $limits{'multi_drop'}        = 0;
  390.   $limits{'select_without_from'}= 0;
  391.   $limits{'subqueries'}        = 0;
  392.   $limits{'left_outer_join'}    = 0;
  393.   $limits{'table_wildcard'}    = 0;
  394.   $limits{'having_with_alias'}  = 0;
  395.   $limits{'having_with_group'}    = 0;
  396.   $limits{'like_with_column'}    = 1;
  397.   $limits{'order_by_position'}  = 1;
  398.   $limits{'group_by_position'}  = 1;
  399.   $limits{'alter_table'}    = 0;
  400.   $limits{'alter_add_multi_col'}= 0;
  401.   $limits{'alter_table_dropcol'}= 0;
  402.   $limits{'group_func_extra_std'} = 0;
  403.   $limits{'limit'}        = 1;        # supports the limit attribute
  404.   $limits{'unique_index'}    = 1; # Unique index works or not
  405.   $limits{'insert_select'}    = 0;
  406.  
  407.   $limits{'func_odbc_mod'}    = 0;
  408.   $limits{'func_extra_%'}    = 0;
  409.   $limits{'func_odbc_floor'}    = 0;
  410.   $limits{'func_extra_if'}    = 0;
  411.   $limits{'column_alias'}    = 0;
  412.   $limits{'NEG'}        = 0;
  413.   $limits{'func_extra_in_num'}    = 0;
  414.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  415.   $limits{'order_by_unused'}    = 1;
  416.   $limits{'working_all_fields'} = 1;
  417.   return $self;
  418. }
  419.  
  420. #
  421. # Get the version number of the database
  422. #
  423.  
  424. sub version
  425. {
  426.   my ($tmp,$dir);
  427.   foreach $dir ("/usr/local/Hughes", "/usr/local/mSQL","/my/local/mSQL",
  428.         "/usr/local")
  429.   {
  430.     if (-x "$dir/bin/msqladmin")
  431.     {
  432.       $tmp=`$dir/bin/msqladmin version | grep server`;
  433.       if ($tmp =~ /^\s*(.*\w)\s*$/)
  434.       {                # Strip pre- and endspace
  435.     $tmp=$1;
  436.     $tmp =~ s/\s+/ /g;    # Remove unnecessary spaces
  437.     return $tmp;
  438.       }
  439.     }
  440.   }
  441.   return "mSQL version ???";
  442. }
  443.  
  444.  
  445. sub connect
  446. {
  447.   my ($self)=@_;
  448.   my ($dbh);
  449.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  450.             $main::opt_password,{ PrintError => 0}) ||
  451.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  452.   return $dbh;
  453. }
  454.  
  455. #
  456. # Can't handle many field types, so we map everything to int and real.
  457. #
  458.  
  459. sub create
  460. {
  461.   my($self,$table_name,$fields,$index) = @_;
  462.   my($query,@queries,$name,$nr);
  463.  
  464.   $query="create table $table_name (";
  465.   foreach $field (@$fields)
  466.   {
  467.     $field =~ s/varchar/char/i;        # mSQL doesn't have VARCHAR()
  468.     # mSQL can't handle more than the real basic int types
  469.     $field =~ s/tinyint|smallint|mediumint|integer/int/i;
  470.     # mSQL can't handle different visual lengths
  471.     $field =~ s/int\(\d*\)/int/i;
  472.     # mSQL doesn't have float, change it to real
  473.     $field =~ s/float(\(\d*,\d*\)){0,1}/real/i;
  474.     $field =~ s/double(\(\d*,\d*\)){0,1}/real/i;
  475.     # mSQL doesn't have blob, it has text instead
  476.     if ($field =~ / blob/i)
  477.     {
  478.       $name=$self->{'blob'};
  479.       $field =~ s/ blob/ $name/;
  480.     }
  481.     $query.= $field . ',';
  482.   }
  483.   substr($query,-1)=")";        # Remove last ',';
  484.   push(@queries,$query);
  485.   $nr=0;
  486.  
  487.   # Prepend table_name to index name because the the name may clash with
  488.   # a field name. (Should be diffent name space, but this is mSQL...)
  489.  
  490.   foreach $index (@$index)
  491.   {
  492.     # Primary key is unique index in mSQL
  493.     $index =~ s/primary key/unique index primary/i;
  494.     if ($index =~ /^unique\s*\(([^\(]*)\)$/i)
  495.     {
  496.       $nr++;
  497.       push(@queries,"create unique index ${table_name}_$nr on $table_name ($1)");
  498.     }
  499.     else
  500.     {
  501.       if (!($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i))
  502.       {
  503.     die "Can't parse index information in '$index'\n";
  504.       }
  505.       push(@queries,"create $1 ${table_name}_$2 on $table_name $3");
  506.     }
  507.   }
  508.   return @queries;
  509. }
  510.  
  511.  
  512. sub insert_file {
  513.   my($self,$dbname, $file) = @_;
  514.   print "insert an ascii file isn't supported by mSQL\n";
  515.   return 0;
  516. }
  517.  
  518.  
  519. sub query {
  520.   my($self,$sql) = @_;
  521.   return $sql;
  522. }
  523.  
  524. sub drop_index
  525. {
  526.   my ($self,$table,$index) = @_;
  527.   return "DROP INDEX $index FROM $table";
  528. }
  529.  
  530. sub abort_if_fatal_error
  531. {
  532.   return 0;
  533. }
  534.  
  535. sub small_rollback_segment
  536. {
  537.   return 0;
  538. }
  539.  
  540. sub reconnect_on_errors
  541. {
  542.   return 0;
  543. }
  544.  
  545. #############################################################################
  546. #             Definitions for PostgreSQL                    #
  547. #############################################################################
  548.  
  549. package db_Pg;
  550.  
  551. sub new
  552. {
  553.   my ($type,$host,$database)= @_;
  554.   my $self= {};
  555.   my %limits;
  556.   bless $self;
  557.  
  558.   $self->{'cmp_name'}        = "pg";
  559.   $self->{'data_source'}    = "DBI:Pg:dbname=$database";
  560.   $self->{'limits'}        = \%limits;
  561.   $self->{'smds'}        = \%smds;
  562.   $self->{'blob'}        = "text";
  563.   $self->{'text'}        = "text";
  564.   $self->{'double_quotes'}    = 1;
  565.   $self->{'drop_attr'}        = "";
  566.   $self->{"vacuum"}        = 1;
  567.   $limits{'join_optimizer'}    = 1;        # Can optimize FROM tables
  568.   $limits{'load_data_infile'}    = 0;
  569.  
  570.   $limits{'NEG'}        = 1;
  571.   $limits{'alter_add_multi_col'}= 0;        # alter_add_multi_col ?
  572.   $limits{'alter_table'}    = 1;
  573.   $limits{'alter_table_dropcol'}= 0;
  574.   $limits{'column_alias'}    = 1;
  575.   $limits{'func_extra_%'}    = 1;
  576.   $limits{'func_extra_if'}    = 0;
  577.   $limits{'func_extra_in_num'}    = 1;
  578.   $limits{'func_odbc_floor'}    = 1;
  579.   $limits{'func_odbc_mod'}    = 1;        # Has %
  580.   $limits{'functions'}        = 1;
  581.   $limits{'group_by_position'}  = 1;
  582.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  583.   $limits{'group_func_extra_std'} = 0;
  584.   $limits{'group_func_sql_min_str'}= 1; # Can execute MIN() and MAX() on strings
  585.   $limits{'group_functions'}    = 1;
  586.   $limits{'having_with_alias'}  = 0;
  587.   $limits{'having_with_group'}    = 1;
  588.   $limits{'insert_select'}    = 1;
  589.   $limits{'left_outer_join'}    = 1;
  590.   $limits{'like_with_column'}    = 1;
  591.   $limits{'lock_tables'}    = 0;        # in ATIS gives this a problem
  592.   $limits{'max_column_name'}     = 128;
  593.   $limits{'max_columns'}    = 1000;        # 500 crashes pg 6.3
  594.   $limits{'max_conditions'}    = 9999;        # This makes Pg real slow
  595.   $limits{'max_index'}        = 64;        # Big enough
  596.   $limits{'max_index_parts'}    = 16;
  597.   $limits{'max_tables'}        = 5000;        # 10000 crashes pg 7.0.2
  598.   $limits{'max_text_size'}    = 65000;    # Good enough for test
  599.   $limits{'multi_drop'}        = 1;
  600.   $limits{'order_by_position'}  = 1;
  601.   $limits{'order_by_unused'}    = 1;
  602.   $limits{'query_size'}        = 16777216;
  603.   $limits{'select_without_from'}= 1;
  604.   $limits{'subqueries'}        = 1;
  605.   $limits{'table_wildcard'}    = 1;
  606.   $limits{'unique_index'}    = 1; # Unique index works or not
  607.   $limits{'working_all_fields'} = 1;
  608.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  609.  
  610.   # the different cases per query ...
  611.   $smds{'q1'}     = 'b'; # with time
  612.   $smds{'q2'}     = 'b';
  613.   $smds{'q3'}     = 'b'; # with time
  614.   $smds{'q4'}     = 'c'; # with time
  615.   $smds{'q5'}     = 'b'; # with time
  616.   $smds{'q6'}     = 'c'; # strange error ....
  617.   $smds{'q7'}     = 'c';
  618.   $smds{'q8'}     = 'f'; # needs 128M to execute - can't do insert ...group by
  619.   $smds{'q9'}     = 'c';
  620.   $smds{'q10'}     = 'b';
  621.   $smds{'q11'}     = 'b'; # can't do float8 * int4 - create operator
  622.   $smds{'q12'}     = 'd'; # strange error???
  623.   $smds{'q13'}     = 'c';
  624.   $smds{'q14'}     = 'd'; # strange error???
  625.   $smds{'q15'}     = 'd'; # strange error???
  626.   $smds{'q16'}     = 'a';
  627.   $smds{'q17'}     = 'c';
  628.   $smds{'time'} = 1;    # the use of the time table -> 1 is on.
  629.             # when 0 then the date field must be a
  630.             # date field not a int field!!!
  631.   return $self;
  632. }
  633.  
  634. # couldn't find the option to get the version number
  635.  
  636. sub version
  637. {
  638.   my ($version,$dir);
  639.   foreach $dir ($ENV{'PGDATA'},"/usr/local/pgsql/data", "/usr/local/pg/data")
  640.   {
  641.     if ($dir && -e "$dir/PG_VERSION")
  642.     {
  643.       $version= `cat $dir/PG_VERSION`;
  644.       if ($? == 0)
  645.       {
  646.     chomp($version);
  647.     return "PostgreSQL $version";
  648.       }
  649.     }
  650.   }
  651.   return "PostgreSQL version ???";
  652. }
  653.  
  654.  
  655. sub connect
  656. {
  657.   my ($self)=@_;
  658.   my ($dbh);
  659.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  660.             $main::opt_password,{ PrintError => 0}) ||
  661.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  662.   return $dbh;
  663. }
  664.  
  665.  
  666. sub create
  667. {
  668.   my($self,$table_name,$fields,$index) = @_;
  669.   my($query,@queries,$name,$in,$indfield,$table,$nr);
  670.  
  671.   $query="create table $table_name (";
  672.   foreach $field (@$fields)
  673.   {
  674.     if ($main::opt_fast)
  675.     {
  676.       # Allow use of char2, char4, char8 or char16
  677.       $field =~ s/char(2|4|8|16)/char$1/;
  678.     }
  679.     # Pg can't handle more than the real basic int types
  680.     $field =~ s/tinyint|smallint|mediumint|integer/int/;
  681.     # Pg can't handle different visual lengths
  682.     $field =~ s/int\(\d*\)/int/;
  683.     $field =~ s/float\(\d*,\d*\)/float/;
  684.     $field =~ s/ double/ float/;
  685.     $field =~ s/ decimal/ float/i;
  686.     $field =~ s/ big_decimal/ float/i;
  687.     $field =~ s/ date/ int/i;
  688.     # Pg doesn't have blob, it has text instead
  689.     $field =~ s/ blob/ text/;
  690.     $query.= $field . ',';
  691.   }
  692.   substr($query,-1)=")";        # Remove last ',';
  693.   push(@queries,$query);
  694.   foreach $index (@$index)
  695.   {
  696.     $index =~ s/primary key/unique index primary_key/i;
  697.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  698.     {
  699.       # original: $indfield="using btree (" .$1.")";
  700.       # using btree doesn┤t seem to work with Postgres anymore; it creates
  701.       # the table and adds the index, but it isn┤t unique
  702.       $indfield=" (" .$1.")";    
  703.       $in="unique index";
  704.       $table="index_$nr"; $nr++;
  705.     }
  706.     elsif ($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i)
  707.     {
  708.       # original: $indfield="using btree (" .$1.")";
  709.       $indfield=" " .$3;
  710.       $in="index";
  711.       $table="index_$nr"; $nr++;
  712.     }
  713.     else
  714.     {
  715.       die "Can't parse index information in '$index'\n";
  716.     }
  717.     push(@queries,"create $in ${table_name}_$table on $table_name $indfield");
  718.   }
  719.   $queries[0]=$query;
  720.   return @queries;
  721. }
  722.  
  723. sub insert_file {
  724.   my ($self,$dbname, $file, $dbh) = @_;
  725.   my ($command, $sth);
  726.  
  727. # Syntax:
  728. # copy [binary] <class_name> [with oids]
  729. #      {to|from} {<filename>|stdin|stdout} [using delimiters <delim>]
  730.   print "The ascii files aren't correct for postgres ....!!!\n";
  731.   $command = "copy $dbname from '$file' using delimiters ','";
  732.   print "$command\n";
  733.   $sth = $dbh->do($command) or die $DBI::errstr;
  734.   return $sth;
  735. }
  736.  
  737. #
  738. # As postgreSQL wants A % B instead of standard mod(A,B) we have to map
  739. # This will not handle all cases, but as the benchmarks doesn't use functions
  740. # inside MOD() the following should work
  741. #
  742. # PostgreSQL cant handle count(*) or even count(1), but it can handle
  743. # count(1+1) sometimes. ==> this is solved in PostgreSQL 6.3
  744. #
  745. # PostgreSQL 6.5 is supporting MOD.
  746.  
  747. sub query {
  748.   my($self,$sql) = @_;
  749.   my(@select,$change);
  750. # if you use PostgreSQL 6.x and x is lower as 5 then uncomment the line below.
  751. #  $sql =~ s/mod\(([^,]*),([^\)]*)\)/\($1 % $2\)/gi;
  752. #
  753. # if you use PostgreSQL 6.1.x uncomment the lines below
  754. #  if ($sql =~ /select\s+count\(\*\)\s+from/i) {
  755. #  }
  756. #  elsif ($sql =~ /count\(\*\)/i)
  757. #  {
  758. #    if ($sql =~ /select\s+(.*)\s+from/i)
  759. #    {
  760. #      @select = split(/,/,$1);
  761. #      if ($select[0] =~ /(.*)\s+as\s+\w+$/i)
  762. #      {
  763. #     $change = $1;
  764. #      }
  765. #      else
  766. #      {
  767. #    $change = $select[0];
  768. #      }
  769. #    }
  770. #    if (($change =~ /count/i) || ($change eq "")) {
  771. #      $change = "1+1";
  772. #    }
  773. #    $sql =~ s/count\(\*\)/count($change)/gi;
  774. #  }
  775. # till here.
  776.   return $sql;
  777. }
  778.  
  779. sub drop_index
  780. {
  781.   my ($self,$table,$index) = @_;
  782.   return "DROP INDEX $index";
  783. }
  784.  
  785. sub abort_if_fatal_error
  786. {
  787.   return 1 if ($DBI::errstr =~ /sent to backend, but backend closed/i);
  788.   return 0;
  789. }
  790.  
  791. sub small_rollback_segment
  792. {
  793.   return 0;
  794. }
  795.  
  796. sub reconnect_on_errors
  797. {
  798.   return 0;
  799. }
  800.  
  801. sub vacuum
  802. {
  803.   my ($self,$full_vacuum,$dbh_ref,@tables)=@_;
  804.   my ($loop_time,$end_time,$dbh,$table);
  805.   if (defined($full_vacuum))
  806.   {
  807.     $$dbh_ref->disconnect;  $$dbh_ref= $self->connect();
  808.   }
  809.   $dbh=$$dbh_ref;
  810.   $loop_time=new Benchmark;
  811.   if ($#tables >= 0)
  812.   {
  813.     foreach $table (@tables)
  814.     {
  815.       $dbh->do("vacuum analyze $table") || die "Got error: $DBI::errstr when executing 'vacuum analyze $table'\n";
  816.       $dbh->do("vacuum $table") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
  817.     }
  818.   }
  819.   else
  820.   {
  821. #    $dbh->do("vacuum pg_attributes") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
  822. #    $dbh->do("vacuum pg_index") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
  823.     $dbh->do("vacuum analyze") || die "Got error: $DBI::errstr when executing 'vacuum analyze'\n";
  824.     $dbh->do("vacuum") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
  825.   }
  826.   $end_time=new Benchmark;
  827.   print "Time for book-keeping (1): " .
  828.   Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"all") . "\n\n";
  829.   $dbh->disconnect;  $$dbh_ref= $self->connect();
  830. }
  831.  
  832.  
  833. #############################################################################
  834. #             Definitions for Solid
  835. #############################################################################
  836.  
  837. package db_Solid;
  838.  
  839. sub new
  840. {
  841.   my ($type,$host,$database)= @_;
  842.   my $self= {};
  843.   my %limits;
  844.   bless $self;
  845.  
  846.   $self->{'cmp_name'}        = "solid";
  847.   $self->{'data_source'}    = "DBI:Solid:";
  848.   $self->{'limits'}        = \%limits;
  849.   $self->{'smds'}        = \%smds;
  850.   $self->{'blob'}        = "long varchar";
  851.   $self->{'text'}        = "long varchar";
  852.   $self->{'double_quotes'}    = 1;
  853.   $self->{'drop_attr'}        = "";
  854.  
  855.   $limits{'max_conditions'}    = 9999;        # Probably big enough
  856.   $limits{'max_columns'}    = 2000;        # From crash-me
  857.   $limits{'max_tables'}        = 65000;    # Should be big enough
  858.   $limits{'max_text_size'}    = 65492;    # According to tests
  859.   $limits{'query_size'}        = 65535;    # Probably a limit
  860.   $limits{'max_index'}        = 64;        # Probably big enough
  861.   $limits{'max_index_parts'}    = 64;
  862.   $limits{'max_column_name'} = 80;
  863.  
  864.   $limits{'join_optimizer'}    = 1;
  865.   $limits{'load_data_infile'}    = 0;
  866.   $limits{'lock_tables'}    = 0;
  867.   $limits{'functions'}        = 1;
  868.   $limits{'group_functions'}    = 1;
  869.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  870.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  871.   $limits{'select_without_from'}= 0;        # Can do 'select 1' ?;
  872.   $limits{'multi_drop'}        = 0;
  873.   $limits{'subqueries'}        = 1;
  874.   $limits{'left_outer_join'}    = 1;
  875.   $limits{'table_wildcard'}    = 1;
  876.   $limits{'having_with_alias'}  = 0;
  877.   $limits{'having_with_group'}    = 1;
  878.   $limits{'like_with_column'}    = 1;
  879.   $limits{'order_by_position'}  = 0;        # 2.30.0018 can this
  880.   $limits{'group_by_position'}  = 0;
  881.   $limits{'alter_table'}    = 1;
  882.   $limits{'alter_add_multi_col'}= 0;
  883.   $limits{'alter_table_dropcol'}= 0;
  884.  
  885.   $limits{'group_func_extra_std'}    = 0;    # Have group function std().
  886.  
  887.   $limits{'func_odbc_mod'}    = 1;
  888.   $limits{'func_extra_%'}    = 0;
  889.   $limits{'func_odbc_floor'}    = 1;
  890.   $limits{'column_alias'}    = 1;
  891.   $limits{'NEG'}        = 1;
  892.   $limits{'func_extra_in_num'}    = 1;
  893.   $limits{'unique_index'}    = 1; # Unique index works or not
  894.   $limits{'insert_select'}    = 1;
  895.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  896.   $limits{'order_by_unused'}    = 1;
  897.   $limits{'working_all_fields'} = 1;
  898.  
  899.   # for the smds small benchmark test ....
  900.   # the different cases per query ...
  901.   $smds{'q1'}     = 'a';
  902.   $smds{'q2'}     = '';
  903.   $smds{'q3'}     = 'b'; #doesn't work -> strange error about column -fixed
  904.   $smds{'q4'}     = 'a';
  905.   $smds{'q5'}     = 'b';
  906.   $smds{'q6'}     = 'c';
  907.   $smds{'q7'}     = 'b';
  908.   $smds{'q8'}     = 'f';
  909.   $smds{'q9'}     = 'b';
  910.   $smds{'q10'}     = 'b';
  911.   $smds{'q11'}     = '';
  912.   $smds{'q12'}     = 'd';
  913.   $smds{'q13'}     = 'b';
  914.   $smds{'q14'}     = 'd';
  915.   $smds{'q15'}     = 'd';
  916.   $smds{'q16'}     = '';
  917.   $smds{'q17'}     = '';
  918.   $smds{'time'} = 1;    # the use of the time table -> 1 is on.
  919.             # when 0 then the date field must be a
  920.             # date field not a int field!!!
  921.   return $self;
  922. }
  923.  
  924. #
  925. # Get the version number of the database
  926. #
  927.  
  928. sub version
  929. {
  930.   my ($version,$dir);
  931.   foreach $dir ($ENV{'SOLIDDIR'},"/usr/local/solid", "/my/local/solid")
  932.   {
  933.     if ($dir && -e "$dir/bin/solcon")
  934.     {
  935.       $version=`$dir/bin/solcon -e"ver" $main::opt_user $main::opt_password | grep Server | head -1`;
  936.       if ($? == 0)
  937.       {
  938.     chomp($version);
  939.     return $version;
  940.       }
  941.     }
  942.   }
  943.   return "Solid version ???";
  944. }
  945.  
  946. sub connect
  947. {
  948.   my ($self)=@_;
  949.   my ($dbh);
  950.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  951.             $main::opt_password,{ PrintError => 0}) ||
  952.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  953.   return $dbh;
  954. }
  955.  
  956. #
  957. # Returns a list of statements to create a table
  958. # The field types are in ANSI SQL format.
  959. #
  960.  
  961. sub create
  962. {
  963.   my($self,$table_name,$fields,$index) = @_;
  964.   my($query,@queries,$nr);
  965.  
  966.   $query="create table $table_name (";
  967.   foreach $field (@$fields)
  968.   {
  969.     $field =~ s/mediumint/integer/i;
  970.     $field =~ s/ double/ float/i;
  971.     # Solid doesn't have blob, it has long varchar
  972.     $field =~ s/ blob/ long varchar/;
  973.     $field =~ s/ decimal/ float/i;
  974.     $field =~ s/ big_decimal/ float/i;
  975.     $field =~ s/ date/ int/i;
  976.     $query.= $field . ',';
  977.   }
  978.   substr($query,-1)=")";        # Remove last ',';
  979.   push(@queries,$query);
  980.   $nr=0;
  981.   foreach $index (@$index)
  982.   {
  983.     if ($index =~ /^primary key/i || $index =~ /^unique/i)
  984.     {                    # Add to create statement
  985.       substr($queries[0],-1,0)="," . $index;
  986.     }
  987.     else
  988.     {
  989.       $index =~ /^(.*)\s+(\(.*\))$/;
  990.       push(@queries,"create ${1}$nr on $table_name $2");
  991.       $nr++;
  992.     }
  993.   }
  994.   return @queries;
  995. }
  996.  
  997. # there is no sql statement in solid which can do the load from
  998. # an ascii file in the db ... but there is the speedloader program
  999. # an external program which can load the ascii file in the db ...
  1000. # the server must be down before using speedloader !!!!
  1001. # (in the standalone version)
  1002. # it works also with a control file ... that one must be made ....
  1003. sub insert_file {
  1004.   my ($self, $dbname, $file) = @_;
  1005.   my ($speedcmd);
  1006.   $speedcmd = '/usr/local/solid/bin/solload';
  1007.   print "At this moment not supported - solid server must go down \n";
  1008.   return 0;
  1009. }
  1010.  
  1011. # solid can't handle an alias in a having statement so
  1012. # select test as foo from tmp group by foo having foor > 2
  1013. # becomes
  1014. # select test as foo from tmp group by foo having test > 2
  1015. #
  1016. sub query {
  1017.   my($self,$sql) = @_;
  1018.   my(@select,$tmp,$newhaving,$key,%change);
  1019.  
  1020.   if ($sql =~ /having\s+/i)
  1021.   {
  1022.     if ($sql =~ /select (.*) from/i)
  1023.     {
  1024.       (@select) = split(/,\s*/, $1);
  1025.       foreach $tmp (@select)
  1026.       {
  1027.     if ($tmp =~ /(.*)\s+as\s+(\w+)/)
  1028.     {
  1029.       $change{$2} = $1;
  1030.     }
  1031.       }
  1032.     }
  1033.     if ($sql =~ /having\s+(\w+)/i)
  1034.     {
  1035.       $newhaving = $1;
  1036.       foreach $key (sort {$a cmp $b} keys %change)
  1037.       {
  1038.     if ($newhaving eq $key)
  1039.     {
  1040.       $newhaving =~ s/$key/$change{$key}/g;
  1041.     }
  1042.       }
  1043.     }
  1044.     $sql =~ s/(having)\s+(\w+)/$1 $newhaving/i;
  1045.   }
  1046.   return $sql;
  1047. }
  1048.  
  1049.  
  1050. sub drop_index
  1051. {
  1052.   my ($self,$table,$index) = @_;
  1053.   return "DROP INDEX $index";
  1054. }
  1055.  
  1056. sub abort_if_fatal_error
  1057. {
  1058.   return 0;
  1059. }
  1060.  
  1061. sub small_rollback_segment
  1062. {
  1063.   return 0;
  1064. }
  1065.  
  1066. sub reconnect_on_errors
  1067. {
  1068.   return 0;
  1069. }
  1070.  
  1071. #############################################################################
  1072. #             Definitions for Empress
  1073. #
  1074. # at this moment DBI:Empress can only handle 200 prepare statements ...
  1075. # so Empress can't be tested with the benchmark test :(
  1076. #############################################################################
  1077.  
  1078. package db_Empress;
  1079.  
  1080. sub new
  1081. {
  1082.   my ($type,$host,$database)= @_;
  1083.   my $self= {};
  1084.   my %limits;
  1085.   bless $self;
  1086.  
  1087.   $self->{'cmp_name'}        = "empress";
  1088.   $self->{'data_source'}        = "DBI:EmpressNet:SERVER=$host;Database=/usr/local/empress/rdbms/bin/$database";
  1089.   $self->{'limits'}        = \%limits;
  1090.   $self->{'smds'}        = \%smds;
  1091.   $self->{'blob'}        = "text";
  1092.   $self->{'text'}        = "text";
  1093.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  1094.   $self->{'drop_attr'}        = "";
  1095.  
  1096.   $limits{'max_conditions'}    = 1258;
  1097.   $limits{'max_columns'}    = 226;        # server is disconnecting????
  1098.             # above this value .... but can handle 2419 columns
  1099.             # maybe something for crash-me ... but how to check ???
  1100.   $limits{'max_tables'}        = 65000;    # Should be big enough
  1101.   $limits{'max_text_size'}    = 4095;        # max returned ....
  1102.   $limits{'query_size'}        = 65535;    # Not a limit, big enough
  1103.   $limits{'max_index'}        = 64;        # Big enough
  1104.   $limits{'max_index_parts'}    = 64;        # Big enough
  1105.   $limits{'max_column_name'}     = 31;
  1106.  
  1107.   $limits{'join_optimizer'}    = 1;
  1108.   $limits{'load_data_infile'}    = 0;
  1109.   $limits{'lock_tables'}    = 1;
  1110.   $limits{'functions'}        = 1;
  1111.   $limits{'group_functions'}    = 1;
  1112.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  1113.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  1114.   $limits{'select_without_from'}= 0;
  1115.   $limits{'multi_drop'}        = 0;
  1116.   $limits{'subqueries'}        = 1;
  1117.   $limits{'table_wildcard'}    = 0;
  1118.   $limits{'having_with_alias'}  = 0;     # AS isn't supported in a select
  1119.   $limits{'having_with_group'}    = 1;
  1120.   $limits{'like_with_column'}    = 1;
  1121.   $limits{'order_by_position'}  = 1;
  1122.   $limits{'group_by_position'}  = 0;
  1123.   $limits{'alter_table'}    = 1;
  1124.   $limits{'alter_add_multi_col'}= 0;
  1125.   $limits{'alter_table_dropcol'}= 0;
  1126.  
  1127.   $limits{'group_func_extra_std'}= 0;    # Have group function std().
  1128.  
  1129.   $limits{'func_odbc_mod'}    = 0;
  1130.   $limits{'func_extra_%'}    = 1;
  1131.   $limits{'func_odbc_floor'}    = 1;
  1132.   $limits{'func_extra_if'}    = 0;
  1133.   $limits{'column_alias'}    = 0;
  1134.   $limits{'NEG'}        = 1;
  1135.   $limits{'func_extra_in_num'}    = 0;
  1136.   $limits{'unique_index'}    = 1; # Unique index works or not
  1137.   $limits{'insert_select'}    = 1;
  1138.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  1139.   $limits{'order_by_unused'}    = 1;
  1140.   $limits{'working_all_fields'} = 1;
  1141.  
  1142.   # for the smds small benchmark test ....
  1143.   # the different cases per query ... EMPRESS
  1144.   $smds{'q1'}     = 'a';
  1145.   $smds{'q2'}     = '';
  1146.   $smds{'q3'}     = 'a';
  1147.   $smds{'q4'}     = 'a';
  1148.   $smds{'q5'}     = 'a';
  1149.   $smds{'q6'}     = 'a';
  1150.   $smds{'q7'}     = 'b';
  1151.   $smds{'q8'}     = 'd';
  1152.   $smds{'q9'}     = 'b';
  1153.   $smds{'q10'}     = 'a';
  1154.   $smds{'q11'}     = '';
  1155.   $smds{'q12'}     = 'd';
  1156.   $smds{'q13'}     = 'b';
  1157.   $smds{'q14'}     = 'b';
  1158.   $smds{'q15'}     = 'a';
  1159.   $smds{'q16'}     = '';
  1160.   $smds{'q17'}     = '';
  1161.   $smds{'time'} = 1;    # the use of the time table -> 1 is on.
  1162.             # when 0 then the date field must be a
  1163.             # date field not a int field!!!
  1164.   return $self;
  1165. }
  1166.  
  1167. #
  1168. # Get the version number of the database
  1169. #
  1170.  
  1171. sub version
  1172. {
  1173.   my ($self,$dbh)=@_;
  1174.   my ($version);
  1175.   $version="";
  1176.   if (-x "/usr/local/empress/rdbms/bin/empvers")
  1177.   {
  1178.     $version=`/usr/local/empress/rdbms/bin/empvers | grep Version`;
  1179.   }
  1180.   if ($version)
  1181.   {
  1182.     chomp($version);
  1183.   }
  1184.   else
  1185.   {
  1186.     $version="Empress version ???";
  1187.   }
  1188.   return $version;
  1189. }
  1190.  
  1191. sub connect
  1192. {
  1193.   my ($self)=@_;
  1194.   my ($dbh);
  1195.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  1196.             $main::opt_password,{ PrintError => 0}) ||
  1197.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  1198.   return $dbh;
  1199. }
  1200.  
  1201. sub insert_file {
  1202.   my($self,$dbname, $file) = @_;
  1203.   my($command,$sth);
  1204.   $command = "insert into $dbname from '$file'";
  1205.   print "$command\n" if ($opt_debug);
  1206.   $sth = $dbh->do($command) or die $DBI::errstr;
  1207.  
  1208.   return $sth;
  1209. }
  1210.  
  1211. #
  1212. # Returns a list of statements to create a table
  1213. # The field types are in ANSI SQL format.
  1214. #
  1215.  
  1216. sub create
  1217. {
  1218.   my($self,$table_name,$fields,$index) = @_;
  1219.   my($query,@queries,$nr);
  1220.  
  1221.   $query="create table $table_name (";
  1222.   foreach $field (@$fields)
  1223.   {
  1224.     $field =~ s/mediumint/int/i;
  1225.     $field =~ s/tinyint/int/i;
  1226.     $field =~ s/smallint/int/i;
  1227.     $field =~ s/longint/int/i;
  1228.     $field =~ s/integer/int/i;
  1229.     $field =~ s/ double/ longfloat/i;
  1230.     # Solid doesn't have blob, it has long varchar
  1231. #    $field =~ s/ blob/ text(65535,65535,65535,65535)/;
  1232.     $field =~ s/ blob/ text/;
  1233.     $field =~ s/ varchar\((\d+)\)/ char($1,3)/;
  1234.     $field =~ s/ char\((\d+)\)/ char($1,3)/;
  1235.     $field =~ s/ decimal/ float/i;
  1236.     $field =~ s/ big_decimal/ longfloat/i;
  1237.     $field =~ s/ date/ int/i;
  1238.     $field =~ s/ float(.*)/ float/i;
  1239.     if ($field =~ / int\((\d+)\)/) {
  1240.       if ($1 > 4) {
  1241.         $field =~ s/ int\(\d+\)/ longinteger/i;
  1242.       } else {
  1243.         $field =~ s/ int\(\d+\)/ longinteger/i;
  1244.       }
  1245.     } else {
  1246.       $field =~ s/ int/ longinteger/i;
  1247.     }
  1248.     $query.= $field . ',';
  1249.   }
  1250.   substr($query,-1)=")";        # Remove last ',';
  1251.   push(@queries,$query);
  1252.   $nr=1;
  1253.   foreach $index (@$index)
  1254.   {
  1255.     # Primary key is unique index in Empress
  1256.     $index =~ s/primary key/unique index/i;
  1257.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  1258.     {
  1259.       $nr++;
  1260.       push(@queries,"create unique index ${table_name}_$nr on $table_name ($1)");
  1261.     }
  1262.     else
  1263.     {
  1264.       if (!($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i))
  1265.       {
  1266.     die "Can't parse index information in '$index'\n";
  1267.       }
  1268.       push(@queries,"create $1 ${table_name}_$2 on $table_name $3");
  1269.     }
  1270.   }
  1271.   return @queries;
  1272. }
  1273.  
  1274. # empress can't handle an alias and but can handle the number of the
  1275. # columname - so
  1276. # select test as foo from tmp order by foo
  1277. # becomes
  1278. # select test from tmp order by 1
  1279. #
  1280. sub query {
  1281.   my($self,$sql) = @_;
  1282.   my(@select,$i,$tmp,$newselect,$neworder,@order,$key,%change);
  1283.   my($tmp1,$otmp,$tmp2);
  1284.  
  1285.   if ($sql =~ /\s+as\s+/i)
  1286.   {
  1287.     if ($sql =~ /select\s+(.*)\s+from/i) {
  1288.       $newselect = $1;
  1289.       (@select) = split(/,\s*/, $1);
  1290.       $i = 1;
  1291.       foreach $tmp (@select) {
  1292.     if ($tmp =~ /\s+as\s+(\w+)/) {
  1293.       $change{$1} = $i;
  1294.     }
  1295.     $i++;
  1296.       }
  1297.     }
  1298.     $newselect =~ s/\s+as\s+(\w+)//gi;
  1299.     $tmp2 = 0;
  1300.     if ($sql =~ /order\s+by\s+(.*)$/i) {
  1301.       (@order) = split(/,\s*/, $1);
  1302.       foreach $otmp (@order) {
  1303.     foreach $key (sort {$a cmp $b} keys %change) {
  1304.       if ($otmp eq $key) {
  1305.         $neworder .= "$tmp1"."$change{$key}";
  1306.         $tmp1 = ", ";
  1307.         $tmp2 = 1;
  1308.       } elsif ($otmp =~ /(\w+)\s+(.+)$/) {
  1309.         if ($key eq $1) {
  1310.           $neworder .= "$tmp1"."$change{$key} $2";
  1311.           $tmp2 = 1;
  1312.         }
  1313.       }
  1314.     }
  1315.     if ($tmp2 == 0) {
  1316.       $neworder .= "$tmp1"."$otmp";
  1317.     }
  1318.     $tmp2 = 0;
  1319.     $tmp1 = ", ";
  1320.       }
  1321.     }
  1322.     $sql =~ s/(select)\s+(.*)\s+(from)/$1 $newselect $3/i;
  1323.     $sql =~ s/(order\s+by)\s+(.*)$/$1 $neworder/i;
  1324.   }
  1325.   return $sql;
  1326. }
  1327.  
  1328. sub drop_index
  1329. {
  1330.   my ($self,$table,$index) = @_;
  1331.   return "DROP INDEX $index";
  1332. }
  1333.  
  1334. # This is a because of the 200 statement problem with DBI-Empress
  1335.  
  1336. sub abort_if_fatal_error
  1337. {
  1338.   if ($DBI::errstr =~ /Overflow of table of prepared statements/i)
  1339.   {
  1340.     print "Overflow of prepared statements ... killing the process\n";
  1341.     exit 1;
  1342.   }
  1343.   return 0;
  1344. }
  1345.  
  1346. sub small_rollback_segment
  1347. {
  1348.   return 0;
  1349. }
  1350.  
  1351. sub reconnect_on_errors
  1352. {
  1353.   return 0;
  1354. }
  1355.  
  1356. #############################################################################
  1357. #                     Definitions for Oracle
  1358. #############################################################################
  1359.  
  1360. package db_Oracle;
  1361.  
  1362. sub new
  1363. {
  1364.   my ($type,$host,$database)= @_;
  1365.   my $self= {};
  1366.   my %limits;
  1367.   bless $self;
  1368.  
  1369.   $self->{'cmp_name'}        = "Oracle";
  1370.   $self->{'data_source'}    = "DBI:Oracle:$database";
  1371.   $self->{'limits'}        = \%limits;
  1372.   $self->{'smds'}        = \%smds;
  1373.   $self->{'blob'}        = "long";
  1374.   $self->{'text'}        = "long";
  1375.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  1376.   $self->{'drop_attr'}        = "";
  1377.   $self->{"vacuum"}        = 1;
  1378.  
  1379.   $limits{'max_conditions'}    = 9999; # (Actually not a limit)
  1380.   $limits{'max_columns'}    = 254;    # Max number of columns in table
  1381.   $limits{'max_tables'}        = 65000; # Should be big enough
  1382.   $limits{'max_text_size'}    = 2000; # Limit for blob test-connect
  1383.   $limits{'query_size'}        = 65525; # Max size with default buffers.
  1384.   $limits{'max_index'}        = 16; # Max number of keys
  1385.   $limits{'max_index_parts'}    = 16; # Max segments/key
  1386.   $limits{'max_column_name'} = 32; # max table and column name
  1387.  
  1388.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  1389.   $limits{'load_data_infile'}    = 0; # Has load data infile
  1390.   $limits{'lock_tables'}    = 0; # Has lock tables
  1391.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  1392.   $limits{'group_functions'}    = 1; # Have group functions
  1393.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  1394.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  1395.   $limits{'select_without_from'}= 0;
  1396.   $limits{'multi_drop'}        = 0;
  1397.   $limits{'subqueries'}        = 1;
  1398.   $limits{'left_outer_join'}    = 0; # This may be fixed in the query module
  1399.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  1400.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  1401.   $limits{'having_with_group'}    = 1; # Can't use group functions in HAVING
  1402.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  1403.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  1404.   $limits{'group_by_position'}  = 0;
  1405.   $limits{'alter_table'}    = 1;
  1406.   $limits{'alter_add_multi_col'}= 0;
  1407.   $limits{'alter_table_dropcol'}= 0;
  1408.  
  1409.   $limits{'group_func_extra_std'}    = 0; # Have group function std().
  1410.  
  1411.   $limits{'func_odbc_mod'}    = 0; # Oracle has problem with mod()
  1412.   $limits{'func_extra_%'}    = 0; # Has % as alias for mod()
  1413.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  1414.   $limits{'func_extra_if'}    = 0; # Have function if.
  1415.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  1416.   $limits{'NEG'}        = 1; # Supports -id
  1417.   $limits{'func_extra_in_num'}    = 1; # Has function in
  1418.   $limits{'unique_index'}    = 1; # Unique index works or not
  1419.   $limits{'insert_select'}    = 1;
  1420.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  1421.   $limits{'order_by_unused'}    = 1;
  1422.   $limits{'working_all_fields'} = 1;
  1423.  
  1424.   $smds{'time'}            = 1;
  1425.   $smds{'q1'}     = 'b';        # with time not supp by mysql ('')
  1426.   $smds{'q2'}     = 'b';
  1427.   $smds{'q3'}     = 'b';        # with time ('')
  1428.   $smds{'q4'}     = 'c';        # with time not supp by mysql (d)
  1429.   $smds{'q5'}     = 'b';        # with time not supp by mysql ('')
  1430.   $smds{'q6'}     = 'c';        # with time not supp by mysql ('')
  1431.   $smds{'q7'}     = 'c';
  1432.   $smds{'q8'}     = 'f';
  1433.   $smds{'q9'}     = 'c';
  1434.   $smds{'q10'}     = 'b';
  1435.   $smds{'q11'}     = 'b';
  1436.   $smds{'q12'}     = 'd';
  1437.   $smds{'q13'}     = 'c';
  1438.   $smds{'q14'}     = 'd';
  1439.   $smds{'q15'}     = 'd';
  1440.   $smds{'q16'}     = 'a';
  1441.   $smds{'q17'}     = 'c';
  1442.  
  1443.   return $self;
  1444. }
  1445.  
  1446. #
  1447. # Get the version number of the database
  1448. #
  1449.  
  1450. sub version
  1451. {
  1452.   my ($self)=@_;
  1453.   my ($dbh,$sth,$version,@row);
  1454.  
  1455.   $dbh=$self->connect();
  1456.   $sth = $dbh->prepare("select VERSION from product_component_version WHERE PRODUCT like 'Oracle%'") or die $DBI::errstr;
  1457.   $version="Oracle 7.x";
  1458.   if ($sth->execute && (@row = $sth->fetchrow_array))
  1459.   {
  1460.     $version="Oracle $row[0]";
  1461.   }
  1462.   $sth->finish;
  1463.   $dbh->disconnect;
  1464.   return $version;
  1465. }
  1466.  
  1467. sub connect
  1468. {
  1469.   my ($self)=@_;
  1470.   my ($dbh);
  1471.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  1472.             $main::opt_password,{ PrintError => 0}) ||
  1473.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  1474.   return $dbh;
  1475. }
  1476.  
  1477. #
  1478. # Returns a list of statements to create a table
  1479. # The field types are in ANSI SQL format.
  1480. #
  1481. # If one uses $main::opt_fast then one is allowed to use
  1482. # non standard types to get better speed.
  1483. #
  1484.  
  1485. sub create
  1486. {
  1487.   my($self,$table_name,$fields,$index) = @_;
  1488.   my($query,@queries,$ind,@keys);
  1489.  
  1490.   $query="create table $table_name (";
  1491.   foreach $field (@$fields)
  1492.   {
  1493.     $field =~ s/ character\((\d+)\)/ char\($1\)/i;
  1494.     $field =~ s/ character varying\((\d+)\)/ varchar\($1\)/i;
  1495.     $field =~ s/ char varying\((\d+)\)/ varchar\($1\)/i;
  1496.     $field =~ s/ integer/ number\(38\)/i;
  1497.     $field =~ s/ int/ number\(38\)/i;
  1498.     $field =~ s/ tinyint/ number\(38\)/i;
  1499.     $field =~ s/ smallint/ number\(38\)/i;
  1500.     $field =~ s/ mediumint/ number\(38\)/i;
  1501.     $field =~ s/ tinynumber\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1502.     $field =~ s/ smallnumber\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1503.     $field =~ s/ mediumnumber\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1504.     $field =~ s/ number\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1505.     $field =~ s/ numeric\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1506.     $field =~ s/ decimal\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1507.     $field =~ s/ dec\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
  1508.     $field =~ s/ float/ number/;
  1509.     $field =~ s/ real/ number/;
  1510.     $field =~ s/ double precision/ number/;
  1511.     $field =~ s/ double/ number/;
  1512.     $field =~ s/ blob/ long/;
  1513.     $query.= $field . ',';
  1514.   }
  1515.  
  1516.   foreach $ind (@$index)
  1517.   {
  1518.     my @index;
  1519.     if ( $ind =~ /\bKEY\b/i ){
  1520.       push(@keys,"ALTER TABLE $table_name ADD $ind");
  1521.     }else{
  1522.       my @fields = split(' ',$index);
  1523.       my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
  1524.       push(@index,$query);
  1525.     }
  1526.   }
  1527.   substr($query,-1)=")";        # Remove last ',';
  1528.   push(@queries,$query,@keys,@index);
  1529. #print "query:$query\n";
  1530.  
  1531.   return @queries;
  1532. }
  1533.  
  1534. sub insert_file {
  1535.   my($self,$dbname, $file) = @_;
  1536.   print "insert an ascii file isn't supported by Oracle (?)\n";
  1537.   return 0;
  1538. }
  1539.  
  1540. #
  1541. # Do any conversions to the ANSI SQL query so that the database can handle it
  1542. #
  1543.  
  1544. sub query {
  1545.   my($self,$sql) = @_;
  1546.   return $sql;
  1547. }
  1548.  
  1549. sub drop_index
  1550. {
  1551.   my ($self,$table,$index) = @_;
  1552.   return "DROP INDEX $index";
  1553. }
  1554.  
  1555. #
  1556. # Abort if the server has crashed
  1557. # return: 0 if ok
  1558. #      1 question should be retried
  1559. #
  1560.  
  1561. sub abort_if_fatal_error
  1562. {
  1563.   return 0;
  1564. }
  1565.  
  1566. sub small_rollback_segment
  1567. {
  1568.   return 1;
  1569. }
  1570.  
  1571. sub reconnect_on_errors
  1572. {
  1573.   return 0;
  1574. }
  1575.  
  1576. #
  1577. # optimize the tables ....
  1578. #
  1579. sub vacuum
  1580. {
  1581.   my ($self,$full_vacuum,$dbh_ref)=@_;
  1582.   my ($loop_time,$end_time,$sth,$dbh);
  1583.  
  1584.   if (defined($full_vacuum))
  1585.   {
  1586.     $$dbh_ref->disconnect;  $$dbh_ref= $self->connect();
  1587.   }
  1588.   $dbh=$$dbh_ref;
  1589.   $loop_time=new Benchmark;
  1590.   # first analyze all tables
  1591.   $sth = $dbh->prepare("select table_name from user_tables") || die "Got error: $DBI::errstr";
  1592.   $sth->execute || die "Got error: $DBI::errstr when select user_tables";
  1593.   while (my @r = $sth->fetchrow_array)
  1594.   {
  1595.     $dbh->do("analyze table $r[0] compute statistics") || die "Got error: $DBI::errstr when executing 'analyze table'\n";
  1596.   }
  1597.   # now analyze all indexes ...
  1598.   $sth = $dbh->prepare("select index_name from user_indexes") || die "Got error: $DBI::errstr";
  1599.   $sth->execute || die "Got error: $DBI::errstr when select user_indexes";
  1600.   while (my @r1 = $sth->fetchrow_array)
  1601.   {
  1602.     $dbh->do("analyze index $r1[0] compute statistics") || die "Got error: $DBI::errstr when executing 'analyze index $r1[0]'\n";
  1603.   }
  1604.   $end_time=new Benchmark;
  1605.   print "Time for book-keeping (1): " .
  1606.   Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"all") . "\n\n";
  1607.   $dbh->disconnect;  $$dbh_ref= $self->connect();
  1608. }
  1609.  
  1610.  
  1611. #############################################################################
  1612. #                     Definitions for Informix
  1613. #############################################################################
  1614.  
  1615. package db_Informix;
  1616.  
  1617. sub new
  1618. {
  1619.   my ($type,$host,$database)= @_;
  1620.   my $self= {};
  1621.   my %limits;
  1622.   bless $self;
  1623.  
  1624.   $self->{'cmp_name'}        = "Informix";
  1625.   $self->{'data_source'}    = "DBI:Informix:$database";
  1626.   $self->{'limits'}        = \%limits;
  1627.   $self->{'smds'}        = \%smds;
  1628.   $self->{'blob'}        = "byte in table";
  1629.   $self->{'text'}        = "byte in table";
  1630.   $self->{'double_quotes'}    = 0; # Can handle:  'Walker''s'
  1631.   $self->{'drop_attr'}        = "";
  1632.   $self->{'host'}        = $host;
  1633.  
  1634.   $limits{'NEG'}        = 1; # Supports -id
  1635.   $limits{'alter_table'}    = 1;
  1636.   $limits{'alter_add_multi_col'}= 0;
  1637.   $limits{'alter_table_dropcol'}= 1;
  1638.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  1639.   $limits{'func_extra_%'}    = 0; # Has % as alias for mod()
  1640.   $limits{'func_extra_if'}    = 0; # Have function if.
  1641.   $limits{'func_extra_in_num'}= 0; # Has function in
  1642.   $limits{'func_odbc_floor'}    = 0; # Has func_odbc_floor function
  1643.   $limits{'func_odbc_mod'}    = 1; # Have function mod.
  1644.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  1645.   $limits{'group_by_position'}  = 1; # Can use 'GROUP BY 1'
  1646.   $limits{'group_by_alias'}  = 0; # Can use 'select a as ab from x GROUP BY ab'
  1647.   $limits{'group_func_extra_std'} = 0; # Have group function std().
  1648.   $limits{'group_functions'}    = 1; # Have group functions
  1649.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  1650.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  1651.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  1652.   $limits{'having_with_group'}= 1; # Can't use group functions in HAVING
  1653.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables (always 1 only for msql)
  1654.   $limits{'left_outer_join'}    = 0; # Supports left outer joins (ANSI)
  1655.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  1656.   $limits{'load_data_infile'}    = 0; # Has load data infile
  1657.   $limits{'lock_tables'}    = 1; # Has lock tables
  1658.   $limits{'max_conditions'}    = 1214; # (Actually not a limit)
  1659.   $limits{'max_column_name'}    = 18; # max table and column name
  1660.   $limits{'max_columns'}    = 994;    # Max number of columns in table
  1661.   $limits{'max_tables'}        = 65000;    # Should be big enough
  1662.   $limits{'max_index'}        = 64; # Max number of keys
  1663.   $limits{'max_index_parts'}    = 15; # Max segments/key
  1664.   $limits{'max_text_size'}    = 65535;  # Max size with default buffers. ??
  1665.   $limits{'multi_drop'}        = 0; # Drop table can take many tables
  1666.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  1667.   $limits{'query_size'}        = 32766; # Max size with default buffers.
  1668.   $limits{'select_without_from'}= 0; # Can do 'select 1';
  1669.   $limits{'subqueries'}        = 1; # Doesn't support sub-queries.
  1670.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  1671.   $limits{'unique_index'}    = 1; # Unique index works or not
  1672.   $limits{'insert_select'}    = 1;
  1673.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  1674.   $limits{'order_by_unused'}    = 1;
  1675.   $limits{'working_all_fields'} = 1;
  1676.  
  1677.   return $self;
  1678. }
  1679.  
  1680. #
  1681. # Get the version number of the database
  1682. #
  1683.  
  1684. sub version
  1685. {
  1686.   my ($self)=@_;
  1687.   my ($dbh,$sth,$version,@row);
  1688.  
  1689.   $ENV{'INFORMIXSERVER'} = $self->{'host'};
  1690.   $dbh=$self->connect();
  1691.   $sth = $dbh->prepare("SELECT owner FROM systables WHERE tabname = ' VERSION'")
  1692.                               or die $DBI::errstr;
  1693.   $version='Informix unknown';
  1694.   if ($sth->execute && (@row = $sth->fetchrow_array))
  1695.   {
  1696.     $version="Informix $row[0]";
  1697.   }
  1698.   $sth->finish;
  1699.   $dbh->disconnect;
  1700.   return $version;
  1701. }
  1702.  
  1703. sub connect
  1704. {
  1705.   my ($self)=@_;
  1706.   my ($dbh);
  1707.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  1708.             $main::opt_password,{ PrintError => 0}) ||
  1709.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  1710.   return $dbh;
  1711. }
  1712.  
  1713.  
  1714. #
  1715. # Create table
  1716. #
  1717.  
  1718. sub create
  1719. {
  1720.   my($self,$table_name,$fields,$index) = @_;
  1721.   my($query,@queries,$name,$nr);
  1722.  
  1723.   $query="create table $table_name (";
  1724.   foreach $field (@$fields)
  1725.   {
  1726. #    $field =~ s/\btransport_description\b/transport_desc/;
  1727.                 # to overcome limit 18 chars
  1728.     $field =~ s/tinyint/smallint/i;
  1729.     $field =~ s/tinyint\(\d+\)/smallint/i;
  1730.     $field =~ s/mediumint/integer/i;
  1731.     $field =~ s/mediumint\(\d+\)/integer/i;
  1732.     $field =~ s/smallint\(\d+\)/smallint/i;
  1733.     $field =~ s/integer\(\d+\)/integer/i;
  1734.     $field =~ s/int\(\d+\)/integer/i;
  1735. #    $field =~ s/\b(?:small)?int(?:eger)?\((\d+)\)/decimal($1)/i;
  1736. #    $field =~ s/float(\(\d*,\d*\)){0,1}/real/i;
  1737.     $field =~ s/(float|double)(\(.*?\))?/float/i;
  1738.  
  1739.     if ($field =~ / blob/i)
  1740.     {
  1741.       $name=$self->{'blob'};
  1742.       $field =~ s/ blob/ $name/;
  1743.     }
  1744.     $query.= $field . ',';
  1745.   }
  1746.   substr($query,-1)=")";        # Remove last ',';
  1747.   push(@queries,$query);
  1748.   $nr=0;
  1749.  
  1750.   foreach $index (@$index)
  1751.   {
  1752.     # Primary key is unique index in Informix
  1753.     $index =~ s/primary key/unique index primary/i;
  1754.     if ($index =~ /^unique\s*\(([^\(]*)\)$/i)
  1755.     {
  1756.       $nr++;
  1757.       push(@queries,"create unique index ${table_name}_$nr on $table_name ($1)");
  1758.     }
  1759.     else
  1760.     {
  1761.       if (!($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i))
  1762.       {
  1763.     die "Can't parse index information in '$index'\n";
  1764.       }
  1765.       ### push(@queries,"create $1 ${table_name}_$2 on $table_name $3");
  1766.       $nr++;
  1767.       push(@queries,"create $1 ${table_name}_$nr on $table_name $3");
  1768.     }
  1769.   }
  1770.   return @queries;
  1771. }
  1772. #
  1773. # Some test needed this
  1774. #
  1775.  
  1776. sub query {
  1777.   my($self,$sql) = @_;
  1778.   return $sql;
  1779. }
  1780.  
  1781. sub drop_index
  1782. {
  1783.   my ($self,$table,$index) = @_;
  1784.   return "DROP INDEX $index";
  1785. }
  1786.  
  1787. #
  1788. # Abort if the server has crashed
  1789. # return: 0 if ok
  1790. #      1 question should be retried
  1791. #
  1792.  
  1793. sub abort_if_fatal_error
  1794. {
  1795.   return 0;
  1796. }
  1797.  
  1798. sub small_rollback_segment
  1799. {
  1800.   return 0;
  1801. }
  1802.  
  1803. sub reconnect_on_errors
  1804. {
  1805.   return 0;
  1806. }
  1807.  
  1808. #############################################################################
  1809. #         Configuration for Access
  1810. #############################################################################
  1811.  
  1812. package db_access;
  1813.  
  1814. sub new
  1815. {
  1816.   my ($type,$host,$database)= @_;
  1817.   my $self= {};
  1818.   my %limits;
  1819.   bless $self;
  1820.  
  1821.   $self->{'cmp_name'}        = "access";
  1822.   $self->{'data_source'}    = "DBI:ODBC:$database";
  1823.   if (defined($host) && $host ne "")
  1824.   {
  1825.     $self->{'data_source'}    .= ":$host";
  1826.   }
  1827.   $self->{'limits'}        = \%limits;
  1828.   $self->{'smds'}        = \%smds;
  1829.   $self->{'blob'}        = "blob";
  1830.   $self->{'text'}        = "blob"; # text ? 
  1831.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  1832.   $self->{'drop_attr'}        = "";
  1833.  
  1834.   $limits{'max_conditions'}    = 97; # We get 'Query is too complex'
  1835.   $limits{'max_columns'}    = 255;    # Max number of columns in table
  1836.   $limits{'max_tables'}        = 65000;    # Should be big enough
  1837.   $limits{'max_text_size'}    = 255;  # Max size with default buffers.
  1838.   $limits{'query_size'}        = 65535; # Not a limit, big enough
  1839.   $limits{'max_index'}        = 32; # Max number of keys
  1840.   $limits{'max_index_parts'}    = 10; # Max segments/key
  1841.   $limits{'max_column_name'}    = 64; # max table and column name
  1842.  
  1843.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  1844.   $limits{'load_data_infile'}    = 0; # Has load data infile
  1845.   $limits{'lock_tables'}    = 0; # Has lock tables
  1846.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  1847.   $limits{'group_functions'}    = 1; # Have group functions
  1848.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  1849.   $limits{'group_distinct_functions'}= 0; # Have count(distinct)
  1850.   $limits{'select_without_from'}= 1; # Can do 'select 1';
  1851.   $limits{'multi_drop'}        = 0; # Drop table can take many tables
  1852.   $limits{'subqueries'}        = 1; # Supports sub-queries.
  1853.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  1854.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  1855.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  1856.   $limits{'having_with_group'}    = 1; # Can use group functions in HAVING
  1857.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  1858.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  1859.   $limits{'group_by_position'}  = 0; # Can use 'GROUP BY 1'
  1860.   $limits{'alter_table'}    = 1;
  1861.   $limits{'alter_add_multi_col'}= 2; #Have ALTER TABLE t add a int, b int;
  1862.   $limits{'alter_table_dropcol'}= 1;
  1863.  
  1864.   $limits{'group_func_extra_std'} = 0; # Have group function std().
  1865.  
  1866.   $limits{'func_odbc_mod'}    = 0; # Have function mod.
  1867.   $limits{'func_extra_%'}    = 0; # Has % as alias for mod()
  1868.   $limits{'func_odbc_floor'}    = 0; # Has func_odbc_floor function
  1869.   $limits{'func_extra_if'}    = 0; # Have function if.
  1870.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  1871.   $limits{'NEG'}        = 1; # Supports -id
  1872.   $limits{'func_extra_in_num'}    = 1; # Has function in
  1873.   $limits{'unique_index'}    = 1; # Unique index works or not
  1874.   $limits{'insert_select'}    = 1;
  1875.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  1876.   $limits{'order_by_unused'}    = 1;
  1877.   $limits{'working_all_fields'} = 1;
  1878.   return $self;
  1879. }
  1880.  
  1881. #
  1882. # Get the version number of the database
  1883. #
  1884.  
  1885. sub version
  1886. {
  1887.   my ($self)=@_;
  1888.   return "Access 2000";        #DBI/ODBC can't return the server version
  1889. }
  1890.  
  1891. sub connect
  1892. {
  1893.   my ($self)=@_;
  1894.   my ($dbh);
  1895.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  1896.             $main::opt_password,{ PrintError => 0}) ||
  1897.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  1898.   return $dbh;
  1899. }
  1900.  
  1901. #
  1902. # Returns a list of statements to create a table
  1903. # The field types are in ANSI SQL format.
  1904. #
  1905.  
  1906. sub create
  1907. {
  1908.   my($self,$table_name,$fields,$index) = @_;
  1909.   my($query,@queries,$nr);
  1910.  
  1911.   $query="create table $table_name (";
  1912.   foreach $field (@$fields)
  1913.   {
  1914.     $field =~ s/mediumint/integer/i;
  1915.     $field =~ s/tinyint/smallint/i;
  1916.     $field =~ s/float\(\d+,\d+\)/float/i;
  1917.     $field =~ s/integer\(\d+\)/integer/i;
  1918.     $field =~ s/smallint\(\d+\)/smallint/i;
  1919.     $field =~ s/int\(\d+\)/integer/i;
  1920.     $field =~ s/blob/text/i;
  1921.     $query.= $field . ',';
  1922.   }
  1923.   substr($query,-1)=")";        # Remove last ',';
  1924.   push(@queries,$query);
  1925.   $nr=0;
  1926.   foreach $index (@$index)
  1927.   {
  1928.     $ext="WITH DISALLOW NULL";
  1929.     if (($index =~ s/primary key/unique index primary_key/i))
  1930.     {
  1931.       $ext="WITH PRIMARY;"
  1932.     }
  1933.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  1934.     {
  1935.       $nr++;
  1936.       $index="unique index ${table_name}_$nr ($1)";
  1937.     }
  1938.     $index =~ /^(.*)\s+(\(.*\))$/;
  1939.     push(@queries,"create ${1} on $table_name $2");
  1940.   }
  1941.   return @queries;
  1942. }
  1943.  
  1944. #
  1945. # Do any conversions to the ANSI SQL query so that the database can handle it
  1946. #
  1947.  
  1948. sub query {
  1949.   my($self,$sql) = @_;
  1950.   return $sql;
  1951. }
  1952.  
  1953. sub drop_index
  1954. {
  1955.   my ($self,$table,$index) = @_;
  1956.   return "DROP INDEX $index ON $table";
  1957. }
  1958.  
  1959. #
  1960. # Abort if the server has crashed
  1961. # return: 0 if ok
  1962. #      1 question should be retried
  1963. #
  1964.  
  1965. sub abort_if_fatal_error
  1966. {
  1967.   return 1 if (($DBI::errstr =~ /The database engine couldn\'t lock table/i) ||
  1968.                ($DBI::errstr =~ /niet vergrendelen. De tabel is momenteel in gebruik /i) ||
  1969.            ($DBI::errstr =~ /Den anv.* redan av en annan/i) ||
  1970.            ($DBI::errstr =~ /non-exclusive access/));
  1971.   return 0;
  1972. }
  1973.  
  1974. sub small_rollback_segment
  1975. {
  1976.   return 0;
  1977. }
  1978.  
  1979. sub reconnect_on_errors
  1980. {
  1981.   return 1;
  1982. }
  1983.  
  1984. #############################################################################
  1985. #         Configuration for Microsoft SQL server
  1986. #############################################################################
  1987.  
  1988. package db_ms_sql;
  1989.  
  1990. sub new
  1991. {
  1992.   my ($type,$host,$database)= @_;
  1993.   my $self= {};
  1994.   my %limits;
  1995.   bless $self;
  1996.  
  1997.   $self->{'cmp_name'}        = "ms-sql";
  1998.   $self->{'data_source'}    = "DBI:ODBC:$database";
  1999.   if (defined($host) && $host ne "")
  2000.   {
  2001.     $self->{'data_source'}    .= ":$host";
  2002.   }
  2003.   $self->{'limits'}        = \%limits;
  2004.   $self->{'smds'}        = \%smds;
  2005.   $self->{'blob'}        = "text";
  2006.   $self->{'text'}        = "text";
  2007.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  2008.   $self->{'drop_attr'}        = "";
  2009.  
  2010.   $limits{'max_conditions'}    = 1030; # We get 'Query is too complex'
  2011.   $limits{'max_columns'}    = 250;    # Max number of columns in table
  2012.   $limits{'max_tables'}        = 65000;    # Should be big enough
  2013.   $limits{'max_text_size'}    = 9830;  # Max size with default buffers.
  2014.   $limits{'query_size'}        = 9830; # Max size with default buffers.
  2015.   $limits{'max_index'}        = 64; # Max number of keys
  2016.   $limits{'max_index_parts'}    = 15; # Max segments/key
  2017.   $limits{'max_column_name'}    = 30; # max table and column name
  2018.  
  2019.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  2020.   $limits{'load_data_infile'}    = 0; # Has load data infile
  2021.   $limits{'lock_tables'}    = 0; # Has lock tables
  2022.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  2023.   $limits{'group_functions'}    = 1; # Have group functions
  2024.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  2025.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  2026.   $limits{'select_without_from'}= 1; # Can do 'select 1';
  2027.   $limits{'multi_drop'}        = 1; # Drop table can take many tables
  2028.   $limits{'subqueries'}        = 1; # Supports sub-queries.
  2029.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  2030.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  2031.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  2032.   $limits{'having_with_group'}    = 1; # Can't use group functions in HAVING
  2033.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  2034.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  2035.   $limits{'group_by_position'}  = 0; # Can use 'GROUP BY 1'
  2036.   $limits{'alter_table'}    = 1;
  2037.   $limits{'alter_add_multi_col'}= 0;
  2038.   $limits{'alter_table_dropcol'}= 0;
  2039.  
  2040.   $limits{'group_func_extra_std'} = 0; # Have group function std().
  2041.  
  2042.   $limits{'func_odbc_mod'}    = 0; # Have function mod.
  2043.   $limits{'func_extra_%'}    = 1; # Has % as alias for mod()
  2044.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  2045.   $limits{'func_extra_if'}    = 0; # Have function if.
  2046.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  2047.   $limits{'NEG'}        = 1; # Supports -id
  2048.   $limits{'func_extra_in_num'}    = 0; # Has function in
  2049.   $limits{'unique_index'}    = 1; # Unique index works or not
  2050.   $limits{'insert_select'}    = 1;
  2051.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  2052.   $limits{'order_by_unused'}    = 1;
  2053.   $limits{'working_all_fields'} = 1;
  2054.   return $self;
  2055. }
  2056.  
  2057. #
  2058. # Get the version number of the database
  2059. #
  2060.  
  2061. sub version
  2062. {
  2063.   my ($self)=@_;
  2064.   my($sth,@row);
  2065.   $dbh=$self->connect();
  2066.   $sth = $dbh->prepare("SELECT \@\@VERSION") or die $DBI::errstr;
  2067.   $sth->execute or die $DBI::errstr;
  2068.   @row = $sth->fetchrow_array;
  2069.   if ($row[0]) {
  2070.      @server = split(/\n/,$row[0]);
  2071.      chomp(@server);
  2072.      return "$server[0]";
  2073.   } else {
  2074.     return "Microsoft SQL server ?";
  2075.   }
  2076. }
  2077.  
  2078. sub connect
  2079. {
  2080.   my ($self)=@_;
  2081.   my ($dbh);
  2082.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  2083.             $main::opt_password,{ PrintError => 0}) ||
  2084.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  2085.   return $dbh;
  2086. }
  2087.  
  2088. #
  2089. # Returns a list of statements to create a table
  2090. # The field types are in ANSI SQL format.
  2091. #
  2092.  
  2093. sub create
  2094. {
  2095.   my($self,$table_name,$fields,$index) = @_;
  2096.   my($query,@queries,$nr);
  2097.  
  2098.   $query="create table $table_name (";
  2099.   foreach $field (@$fields)
  2100.   {
  2101.     $field =~ s/mediumint/integer/i;
  2102.     $field =~ s/float\(\d+,\d+\)/float/i;
  2103.     $field =~ s/double\(\d+,\d+\)/float/i;
  2104.     $field =~ s/double/float/i;
  2105.     $field =~ s/integer\(\d+\)/integer/i;
  2106.     $field =~ s/int\(\d+\)/integer/i;
  2107.     $field =~ s/smallint\(\d+\)/smallint/i;
  2108.     $field =~ s/smallinteger/smallint/i;
  2109.     $field =~ s/tinyint\(\d+\)/tinyint/i;
  2110.     $field =~ s/tinyinteger/tinyint/i;
  2111.     $field =~ s/blob/text/i;
  2112.     $query.= $field . ',';
  2113.   }
  2114.   substr($query,-1)=")";        # Remove last ',';
  2115.   push(@queries,$query);
  2116.   $nr=0;
  2117.   foreach $index (@$index)
  2118.   {
  2119.     $ext="WITH DISALLOW NULL";
  2120.     if (($index =~ s/primary key/unique index primary_key/i))
  2121.     {
  2122.       $ext="WITH PRIMARY;"
  2123.     }
  2124.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  2125.     {
  2126.       $nr++;
  2127.       $index="unique index ${table_name}_$nr ($1)";
  2128.     }
  2129.     $index =~ /^(.*)\s+(\(.*\))$/;
  2130.     push(@queries,"create ${1} on $table_name $2");
  2131.   }
  2132.   return @queries;
  2133. }
  2134.  
  2135. #
  2136. # Do any conversions to the ANSI SQL query so that the database can handle it
  2137. #
  2138.  
  2139. sub query {
  2140.   my($self,$sql) = @_;
  2141.   return $sql;
  2142. }
  2143.  
  2144. sub drop_index
  2145. {
  2146.   my ($self,$table,$index) = @_;
  2147.   return "DROP INDEX $table.$index";
  2148. }
  2149.  
  2150. #
  2151. # Abort if the server has crashed
  2152. # return: 0 if ok
  2153. #      1 question should be retried
  2154. #
  2155.  
  2156. sub abort_if_fatal_error
  2157. {
  2158.   return 0;
  2159. }
  2160.  
  2161. sub small_rollback_segment
  2162. {
  2163.   return 0;
  2164. }
  2165.  
  2166. sub reconnect_on_errors
  2167. {
  2168.   return 0;
  2169. }
  2170.  
  2171. #############################################################################
  2172. #         Configuration for Sybase
  2173. #############################################################################
  2174.  
  2175. package db_sybase;
  2176.  
  2177. sub new
  2178. {
  2179.   my ($type,$host,$database)= @_;
  2180.   my $self= {};
  2181.   my %limits;
  2182.   bless $self;
  2183.  
  2184.   $self->{'cmp_name'}        = "sybase";
  2185.   $self->{'data_source'}    = "DBI:ODBC:$database";
  2186.   if (defined($host) && $host ne "")
  2187.   {
  2188.     $self->{'data_source'}    .= ":$host";
  2189.   }
  2190.   $self->{'limits'}        = \%limits;
  2191.   $self->{'smds'}        = \%smds;
  2192.   $self->{'blob'}        = "text";
  2193.   $self->{'text'}        = "text";
  2194.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  2195.   $self->{'drop_attr'}        = "";
  2196.   $self->{"vacuum"}        = 1;
  2197.  
  2198.   $limits{'max_conditions'}    = 1030; # We get 'Query is too complex'
  2199.   $limits{'max_columns'}    = 250;    # Max number of columns in table
  2200.   $limits{'max_tables'}        = 65000;    # Should be big enough
  2201.   $limits{'max_text_size'}    = 9830;  # Max size with default buffers.
  2202.   $limits{'query_size'}        = 9830; # Max size with default buffers.
  2203.   $limits{'max_index'}        = 64; # Max number of keys
  2204.   $limits{'max_index_parts'}    = 15; # Max segments/key
  2205.   $limits{'max_column_name'}    = 30; # max table and column name
  2206.  
  2207.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  2208.   $limits{'load_data_infile'}    = 0; # Has load data infile
  2209.   $limits{'lock_tables'}    = 0; # Has lock tables
  2210.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  2211.   $limits{'group_functions'}    = 1; # Have group functions
  2212.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  2213.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  2214.   $limits{'select_without_from'}= 1; # Can do 'select 1';
  2215.   $limits{'multi_drop'}        = 1; # Drop table can take many tables
  2216.   $limits{'subqueries'}        = 1; # Supports sub-queries.
  2217.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  2218.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  2219.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  2220.   $limits{'having_with_group'}    = 1; # Can't use group functions in HAVING
  2221.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  2222.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  2223.   $limits{'group_by_position'}  = 0; # Can use 'GROUP BY 1'
  2224.   $limits{'alter_table'}    = 1;
  2225.   $limits{'alter_add_multi_col'}= 0;
  2226.   $limits{'alter_table_dropcol'}= 0;
  2227.  
  2228.   $limits{'group_func_extra_std'} = 0; # Have group function std().
  2229.  
  2230.   $limits{'func_odbc_mod'}    = 0; # Have function mod.
  2231.   $limits{'func_extra_%'}    = 1; # Has % as alias for mod()
  2232.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  2233.   $limits{'func_extra_if'}    = 0; # Have function if.
  2234.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  2235.   $limits{'NEG'}        = 1; # Supports -id
  2236.   $limits{'func_extra_in_num'}    = 0; # Has function in
  2237.   $limits{'unique_index'}    = 1; # Unique index works or not
  2238.   $limits{'insert_select'}    = 1;
  2239.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  2240.   $limits{'order_by_unused'}    = 1;
  2241.   $limits{'working_all_fields'} = 1;
  2242.   return $self;
  2243. }
  2244.  
  2245. #
  2246. # Get the version number of the database
  2247. #
  2248.  
  2249. sub version
  2250. {
  2251.   my ($self)=@_;
  2252.   return "Sybase enterprise 11.5 NT";        #DBI/ODBC can't return the server version
  2253. }
  2254.  
  2255. sub connect
  2256. {
  2257.   my ($self)=@_;
  2258.   my ($dbh);
  2259.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  2260.             $main::opt_password,{ PrintError => 0}) ||
  2261.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  2262.   return $dbh;
  2263. }
  2264.  
  2265. #
  2266. # Returns a list of statements to create a table
  2267. # The field types are in ANSI SQL format.
  2268. #
  2269.  
  2270. sub create
  2271. {
  2272.   my($self,$table_name,$fields,$index) = @_;
  2273.   my($query,@queries,$nr);
  2274.  
  2275.   $query="create table $table_name (";
  2276.   foreach $field (@$fields)
  2277.   {
  2278.     $field =~ s/mediumint/integer/i;
  2279.     $field =~ s/float\(\d+,\d+\)/float/i;
  2280.     $field =~ s/int\(\d+\)/int/i;
  2281.     $field =~ s/double/float/i;
  2282.     $field =~ s/integer\(\d+\)/integer/i;
  2283.     $field =~ s/smallint\(\d+\)/smallint/i;
  2284.     $field =~ s/tinyint\(\d+\)/tinyint/i;
  2285.     $field =~ s/blob/text/i;
  2286.     $query.= $field . ',';
  2287.   }
  2288.   substr($query,-1)=")";        # Remove last ',';
  2289.   push(@queries,$query);
  2290.   $nr=0;
  2291.   foreach $index (@$index)
  2292.   {
  2293. #    $ext="WITH DISALLOW NULL";
  2294.     if (($index =~ s/primary key/unique index primary_key/i))
  2295.     {
  2296. #      $ext="WITH PRIMARY;"
  2297.     }
  2298.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  2299.     {
  2300.       $nr++;
  2301.       $index="unique index ${table_name}_$nr ($1)";
  2302.     }
  2303.     $index =~ /^(.*)\s+(\(.*\))$/;
  2304.     push(@queries,"create ${1} on $table_name $2");
  2305.   }
  2306.   return @queries;
  2307. }
  2308.  
  2309. #
  2310. # Do any conversions to the ANSI SQL query so that the database can handle it
  2311. #
  2312.  
  2313. sub query {
  2314.   my($self,$sql) = @_;
  2315.   return $sql;
  2316. }
  2317.  
  2318. sub drop_index
  2319. {
  2320.   my ($self,$table,$index) = @_;
  2321.   return "DROP INDEX $table.$index";
  2322. }
  2323.  
  2324. #
  2325. # Abort if the server has crashed
  2326. # return: 0 if ok
  2327. #      1 question should be retried
  2328. #
  2329.  
  2330. sub abort_if_fatal_error
  2331. {
  2332.   return 0;
  2333. }
  2334.  
  2335. sub small_rollback_segment
  2336. {
  2337.   return 0;
  2338. }
  2339.  
  2340. sub reconnect_on_errors
  2341. {
  2342.   return 0;
  2343. }
  2344.  
  2345. #
  2346. # optimize the tables ....
  2347. #
  2348. sub vacuum
  2349. {
  2350.   my ($self,$full_vacuum,$dbh_ref)=@_;
  2351.   my ($loop_time,$end_time,$dbh);
  2352.  
  2353.   if (defined($full_vacuum))
  2354.   {
  2355.     $$dbh_ref->disconnect;  $$dbh_ref= $self->connect();
  2356.   }
  2357.   $dbh=$$dbh_ref;
  2358.   $loop_time=new Benchmark;
  2359.   $dbh->do("analyze table ?? compute statistics") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
  2360.   $end_time=new Benchmark;
  2361.   print "Time for book-keeping (1): " .
  2362.   Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"all") . "\n\n";
  2363.   $dbh->disconnect;  $$dbh_ref= $self->connect();
  2364. }
  2365.  
  2366.  
  2367. #############################################################################
  2368. #                     Definitions for Adabas
  2369. #############################################################################
  2370.  
  2371. package db_Adabas;
  2372.  
  2373. sub new
  2374. {
  2375.   my ($type,$host,$database)= @_;
  2376.   my $self= {};
  2377.   my %limits;
  2378.   bless $self;
  2379.  
  2380.   $self->{'cmp_name'}        = "Adabas";
  2381.   $self->{'data_source'}    = "DBI:Adabas:$database";
  2382.   $self->{'limits'}        = \%limits;
  2383.   $self->{'smds'}        = \%smds;
  2384.   $self->{'blob'}        = "long";
  2385.   $self->{'text'}        = "long";
  2386.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  2387.   $self->{'drop_attr'}        = "";
  2388.  
  2389.   $limits{'max_conditions'}    = 50; # (Actually not a limit)
  2390.   $limits{'max_columns'}    = 254;    # Max number of columns in table
  2391.   $limits{'max_tables'}        = 65000;    # Should be big enough
  2392.   $limits{'max_text_size'}    = 2000; # Limit for blob test-connect
  2393.   $limits{'query_size'}        = 65525; # Max size with default buffers.
  2394.   $limits{'max_index'}        = 16; # Max number of keys
  2395.   $limits{'max_index_parts'}    = 16; # Max segments/key
  2396.   $limits{'max_column_name'} = 32; # max table and column name
  2397.  
  2398.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  2399.   $limits{'load_data_infile'}    = 0; # Has load data infile
  2400.   $limits{'lock_tables'}    = 0; # Has lock tables
  2401.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  2402.   $limits{'group_functions'}    = 1; # Have group functions
  2403.   $limits{'group_func_sql_min_str'}    = 1; # Can execute MIN() and MAX() on strings
  2404.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  2405.   $limits{'select_without_from'}= 0;
  2406.   $limits{'multi_drop'}        = 0;
  2407.   $limits{'subqueries'}        = 1;
  2408.   $limits{'left_outer_join'}    = 0; # This may be fixed in the query module
  2409.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  2410.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  2411.   $limits{'having_with_group'}    = 1; # Can't use group functions in HAVING
  2412.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  2413.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  2414.   $limits{'group_by_position'}  = 1;
  2415.   $limits{'alter_table'}    = 1;
  2416.   $limits{'alter_add_multi_col'}= 2; #Have ALTER TABLE t add a int, b int;
  2417.   $limits{'alter_table_dropcol'}= 1;
  2418.  
  2419.   $limits{'group_func_extra_std'}    = 0; # Have group function std().
  2420.  
  2421.   $limits{'func_odbc_mod'}    = 0; # Oracle has problem with mod()
  2422.   $limits{'func_extra_%'}    = 0; # Has % as alias for mod()
  2423.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  2424.   $limits{'func_extra_if'}    = 0; # Have function if.
  2425.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  2426.   $limits{'NEG'}        = 1; # Supports -id
  2427.   $limits{'func_extra_in_num'}    = 1; # Has function in
  2428.   $limits{'unique_index'}    = 1; # Unique index works or not
  2429.   $limits{'insert_select'}    = 1;
  2430.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  2431.   $limits{'order_by_unused'}    = 1;
  2432.   $limits{'working_all_fields'} = 1;
  2433.  
  2434.   $smds{'time'}            = 1;
  2435.   $smds{'q1'}     = 'b';        # with time not supp by mysql ('')
  2436.   $smds{'q2'}     = 'b';
  2437.   $smds{'q3'}     = 'b';        # with time ('')
  2438.   $smds{'q4'}     = 'c';        # with time not supp by mysql (d)
  2439.   $smds{'q5'}     = 'b';        # with time not supp by mysql ('')
  2440.   $smds{'q6'}     = 'c';        # with time not supp by mysql ('')
  2441.   $smds{'q7'}     = 'c';
  2442.   $smds{'q8'}     = 'f';
  2443.   $smds{'q9'}     = 'c';
  2444.   $smds{'q10'}     = 'b';
  2445.   $smds{'q11'}     = 'b';
  2446.   $smds{'q12'}     = 'd';
  2447.   $smds{'q13'}     = 'c';
  2448.   $smds{'q14'}     = 'd';
  2449.   $smds{'q15'}     = 'd';
  2450.   $smds{'q16'}     = 'a';
  2451.   $smds{'q17'}     = 'c';
  2452.  
  2453.   return $self;
  2454. }
  2455.  
  2456. #
  2457. # Get the version number of the database
  2458. #
  2459.  
  2460. sub version
  2461. {
  2462.   my ($self)=@_;
  2463.   my ($dbh,$sth,$version,@row);
  2464.  
  2465.   $dbh=$self->connect();
  2466.   $sth = $dbh->prepare("SELECT KERNEL FROM VERSIONS") or die $DBI::errstr;
  2467.   $version="Adabas (unknown)";
  2468.   if ($sth->execute && (@row = $sth->fetchrow_array)
  2469.       && $row[0] =~ /([\d\.]+)/)
  2470.   {
  2471.     $version="Adabas $1";
  2472.   }
  2473.   $sth->finish;
  2474.   $dbh->disconnect;
  2475.   return $version;
  2476. }
  2477.  
  2478. sub connect
  2479. {
  2480.   my ($self)=@_;
  2481.   my ($dbh);
  2482.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  2483.             $main::opt_password,{ PrintError => 0}) ||
  2484.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  2485.   return $dbh;
  2486. }
  2487.  
  2488. #
  2489. # Returns a list of statements to create a table
  2490. # The field types are in ANSI SQL format.
  2491. #
  2492. # If one uses $main::opt_fast then one is allowed to use
  2493. # non standard types to get better speed.
  2494. #
  2495.  
  2496. sub create
  2497. {
  2498.   my($self,$table_name,$fields,$index) = @_;
  2499.   my($query,@queries,$ind,@keys);
  2500.  
  2501.   $query="create table $table_name (";
  2502.   foreach $field (@$fields)
  2503.   {
  2504.     $field =~ s/CHARACTER\s+VARYING/VARCHAR/i;
  2505.     $field =~ s/TINYINT/SMALLINT/i;
  2506.     $field =~ s/MEDIUMINT/INT/i;
  2507.     $field =~ s/SMALLINT\s*\(\d+\)/SMALLINT/i;
  2508.     $field =~ s/INT\s*\(\d+\)/INT/i;
  2509.     $field =~ s/BLOB/LONG/i;
  2510.     $field =~ s/INTEGER\s*\(\d+\)/INTEGER/i;
  2511.     $field =~ s/FLOAT\s*\((\d+),\d+\)/FLOAT\($1\)/i;
  2512.     $field =~ s/DOUBLE/FLOAT\(38\)/i;
  2513.     $field =~ s/DOUBLE\s+PRECISION/FLOAT\(38\)/i;
  2514.     $query.= $field . ',';
  2515.   }
  2516.  
  2517.   foreach $ind (@$index)
  2518.   {
  2519.     my @index;
  2520.     if ( $ind =~ /\bKEY\b/i ){
  2521.       push(@keys,"ALTER TABLE $table_name ADD $ind");
  2522.     }else{
  2523.       my @fields = split(' ',$index);
  2524.       my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
  2525.       push(@index,$query);
  2526.     }
  2527.   }
  2528.   substr($query,-1)=")";        # Remove last ',';
  2529.   push(@queries,$query,@keys,@index);
  2530. #print "query:$query\n";
  2531.  
  2532.   return @queries;
  2533. }
  2534.  
  2535. sub insert_file {
  2536.   my($self,$dbname, $file) = @_;
  2537.   print "insert an ascii file isn't supported by Oracle (?)\n";
  2538.   return 0;
  2539. }
  2540.  
  2541. #
  2542. # Do any conversions to the ANSI SQL query so that the database can handle it
  2543. #
  2544.  
  2545. sub query {
  2546.   my($self,$sql) = @_;
  2547.   return $sql;
  2548. }
  2549.  
  2550. sub drop_index
  2551. {
  2552.   my ($self,$table,$index) = @_;
  2553.   return "DROP INDEX $index";
  2554. }
  2555.  
  2556. #
  2557. # Abort if the server has crashed
  2558. # return: 0 if ok
  2559. #      1 question should be retried
  2560. #
  2561.  
  2562. sub abort_if_fatal_error
  2563. {
  2564.   return 0;
  2565. }
  2566.  
  2567. sub small_rollback_segment
  2568. {
  2569.   return 0;
  2570. }
  2571.  
  2572. sub reconnect_on_errors
  2573. {
  2574.   return 0;
  2575. }
  2576.  
  2577. #############################################################################
  2578. #         Configuration for IBM DB2
  2579. #############################################################################
  2580.  
  2581. package db_db2;
  2582.  
  2583. sub new
  2584. {
  2585.   my ($type,$host,$database)= @_;
  2586.   my $self= {};
  2587.   my %limits;
  2588.   bless $self;
  2589.  
  2590.   $self->{'cmp_name'}        = "DB2";
  2591.   $self->{'data_source'}    = "DBI:ODBC:$database";
  2592.   if (defined($host) && $host ne "")
  2593.   {
  2594.     $self->{'data_source'}    .= ":$host";
  2595.   }
  2596.   $self->{'limits'}        = \%limits;
  2597.   $self->{'smds'}        = \%smds;
  2598.   $self->{'blob'}        = "varchar(255)";
  2599.   $self->{'text'}        = "varchar(255)";
  2600.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  2601.   $self->{'drop_attr'}        = "";
  2602.  
  2603.   $limits{'max_conditions'}    = 418; # We get 'Query is too complex'
  2604.   $limits{'max_columns'}    = 500;    # Max number of columns in table
  2605.   $limits{'max_tables'}        = 65000;    # Should be big enough
  2606.   $limits{'max_text_size'}    = 254;  # Max size with default buffers.
  2607.   $limits{'query_size'}        = 254; # Max size with default buffers.
  2608.   $limits{'max_index'}        = 48; # Max number of keys
  2609.   $limits{'max_index_parts'}    = 15; # Max segments/key
  2610.   $limits{'max_column_name'}    = 18; # max table and column name
  2611.  
  2612.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  2613.   $limits{'load_data_infile'}    = 0; # Has load data infile
  2614.   $limits{'lock_tables'}    = 0; # Has lock tables
  2615.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  2616.   $limits{'group_functions'}    = 1; # Have group functions
  2617.   $limits{'group_func_sql_min_str'}= 1;
  2618.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  2619.   $limits{'select_without_from'}= 0; # Can do 'select 1';
  2620.   $limits{'multi_drop'}        = 0; # Drop table can take many tables
  2621.   $limits{'subqueries'}        = 1; # Supports sub-queries.
  2622.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  2623.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  2624.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  2625.   $limits{'having_with_group'}    = 1; # Can't use group functions in HAVING
  2626.   $limits{'like_with_column'}    = 0; # Can use column1 LIKE column2
  2627.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  2628.   $limits{'group_by_position'}  = 0; # Can use 'GROUP BY 1'
  2629.   $limits{'alter_table'}    = 1;
  2630.   $limits{'alter_add_multi_col'}= 0;
  2631.   $limits{'alter_table_dropcol'}= 0;
  2632.  
  2633.   $limits{'group_func_extra_std'} = 0; # Have group function std().
  2634.  
  2635.   $limits{'func_odbc_mod'}    = 1; # Have function mod.
  2636.   $limits{'func_extra_%'}    = 0; # Has % as alias for mod()
  2637.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  2638.   $limits{'func_extra_if'}    = 0; # Have function if.
  2639.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  2640.   $limits{'NEG'}        = 1; # Supports -id
  2641.   $limits{'func_extra_in_num'}    = 0; # Has function in
  2642.   $limits{'unique_index'}    = 1; # Unique index works or not
  2643.   $limits{'insert_select'}    = 1;
  2644.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  2645.   $limits{'order_by_unused'}    = 1;
  2646.   $limits{'working_all_fields'} = 1;
  2647.   return $self;
  2648. }
  2649.  
  2650. #
  2651. # Get the version number of the database
  2652. #
  2653.  
  2654. sub version
  2655. {
  2656.   my ($self)=@_;
  2657.   return "IBM DB2 5";        #DBI/ODBC can't return the server version
  2658. }
  2659.  
  2660. sub connect
  2661. {
  2662.   my ($self)=@_;
  2663.   my ($dbh);
  2664.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user, $main::opt_password) ||
  2665.     die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  2666.   return $dbh;
  2667. }
  2668.  
  2669. #
  2670. # Returns a list of statements to create a table
  2671. # The field types are in ANSI SQL format.
  2672. #
  2673.  
  2674. sub create
  2675. {
  2676.   my($self,$table_name,$fields,$index) = @_;
  2677.   my($query,@queries,$nr);
  2678.  
  2679.   $query="create table $table_name (";
  2680.   foreach $field (@$fields)
  2681.   {
  2682.     $field =~ s/mediumint/integer/i;
  2683.     $field =~ s/float\(\d+,\d+\)/float/i;
  2684.     $field =~ s/integer\(\d+\)/integer/i;
  2685.     $field =~ s/int\(\d+\)/integer/i;
  2686.     $field =~ s/tinyint\(\d+\)/smallint/i;
  2687.     $field =~ s/tinyint/smallint/i;
  2688.     $field =~ s/smallint\(\d+\)/smallint/i;
  2689.     $field =~ s/smallinteger/smallint/i;
  2690.     $field =~ s/blob/varchar(256)/i;
  2691.     $query.= $field . ',';
  2692.   }
  2693.   substr($query,-1)=")";        # Remove last ',';
  2694.   push(@queries,$query);
  2695.   $nr=0;
  2696.   foreach $index (@$index)
  2697.   {
  2698.     $ext="WITH DISALLOW NULL";
  2699.     if (($index =~ s/primary key/unique index primary_key/i))
  2700.     {
  2701.       $ext="WITH PRIMARY;"
  2702.     }
  2703.     if ($index =~ /^unique.*\(([^\(]*)\)$/i)
  2704.     {
  2705.       $nr++;
  2706.       $index="unique index ${table_name}_$nr ($1)";
  2707.     }
  2708.     $index =~ /^(.*)\s+(\(.*\))$/;
  2709.     push(@queries,"create ${1} on $table_name $2");
  2710.   }
  2711.   return @queries;
  2712. }
  2713.  
  2714. #
  2715. # Do any conversions to the ANSI SQL query so that the database can handle it
  2716. #
  2717.  
  2718. sub query {
  2719.   my($self,$sql) = @_;
  2720.   return $sql;
  2721. }
  2722.  
  2723. sub drop_index
  2724. {
  2725.   my ($self,$table,$index) = @_;
  2726.   return "DROP INDEX $table.$index";
  2727. }
  2728.  
  2729. #
  2730. # Abort if the server has crashed
  2731. # return: 0 if ok
  2732. #      1 question should be retried
  2733. #
  2734.  
  2735. sub abort_if_fatal_error
  2736. {
  2737.   return 0;
  2738. }
  2739.  
  2740. sub small_rollback_segment
  2741. {
  2742.   return 1;
  2743. }
  2744.  
  2745. sub reconnect_on_errors
  2746. {
  2747.   return 0;
  2748. }
  2749.  
  2750. #############################################################################
  2751. #         Configuration for MIMER 
  2752. #############################################################################
  2753.  
  2754. package db_Mimer;
  2755.  
  2756. sub new
  2757. {
  2758.   my ($type,$host,$database)= @_;
  2759.   my $self= {};
  2760.   my %limits;
  2761.   bless $self;
  2762.  
  2763.   $self->{'cmp_name'}        = "mimer";
  2764.   $self->{'data_source'}    = "DBI:mimer:$database:$host";
  2765.   $self->{'limits'}        = \%limits;
  2766.   $self->{'smds'}        = \%smds;
  2767.   $self->{'blob'}        = "binary varying(15000)";
  2768.   $self->{'text'}        = "character varying(15000)";
  2769.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  2770.   $self->{'drop_attr'}        = "";
  2771.   $self->{'char_null'}          = "cast(NULL as char(1))";
  2772.   $self->{'numeric_null'}       = "cast(NULL as int)";
  2773.  
  2774.   $limits{'max_conditions'}    = 9999; # (Actually not a limit)
  2775.   $limits{'max_columns'}    = 252;    # Max number of columns in table
  2776.   $limits{'max_tables'}        = 65000;    # Should be big enough
  2777.   $limits{'max_text_size'}    = 15000; # Max size with default buffers.
  2778.   $limits{'query_size'}        = 1000000; # Max size with default buffers.
  2779.   $limits{'max_index'}        = 32; # Max number of keys
  2780.   $limits{'max_index_parts'}    = 16; # Max segments/key
  2781.   $limits{'max_column_name'}    = 128; # max table and column name
  2782.  
  2783.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  2784.   $limits{'load_data_infile'}    = 1; # Has load data infile
  2785.   $limits{'lock_tables'}    = 0; # Has lock tables
  2786.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  2787.   $limits{'group_functions'}    = 1; # Have group functions
  2788.   $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
  2789.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  2790.   $limits{'select_without_from'}= 0; # Cannot do 'select 1';
  2791.   $limits{'multi_drop'}        = 0; # Drop table cannot take many tables
  2792.   $limits{'subqueries'}        = 1; # Supports sub-queries.
  2793.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  2794.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  2795.   $limits{'having_with_alias'}  = 1; # Can use aliases in HAVING
  2796.   $limits{'having_with_group'}    = 1; # Can use group functions in HAVING
  2797.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  2798.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  2799.   $limits{'group_by_position'}  = 0; # Cannot use 'GROUP BY 1'
  2800.   $limits{'alter_table'}    = 1; # Have ALTER TABLE
  2801.   $limits{'alter_add_multi_col'}= 0; # Have ALTER TABLE t add a int,add b int;
  2802.   $limits{'alter_table_dropcol'}= 1; # Have ALTER TABLE DROP column
  2803.   $limits{'insert_multi_value'} = 0; # Does not have INSERT ... values (1,2),(3,4)
  2804.  
  2805.   $limits{'group_func_extra_std'} = 0; # Does not have group function std().
  2806.  
  2807.   $limits{'func_odbc_mod'}    = 1; # Have function mod.
  2808.   $limits{'func_extra_%'}    = 0; # Does not have % as alias for mod()
  2809.   $limits{'func_odbc_floor'}    = 1; # Has func_odbc_floor function
  2810.   $limits{'func_extra_if'}    = 0; # Does not have function if.
  2811.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  2812.   $limits{'NEG'}        = 1; # Supports -id
  2813.   $limits{'func_extra_in_num'}    = 1; # Has function in
  2814.   $limits{'limit'}        = 0; # Does not support the limit attribute
  2815.   $limits{'unique_index'}    = 1; # Unique index works or not
  2816.   $limits{'insert_select'}    = 1;
  2817.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  2818.   $limits{'order_by_unused'}    = 1;
  2819.   $limits{'working_all_fields'} = 1;
  2820.  
  2821.   $smds{'time'}            = 1;
  2822.   $smds{'q1'}     = 'b';        # with time not supp by mysql ('')
  2823.   $smds{'q2'}     = 'b';
  2824.   $smds{'q3'}     = 'b';        # with time ('')
  2825.   $smds{'q4'}     = 'c';        # with time not supp by mysql (d)
  2826.   $smds{'q5'}     = 'b';        # with time not supp by mysql ('')
  2827.   $smds{'q6'}     = 'c';        # with time not supp by mysql ('')
  2828.   $smds{'q7'}     = 'c';
  2829.   $smds{'q8'}     = 'f';
  2830.   $smds{'q9'}     = 'c';
  2831.   $smds{'q10'}     = 'b';
  2832.   $smds{'q11'}     = 'b';
  2833.   $smds{'q12'}     = 'd';
  2834.   $smds{'q13'}     = 'c';
  2835.   $smds{'q14'}     = 'd';
  2836.   $smds{'q15'}     = 'd';
  2837.   $smds{'q16'}     = 'a';
  2838.   $smds{'q17'}     = 'c';
  2839.  
  2840.   return $self;
  2841. }
  2842.  
  2843. #
  2844. # Get the version number of the database
  2845. #
  2846.  
  2847. sub version
  2848. {
  2849.   my ($self)=@_;
  2850.   my ($dbh,$sth,$version,@row);
  2851.  
  2852.   $dbh=$self->connect();
  2853. #
  2854. #  Pick up SQLGetInfo option SQL_DBMS_VER (18)
  2855. #
  2856.   $version = $dbh->func(18, GetInfo);
  2857.   $dbh->disconnect;
  2858.   return $version;
  2859. }
  2860.  
  2861. #
  2862. # Connection with optional disabling of logging
  2863. #
  2864.  
  2865. sub connect
  2866. {
  2867.   my ($self)=@_;
  2868.   my ($dbh);
  2869.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  2870.             $main::opt_password,{ PrintError => 0}) ||
  2871.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  2872.  
  2873.   $dbh->do("SET OPTION LOG_OFF=1,UPDATE_LOG=0");
  2874.   return $dbh;
  2875. }
  2876.  
  2877. #
  2878. # Returns a list of statements to create a table
  2879. # The field types are in ANSI SQL format.
  2880. #
  2881. # If one uses $main::opt_fast then one is allowed to use
  2882. # non standard types to get better speed.
  2883. #
  2884.  
  2885. sub create
  2886. {
  2887.   my($self,$table_name,$fields,$index,$options) = @_;
  2888.   my($query,@queries);
  2889.  
  2890.   $query="create table $table_name (";
  2891.   foreach $field (@$fields)
  2892.   {
  2893.     $field =~ s/ decimal/ double(10,2)/i;
  2894.     $field =~ s/ big_decimal/ double(10,2)/i;
  2895.     $field =~ s/ date/ int/i;        # Because of tcp ?
  2896.     $query.= $field . ',';
  2897.   }
  2898.   foreach $index (@$index)
  2899.   {
  2900.     $query.= $index . ',';
  2901.   }
  2902.   substr($query,-1)=")";        # Remove last ',';
  2903.   $query.=" $options" if (defined($options));
  2904.   push(@queries,$query);
  2905.   return @queries;
  2906. }
  2907.  
  2908. sub insert_file {
  2909.   my($self,$dbname, $file) = @_;
  2910.   print "insert of an ascii file isn't supported by Mimer\n";
  2911.   return 0;
  2912. }
  2913.  
  2914. #
  2915. # Do any conversions to the ANSI SQL query so that the database can handle it
  2916. #
  2917.  
  2918. sub query {
  2919.   my($self,$sql) = @_;
  2920.   return $sql;
  2921. }
  2922.  
  2923. sub drop_index {
  2924.   my ($self,$table,$index) = @_;
  2925.   return "DROP INDEX $index";
  2926. }
  2927.  
  2928. #
  2929. # Abort if the server has crashed
  2930. # return: 0 if ok
  2931. #      1 question should be retried
  2932. #
  2933.  
  2934. sub abort_if_fatal_error
  2935. {
  2936.   return 1 if ($DBI::errstr =~ /Table locked by another cursor/);
  2937.   return 0;
  2938. }
  2939.  
  2940. sub small_rollback_segment
  2941. {
  2942.   return 0;
  2943. }
  2944.  
  2945. sub reconnect_on_errors
  2946. {
  2947.   return 0;
  2948. }
  2949.  
  2950. #############################################################################
  2951. #         Configuration for InterBase
  2952. #############################################################################
  2953.  
  2954. package db_interbase;
  2955.  
  2956. sub new
  2957. {
  2958.   my ($type,$host,$database)= @_;
  2959.   my $self= {};
  2960.   my %limits;
  2961.   bless $self;
  2962.  
  2963.   $self->{'cmp_name'}        = "interbase";
  2964.   $self->{'data_source'}    = "DBI:InterBase:database=$database";
  2965.   $self->{'limits'}        = \%limits;
  2966.   $self->{'smds'}        = \%smds;
  2967.   $self->{'blob'}        = "blob";
  2968.   $self->{'text'}        = "";
  2969.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  2970.   $self->{'drop_attr'}        = "";
  2971.   $self->{'char_null'}          = "";
  2972.   $self->{'numeric_null'}       = "";
  2973.  
  2974.   $limits{'max_conditions'}    = 9999; # (Actually not a limit)
  2975.   $limits{'max_columns'}    = 252;    # Max number of columns in table
  2976.   $limits{'max_tables'}        = 65000;    # Should be big enough
  2977.   $limits{'max_text_size'}    = 15000; # Max size with default buffers.
  2978.   $limits{'query_size'}        = 1000000; # Max size with default buffers.
  2979.   $limits{'max_index'}        = 31; # Max number of keys
  2980.   $limits{'max_index_parts'}    = 8; # Max segments/key
  2981.   $limits{'max_column_name'}    = 128; # max table and column name
  2982.  
  2983.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  2984.   $limits{'load_data_infile'}    = 0; # Has load data infile
  2985.   $limits{'lock_tables'}    = 0; # Has lock tables
  2986.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  2987.   $limits{'group_functions'}    = 1; # Have group functions
  2988.   $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
  2989.   $limits{'group_distinct_functions'}= 1; # Have count(distinct)
  2990.   $limits{'select_without_from'}= 0; # Cannot do 'select 1';
  2991.   $limits{'multi_drop'}        = 0; # Drop table cannot take many tables
  2992.   $limits{'subqueries'}        = 1; # Supports sub-queries.
  2993.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  2994.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  2995.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  2996.   $limits{'having_with_group'}    = 1; # Can use group functions in HAVING
  2997.   $limits{'like_with_column'}    = 0; # Can use column1 LIKE column2
  2998.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  2999.   $limits{'group_by_position'}  = 0; # Cannot use 'GROUP BY 1'
  3000.   $limits{'alter_table'}    = 1; # Have ALTER TABLE
  3001.   $limits{'alter_add_multi_col'}= 1; # Have ALTER TABLE t add a int,add b int;
  3002.   $limits{'alter_table_dropcol'}= 1; # Have ALTER TABLE DROP column
  3003.   $limits{'insert_multi_value'} = 0; # Does not have INSERT ... values (1,2),(3,4)
  3004.  
  3005.   $limits{'group_func_extra_std'} = 0; # Does not have group function std().
  3006.  
  3007.   $limits{'func_odbc_mod'}    = 0; # Have function mod.
  3008.   $limits{'func_extra_%'}    = 0; # Does not have % as alias for mod()
  3009.   $limits{'func_odbc_floor'}    = 0; # Has func_odbc_floor function
  3010.   $limits{'func_extra_if'}    = 0; # Does not have function if.
  3011.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  3012.   $limits{'NEG'}        = 0; # Supports -id
  3013.   $limits{'func_extra_in_num'}    = 0; # Has function in
  3014.   $limits{'limit'}        = 0; # Does not support the limit attribute
  3015.   $limits{'working_blobs'}    = 1; # If big varchar/blobs works
  3016.   $limits{'order_by_unused'}    = 1;
  3017.   $limits{'working_all_fields'} = 1;
  3018.  
  3019.   $smds{'time'}            = 1;
  3020.   $smds{'q1'}     = 'b';        # with time not supp by mysql ('')
  3021.   $smds{'q2'}     = 'b';
  3022.   $smds{'q3'}     = 'b';        # with time ('')
  3023.   $smds{'q4'}     = 'c';        # with time not supp by mysql (d)
  3024.   $smds{'q5'}     = 'b';        # with time not supp by mysql ('')
  3025.   $smds{'q6'}     = 'c';        # with time not supp by mysql ('')
  3026.   $smds{'q7'}     = 'c';
  3027.   $smds{'q8'}     = 'f';
  3028.   $smds{'q9'}     = 'c';
  3029.   $smds{'q10'}     = 'b';
  3030.   $smds{'q11'}     = 'b';
  3031.   $smds{'q12'}     = 'd';
  3032.   $smds{'q13'}     = 'c';
  3033.   $smds{'q14'}     = 'd';
  3034.   $smds{'q15'}     = 'd';
  3035.   $smds{'q16'}     = 'a';
  3036.   $smds{'q17'}     = 'c';
  3037.  
  3038.   return $self;
  3039. }
  3040.  
  3041. #
  3042. # Get the version number of the database
  3043. #
  3044.  
  3045. sub version
  3046. {
  3047.   my ($self)=@_;
  3048.   my ($dbh,$sth,$version,@row);
  3049.  
  3050.   $dbh=$self->connect();
  3051. #  $sth = $dbh->prepare("show version");
  3052. #  $sth->execute;
  3053. #  @row = $sth->fetchrow_array;
  3054. #  $version = $row[0];
  3055. #  $version =~ s/.*version \"(.*)\"$/$1/;
  3056.   $dbh->disconnect;
  3057.   $version = "6.0Beta";
  3058.   return $version;
  3059. }
  3060.  
  3061. #
  3062. # Connection with optional disabling of logging
  3063. #
  3064.  
  3065. sub connect
  3066. {
  3067.   my ($self)=@_;
  3068.   my ($dbh);
  3069.   $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
  3070.             $main::opt_password,{ PrintError => 0, AutoCommit => 1}) ||
  3071.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  3072.  
  3073.   return $dbh;
  3074. }
  3075.  
  3076. #
  3077. # Returns a list of statements to create a table
  3078. # The field types are in ANSI SQL format.
  3079. #
  3080. # If one uses $main::opt_fast then one is allowed to use
  3081. # non standard types to get better speed.
  3082. #
  3083.  
  3084. sub create
  3085. {
  3086.   my($self,$table_name,$fields,$index,$options) = @_;
  3087.   my($query,@queries);
  3088.  
  3089.   $query="create table $table_name (";
  3090.   foreach $field (@$fields)
  3091.   {
  3092.     $field =~ s/ big_decimal/ float/i;
  3093.     $field =~ s/ double/ float/i;
  3094.     $field =~ s/ tinyint/ smallint/i;
  3095.     $field =~ s/ mediumint/ int/i;
  3096.     $field =~ s/ integer/ int/i;
  3097.     $field =~ s/ float\(\d,\d\)/ float/i;
  3098.     $field =~ s/ date/ int/i;        # Because of tcp ?
  3099.     $field =~ s/ smallint\(\d\)/ smallint/i;
  3100.     $field =~ s/ int\(\d\)/ int/i;
  3101.     $query.= $field . ',';
  3102.   }
  3103.   foreach $ind (@$index)
  3104.   {
  3105.     my @index;
  3106.     if ( $ind =~ /\bKEY\b/i ){
  3107.       push(@keys,"ALTER TABLE $table_name ADD $ind");
  3108.     }else{
  3109.       my @fields = split(' ',$index);
  3110.       my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
  3111.       push(@index,$query);
  3112.     }
  3113.   }
  3114.   substr($query,-1)=")";        # Remove last ',';
  3115.   $query.=" $options" if (defined($options));
  3116.   push(@queries,$query);
  3117.   return @queries;
  3118. }
  3119.  
  3120. sub insert_file {
  3121.   my($self,$dbname, $file) = @_;
  3122.   print "insert of an ascii file isn't supported by InterBase\n";
  3123.   return 0;
  3124. }
  3125.  
  3126. #
  3127. # Do any conversions to the ANSI SQL query so that the database can handle it
  3128. #
  3129.  
  3130. sub query {
  3131.   my($self,$sql) = @_;
  3132.   return $sql;
  3133. }
  3134.  
  3135. sub drop_index {
  3136.   my ($self,$table,$index) = @_;
  3137.   return "DROP INDEX $index";
  3138. }
  3139.  
  3140. #
  3141. # Abort if the server has crashed
  3142. # return: 0 if ok
  3143. #      1 question should be retried
  3144. #
  3145.  
  3146. sub abort_if_fatal_error
  3147. {
  3148.   return 1 if ($DBI::errstr =~ /Table locked by another cursor/);
  3149.   return 0;
  3150. }
  3151.  
  3152. sub small_rollback_segment
  3153. {
  3154.   return 1;
  3155. }
  3156.  
  3157. sub reconnect_on_errors
  3158. {
  3159.   return 1;
  3160. }
  3161.  
  3162. #############################################################################
  3163. #         Configuration for FrontBase 
  3164. #############################################################################
  3165.  
  3166. package db_FrontBase;
  3167.  
  3168. sub new
  3169. {
  3170.   my ($type,$host,$database)= @_;
  3171.   my $self= {};
  3172.   my %limits;
  3173.   bless $self;
  3174.  
  3175.   $self->{'cmp_name'}        = "FrontBase";
  3176.   $self->{'data_source'}    = "DBI:FB:dbname=$database;host=$host";
  3177.   $self->{'limits'}        = \%limits;
  3178.   $self->{'smds'}        = \%smds;
  3179.   $self->{'blob'}        = "varchar(8000000)";
  3180.   $self->{'text'}        = "varchar(8000000)";
  3181.   $self->{'double_quotes'}    = 1; # Can handle:  'Walker''s'
  3182.   $self->{'drop_attr'}        = ' restrict';
  3183.   $self->{'error_on_execute_means_zero_rows'}=1;
  3184.  
  3185.   $limits{'max_conditions'}    = 5427; # (Actually not a limit)
  3186.   # The following should be 8192, but is smaller because Frontbase crashes..
  3187.   $limits{'max_columns'}    = 150;    # Max number of columns in table
  3188.   $limits{'max_tables'}        = 5000;    # 10000 crashed FrontBase
  3189.   $limits{'max_text_size'}    = 65000; # Max size with default buffers.
  3190.   $limits{'query_size'}        = 8000000; # Max size with default buffers.
  3191.   $limits{'max_index'}        = 38; # Max number of keys
  3192.   $limits{'max_index_parts'}    = 20; # Max segments/key
  3193.   $limits{'max_column_name'}    = 128; # max table and column name
  3194.  
  3195.   $limits{'join_optimizer'}    = 1; # Can optimize FROM tables
  3196.   $limits{'load_data_infile'}    = 1; # Has load data infile
  3197.   $limits{'lock_tables'}    = 0; # Has lock tables
  3198.   $limits{'functions'}        = 1; # Has simple functions (+/-)
  3199.   $limits{'group_functions'}    = 1; # Have group functions
  3200.   $limits{'group_distinct_functions'}= 0; # Have count(distinct)
  3201.   $limits{'select_without_from'}= 0;
  3202.   $limits{'multi_drop'}        = 0; # Drop table cannot take many tables
  3203.   $limits{'subqueries'}        = 1; # Supports sub-queries.
  3204.   $limits{'left_outer_join'}    = 1; # Supports left outer joins
  3205.   $limits{'table_wildcard'}    = 1; # Has SELECT table_name.*
  3206.   $limits{'having_with_alias'}  = 0; # Can use aliases in HAVING
  3207.   $limits{'having_with_group'}    = 0; # Can use group functions in HAVING
  3208.   $limits{'like_with_column'}    = 1; # Can use column1 LIKE column2
  3209.   $limits{'order_by_position'}  = 1; # Can use 'ORDER BY 1'
  3210.   $limits{'group_by_position'}  = 0; # Use of 'GROUP BY 1'
  3211.   $limits{'alter_table'}    = 1; # Have ALTER TABLE
  3212.   $limits{'alter_add_multi_col'}= 0; # Have ALTER TABLE t add a int,add b int;
  3213.   $limits{'alter_table_dropcol'}= 0; # Have ALTER TABLE DROP column
  3214.   $limits{'insert_multi_value'} = 1;
  3215.  
  3216.   $limits{'group_func_extra_std'} = 0; # Does not have group function std().
  3217.  
  3218.   $limits{'func_odbc_mod'}    = 0; # Have function mod.
  3219.   $limits{'func_extra_%'}    = 0; # Does not have % as alias for mod()
  3220.   $limits{'func_odbc_floor'}    = 0; # Has func_odbc_floor function
  3221.   $limits{'func_extra_if'}    = 0; # Does not have function if.
  3222.   $limits{'column_alias'}    = 1; # Alias for fields in select statement.
  3223.   $limits{'NEG'}        = 1; # Supports -id
  3224.   $limits{'func_extra_in_num'}    = 0; # Has function in
  3225.   $limits{'limit'}        = 0; # Does not support the limit attribute
  3226.   $limits{'insert_select'}    = 0;
  3227.   $limits{'order_by_unused'}    = 0;
  3228.  
  3229.   # We don't get an error for duplicate row in 'test-insert'
  3230.   $limits{'unique_index'}    = 0; # Unique index works or not
  3231.   # We can't use a blob as a normal string (we got a wierd error)
  3232.   $limits{'working_blobs'}    = 0;
  3233.   # 'select min(region),max(region) from bench1' kills the server after a while
  3234.   $limits{'group_func_sql_min_str'} = 0;
  3235.   # If you do select f1,f2,f3...f200 from table, Frontbase dies.
  3236.   $limits{'working_all_fields'} = 0;
  3237.  
  3238.   return $self;
  3239. }
  3240.  
  3241. #
  3242. # Get the version number of the database
  3243. #
  3244.  
  3245. sub version
  3246. {
  3247.   my ($self)=@_;
  3248.   my ($dbh,$sth,$version,@row);
  3249.  
  3250.   $dbh=$self->connect();
  3251. #
  3252. #  Pick up SQLGetInfo option SQL_DBMS_VER (18)
  3253. #
  3254.   #$version = $dbh->func(18, GetInfo);
  3255.   $version="FrontBase 2.1";
  3256.   $dbh->disconnect;
  3257.   return $version;
  3258. }
  3259.  
  3260. #
  3261. # Connection with optional disabling of logging
  3262. #
  3263.  
  3264. sub connect
  3265. {
  3266.   my ($self)=@_;
  3267.   my ($dbh);
  3268.   $dbh=DBI->connect($self->{'data_source'}, 
  3269.             $main::opt_user,
  3270.             $main::opt_password,
  3271.             { PrintError => 0 , 
  3272.               'fb_host'=>$main::opt_host
  3273.             }) ||
  3274.               die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
  3275.   $db->{AutoCommit}=1;
  3276.   # $dbh->do("SET OPTION LOG_OFF=1,UPDATE_LOG=0");
  3277.   return $dbh;
  3278. }
  3279.  
  3280. #
  3281. # Returns a list of statements to create a table
  3282. # The field types are in ANSI SQL format.
  3283. #
  3284. # If one uses $main::opt_fast then one is allowed to use
  3285. # non standard types to get better speed.
  3286. #
  3287.  
  3288. sub create
  3289. {
  3290.   my($self,$table_name,$fields,$index,$options) = @_;
  3291.   my($query,@queries);
  3292.  
  3293.   $query="create table $table_name (";
  3294.   foreach $field (@$fields)
  3295.   {
  3296.     $field =~ s/ blob/ varchar(32000)/i;
  3297.     $field =~ s/ big_decimal/ float/i;
  3298.     $field =~ s/ double/ float/i;
  3299.     $field =~ s/ tinyint/ smallint/i;
  3300.     $field =~ s/ mediumint/ int/i;
  3301.     $field =~ s/ integer/ int/i;
  3302.     $field =~ s/ float\(\d,\d\)/ float/i;
  3303.     $field =~ s/ smallint\(\d\)/ smallint/i;
  3304.     $field =~ s/ int\(\d\)/ int/i;
  3305.     $query.= $field . ',';
  3306.   }
  3307.   foreach $ind (@$index)
  3308.   {
  3309.     my @index;
  3310.     if ( $ind =~ /\bKEY\b/i ){
  3311.       push(@keys,"ALTER TABLE $table_name ADD $ind");
  3312.     }else{
  3313.       my @fields = split(' ',$index);
  3314.       my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
  3315.       push(@index,$query);
  3316.     }
  3317.   }
  3318.   substr($query,-1)=")";        # Remove last ',';
  3319.   $query.=" $options" if (defined($options));
  3320.   push(@queries,$query);
  3321.   return @queries;
  3322. }
  3323.  
  3324. sub insert_file {
  3325.   my($self,$dbname, $file) = @_;
  3326.   print "insert of an ascii file isn't supported by InterBase\n";
  3327.   return 0;
  3328. }
  3329.  
  3330. #
  3331. # Do any conversions to the ANSI SQL query so that the database can handle it
  3332. #
  3333.  
  3334. sub query {
  3335.   my($self,$sql) = @_;
  3336.   return $sql;
  3337. }
  3338.  
  3339. sub drop_index {
  3340.   my ($self,$table,$index) = @_;
  3341.   return "DROP INDEX $index";
  3342. }
  3343.  
  3344. #
  3345. # Abort if the server has crashed
  3346. # return: 0 if ok
  3347. #      1 question should be retried
  3348. #
  3349.  
  3350. sub abort_if_fatal_error
  3351. {
  3352.   return 0 if ($DBI::errstr =~ /No raw data handle/);
  3353.   return 1;
  3354. }
  3355.  
  3356. sub small_rollback_segment
  3357. {
  3358.   return 0;
  3359. }
  3360.  
  3361. sub reconnect_on_errors
  3362. {
  3363.   return 1;
  3364. }
  3365.  
  3366. 1;
  3367.