server-cfg.sh
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:95k
源码类别:

MySQL数据库

开发平台:

Visual C++

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