home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win.exe / DATA1.CAB / Benchmark_Files / bench / server-cfg < prev    next >
Text File  |  2000-11-22  |  88KB  |  3,081 lines

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