home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 July & August / PCWorld_2003-07-08_cd.bin / Software / Vyzkuste / mysql / data1.cab / Development / bench / server-cfg < prev    next >
Text File  |  2003-05-17  |  105KB  |  3,615 lines

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