home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 December / Chip_2001-12_cd1.bin / sharewar / mysql / data1.cab / Development / bench / server-cfg < prev    next >
Encoding:
Text File  |  2001-11-02  |  95.0 KB  |  3,359 lines

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