server-cfg
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:98k
源码类别:

模拟服务器

开发平台:

C/C++

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