switch4g: completely re-writen
[tomato.git] / release / src / router / mysql / sql-bench / server-cfg.sh
blob9137e57bfe19710661436f082a7131fe0ddefaba
1 #!/usr/bin/perl
2 # -*- perl -*-
3 # Copyright (c) 2000-2006 MySQL AB, 2009 Sun Microsystems, Inc.
4 # Use is subject to license terms.
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Library General Public
8 # License as published by the Free Software Foundation; version 2
9 # of the License.
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Library General Public License for more details.
16 # You should have received a copy of the GNU Library General Public
17 # License along with this library; if not, write to the Free
18 # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19 # MA 02110-1301, USA
21 # The configuration file for the DBI/DBD tests on different databases ....
22 # You will need the DBD module for the database you are running.
23 # Monty made this bench script and I (Luuk de Boer) rewrote it to DBI/DBD.
24 # Monty rewrote this again to use packages.
26 # Each database has a different package that has 3 functions:
27 # new Creates a object with some standard slot
28 # version Version number of the server
29 # create Generates commands to create a table
33 # First some global functions that help use the packages:
36 sub get_server
38 my ($name,$host,$database,$odbc,$machine,$socket,$connect_options)=@_;
39 my ($server);
40 if ($name =~ /mysql/i)
41 { $server=new db_MySQL($host, $database, $machine, $socket,$connect_options); }
42 elsif ($name =~ /pg/i)
43 { $server= new db_Pg($host,$database); }
44 elsif ($name =~ /msql/i)
45 { $server= new db_mSQL($host,$database); }
46 elsif ($name =~ /solid/i)
47 { $server= new db_Solid($host,$database); }
48 elsif ($name =~ /Empress/i)
49 { $server= new db_Empress($host,$database); }
50 elsif ($name =~ /FrontBase/i)
51 { $server= new db_FrontBase($host,$database); }
52 elsif ($name =~ /Oracle/i)
53 { $server= new db_Oracle($host,$database); }
54 elsif ($name =~ /Access/i)
55 { $server= new db_access($host,$database); }
56 elsif ($name =~ /Informix/i)
57 { $server= new db_Informix($host,$database); }
58 elsif ($name =~ /ms-sql/i)
59 { $server= new db_ms_sql($host,$database); }
60 elsif ($name =~ /sybase/i)
61 { $server= new db_sybase($host,$database); }
62 elsif ($name =~ /Adabas/i) # Adabas has two drivers
64 $server= new db_Adabas($host,$database);
65 if ($name =~ /AdabasD/i)
67 $server->{'data_source'} =~ s/:Adabas:/:AdabasD:/;
70 elsif ($name =~ /DB2/i)
71 { $server= new db_db2($host,$database); }
72 elsif ($name =~ /Mimer/i)
73 { $server= new db_Mimer($host,$database); }
74 elsif ($name =~ /Sapdb/i)
75 { $server= new db_sapdb($host,$database); }
76 elsif ($name =~ /interBase/i)
77 { $server= new db_interbase($host,$database); }
78 else
80 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";
82 if ($name =~ /_ODBC$/i || defined($odbc) && $odbc)
84 if (! ($server->{'data_source'} =~ /^([^:]*):([^:]+):([^:]*)/ ))
86 die "Can't find databasename in data_source: '" .
87 $server->{'data_source'}. "'\n";
89 if ($3) {
90 $server->{'data_source'} = "$1:ODBC:$3";
91 } else {
92 $server->{'data_source'} = "$1:ODBC:$database";
95 return $server;
98 sub all_servers
100 return ["Access", "Adabas", "DB2", "Empress", "FrontBase", "Oracle",
101 "Informix", "InterBase", "Mimer", "mSQL", "MS-SQL", "MySQL", "Pg","SAPDB",
102 "Solid", "Sybase"];
105 #############################################################################
106 # First the configuration for MySQL off course :-)
107 #############################################################################
109 package db_MySQL;
111 sub new
113 my ($type,$host,$database,$machine,$socket,$connect_options)= @_;
114 my $self= {};
115 my %limits;
116 bless $self;
118 $self->{'cmp_name'} = "mysql";
119 $self->{'data_source'} = "DBI:mysql:database=$database;host=$host";
120 $self->{'data_source'} .= ";mysql_socket=$socket" if($socket);
121 $self->{'data_source'} .= ";$connect_options" if($connect_options);
122 $self->{'limits'} = \%limits;
123 $self->{'blob'} = "blob";
124 $self->{'text'} = "text";
125 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
126 $self->{'vacuum'} = 1; # When using with --fast
127 $self->{'drop_attr'} = "";
128 $self->{'transactions'} = 0; # Transactions disabled by default
130 $limits{'NEG'} = 1; # Supports -id
131 $limits{'alter_add_multi_col'}= 1; #Have ALTER TABLE t add a int,add b int;
132 $limits{'alter_table'} = 1; # Have ALTER TABLE
133 $limits{'alter_table_dropcol'}= 1; # Have ALTER TABLE DROP column
134 $limits{'column_alias'} = 1; # Alias for fields in select statement.
135 $limits{'func_extra_%'} = 1; # Has % as alias for mod()
136 $limits{'func_extra_if'} = 1; # Have function if.
137 $limits{'func_extra_in_num'} = 1; # Has function in
138 $limits{'func_odbc_floor'} = 1; # Has func_odbc_floor function
139 $limits{'func_odbc_mod'} = 1; # Have function mod.
140 $limits{'functions'} = 1; # Has simple functions (+/-)
141 $limits{'group_by_position'} = 1; # Can use 'GROUP BY 1'
142 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
143 $limits{'group_func_extra_std'} = 1; # Have group function std().
144 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
145 $limits{'group_functions'} = 1; # Have group functions
146 $limits{'having_with_alias'} = 1; # Can use aliases in HAVING
147 $limits{'having_with_group'} = 1; # Can use group functions in HAVING
148 $limits{'insert_multi_value'} = 1; # Have INSERT ... values (1,2),(3,4)
149 $limits{'insert_select'} = 1;
150 $limits{'join_optimizer'} = 1; # Can optimize FROM tables
151 $limits{'left_outer_join'} = 1; # Supports left outer joins
152 $limits{'like_with_column'} = 1; # Can use column1 LIKE column2
153 $limits{'limit'} = 1; # supports the limit attribute
154 $limits{'truncate_table'} = 1;
155 $limits{'load_data_infile'} = 1; # Has load data infile
156 $limits{'lock_tables'} = 1; # Has lock tables
157 $limits{'max_column_name'} = 64; # max table and column name
158 $limits{'max_columns'} = 2000; # Max number of columns in table
159 $limits{'max_conditions'} = 9999; # (Actually not a limit)
160 $limits{'max_index'} = 16; # Max number of keys
161 $limits{'max_index_parts'} = 16; # Max segments/key
162 $limits{'max_tables'} = (($machine || '') =~ "^win") ? 5000 : 65000;
163 $limits{'max_text_size'} = 1000000; # Good enough for tests
164 $limits{'multi_drop'} = 1; # Drop table can take many tables
165 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1'
166 $limits{'order_by_unused'} = 1;
167 $limits{'query_size'} = 1000000; # Max size with default buffers.
168 $limits{'select_without_from'}= 1; # Can do 'select 1';
169 $limits{'subqueries'} = 0; # Doesn't support sub-queries.
170 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
171 $limits{'unique_index'} = 1; # Unique index works or not
172 $limits{'working_all_fields'} = 1;
173 $limits{'working_blobs'} = 1; # If big varchar/blobs works
174 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
176 # Some fixes that depends on the environment
177 if (defined($main::opt_create_options) &&
178 $main::opt_create_options =~ /engine=heap/i)
180 $limits{'working_blobs'} = 0; # HEAP tables can't handle BLOB's
182 if (defined($main::opt_create_options) &&
183 $main::opt_create_options =~ /engine=innodb/i)
185 $self->{'transactions'} = 1; # Transactions enabled
187 if (defined($main::opt_create_options) &&
188 $main::opt_create_options =~ /engine=ndb/i)
190 $self->{'transactions'} = 1; # Transactions enabled
191 $limits{'max_columns'} = 90; # Max number of columns in table
192 $limits{'max_tables'} = 32; # No comments
194 if (defined($main::opt_create_options) &&
195 $main::opt_create_options =~ /engine=bdb/i)
197 $self->{'transactions'} = 1; # Transactions enabled
199 if (defined($main::opt_create_options) &&
200 $main::opt_create_options =~ /engine=gemini/i)
202 $limits{'working_blobs'} = 0; # Blobs not implemented yet
203 $limits{'max_tables'} = 500;
204 $self->{'transactions'} = 1; # Transactions enabled
207 return $self;
211 # Get the version number of the database
214 sub version
216 my ($self)=@_;
217 my ($dbh,$sth,$version,@row);
219 $dbh=$self->connect();
220 $sth = $dbh->prepare("select VERSION()") or die $DBI::errstr;
221 $version="MySQL 3.20.?";
222 if ($sth->execute && (@row = $sth->fetchrow_array))
224 $row[0] =~ s/-/ /g; # To get better tables with long names
225 $version="MySQL $row[0]";
227 $sth->finish;
229 $sth = $dbh->prepare("show status like 'ssl_version'") or die $DBI::errstr;
230 if ($sth->execute && (@row = $sth->fetchrow_array) && $row[1])
232 $version .= "/$row[1]";
234 $sth->finish;
235 $dbh->disconnect;
236 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
237 return $version;
241 # Connection with optional disabling of logging
244 sub connect
246 my ($self)=@_;
247 my ($dbh);
248 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
249 $main::opt_password,{ PrintError => 0}) ||
250 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
252 $dbh->do("SET OPTION LOG_OFF=1,UPDATE_LOG=0");
253 return $dbh;
257 # Returns a list of statements to create a table
258 # The field types are in ANSI SQL format.
260 # If one uses $main::opt_fast then one is allowed to use
261 # non standard types to get better speed.
264 sub create
266 my($self,$table_name,$fields,$index,$options) = @_;
267 my($query,@queries);
269 $query="create table $table_name (";
270 foreach $field (@$fields)
272 # $field =~ s/ decimal/ double(10,2)/i;
273 $field =~ s/ big_decimal/ double(10,2)/i;
274 $query.= $field . ',';
276 foreach $index (@$index)
278 $query.= $index . ',';
280 substr($query,-1)=")"; # Remove last ',';
281 $query.=" $options" if (defined($options));
282 $query.=" $main::opt_create_options" if (defined($main::opt_create_options));
283 push(@queries,$query);
284 return @queries;
287 sub insert_file {
288 my ($self,$dbname, $file, $dbh) = @_;
289 my ($command, $sth);
291 $file =~ s|\\|/|g; # Change Win32 names to Unix syntax
292 $command = "load data infile '$file' into table $dbname columns optionally enclosed by '\\'' terminated by ','";
293 # print "$command\n";
294 $sth = $dbh->do($command) or die $DBI::errstr;
295 return $sth; # Contains number of rows
299 # Do any conversions to the ANSI SQL query so that the database can handle it
302 sub query {
303 my($self,$sql) = @_;
304 return $sql;
307 sub drop_index {
308 my ($self,$table,$index) = @_;
309 return "DROP INDEX $index ON $table";
313 # Abort if the server has crashed
314 # return: 0 if ok
315 # 1 question should be retried
318 sub abort_if_fatal_error
320 return 0;
324 # This should return 1 if we to do disconnect / connect when doing
325 # big batches
328 sub small_rollback_segment
330 return 0;
334 # reconnect on errors (needed mainly be crash-me)
337 sub reconnect_on_errors
339 return 0;
342 sub fix_for_insert
344 my ($self,$cmd) = @_;
345 return $cmd;
349 # Optimize tables for better performance
352 sub vacuum
354 my ($self,$full_vacuum,$dbh_ref,@tables)=@_;
355 my ($loop_time,$end_time,$dbh);
356 if ($#tables >= 0)
358 $dbh=$$dbh_ref;
359 $loop_time=new Benchmark;
360 $dbh->do("OPTIMIZE TABLE " . join(',',@tables)) || die "Got error: $DBI::errstr when executing 'OPTIMIZE TABLE'\n";
361 $end_time=new Benchmark;
362 print "Time for book-keeping (1): " .
363 Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"all") . "\n\n";
367 #############################################################################
368 # Definitions for mSQL
369 #############################################################################
371 package db_mSQL;
373 sub new
375 my ($type,$host,$database)= @_;
376 my $self= {};
377 my %limits;
378 bless $self;
380 $self->{'cmp_name'} = "msql";
381 $self->{'data_source'} = "DBI:mSQL:$database:$host";
382 $self->{'limits'} = \%limits;
383 $self->{'double_quotes'} = 0;
384 $self->{'drop_attr'} = "";
385 $self->{'transactions'} = 0; # No transactions
386 $self->{'blob'} = "text(" . $limits{'max_text_size'} .")";
387 $self->{'text'} = "text(" . $limits{'max_text_size'} .")";
389 $limits{'max_conditions'} = 74;
390 $limits{'max_columns'} = 75;
391 $limits{'max_tables'} = 65000; # Should be big enough
392 $limits{'max_text_size'} = 32000;
393 $limits{'query_size'} = 65535;
394 $limits{'max_index'} = 5;
395 $limits{'max_index_parts'} = 10;
396 $limits{'max_column_name'} = 35;
398 $limits{'join_optimizer'} = 0; # Can't optimize FROM tables
399 $limits{'load_data_infile'} = 0;
400 $limits{'lock_tables'} = 0;
401 $limits{'functions'} = 0;
402 $limits{'group_functions'} = 0;
403 $limits{'group_distinct_functions'}= 0; # Have count(distinct)
404 $limits{'multi_drop'} = 0;
405 $limits{'select_without_from'}= 0;
406 $limits{'subqueries'} = 0;
407 $limits{'left_outer_join'} = 0;
408 $limits{'table_wildcard'} = 0;
409 $limits{'having_with_alias'} = 0;
410 $limits{'having_with_group'} = 0;
411 $limits{'like_with_column'} = 1;
412 $limits{'order_by_position'} = 1;
413 $limits{'group_by_position'} = 1;
414 $limits{'alter_table'} = 0;
415 $limits{'alter_add_multi_col'}= 0;
416 $limits{'alter_table_dropcol'}= 0;
417 $limits{'group_func_extra_std'} = 0;
418 $limits{'limit'} = 1; # supports the limit attribute
419 $limits{'unique_index'} = 1; # Unique index works or not
420 $limits{'insert_select'} = 0;
422 $limits{'func_odbc_mod'} = 0;
423 $limits{'func_extra_%'} = 0;
424 $limits{'func_odbc_floor'} = 0;
425 $limits{'func_extra_if'} = 0;
426 $limits{'column_alias'} = 0;
427 $limits{'NEG'} = 0;
428 $limits{'func_extra_in_num'} = 0;
429 $limits{'working_blobs'} = 1; # If big varchar/blobs works
430 $limits{'order_by_unused'} = 1;
431 $limits{'working_all_fields'} = 1;
432 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
433 return $self;
437 # Get the version number of the database
440 sub version
442 my ($tmp,$dir);
443 foreach $dir ("/usr/local/Hughes", "/usr/local/mSQL","/my/local/mSQL",
444 "/usr/local")
446 if (-x "$dir/bin/msqladmin")
448 $tmp=`$dir/bin/msqladmin version | grep server`;
449 if ($tmp =~ /^\s*(.*\w)\s*$/)
450 { # Strip pre- and endspace
451 $tmp=$1;
452 $tmp =~ s/\s+/ /g; # Remove unnecessary spaces
453 $tmp .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
455 return $tmp;
459 return "mSQL version ???";
463 sub connect
465 my ($self)=@_;
466 my ($dbh);
467 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
468 $main::opt_password,{ PrintError => 0}) ||
469 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
470 return $dbh;
474 # Can't handle many field types, so we map everything to int and real.
477 sub create
479 my($self,$table_name,$fields,$index) = @_;
480 my($query,@queries,$name,$nr);
482 $query="create table $table_name (";
483 foreach $field (@$fields)
485 $field =~ s/varchar/char/i; # mSQL doesn't have VARCHAR()
486 # mSQL can't handle more than the real basic int types
487 $field =~ s/tinyint|smallint|mediumint|integer/int/i;
488 # mSQL can't handle different visual lengths
489 $field =~ s/int\(\d*\)/int/i;
490 # mSQL doesn't have float, change it to real
491 $field =~ s/float(\(\d*,\d*\)){0,1}/real/i;
492 $field =~ s/double(\(\d*,\d*\)){0,1}/real/i;
493 # mSQL doesn't have blob, it has text instead
494 if ($field =~ / blob/i)
496 $name=$self->{'blob'};
497 $field =~ s/ blob/ $name/;
499 $query.= $field . ',';
501 substr($query,-1)=")"; # Remove last ',';
502 push(@queries,$query);
503 $nr=0;
505 # Prepend table_name to index name because the the name may clash with
506 # a field name. (Should be diffent name space, but this is mSQL...)
508 foreach $index (@$index)
510 # Primary key is unique index in mSQL
511 $index =~ s/primary key/unique index primary/i;
512 if ($index =~ /^unique\s*\(([^\(]*)\)$/i)
514 $nr++;
515 push(@queries,"create unique index ${table_name}_$nr on $table_name ($1)");
517 else
519 if (!($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i))
521 die "Can't parse index information in '$index'\n";
523 push(@queries,"create $1 ${table_name}_$2 on $table_name $3");
526 return @queries;
530 sub insert_file {
531 my($self,$dbname, $file) = @_;
532 print "insert an ascii file isn't supported by mSQL\n";
533 return 0;
537 sub query {
538 my($self,$sql) = @_;
539 return $sql;
542 sub drop_index
544 my ($self,$table,$index) = @_;
545 return "DROP INDEX $index FROM $table";
548 sub abort_if_fatal_error
550 return 0;
553 sub small_rollback_segment
555 return 0;
558 sub reconnect_on_errors
560 return 0;
563 sub fix_for_insert
565 my ($self,$cmd) = @_;
566 return $cmd;
569 #############################################################################
570 # Definitions for PostgreSQL #
571 #############################################################################
573 package db_Pg;
575 sub new
577 my ($type,$host,$database)= @_;
578 my $self= {};
579 my %limits;
580 bless $self;
582 $self->{'cmp_name'} = "pg";
583 $self->{'data_source'} = "DBI:Pg:dbname=$database";
584 $self->{'limits'} = \%limits;
585 $self->{'blob'} = "text";
586 $self->{'text'} = "text";
587 $self->{'double_quotes'} = 1;
588 $self->{'drop_attr'} = "";
589 $self->{'transactions'} = 1; # Transactions enabled
590 $self->{"vacuum"} = 1;
591 $limits{'join_optimizer'} = 1; # Can optimize FROM tables
592 $limits{'load_data_infile'} = 0;
594 $limits{'NEG'} = 1;
595 $limits{'alter_add_multi_col'}= 0; # alter_add_multi_col ?
596 $limits{'alter_table'} = 1;
597 $limits{'alter_table_dropcol'}= 0;
598 $limits{'column_alias'} = 1;
599 $limits{'func_extra_%'} = 1;
600 $limits{'func_extra_if'} = 0;
601 $limits{'func_extra_in_num'} = 1;
602 $limits{'func_odbc_floor'} = 1;
603 $limits{'func_odbc_mod'} = 1; # Has %
604 $limits{'functions'} = 1;
605 $limits{'group_by_position'} = 1;
606 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
607 $limits{'group_func_extra_std'} = 0;
608 $limits{'group_func_sql_min_str'}= 1; # Can execute MIN() and MAX() on strings
609 $limits{'group_functions'} = 1;
610 $limits{'having_with_alias'} = 0;
611 $limits{'having_with_group'} = 1;
612 $limits{'insert_select'} = 1;
613 $limits{'left_outer_join'} = 1;
614 $limits{'like_with_column'} = 1;
615 $limits{'lock_tables'} = 0; # in ATIS gives this a problem
616 $limits{'max_column_name'} = 128;
617 $limits{'max_columns'} = 1000; # 500 crashes pg 6.3
618 $limits{'max_conditions'} = 9999; # This makes Pg real slow
619 $limits{'max_index'} = 64; # Big enough
620 $limits{'max_index_parts'} = 16;
621 $limits{'max_tables'} = 5000; # 10000 crashes pg 7.0.2
622 $limits{'max_text_size'} = 65000; # Good enough for test
623 $limits{'multi_drop'} = 1;
624 $limits{'order_by_position'} = 1;
625 $limits{'order_by_unused'} = 1;
626 $limits{'query_size'} = 16777216;
627 $limits{'select_without_from'}= 1;
628 $limits{'subqueries'} = 1;
629 $limits{'table_wildcard'} = 1;
630 $limits{'truncate_table'} = 1;
631 $limits{'unique_index'} = 1; # Unique index works or not
632 $limits{'working_all_fields'} = 1;
633 $limits{'working_blobs'} = 1; # If big varchar/blobs works
634 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
636 return $self;
639 # couldn't find the option to get the version number
641 sub version
643 my ($version,$dir);
644 $version = "PostgreSQL version ???";
645 foreach $dir ($ENV{'PGDATA'},"/usr/local/pgsql/data", "/usr/local/pg/data")
647 if ($dir && -e "$dir/PG_VERSION")
649 $version= `cat $dir/PG_VERSION`;
650 if ($? == 0)
652 chomp($version);
653 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
654 return "PostgreSQL $version";
658 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
659 return $version;
663 sub connect
665 my ($self)=@_;
666 my ($dbh);
667 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
668 $main::opt_password,{ PrintError => 0}) ||
669 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
670 return $dbh;
674 sub create
676 my($self,$table_name,$fields,$index) = @_;
677 my($query,@queries,$name,$in,$indfield,$table,$nr);
679 $query="create table $table_name (";
680 foreach $field (@$fields)
682 if ($main::opt_fast)
684 # Allow use of char2, char4, char8 or char16
685 $field =~ s/char(2|4|8|16)/char$1/;
687 # Pg can't handle more than the real basic int types
688 $field =~ s/tinyint|smallint|mediumint|integer/int/;
689 # Pg can't handle different visual lengths
690 $field =~ s/int\(\d*\)/int/;
691 $field =~ s/float\(\d*,\d*\)/float/;
692 $field =~ s/ double/ float/;
693 # $field =~ s/ decimal/ float/i;
694 # $field =~ s/ big_decimal/ float/i;
695 # $field =~ s/ date/ int/i;
696 # Pg doesn't have blob, it has text instead
697 $field =~ s/ blob/ text/;
698 $query.= $field . ',';
700 substr($query,-1)=")"; # Remove last ',';
701 push(@queries,$query);
702 foreach $index (@$index)
704 $index =~ s/primary key/unique index primary_key/i;
705 if ($index =~ /^unique.*\(([^\(]*)\)$/i)
707 # original: $indfield="using btree (" .$1.")";
708 # using btree doesn´t seem to work with Postgres anymore; it creates
709 # the table and adds the index, but it isn´t unique
710 $indfield=" (" .$1.")";
711 $in="unique index";
712 $table="index_$nr"; $nr++;
714 elsif ($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i)
716 # original: $indfield="using btree (" .$1.")";
717 $indfield=" " .$3;
718 $in="index";
719 $table="index_$nr"; $nr++;
721 else
723 die "Can't parse index information in '$index'\n";
725 push(@queries,"create $in ${table_name}_$table on $table_name $indfield");
727 $queries[0]=$query;
728 return @queries;
731 sub insert_file {
732 my ($self,$dbname, $file, $dbh) = @_;
733 my ($command, $sth);
735 # Syntax:
736 # copy [binary] <class_name> [with oids]
737 # {to|from} {<filename>|stdin|stdout} [using delimiters <delim>]
738 print "The ascii files aren't correct for postgres ....!!!\n";
739 $command = "copy $dbname from '$file' using delimiters ','";
740 print "$command\n";
741 $sth = $dbh->do($command) or die $DBI::errstr;
742 return $sth;
746 # As postgreSQL wants A % B instead of standard mod(A,B) we have to map
747 # This will not handle all cases, but as the benchmarks doesn't use functions
748 # inside MOD() the following should work
750 # PostgreSQL cant handle count(*) or even count(1), but it can handle
751 # count(1+1) sometimes. ==> this is solved in PostgreSQL 6.3
753 # PostgreSQL 6.5 is supporting MOD.
755 sub query {
756 my($self,$sql) = @_;
757 my(@select,$change);
758 # if you use PostgreSQL 6.x and x is lower as 5 then uncomment the line below.
759 # $sql =~ s/mod\(([^,]*),([^\)]*)\)/\($1 % $2\)/gi;
761 # if you use PostgreSQL 6.1.x uncomment the lines below
762 # if ($sql =~ /select\s+count\(\*\)\s+from/i) {
764 # elsif ($sql =~ /count\(\*\)/i)
766 # if ($sql =~ /select\s+(.*)\s+from/i)
768 # @select = split(/,/,$1);
769 # if ($select[0] =~ /(.*)\s+as\s+\w+$/i)
771 # $change = $1;
773 # else
775 # $change = $select[0];
778 # if (($change =~ /count/i) || ($change eq "")) {
779 # $change = "1+1";
781 # $sql =~ s/count\(\*\)/count($change)/gi;
783 # till here.
784 return $sql;
787 sub drop_index
789 my ($self,$table,$index) = @_;
790 return "DROP INDEX $index";
793 sub abort_if_fatal_error
795 return 1 if ($DBI::errstr =~ /sent to backend, but backend closed/i);
796 return 0;
799 sub small_rollback_segment
801 return 0;
804 sub reconnect_on_errors
806 return 0;
809 sub fix_for_insert
811 my ($self,$cmd) = @_;
812 return $cmd;
815 sub vacuum
817 my ($self,$full_vacuum,$dbh_ref,@tables)=@_;
818 my ($loop_time,$end_time,$dbh,$table);
819 if (defined($full_vacuum))
821 $$dbh_ref->disconnect; $$dbh_ref= $self->connect();
823 $dbh=$$dbh_ref;
824 $loop_time=new Benchmark;
825 if ($#tables >= 0)
827 foreach $table (@tables)
829 $dbh->do("vacuum analyze $table") || die "Got error: $DBI::errstr when executing 'vacuum analyze $table'\n";
830 $dbh->do("vacuum $table") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
833 else
835 # $dbh->do("vacuum pg_attributes") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
836 # $dbh->do("vacuum pg_index") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
837 $dbh->do("vacuum analyze") || die "Got error: $DBI::errstr when executing 'vacuum analyze'\n";
838 $dbh->do("vacuum") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
840 $end_time=new Benchmark;
841 print "Time for book-keeping (1): " .
842 Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"all") . "\n\n";
843 $dbh->disconnect; $$dbh_ref= $self->connect();
847 #############################################################################
848 # Definitions for Solid
849 #############################################################################
851 package db_Solid;
853 sub new
855 my ($type,$host,$database)= @_;
856 my $self= {};
857 my %limits;
858 bless $self;
860 $self->{'cmp_name'} = "solid";
861 $self->{'data_source'} = "DBI:Solid:";
862 $self->{'limits'} = \%limits;
863 $self->{'blob'} = "long varchar";
864 $self->{'text'} = "long varchar";
865 $self->{'double_quotes'} = 1;
866 $self->{'drop_attr'} = "";
867 $self->{'transactions'} = 1; # Transactions enabled
869 $limits{'max_conditions'} = 9999; # Probably big enough
870 $limits{'max_columns'} = 2000; # From crash-me
871 $limits{'max_tables'} = 65000; # Should be big enough
872 $limits{'max_text_size'} = 65492; # According to tests
873 $limits{'query_size'} = 65535; # Probably a limit
874 $limits{'max_index'} = 64; # Probably big enough
875 $limits{'max_index_parts'} = 64;
876 $limits{'max_column_name'} = 80;
878 $limits{'join_optimizer'} = 1;
879 $limits{'load_data_infile'} = 0;
880 $limits{'lock_tables'} = 0;
881 $limits{'functions'} = 1;
882 $limits{'group_functions'} = 1;
883 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
884 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
885 $limits{'select_without_from'}= 0; # Can do 'select 1' ?;
886 $limits{'multi_drop'} = 0;
887 $limits{'subqueries'} = 1;
888 $limits{'left_outer_join'} = 1;
889 $limits{'table_wildcard'} = 1;
890 $limits{'having_with_alias'} = 0;
891 $limits{'having_with_group'} = 1;
892 $limits{'like_with_column'} = 1;
893 $limits{'order_by_position'} = 0; # 2.30.0018 can this
894 $limits{'group_by_position'} = 0;
895 $limits{'alter_table'} = 1;
896 $limits{'alter_add_multi_col'}= 0;
897 $limits{'alter_table_dropcol'}= 0;
899 $limits{'group_func_extra_std'} = 0; # Have group function std().
901 $limits{'func_odbc_mod'} = 1;
902 $limits{'func_extra_%'} = 0;
903 $limits{'func_odbc_floor'} = 1;
904 $limits{'column_alias'} = 1;
905 $limits{'NEG'} = 1;
906 $limits{'func_extra_in_num'} = 1;
907 $limits{'unique_index'} = 1; # Unique index works or not
908 $limits{'insert_select'} = 1;
909 $limits{'working_blobs'} = 1; # If big varchar/blobs works
910 $limits{'order_by_unused'} = 1;
911 $limits{'working_all_fields'} = 1;
912 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
914 return $self;
918 # Get the version number of the database
921 sub version
923 my ($version,$dir);
924 $version="Solid version ??";
925 foreach $dir ($ENV{'SOLIDDIR'},"/usr/local/solid", "/my/local/solid")
927 if ($dir && -e "$dir/bin/solcon")
929 $version=`$dir/bin/solcon -e"ver" $main::opt_user $main::opt_password | grep Server | sed q`;
930 if ($? == 0)
932 chomp($version);
933 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
934 return $version;
938 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
939 return $version;
942 sub connect
944 my ($self)=@_;
945 my ($dbh);
946 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
947 $main::opt_password,{ PrintError => 0}) ||
948 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
949 return $dbh;
953 # Returns a list of statements to create a table
954 # The field types are in ANSI SQL format.
957 sub create
959 my($self,$table_name,$fields,$index) = @_;
960 my($query,@queries,$nr);
962 $query="create table $table_name (";
963 foreach $field (@$fields)
965 $field =~ s/mediumint/integer/i;
966 $field =~ s/ double/ float/i;
967 # Solid doesn't have blob, it has long varchar
968 $field =~ s/ blob/ long varchar/;
969 # $field =~ s/ decimal/ float/i;
970 # $field =~ s/ big_decimal/ float/i;
971 # $field =~ s/ date/ int/i;
972 $query.= $field . ',';
974 substr($query,-1)=")"; # Remove last ',';
975 push(@queries,$query);
976 $nr=0;
977 foreach $index (@$index)
979 if ($index =~ /^primary key/i || $index =~ /^unique/i)
980 { # Add to create statement
981 substr($queries[0],-1,0)="," . $index;
983 else
985 $index =~ /^(.*)\s+(\(.*\))$/;
986 push(@queries,"create ${1}$nr on $table_name $2");
987 $nr++;
990 return @queries;
993 # there is no sql statement in solid which can do the load from
994 # an ascii file in the db ... but there is the speedloader program
995 # an external program which can load the ascii file in the db ...
996 # the server must be down before using speedloader !!!!
997 # (in the standalone version)
998 # it works also with a control file ... that one must be made ....
999 sub insert_file {
1000 my ($self, $dbname, $file) = @_;
1001 my ($speedcmd);
1002 $speedcmd = '/usr/local/solid/bin/solload';
1003 print "At this moment not supported - solid server must go down \n";
1004 return 0;
1007 # solid can't handle an alias in a having statement so
1008 # select test as foo from tmp group by foo having foor > 2
1009 # becomes
1010 # select test as foo from tmp group by foo having test > 2
1012 sub query {
1013 my($self,$sql) = @_;
1014 my(@select,$tmp,$newhaving,$key,%change);
1016 if ($sql =~ /having\s+/i)
1018 if ($sql =~ /select (.*) from/i)
1020 (@select) = split(/,\s*/, $1);
1021 foreach $tmp (@select)
1023 if ($tmp =~ /(.*)\s+as\s+(\w+)/)
1025 $change{$2} = $1;
1029 if ($sql =~ /having\s+(\w+)/i)
1031 $newhaving = $1;
1032 foreach $key (sort {$a cmp $b} keys %change)
1034 if ($newhaving eq $key)
1036 $newhaving =~ s/$key/$change{$key}/g;
1040 $sql =~ s/(having)\s+(\w+)/$1 $newhaving/i;
1042 return $sql;
1046 sub drop_index
1048 my ($self,$table,$index) = @_;
1049 return "DROP INDEX $index";
1052 sub abort_if_fatal_error
1054 return 0;
1057 sub small_rollback_segment
1059 return 0;
1062 sub fix_for_insert
1064 my ($self,$cmd) = @_;
1065 return $cmd;
1068 sub reconnect_on_errors
1070 return 0;
1073 #############################################################################
1074 # Definitions for Empress
1076 # at this moment DBI:Empress can only handle 200 prepare statements ...
1077 # so Empress can't be tested with the benchmark test :(
1078 #############################################################################
1080 package db_Empress;
1082 sub new
1084 my ($type,$host,$database)= @_;
1085 my $self= {};
1086 my %limits;
1087 bless $self;
1089 $self->{'cmp_name'} = "empress";
1090 $self->{'data_source'} = "DBI:EmpressNet:SERVER=$host;Database=/usr/local/empress/rdbms/bin/$database";
1091 $self->{'limits'} = \%limits;
1092 $self->{'blob'} = "text";
1093 $self->{'text'} = "text";
1094 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
1095 $self->{'drop_attr'} = "";
1096 $self->{'transactions'} = 1; # Transactions enabled
1098 $limits{'max_conditions'} = 1258;
1099 $limits{'max_columns'} = 226; # server is disconnecting????
1100 # above this value .... but can handle 2419 columns
1101 # maybe something for crash-me ... but how to check ???
1102 $limits{'max_tables'} = 65000; # Should be big enough
1103 $limits{'max_text_size'} = 4095; # max returned ....
1104 $limits{'query_size'} = 65535; # Not a limit, big enough
1105 $limits{'max_index'} = 64; # Big enough
1106 $limits{'max_index_parts'} = 64; # Big enough
1107 $limits{'max_column_name'} = 31;
1109 $limits{'join_optimizer'} = 1;
1110 $limits{'load_data_infile'} = 0;
1111 $limits{'lock_tables'} = 1;
1112 $limits{'functions'} = 1;
1113 $limits{'group_functions'} = 1;
1114 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
1115 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
1116 $limits{'select_without_from'}= 0;
1117 $limits{'multi_drop'} = 0;
1118 $limits{'subqueries'} = 1;
1119 $limits{'table_wildcard'} = 0;
1120 $limits{'having_with_alias'} = 0; # AS isn't supported in a select
1121 $limits{'having_with_group'} = 1;
1122 $limits{'like_with_column'} = 1;
1123 $limits{'order_by_position'} = 1;
1124 $limits{'group_by_position'} = 0;
1125 $limits{'alter_table'} = 1;
1126 $limits{'alter_add_multi_col'}= 0;
1127 $limits{'alter_table_dropcol'}= 0;
1129 $limits{'group_func_extra_std'}= 0; # Have group function std().
1131 $limits{'func_odbc_mod'} = 0;
1132 $limits{'func_extra_%'} = 1;
1133 $limits{'func_odbc_floor'} = 1;
1134 $limits{'func_extra_if'} = 0;
1135 $limits{'column_alias'} = 0;
1136 $limits{'NEG'} = 1;
1137 $limits{'func_extra_in_num'} = 0;
1138 $limits{'unique_index'} = 1; # Unique index works or not
1139 $limits{'insert_select'} = 1;
1140 $limits{'working_blobs'} = 1; # If big varchar/blobs works
1141 $limits{'order_by_unused'} = 1;
1142 $limits{'working_all_fields'} = 1;
1143 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
1145 return $self;
1149 # Get the version number of the database
1152 sub version
1154 my ($self,$dbh)=@_;
1155 my ($version);
1156 $version="";
1157 if (-x "/usr/local/empress/rdbms/bin/empvers")
1159 $version=`/usr/local/empress/rdbms/bin/empvers | grep Version`;
1161 if ($version)
1163 chomp($version);
1165 else
1167 $version="Empress version ???";
1170 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
1171 return $version;
1174 sub connect
1176 my ($self)=@_;
1177 my ($dbh);
1178 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
1179 $main::opt_password,{ PrintError => 0}) ||
1180 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
1181 return $dbh;
1184 sub insert_file {
1185 my($self,$dbname, $file) = @_;
1186 my($command,$sth);
1187 $command = "insert into $dbname from '$file'";
1188 print "$command\n" if ($opt_debug);
1189 $sth = $dbh->do($command) or die $DBI::errstr;
1191 return $sth;
1195 # Returns a list of statements to create a table
1196 # The field types are in ANSI SQL format.
1199 sub create
1201 my($self,$table_name,$fields,$index) = @_;
1202 my($query,@queries,$nr);
1204 $query="create table $table_name (";
1205 foreach $field (@$fields)
1207 $field =~ s/mediumint/int/i;
1208 $field =~ s/tinyint/int/i;
1209 $field =~ s/smallint/int/i;
1210 $field =~ s/longint/int/i;
1211 $field =~ s/integer/int/i;
1212 $field =~ s/ double/ longfloat/i;
1213 # Solid doesn't have blob, it has long varchar
1214 # $field =~ s/ blob/ text(65535,65535,65535,65535)/;
1215 $field =~ s/ blob/ text/;
1216 $field =~ s/ varchar\((\d+)\)/ char($1,3)/;
1217 $field =~ s/ char\((\d+)\)/ char($1,3)/;
1218 # $field =~ s/ decimal/ float/i;
1219 # $field =~ s/ big_decimal/ longfloat/i;
1220 # $field =~ s/ date/ int/i;
1221 $field =~ s/ float(.*)/ float/i;
1222 if ($field =~ / int\((\d+)\)/) {
1223 if ($1 > 4) {
1224 $field =~ s/ int\(\d+\)/ longinteger/i;
1225 } else {
1226 $field =~ s/ int\(\d+\)/ longinteger/i;
1228 } else {
1229 $field =~ s/ int/ longinteger/i;
1231 $query.= $field . ',';
1233 substr($query,-1)=")"; # Remove last ',';
1234 push(@queries,$query);
1235 $nr=1;
1236 foreach $index (@$index)
1238 # Primary key is unique index in Empress
1239 $index =~ s/primary key/unique index/i;
1240 if ($index =~ /^unique.*\(([^\(]*)\)$/i)
1242 $nr++;
1243 push(@queries,"create unique index ${table_name}_$nr on $table_name ($1)");
1245 else
1247 if (!($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i))
1249 die "Can't parse index information in '$index'\n";
1251 push(@queries,"create $1 ${table_name}_$2 on $table_name $3");
1254 return @queries;
1257 # empress can't handle an alias and but can handle the number of the
1258 # columname - so
1259 # select test as foo from tmp order by foo
1260 # becomes
1261 # select test from tmp order by 1
1263 sub query {
1264 my($self,$sql) = @_;
1265 my(@select,$i,$tmp,$newselect,$neworder,@order,$key,%change);
1266 my($tmp1,$otmp,$tmp2);
1268 if ($sql =~ /\s+as\s+/i)
1270 if ($sql =~ /select\s+(.*)\s+from/i) {
1271 $newselect = $1;
1272 (@select) = split(/,\s*/, $1);
1273 $i = 1;
1274 foreach $tmp (@select) {
1275 if ($tmp =~ /\s+as\s+(\w+)/) {
1276 $change{$1} = $i;
1278 $i++;
1281 $newselect =~ s/\s+as\s+(\w+)//gi;
1282 $tmp2 = 0;
1283 if ($sql =~ /order\s+by\s+(.*)$/i) {
1284 (@order) = split(/,\s*/, $1);
1285 foreach $otmp (@order) {
1286 foreach $key (sort {$a cmp $b} keys %change) {
1287 if ($otmp eq $key) {
1288 $neworder .= "$tmp1"."$change{$key}";
1289 $tmp1 = ", ";
1290 $tmp2 = 1;
1291 } elsif ($otmp =~ /(\w+)\s+(.+)$/) {
1292 if ($key eq $1) {
1293 $neworder .= "$tmp1"."$change{$key} $2";
1294 $tmp2 = 1;
1298 if ($tmp2 == 0) {
1299 $neworder .= "$tmp1"."$otmp";
1301 $tmp2 = 0;
1302 $tmp1 = ", ";
1305 $sql =~ s/(select)\s+(.*)\s+(from)/$1 $newselect $3/i;
1306 $sql =~ s/(order\s+by)\s+(.*)$/$1 $neworder/i;
1308 return $sql;
1311 sub fix_for_insert
1313 my ($self,$cmd) = @_;
1314 $cmd =~ s/\'\'/\' \'/g;
1315 return $cmd;
1319 sub drop_index
1321 my ($self,$table,$index) = @_;
1322 return "DROP INDEX $index";
1325 # This is a because of the 200 statement problem with DBI-Empress
1327 sub abort_if_fatal_error
1329 if ($DBI::errstr =~ /Overflow of table of prepared statements/i)
1331 print "Overflow of prepared statements ... killing the process\n";
1332 exit 1;
1334 return 0;
1337 sub small_rollback_segment
1339 return 0;
1342 sub reconnect_on_errors
1344 return 0;
1347 #############################################################################
1348 # Definitions for Oracle
1349 #############################################################################
1351 package db_Oracle;
1353 sub new
1355 my ($type,$host,$database)= @_;
1356 my $self= {};
1357 my %limits;
1358 bless $self;
1360 $self->{'cmp_name'} = "Oracle";
1361 $self->{'data_source'} = "DBI:Oracle:$database";
1362 $self->{'limits'} = \%limits;
1363 $self->{'blob'} = "long";
1364 $self->{'text'} = "long";
1365 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
1366 $self->{'drop_attr'} = "";
1367 $self->{'transactions'} = 1; # Transactions enabled
1368 $self->{"vacuum"} = 1;
1370 $limits{'max_conditions'} = 9999; # (Actually not a limit)
1371 $limits{'max_columns'} = 254; # Max number of columns in table
1372 $limits{'max_tables'} = 65000; # Should be big enough
1373 $limits{'max_text_size'} = 2000; # Limit for blob test-connect
1374 $limits{'query_size'} = 65525; # Max size with default buffers.
1375 $limits{'max_index'} = 16; # Max number of keys
1376 $limits{'max_index_parts'} = 16; # Max segments/key
1377 $limits{'max_column_name'} = 32; # max table and column name
1379 $limits{'truncate_table'} = 1;
1380 $limits{'join_optimizer'} = 1; # Can optimize FROM tables
1381 $limits{'load_data_infile'} = 0; # Has load data infile
1382 $limits{'lock_tables'} = 0; # Has lock tables
1383 $limits{'functions'} = 1; # Has simple functions (+/-)
1384 $limits{'group_functions'} = 1; # Have group functions
1385 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
1386 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
1387 $limits{'select_without_from'}= 0;
1388 $limits{'multi_drop'} = 0;
1389 $limits{'subqueries'} = 1;
1390 $limits{'left_outer_join'} = 0; # This may be fixed in the query module
1391 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
1392 $limits{'having_with_alias'} = 0; # Can use aliases in HAVING
1393 $limits{'having_with_group'} = 1; # Can't use group functions in HAVING
1394 $limits{'like_with_column'} = 1; # Can use column1 LIKE column2
1395 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1'
1396 $limits{'group_by_position'} = 0;
1397 $limits{'alter_table'} = 1;
1398 $limits{'alter_add_multi_col'}= 0;
1399 $limits{'alter_table_dropcol'}= 0;
1401 $limits{'group_func_extra_std'} = 0; # Have group function std().
1403 $limits{'func_odbc_mod'} = 0; # Oracle has problem with mod()
1404 $limits{'func_extra_%'} = 0; # Has % as alias for mod()
1405 $limits{'func_odbc_floor'} = 1; # Has func_odbc_floor function
1406 $limits{'func_extra_if'} = 0; # Have function if.
1407 $limits{'column_alias'} = 1; # Alias for fields in select statement.
1408 $limits{'NEG'} = 1; # Supports -id
1409 $limits{'func_extra_in_num'} = 1; # Has function in
1410 $limits{'unique_index'} = 1; # Unique index works or not
1411 $limits{'insert_select'} = 1;
1412 $limits{'working_blobs'} = 1; # If big varchar/blobs works
1413 $limits{'order_by_unused'} = 1;
1414 $limits{'working_all_fields'} = 1;
1415 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
1418 return $self;
1422 # Get the version number of the database
1425 sub version
1427 my ($self)=@_;
1428 my ($dbh,$sth,$version,@row);
1430 $dbh=$self->connect();
1431 $sth = $dbh->prepare("select VERSION from product_component_version WHERE PRODUCT like 'Oracle%'") or die $DBI::errstr;
1432 $version="Oracle 7.x";
1433 if ($sth->execute && (@row = $sth->fetchrow_array))
1435 $version="Oracle $row[0]";
1437 $sth->finish;
1438 $dbh->disconnect;
1439 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
1440 return $version;
1443 sub connect
1445 my ($self)=@_;
1446 my ($dbh);
1447 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
1448 $main::opt_password,{ PrintError => 0}) ||
1449 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
1450 return $dbh;
1454 # Returns a list of statements to create a table
1455 # The field types are in ANSI SQL format.
1457 # If one uses $main::opt_fast then one is allowed to use
1458 # non standard types to get better speed.
1461 sub create
1463 my($self,$table_name,$fields,$index) = @_;
1464 my($query,@queries,$ind,@keys);
1466 $query="create table $table_name (";
1467 foreach $field (@$fields)
1469 $field =~ s/ character\((\d+)\)/ char\($1\)/i;
1470 $field =~ s/ character varying\((\d+)\)/ varchar\($1\)/i;
1471 $field =~ s/ char varying\((\d+)\)/ varchar\($1\)/i;
1472 $field =~ s/ integer/ number\(38\)/i;
1473 $field =~ s/ int/ number\(38\)/i;
1474 $field =~ s/ tinyint/ number\(38\)/i;
1475 $field =~ s/ smallint/ number\(38\)/i;
1476 $field =~ s/ mediumint/ number\(38\)/i;
1477 $field =~ s/ tinynumber\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
1478 $field =~ s/ smallnumber\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
1479 $field =~ s/ mediumnumber\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
1480 $field =~ s/ number\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
1481 $field =~ s/ numeric\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
1482 $field =~ s/ decimal\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
1483 $field =~ s/ dec\((\d+)\)\((\d+)\)/ number\($1,$2\)/i;
1484 $field =~ s/ float/ number/;
1485 $field =~ s/ real/ number/;
1486 $field =~ s/ double precision/ number/;
1487 $field =~ s/ double/ number/;
1488 $field =~ s/ blob/ long/;
1489 $query.= $field . ',';
1492 foreach $ind (@$index)
1494 my @index;
1495 if ( $ind =~ /\bKEY\b/i ){
1496 push(@keys,"ALTER TABLE $table_name ADD $ind");
1497 }else{
1498 my @fields = split(' ',$index);
1499 my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
1500 push(@index,$query);
1503 substr($query,-1)=")"; # Remove last ',';
1504 push(@queries,$query,@keys,@index);
1505 #print "query:$query\n";
1507 return @queries;
1510 sub insert_file {
1511 my($self,$dbname, $file) = @_;
1512 print "insert an ascii file isn't supported by Oracle (?)\n";
1513 return 0;
1517 # Do any conversions to the ANSI SQL query so that the database can handle it
1520 sub query {
1521 my($self,$sql) = @_;
1522 return $sql;
1525 sub fix_for_insert
1527 my ($self,$cmd) = @_;
1528 $cmd =~ s/\'\'/\' \'/g;
1529 return $cmd;
1533 sub drop_index
1535 my ($self,$table,$index) = @_;
1536 return "DROP INDEX $index";
1540 # Abort if the server has crashed
1541 # return: 0 if ok
1542 # 1 question should be retried
1545 sub abort_if_fatal_error
1547 return 0;
1550 sub small_rollback_segment
1552 return 1;
1555 sub reconnect_on_errors
1557 return 0;
1561 # optimize the tables ....
1563 sub vacuum
1565 my ($self,$full_vacuum,$dbh_ref)=@_;
1566 my ($loop_time,$end_time,$sth,$dbh);
1568 if (defined($full_vacuum))
1570 $$dbh_ref->disconnect; $$dbh_ref= $self->connect();
1572 $dbh=$$dbh_ref;
1573 $loop_time=new Benchmark;
1574 # first analyze all tables
1575 $sth = $dbh->prepare("select table_name from user_tables") || die "Got error: $DBI::errstr";
1576 $sth->execute || die "Got error: $DBI::errstr when select user_tables";
1577 while (my @r = $sth->fetchrow_array)
1579 $dbh->do("analyze table $r[0] compute statistics") || die "Got error: $DBI::errstr when executing 'analyze table'\n";
1581 # now analyze all indexes ...
1582 $sth = $dbh->prepare("select index_name from user_indexes") || die "Got error: $DBI::errstr";
1583 $sth->execute || die "Got error: $DBI::errstr when select user_indexes";
1584 while (my @r1 = $sth->fetchrow_array)
1586 $dbh->do("analyze index $r1[0] compute statistics") || die "Got error: $DBI::errstr when executing 'analyze index $r1[0]'\n";
1588 $end_time=new Benchmark;
1589 print "Time for book-keeping (1): " .
1590 Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"all") . "\n\n";
1591 $dbh->disconnect; $$dbh_ref= $self->connect();
1595 #############################################################################
1596 # Definitions for Informix
1597 #############################################################################
1599 package db_Informix;
1601 sub new
1603 my ($type,$host,$database)= @_;
1604 my $self= {};
1605 my %limits;
1606 bless $self;
1608 $self->{'cmp_name'} = "Informix";
1609 $self->{'data_source'} = "DBI:Informix:$database";
1610 $self->{'limits'} = \%limits;
1611 $self->{'blob'} = "byte in table";
1612 $self->{'text'} = "byte in table";
1613 $self->{'double_quotes'} = 0; # Can handle: 'Walker''s'
1614 $self->{'drop_attr'} = "";
1615 $self->{'transactions'} = 1; # Transactions enabled
1616 $self->{'host'} = $host;
1618 $limits{'NEG'} = 1; # Supports -id
1619 $limits{'alter_table'} = 1;
1620 $limits{'alter_add_multi_col'}= 0;
1621 $limits{'alter_table_dropcol'}= 1;
1622 $limits{'column_alias'} = 1; # Alias for fields in select statement.
1623 $limits{'func_extra_%'} = 0; # Has % as alias for mod()
1624 $limits{'func_extra_if'} = 0; # Have function if.
1625 $limits{'func_extra_in_num'}= 0; # Has function in
1626 $limits{'func_odbc_floor'} = 0; # Has func_odbc_floor function
1627 $limits{'func_odbc_mod'} = 1; # Have function mod.
1628 $limits{'functions'} = 1; # Has simple functions (+/-)
1629 $limits{'group_by_position'} = 1; # Can use 'GROUP BY 1'
1630 $limits{'group_by_alias'} = 0; # Can use 'select a as ab from x GROUP BY ab'
1631 $limits{'group_func_extra_std'} = 0; # Have group function std().
1632 $limits{'group_functions'} = 1; # Have group functions
1633 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
1634 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
1635 $limits{'having_with_alias'} = 0; # Can use aliases in HAVING
1636 $limits{'having_with_group'}= 1; # Can't use group functions in HAVING
1637 $limits{'join_optimizer'} = 1; # Can optimize FROM tables (always 1 only for msql)
1638 $limits{'left_outer_join'} = 0; # Supports left outer joins (ANSI)
1639 $limits{'like_with_column'} = 1; # Can use column1 LIKE column2
1640 $limits{'load_data_infile'} = 0; # Has load data infile
1641 $limits{'lock_tables'} = 1; # Has lock tables
1642 $limits{'max_conditions'} = 1214; # (Actually not a limit)
1643 $limits{'max_column_name'} = 18; # max table and column name
1644 $limits{'max_columns'} = 994; # Max number of columns in table
1645 $limits{'max_tables'} = 65000; # Should be big enough
1646 $limits{'max_index'} = 64; # Max number of keys
1647 $limits{'max_index_parts'} = 15; # Max segments/key
1648 $limits{'max_text_size'} = 65535; # Max size with default buffers. ??
1649 $limits{'multi_drop'} = 0; # Drop table can take many tables
1650 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1'
1651 $limits{'query_size'} = 32766; # Max size with default buffers.
1652 $limits{'select_without_from'}= 0; # Can do 'select 1';
1653 $limits{'subqueries'} = 1; # Doesn't support sub-queries.
1654 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
1655 $limits{'unique_index'} = 1; # Unique index works or not
1656 $limits{'insert_select'} = 1;
1657 $limits{'working_blobs'} = 1; # If big varchar/blobs works
1658 $limits{'order_by_unused'} = 1;
1659 $limits{'working_all_fields'} = 1;
1660 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
1662 return $self;
1666 # Get the version number of the database
1669 sub version
1671 my ($self)=@_;
1672 my ($dbh,$sth,$version,@row);
1674 $ENV{'INFORMIXSERVER'} = $self->{'host'};
1675 $dbh=$self->connect();
1676 $sth = $dbh->prepare("SELECT owner FROM systables WHERE tabname = ' VERSION'")
1677 or die $DBI::errstr;
1678 $version='Informix unknown';
1679 if ($sth->execute && (@row = $sth->fetchrow_array))
1681 $version="Informix $row[0]";
1683 $sth->finish;
1684 $dbh->disconnect;
1685 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
1686 return $version;
1689 sub connect
1691 my ($self)=@_;
1692 my ($dbh);
1693 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
1694 $main::opt_password,{ PrintError => 0}) ||
1695 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
1696 return $dbh;
1701 # Create table
1704 sub create
1706 my($self,$table_name,$fields,$index) = @_;
1707 my($query,@queries,$name,$nr);
1709 $query="create table $table_name (";
1710 foreach $field (@$fields)
1712 # $field =~ s/\btransport_description\b/transport_desc/;
1713 # to overcome limit 18 chars
1714 $field =~ s/tinyint/smallint/i;
1715 $field =~ s/tinyint\(\d+\)/smallint/i;
1716 $field =~ s/mediumint/integer/i;
1717 $field =~ s/mediumint\(\d+\)/integer/i;
1718 $field =~ s/smallint\(\d+\)/smallint/i;
1719 $field =~ s/integer\(\d+\)/integer/i;
1720 $field =~ s/int\(\d+\)/integer/i;
1721 # $field =~ s/\b(?:small)?int(?:eger)?\((\d+)\)/decimal($1)/i;
1722 # $field =~ s/float(\(\d*,\d*\)){0,1}/real/i;
1723 $field =~ s/(float|double)(\(.*?\))?/float/i;
1725 if ($field =~ / blob/i)
1727 $name=$self->{'blob'};
1728 $field =~ s/ blob/ $name/;
1730 $query.= $field . ',';
1732 substr($query,-1)=")"; # Remove last ',';
1733 push(@queries,$query);
1734 $nr=0;
1736 foreach $index (@$index)
1738 # Primary key is unique index in Informix
1739 $index =~ s/primary key/unique index primary/i;
1740 if ($index =~ /^unique\s*\(([^\(]*)\)$/i)
1742 $nr++;
1743 push(@queries,"create unique index ${table_name}_$nr on $table_name ($1)");
1745 else
1747 if (!($index =~ /^(.*index)\s+(\w*)\s+(\(.*\))$/i))
1749 die "Can't parse index information in '$index'\n";
1751 ### push(@queries,"create $1 ${table_name}_$2 on $table_name $3");
1752 $nr++;
1753 push(@queries,"create $1 ${table_name}_$nr on $table_name $3");
1756 return @queries;
1759 # Some test needed this
1762 sub query {
1763 my($self,$sql) = @_;
1764 return $sql;
1768 sub fix_for_insert
1770 my ($self,$cmd) = @_;
1771 $cmd =~ s/\\\'//g;
1772 return $cmd;
1777 sub drop_index
1779 my ($self,$table,$index) = @_;
1780 return "DROP INDEX $index";
1784 # Abort if the server has crashed
1785 # return: 0 if ok
1786 # 1 question should be retried
1789 sub abort_if_fatal_error
1791 return 0;
1794 sub small_rollback_segment
1796 return 0;
1799 sub reconnect_on_errors
1801 return 0;
1805 #############################################################################
1806 # Configuration for Access
1807 #############################################################################
1809 package db_access;
1811 sub new
1813 my ($type,$host,$database)= @_;
1814 my $self= {};
1815 my %limits;
1816 bless $self;
1818 $self->{'cmp_name'} = "access";
1819 $self->{'data_source'} = "DBI:ODBC:$database";
1820 if (defined($host) && $host ne "")
1822 $self->{'data_source'} .= ":$host";
1824 $self->{'limits'} = \%limits;
1825 $self->{'blob'} = "blob";
1826 $self->{'text'} = "blob"; # text ?
1827 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
1828 $self->{'drop_attr'} = "";
1829 $self->{'transactions'} = 1; # Transactions enabled
1831 $limits{'max_conditions'} = 97; # We get 'Query is too complex'
1832 $limits{'max_columns'} = 255; # Max number of columns in table
1833 $limits{'max_tables'} = 65000; # Should be big enough
1834 $limits{'max_text_size'} = 255; # Max size with default buffers.
1835 $limits{'query_size'} = 65535; # Not a limit, big enough
1836 $limits{'max_index'} = 32; # Max number of keys
1837 $limits{'max_index_parts'} = 10; # Max segments/key
1838 $limits{'max_column_name'} = 64; # max table and column name
1840 $limits{'join_optimizer'} = 1; # Can optimize FROM tables
1841 $limits{'load_data_infile'} = 0; # Has load data infile
1842 $limits{'lock_tables'} = 0; # Has lock tables
1843 $limits{'functions'} = 1; # Has simple functions (+/-)
1844 $limits{'group_functions'} = 1; # Have group functions
1845 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
1846 $limits{'group_distinct_functions'}= 0; # Have count(distinct)
1847 $limits{'select_without_from'}= 1; # Can do 'select 1';
1848 $limits{'multi_drop'} = 0; # Drop table can take many tables
1849 $limits{'subqueries'} = 1; # Supports sub-queries.
1850 $limits{'left_outer_join'} = 1; # Supports left outer joins
1851 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
1852 $limits{'having_with_alias'} = 0; # Can use aliases in HAVING
1853 $limits{'having_with_group'} = 1; # Can use group functions in HAVING
1854 $limits{'like_with_column'} = 1; # Can use column1 LIKE column2
1855 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1'
1856 $limits{'group_by_position'} = 0; # Can use 'GROUP BY 1'
1857 $limits{'alter_table'} = 1;
1858 $limits{'alter_add_multi_col'}= 2; #Have ALTER TABLE t add a int, b int;
1859 $limits{'alter_table_dropcol'}= 1;
1861 $limits{'group_func_extra_std'} = 0; # Have group function std().
1863 $limits{'func_odbc_mod'} = 0; # Have function mod.
1864 $limits{'func_extra_%'} = 0; # Has % as alias for mod()
1865 $limits{'func_odbc_floor'} = 0; # Has func_odbc_floor function
1866 $limits{'func_extra_if'} = 0; # Have function if.
1867 $limits{'column_alias'} = 1; # Alias for fields in select statement.
1868 $limits{'NEG'} = 1; # Supports -id
1869 $limits{'func_extra_in_num'} = 1; # Has function in
1870 $limits{'unique_index'} = 1; # Unique index works or not
1871 $limits{'insert_select'} = 1;
1872 $limits{'working_blobs'} = 1; # If big varchar/blobs works
1873 $limits{'order_by_unused'} = 1;
1874 $limits{'working_all_fields'} = 1;
1875 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
1876 return $self;
1880 # Get the version number of the database
1883 sub version
1885 my ($self)=@_;
1886 my $version="Access 2000";
1887 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
1888 return $version; #DBI/ODBC can't return the server version
1891 sub connect
1893 my ($self)=@_;
1894 my ($dbh);
1895 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
1896 $main::opt_password,{ PrintError => 0}) ||
1897 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
1898 return $dbh;
1902 # Returns a list of statements to create a table
1903 # The field types are in ANSI SQL format.
1906 sub create
1908 my($self,$table_name,$fields,$index) = @_;
1909 my($query,@queries,$nr);
1911 $query="create table $table_name (";
1912 foreach $field (@$fields)
1914 $field =~ s/mediumint/integer/i;
1915 $field =~ s/tinyint/smallint/i;
1916 $field =~ s/float\(\d+,\d+\)/float/i;
1917 $field =~ s/integer\(\d+\)/integer/i;
1918 $field =~ s/smallint\(\d+\)/smallint/i;
1919 $field =~ s/int\(\d+\)/integer/i;
1920 $field =~ s/blob/text/i;
1921 $query.= $field . ',';
1923 substr($query,-1)=")"; # Remove last ',';
1924 push(@queries,$query);
1925 $nr=0;
1926 foreach $index (@$index)
1928 $ext="WITH DISALLOW NULL";
1929 if (($index =~ s/primary key/unique index primary_key/i))
1931 $ext="WITH PRIMARY;"
1933 if ($index =~ /^unique.*\(([^\(]*)\)$/i)
1935 $nr++;
1936 $index="unique index ${table_name}_$nr ($1)";
1938 $index =~ /^(.*)\s+(\(.*\))$/;
1939 push(@queries,"create ${1} on $table_name $2");
1941 return @queries;
1945 # Do any conversions to the ANSI SQL query so that the database can handle it
1948 sub query {
1949 my($self,$sql) = @_;
1950 return $sql;
1953 sub drop_index
1955 my ($self,$table,$index) = @_;
1956 return "DROP INDEX $index ON $table";
1960 # Abort if the server has crashed
1961 # return: 0 if ok
1962 # 1 question should be retried
1965 sub abort_if_fatal_error
1967 return 1 if (($DBI::errstr =~ /The database engine couldn\'t lock table/i) ||
1968 ($DBI::errstr =~ /niet vergrendelen. De tabel is momenteel in gebruik /i) ||
1969 ($DBI::errstr =~ /Den anv.* redan av en annan/i) ||
1970 ($DBI::errstr =~ /non-exclusive access/));
1971 return 0;
1974 sub small_rollback_segment
1976 return 0;
1979 sub reconnect_on_errors
1981 return 1;
1984 sub fix_for_insert
1986 my ($self,$cmd) = @_;
1987 return $cmd;
1990 #############################################################################
1991 # Configuration for Microsoft SQL server
1992 #############################################################################
1994 package db_ms_sql;
1996 sub new
1998 my ($type,$host,$database)= @_;
1999 my $self= {};
2000 my %limits;
2001 bless $self;
2003 $self->{'cmp_name'} = "ms-sql";
2004 $self->{'data_source'} = "DBI:ODBC:$database";
2005 if (defined($host) && $host ne "")
2007 $self->{'data_source'} .= ":$host";
2009 $self->{'limits'} = \%limits;
2010 $self->{'blob'} = "text";
2011 $self->{'text'} = "text";
2012 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
2013 $self->{'drop_attr'} = "";
2014 $self->{'transactions'} = 1; # Transactions enabled
2016 $limits{'max_conditions'} = 1030; # We get 'Query is too complex'
2017 $limits{'max_columns'} = 250; # Max number of columns in table
2018 $limits{'max_tables'} = 65000; # Should be big enough
2019 $limits{'max_text_size'} = 9830; # Max size with default buffers.
2020 $limits{'query_size'} = 9830; # Max size with default buffers.
2021 $limits{'max_index'} = 64; # Max number of keys
2022 $limits{'max_index_parts'} = 15; # Max segments/key
2023 $limits{'max_column_name'} = 30; # max table and column name
2025 $limits{'join_optimizer'} = 1; # Can optimize FROM tables
2026 $limits{'load_data_infile'} = 0; # Has load data infile
2027 $limits{'lock_tables'} = 0; # Has lock tables
2028 $limits{'functions'} = 1; # Has simple functions (+/-)
2029 $limits{'group_functions'} = 1; # Have group functions
2030 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
2031 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
2032 $limits{'select_without_from'}= 1; # Can do 'select 1';
2033 $limits{'multi_drop'} = 1; # Drop table can take many tables
2034 $limits{'subqueries'} = 1; # Supports sub-queries.
2035 $limits{'left_outer_join'} = 1; # Supports left outer joins
2036 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
2037 $limits{'having_with_alias'} = 0; # Can use aliases in HAVING
2038 $limits{'having_with_group'} = 1; # Can't use group functions in HAVING
2039 $limits{'like_with_column'} = 1; # Can use column1 LIKE column2
2040 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1'
2041 $limits{'group_by_position'} = 0; # Can use 'GROUP BY 1'
2042 $limits{'alter_table'} = 1;
2043 $limits{'alter_add_multi_col'}= 0;
2044 $limits{'alter_table_dropcol'}= 0;
2046 $limits{'group_func_extra_std'} = 0; # Have group function std().
2048 $limits{'func_odbc_mod'} = 0; # Have function mod.
2049 $limits{'func_extra_%'} = 1; # Has % as alias for mod()
2050 $limits{'func_odbc_floor'} = 1; # Has func_odbc_floor function
2051 $limits{'func_extra_if'} = 0; # Have function if.
2052 $limits{'column_alias'} = 1; # Alias for fields in select statement.
2053 $limits{'NEG'} = 1; # Supports -id
2054 $limits{'func_extra_in_num'} = 0; # Has function in
2055 $limits{'unique_index'} = 1; # Unique index works or not
2056 $limits{'insert_select'} = 1;
2057 $limits{'working_blobs'} = 1; # If big varchar/blobs works
2058 $limits{'order_by_unused'} = 1;
2059 $limits{'working_all_fields'} = 1;
2060 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
2061 return $self;
2065 # Get the version number of the database
2068 sub version
2070 my ($self)=@_;
2071 my($sth,@row, $version);
2072 $version='MS SQL server ?';
2073 $dbh=$self->connect();
2074 $sth = $dbh->prepare("SELECT \@\@VERSION") or die $DBI::errstr;
2075 $sth->execute or die $DBI::errstr;
2076 @row = $sth->fetchrow_array;
2077 if ($row[0]) {
2078 @server = split(/\n/,$row[0]);
2079 chomp(@server);
2080 $version= "$server[0]";
2082 $sth->finish;
2083 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
2084 return $version;
2087 sub connect
2089 my ($self)=@_;
2090 my ($dbh);
2091 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
2092 $main::opt_password,{ PrintError => 0}) ||
2093 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
2094 return $dbh;
2098 # Returns a list of statements to create a table
2099 # The field types are in ANSI SQL format.
2102 sub create
2104 my($self,$table_name,$fields,$index) = @_;
2105 my($query,@queries,$nr);
2107 $query="create table $table_name (";
2108 foreach $field (@$fields)
2110 $field =~ s/mediumint/integer/i;
2111 $field =~ s/float\(\d+,\d+\)/float/i;
2112 $field =~ s/double\(\d+,\d+\)/float/i;
2113 $field =~ s/double/float/i;
2114 $field =~ s/integer\(\d+\)/integer/i;
2115 $field =~ s/int\(\d+\)/integer/i;
2116 $field =~ s/smallint\(\d+\)/smallint/i;
2117 $field =~ s/smallinteger/smallint/i;
2118 $field =~ s/tinyint\(\d+\)/tinyint/i;
2119 $field =~ s/tinyinteger/tinyint/i;
2120 $field =~ s/blob/text/i;
2121 $query.= $field . ',';
2123 substr($query,-1)=")"; # Remove last ',';
2124 push(@queries,$query);
2125 $nr=0;
2126 foreach $index (@$index)
2128 $ext="WITH DISALLOW NULL";
2129 if (($index =~ s/primary key/unique index primary_key/i))
2131 $ext="WITH PRIMARY;"
2133 if ($index =~ /^unique.*\(([^\(]*)\)$/i)
2135 $nr++;
2136 $index="unique index ${table_name}_$nr ($1)";
2138 $index =~ /^(.*)\s+(\(.*\))$/;
2139 push(@queries,"create ${1} on $table_name $2");
2141 return @queries;
2145 # Do any conversions to the ANSI SQL query so that the database can handle it
2148 sub query {
2149 my($self,$sql) = @_;
2150 return $sql;
2153 sub drop_index
2155 my ($self,$table,$index) = @_;
2156 return "DROP INDEX $table.$index";
2160 # Abort if the server has crashed
2161 # return: 0 if ok
2162 # 1 question should be retried
2165 sub abort_if_fatal_error
2167 return 0;
2170 sub small_rollback_segment
2172 return 0;
2175 sub reconnect_on_errors
2177 return 0;
2180 sub fix_for_insert
2182 my ($self,$cmd) = @_;
2183 return $cmd;
2186 #############################################################################
2187 # Configuration for Sybase
2188 #############################################################################
2189 package db_sybase;
2191 sub new
2193 my ($type,$host,$database)= @_;
2194 my $self= {};
2195 my %limits;
2196 bless $self;
2198 $self->{'cmp_name'} = "sybase";
2199 $self->{'data_source'} = "DBI:Sybase:database=$database";
2200 if (defined($host) && $host ne "")
2202 $self->{'data_source'} .= ";hostname=$host";
2204 $self->{'limits'} = \%limits;
2205 $self->{'blob'} = "text";
2206 $self->{'text'} = "text";
2207 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
2208 $self->{'drop_attr'} = "";
2209 $self->{'transactions'} = 1; # Transactions enabled
2210 $self->{"vacuum"} = 1;
2212 $limits{'max_conditions'} = 1030; # We get 'Query is too complex'
2213 $limits{'max_columns'} = 250; # Max number of columns in table
2214 $limits{'max_tables'} = 65000; # Should be big enough
2215 $limits{'max_text_size'} = 9830; # Max size with default buffers.
2216 $limits{'query_size'} = 9830; # Max size with default buffers.
2217 $limits{'max_index'} = 64; # Max number of keys
2218 $limits{'max_index_parts'} = 15; # Max segments/key
2219 $limits{'max_column_name'} = 30; # max table and column name
2221 $limits{'join_optimizer'} = 1; # Can optimize FROM tables
2222 $limits{'load_data_infile'} = 0; # Has load data infile
2223 $limits{'lock_tables'} = 0; # Has lock tables
2224 $limits{'functions'} = 1; # Has simple functions (+/-)
2225 $limits{'group_functions'} = 1; # Have group functions
2226 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
2227 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
2228 $limits{'select_without_from'}= 1; # Can do 'select 1';
2229 $limits{'multi_drop'} = 1; # Drop table can take many tables
2230 $limits{'subqueries'} = 1; # Supports sub-queries.
2231 $limits{'left_outer_join'} = 1; # Supports left outer joins
2232 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
2233 $limits{'having_with_alias'} = 0; # Can use aliases in HAVING
2234 $limits{'having_with_group'} = 1; # Can't use group functions in HAVING
2235 $limits{'like_with_column'} = 1; # Can use column1 LIKE column2
2236 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1'
2237 $limits{'group_by_position'} = 0; # Can use 'GROUP BY 1'
2238 $limits{'alter_table'} = 1;
2239 $limits{'alter_add_multi_col'}= 0;
2240 $limits{'alter_table_dropcol'}= 0;
2242 $limits{'group_func_extra_std'} = 0; # Have group function std().
2244 $limits{'func_odbc_mod'} = 0; # Have function mod.
2245 $limits{'func_extra_%'} = 1; # Has % as alias for mod()
2246 $limits{'func_odbc_floor'} = 1; # Has func_odbc_floor function
2247 $limits{'func_extra_if'} = 0; # Have function if.
2248 $limits{'column_alias'} = 1; # Alias for fields in select statement.
2249 $limits{'NEG'} = 1; # Supports -id
2250 $limits{'func_extra_in_num'} = 0; # Has function in
2251 $limits{'unique_index'} = 1; # Unique index works or not
2252 $limits{'insert_select'} = 1;
2253 $limits{'working_blobs'} = 1; # If big varchar/blobs works
2254 $limits{'order_by_unused'} = 1;
2255 $limits{'working_all_fields'} = 1;
2256 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
2257 return $self;
2261 # Get the version number of the database
2264 sub version
2266 my ($self)=@_;
2267 my ($dbh,$sth,$version,@row);
2269 $dbh=$self->connect();
2270 $sth = $dbh->prepare('SELECT @@version') or die $DBI::errstr;
2271 $version="Sybase (unknown)";
2272 if ($sth->execute && (@row = $sth->fetchrow_array))
2274 $version=$row[0];
2276 $sth->finish;
2277 $dbh->disconnect;
2278 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
2279 return $version;
2282 sub connect
2284 my ($self)=@_;
2285 my ($dbh);
2286 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
2287 $main::opt_password,{ PrintError => 0 , AutoCommit => 1}) ||
2288 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
2289 return $dbh;
2293 # Returns a list of statements to create a table
2294 # The field types are in ANSI SQL format.
2297 sub create
2299 my($self,$table_name,$fields,$index) = @_;
2300 my($query,@queries,$nr);
2302 $query="create table $table_name (";
2303 foreach $field (@$fields)
2305 $field =~ s/mediumint/integer/i;
2306 $field =~ s/float\(\d+,\d+\)/float/i;
2307 $field =~ s/int\(\d+\)/int/i;
2308 $field =~ s/double/float/i;
2309 $field =~ s/integer\(\d+\)/integer/i;
2310 $field =~ s/smallint\(\d+\)/smallint/i;
2311 $field =~ s/tinyint\(\d+\)/tinyint/i;
2312 $field =~ s/blob/text/i;
2313 $query.= $field . ',';
2315 substr($query,-1)=")"; # Remove last ',';
2316 push(@queries,$query);
2317 $nr=0;
2318 foreach $index (@$index)
2320 # $ext="WITH DISALLOW NULL";
2321 if (($index =~ s/primary key/unique index primary_key/i))
2323 # $ext="WITH PRIMARY;"
2325 if ($index =~ /^unique.*\(([^\(]*)\)$/i)
2327 $nr++;
2328 $index="unique index ${table_name}_$nr ($1)";
2330 $index =~ /^(.*)\s+(\(.*\))$/;
2331 push(@queries,"create ${1} on $table_name $2");
2333 return @queries;
2337 # Do any conversions to the ANSI SQL query so that the database can handle it
2340 sub query {
2341 my($self,$sql) = @_;
2342 return $sql;
2345 sub drop_index
2347 my ($self,$table,$index) = @_;
2348 return "DROP INDEX $table.$index";
2352 # Abort if the server has crashed
2353 # return: 0 if ok
2354 # 1 question should be retried
2357 sub abort_if_fatal_error
2359 return 0;
2362 sub small_rollback_segment
2364 return 0;
2367 sub reconnect_on_errors
2369 return 0;
2372 sub fix_for_insert
2374 my ($self,$cmd) = @_;
2375 return $cmd;
2379 # optimize the tables ....
2380 # WARNING (from walrus)! This sub will work only from DBD:sybase
2381 # driver. Because if we use ODBC we don't know actual database name
2382 # (but DSN name only)
2383 sub vacuum
2385 my ($self,$full_vacuum,$dbh_ref)=@_;
2386 my ($loop_time,$end_time,$dbh);
2388 if (defined($full_vacuum))
2390 $$dbh_ref->disconnect; $$dbh_ref= $self->connect();
2392 $dbh=$$dbh_ref;
2393 $loop_time=new Benchmark;
2394 my (@tables,$sth,$current_table,$current_base);
2395 $dbh->do("dump tran $database with truncate_only");
2396 $sth=$dbh->prepare("sp_tables" ) or die "prepere";
2397 $sth->execute() or die "execute";
2398 while (@row = $sth->fetchrow_array()) {
2399 $current_table = $row[2];
2400 $current_base = $row[0];
2401 next if ($current_table =~ /^sys/);
2402 push(@tables,$current_table) if ($database == $current_base);
2405 $sth->finish();
2407 foreach $table (@tables) {
2408 # print "$table: \n";
2409 $dbh->do("update statistics $table") or print "Oops!";
2412 # $dbh->do("analyze table ?? compute statistics") || die "Got error: $DBI::errstr when executing 'vacuum'\n";
2413 $end_time=new Benchmark;
2414 print "Time for book-keeping (1): " .
2415 Benchmark::timestr(Benchmark::timediff($end_time, $loop_time),"all") . "\n\n";
2416 $dbh->disconnect; $$dbh_ref= $self->connect();
2422 #############################################################################
2423 # Definitions for Adabas
2424 #############################################################################
2426 package db_Adabas;
2428 sub new
2430 my ($type,$host,$database)= @_;
2431 my $self= {};
2432 my %limits;
2433 bless $self;
2435 $self->{'cmp_name'} = "Adabas";
2436 $self->{'data_source'} = "DBI:Adabas:$database";
2437 $self->{'limits'} = \%limits;
2438 $self->{'blob'} = "long";
2439 $self->{'text'} = "long";
2440 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
2441 $self->{'drop_attr'} = "";
2442 $self->{'transactions'} = 1; # Transactions enabled
2444 $limits{'max_conditions'} = 50; # (Actually not a limit)
2445 $limits{'max_columns'} = 254; # Max number of columns in table
2446 $limits{'max_tables'} = 65000; # Should be big enough
2447 $limits{'max_text_size'} = 2000; # Limit for blob test-connect
2448 $limits{'query_size'} = 65525; # Max size with default buffers.
2449 $limits{'max_index'} = 16; # Max number of keys
2450 $limits{'max_index_parts'} = 16; # Max segments/key
2451 $limits{'max_column_name'} = 32; # max table and column name
2453 $limits{'join_optimizer'} = 1; # Can optimize FROM tables
2454 $limits{'load_data_infile'} = 0; # Has load data infile
2455 $limits{'lock_tables'} = 0; # Has lock tables
2456 $limits{'functions'} = 1; # Has simple functions (+/-)
2457 $limits{'group_functions'} = 1; # Have group functions
2458 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
2459 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
2460 $limits{'select_without_from'}= 0;
2461 $limits{'multi_drop'} = 0;
2462 $limits{'subqueries'} = 1;
2463 $limits{'left_outer_join'} = 0; # This may be fixed in the query module
2464 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
2465 $limits{'having_with_alias'} = 0; # Can use aliases in HAVING
2466 $limits{'having_with_group'} = 1; # Can't use group functions in HAVING
2467 $limits{'like_with_column'} = 1; # Can use column1 LIKE column2
2468 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1'
2469 $limits{'group_by_position'} = 1;
2470 $limits{'alter_table'} = 1;
2471 $limits{'alter_add_multi_col'}= 2; #Have ALTER TABLE t add a int, b int;
2472 $limits{'alter_table_dropcol'}= 1;
2474 $limits{'group_func_extra_std'} = 0; # Have group function std().
2476 $limits{'func_odbc_mod'} = 0; # Oracle has problem with mod()
2477 $limits{'func_extra_%'} = 0; # Has % as alias for mod()
2478 $limits{'func_odbc_floor'} = 1; # Has func_odbc_floor function
2479 $limits{'func_extra_if'} = 0; # Have function if.
2480 $limits{'column_alias'} = 1; # Alias for fields in select statement.
2481 $limits{'NEG'} = 1; # Supports -id
2482 $limits{'func_extra_in_num'} = 1; # Has function in
2483 $limits{'unique_index'} = 1; # Unique index works or not
2484 $limits{'insert_select'} = 1;
2485 $limits{'working_blobs'} = 1; # If big varchar/blobs works
2486 $limits{'order_by_unused'} = 1;
2487 $limits{'working_all_fields'} = 1;
2488 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
2491 return $self;
2495 # Get the version number of the database
2498 sub version
2500 my ($self)=@_;
2501 my ($dbh,$sth,$version,@row);
2503 $dbh=$self->connect();
2504 $sth = $dbh->prepare("SELECT KERNEL FROM VERSIONS") or die $DBI::errstr;
2505 $version="Adabas (unknown)";
2506 if ($sth->execute && (@row = $sth->fetchrow_array)
2507 && $row[0] =~ /([\d\.]+)/)
2509 $version="Adabas $1";
2511 $sth->finish;
2512 $dbh->disconnect;
2513 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
2514 return $version;
2517 sub connect
2519 my ($self)=@_;
2520 my ($dbh);
2521 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
2522 $main::opt_password,{ PrintError => 0}) ||
2523 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
2524 return $dbh;
2528 # Returns a list of statements to create a table
2529 # The field types are in ANSI SQL format.
2531 # If one uses $main::opt_fast then one is allowed to use
2532 # non standard types to get better speed.
2535 sub create
2537 my($self,$table_name,$fields,$index) = @_;
2538 my($query,@queries,$ind,@keys);
2540 $query="create table $table_name (";
2541 foreach $field (@$fields)
2543 $field =~ s/CHARACTER\s+VARYING/VARCHAR/i;
2544 $field =~ s/TINYINT/SMALLINT/i;
2545 $field =~ s/MEDIUMINT/INT/i;
2546 $field =~ s/SMALLINT\s*\(\d+\)/SMALLINT/i;
2547 $field =~ s/INT\s*\(\d+\)/INT/i;
2548 $field =~ s/BLOB/LONG/i;
2549 $field =~ s/INTEGER\s*\(\d+\)/INTEGER/i;
2550 $field =~ s/FLOAT\s*\((\d+),\d+\)/FLOAT\($1\)/i;
2551 $field =~ s/DOUBLE/FLOAT\(38\)/i;
2552 $field =~ s/DOUBLE\s+PRECISION/FLOAT\(38\)/i;
2553 $query.= $field . ',';
2556 foreach $ind (@$index)
2558 my @index;
2559 if ( $ind =~ /\bKEY\b/i ){
2560 push(@keys,"ALTER TABLE $table_name ADD $ind");
2561 }else{
2562 my @fields = split(' ',$index);
2563 my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
2564 push(@index,$query);
2567 substr($query,-1)=")"; # Remove last ',';
2568 push(@queries,$query,@keys,@index);
2569 #print "query:$query\n";
2571 return @queries;
2574 sub insert_file {
2575 my($self,$dbname, $file) = @_;
2576 print "insert an ascii file isn't supported by Oracle (?)\n";
2577 return 0;
2581 # Do any conversions to the ANSI SQL query so that the database can handle it
2584 sub query {
2585 my($self,$sql) = @_;
2586 return $sql;
2589 sub drop_index
2591 my ($self,$table,$index) = @_;
2592 return "DROP INDEX $index";
2596 # Abort if the server has crashed
2597 # return: 0 if ok
2598 # 1 question should be retried
2601 sub abort_if_fatal_error
2603 return 0;
2606 sub small_rollback_segment
2608 return 0;
2611 sub reconnect_on_errors
2613 return 0;
2616 sub fix_for_insert
2618 my ($self,$cmd) = @_;
2619 return $cmd;
2622 #############################################################################
2623 # Configuration for IBM DB2
2624 #############################################################################
2626 package db_db2;
2628 sub new
2630 my ($type,$host,$database)= @_;
2631 my $self= {};
2632 my %limits;
2633 bless $self;
2635 $self->{'cmp_name'} = "DB2";
2636 $self->{'data_source'} = "DBI:ODBC:$database";
2637 if (defined($host) && $host ne "")
2639 $self->{'data_source'} .= ":$host";
2641 $self->{'limits'} = \%limits;
2642 $self->{'blob'} = "varchar(255)";
2643 $self->{'text'} = "varchar(255)";
2644 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
2645 $self->{'drop_attr'} = "";
2646 $self->{'transactions'} = 1; # Transactions enabled
2648 $limits{'max_conditions'} = 418; # We get 'Query is too complex'
2649 $limits{'max_columns'} = 500; # Max number of columns in table
2650 $limits{'max_tables'} = 65000; # Should be big enough
2651 $limits{'max_text_size'} = 254; # Max size with default buffers.
2652 $limits{'query_size'} = 254; # Max size with default buffers.
2653 $limits{'max_index'} = 48; # Max number of keys
2654 $limits{'max_index_parts'} = 15; # Max segments/key
2655 $limits{'max_column_name'} = 18; # max table and column name
2657 $limits{'join_optimizer'} = 1; # Can optimize FROM tables
2658 $limits{'load_data_infile'} = 0; # Has load data infile
2659 $limits{'lock_tables'} = 0; # Has lock tables
2660 $limits{'functions'} = 1; # Has simple functions (+/-)
2661 $limits{'group_functions'} = 1; # Have group functions
2662 $limits{'group_func_sql_min_str'}= 1;
2663 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
2664 $limits{'select_without_from'}= 0; # Can do 'select 1';
2665 $limits{'multi_drop'} = 0; # Drop table can take many tables
2666 $limits{'subqueries'} = 1; # Supports sub-queries.
2667 $limits{'left_outer_join'} = 1; # Supports left outer joins
2668 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
2669 $limits{'having_with_alias'} = 0; # Can use aliases in HAVING
2670 $limits{'having_with_group'} = 1; # Can't use group functions in HAVING
2671 $limits{'like_with_column'} = 0; # Can use column1 LIKE column2
2672 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1'
2673 $limits{'group_by_position'} = 0; # Can use 'GROUP BY 1'
2674 $limits{'alter_table'} = 1;
2675 $limits{'alter_add_multi_col'}= 0;
2676 $limits{'alter_table_dropcol'}= 0;
2678 $limits{'group_func_extra_std'} = 0; # Have group function std().
2680 $limits{'func_odbc_mod'} = 1; # Have function mod.
2681 $limits{'func_extra_%'} = 0; # Has % as alias for mod()
2682 $limits{'func_odbc_floor'} = 1; # Has func_odbc_floor function
2683 $limits{'func_extra_if'} = 0; # Have function if.
2684 $limits{'column_alias'} = 1; # Alias for fields in select statement.
2685 $limits{'NEG'} = 1; # Supports -id
2686 $limits{'func_extra_in_num'} = 0; # Has function in
2687 $limits{'unique_index'} = 1; # Unique index works or not
2688 $limits{'insert_select'} = 1;
2689 $limits{'working_blobs'} = 1; # If big varchar/blobs works
2690 $limits{'order_by_unused'} = 1;
2691 $limits{'working_all_fields'} = 1;
2692 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
2693 return $self;
2697 # Get the version number of the database
2700 sub version
2702 my ($self)=@_;
2703 return "IBM DB2 5"; #DBI/ODBC can't return the server version
2706 sub connect
2708 my ($self)=@_;
2709 my ($dbh);
2710 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user, $main::opt_password) ||
2711 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
2712 return $dbh;
2716 # Returns a list of statements to create a table
2717 # The field types are in ANSI SQL format.
2720 sub create
2722 my($self,$table_name,$fields,$index) = @_;
2723 my($query,@queries,$nr);
2725 $query="create table $table_name (";
2726 foreach $field (@$fields)
2728 $field =~ s/mediumint/integer/i;
2729 $field =~ s/float\(\d+,\d+\)/float/i;
2730 $field =~ s/integer\(\d+\)/integer/i;
2731 $field =~ s/int\(\d+\)/integer/i;
2732 $field =~ s/tinyint\(\d+\)/smallint/i;
2733 $field =~ s/tinyint/smallint/i;
2734 $field =~ s/smallint\(\d+\)/smallint/i;
2735 $field =~ s/smallinteger/smallint/i;
2736 $field =~ s/blob/varchar(256)/i;
2737 $query.= $field . ',';
2739 substr($query,-1)=")"; # Remove last ',';
2740 push(@queries,$query);
2741 $nr=0;
2742 foreach $index (@$index)
2744 $ext="WITH DISALLOW NULL";
2745 if (($index =~ s/primary key/unique index primary_key/i))
2747 $ext="WITH PRIMARY;"
2749 if ($index =~ /^unique.*\(([^\(]*)\)$/i)
2751 $nr++;
2752 $index="unique index ${table_name}_$nr ($1)";
2754 $index =~ /^(.*)\s+(\(.*\))$/;
2755 push(@queries,"create ${1} on $table_name $2");
2757 return @queries;
2761 # Do any conversions to the ANSI SQL query so that the database can handle it
2764 sub query {
2765 my($self,$sql) = @_;
2766 return $sql;
2769 sub drop_index
2771 my ($self,$table,$index) = @_;
2772 return "DROP INDEX $table.$index";
2776 # Abort if the server has crashed
2777 # return: 0 if ok
2778 # 1 question should be retried
2781 sub abort_if_fatal_error
2783 return 0;
2786 sub small_rollback_segment
2788 return 1;
2791 sub reconnect_on_errors
2793 return 0;
2796 sub fix_for_insert
2798 my ($self,$cmd) = @_;
2799 return $cmd;
2802 #############################################################################
2803 # Configuration for MIMER
2804 #############################################################################
2806 package db_Mimer;
2808 sub new
2810 my ($type,$host,$database)= @_;
2811 my $self= {};
2812 my %limits;
2813 bless $self;
2815 $self->{'cmp_name'} = "mimer";
2816 $self->{'data_source'} = "DBI:mimer:$database:$host";
2817 $self->{'limits'} = \%limits;
2818 $self->{'blob'} = "binary varying(15000)";
2819 $self->{'text'} = "character varying(15000)";
2820 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
2821 $self->{'drop_attr'} = "";
2822 $self->{'transactions'} = 1; # Transactions enabled
2823 $self->{'char_null'} = "cast(NULL as char(1))";
2824 $self->{'numeric_null'} = "cast(NULL as int)";
2826 $limits{'max_conditions'} = 9999; # (Actually not a limit)
2827 $limits{'max_columns'} = 252; # Max number of columns in table
2828 $limits{'max_tables'} = 65000; # Should be big enough
2829 $limits{'max_text_size'} = 15000; # Max size with default buffers.
2830 $limits{'query_size'} = 1000000; # Max size with default buffers.
2831 $limits{'max_index'} = 32; # Max number of keys
2832 $limits{'max_index_parts'} = 16; # Max segments/key
2833 $limits{'max_column_name'} = 128; # max table and column name
2835 $limits{'join_optimizer'} = 1; # Can optimize FROM tables
2836 $limits{'load_data_infile'} = 1; # Has load data infile
2837 $limits{'lock_tables'} = 0; # Has lock tables
2838 $limits{'functions'} = 1; # Has simple functions (+/-)
2839 $limits{'group_functions'} = 1; # Have group functions
2840 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
2841 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
2842 $limits{'select_without_from'}= 0; # Cannot do 'select 1';
2843 $limits{'multi_drop'} = 0; # Drop table cannot take many tables
2844 $limits{'subqueries'} = 1; # Supports sub-queries.
2845 $limits{'left_outer_join'} = 1; # Supports left outer joins
2846 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
2847 $limits{'having_with_alias'} = 0; # Can use aliases in HAVING
2848 $limits{'having_with_group'} = 1; # Can use group functions in HAVING
2849 $limits{'like_with_column'} = 1; # Can use column1 LIKE column2
2850 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1'
2851 $limits{'group_by_position'} = 0; # Cannot use 'GROUP BY 1'
2852 $limits{'alter_table'} = 1; # Have ALTER TABLE
2853 $limits{'alter_add_multi_col'}= 0; # Have ALTER TABLE t add a int,add b int;
2854 $limits{'alter_table_dropcol'}= 1; # Have ALTER TABLE DROP column
2855 $limits{'insert_multi_value'} = 0; # Does not have INSERT ... values (1,2),(3,4)
2856 $limits{'multi_distinct'} = 0; # Does not allow select count(distinct a),count(distinct b)..
2858 $limits{'group_func_extra_std'} = 0; # Does not have group function std().
2860 $limits{'func_odbc_mod'} = 1; # Have function mod.
2861 $limits{'func_extra_%'} = 0; # Does not have % as alias for mod()
2862 $limits{'func_odbc_floor'} = 1; # Has func_odbc_floor function
2863 $limits{'func_extra_if'} = 0; # Does not have function if.
2864 $limits{'column_alias'} = 1; # Alias for fields in select statement.
2865 $limits{'NEG'} = 1; # Supports -id
2866 $limits{'func_extra_in_num'} = 1; # Has function in
2867 $limits{'limit'} = 0; # Does not support the limit attribute
2868 $limits{'unique_index'} = 1; # Unique index works or not
2869 $limits{'insert_select'} = 1;
2870 $limits{'working_blobs'} = 1; # If big varchar/blobs works
2871 $limits{'order_by_unused'} = 0;
2872 $limits{'working_all_fields'} = 1;
2874 return $self;
2878 # Get the version number of the database
2881 sub version
2883 my ($self)=@_;
2884 my ($dbh,$sth,$version,@row);
2886 $dbh=$self->connect();
2888 # Pick up SQLGetInfo option SQL_DBMS_VER (18)
2890 $version = $dbh->func(18, GetInfo);
2891 $dbh->disconnect;
2892 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
2893 return $version;
2897 # Connection with optional disabling of logging
2900 sub connect
2902 my ($self)=@_;
2903 my ($dbh);
2904 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
2905 $main::opt_password,{ PrintError => 0}) ||
2906 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
2908 $dbh->do("SET OPTION LOG_OFF=1,UPDATE_LOG=0");
2909 return $dbh;
2913 # Returns a list of statements to create a table
2914 # The field types are in ANSI SQL format.
2916 # If one uses $main::opt_fast then one is allowed to use
2917 # non standard types to get better speed.
2920 sub create
2922 my($self,$table_name,$fields,$index,$options) = @_;
2923 my($query,@queries,@indexes);
2925 $query="create table $table_name (";
2926 foreach $field (@$fields)
2928 # $field =~ s/ decimal/ double(10,2)/i;
2929 # $field =~ s/ big_decimal/ double(10,2)/i;
2930 $field =~ s/ double/ double precision/i;
2931 $field =~ s/ tinyint\(.*\)/ smallint/i;
2932 $field =~ s/ smallint\(.*\)/ smallint/i;
2933 $field =~ s/ mediumint/ integer/i;
2934 $field =~ s/ float\(.*\)/ float/i;
2935 # $field =~ s/ date/ int/i; # Because of tcp ?
2936 $query.= $field . ',';
2938 foreach $index (@$index)
2940 if ( $index =~ /\bINDEX\b/i )
2942 my @fields = split(' ',$index);
2943 my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
2944 push(@indexes,$query);
2946 } else {
2947 $query.= $index . ',';
2950 substr($query,-1)=")"; # Remove last ',';
2951 $query.=" $options" if (defined($options));
2952 push(@queries,$query,@indexes);
2953 return @queries;
2956 sub insert_file {
2957 my($self,$dbname, $file) = @_;
2958 print "insert of an ascii file isn't supported by Mimer\n";
2959 return 0;
2963 # Do any conversions to the ANSI SQL query so that the database can handle it
2966 sub query {
2967 my($self,$sql) = @_;
2968 return $sql;
2971 sub drop_index {
2972 my ($self,$table,$index) = @_;
2973 return "DROP INDEX $index";
2977 # Abort if the server has crashed
2978 # return: 0 if ok
2979 # 1 question should be retried
2982 sub abort_if_fatal_error
2984 return 1 if ($DBI::errstr =~ /Table locked by another cursor/);
2985 return 0;
2988 sub small_rollback_segment
2990 return 0;
2993 sub reconnect_on_errors
2995 return 0;
2998 sub fix_for_insert
3000 my ($self,$cmd) = @_;
3001 return $cmd;
3004 #############################################################################
3005 # Configuration for InterBase
3006 #############################################################################
3008 package db_interbase;
3010 sub new
3012 my ($type,$host,$database)= @_;
3013 my $self= {};
3014 my %limits;
3015 bless $self;
3017 $self->{'cmp_name'} = "interbase";
3018 $self->{'data_source'} = "DBI:InterBase:database=$database;ib_dialect=3";
3019 $self->{'limits'} = \%limits;
3020 $self->{'blob'} = "blob";
3021 $self->{'text'} = "";
3022 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
3023 $self->{'drop_attr'} = "";
3024 $self->{'transactions'} = 1; # Transactions enabled
3025 $self->{'char_null'} = "";
3026 $self->{'numeric_null'} = "";
3028 $limits{'max_conditions'} = 9999; # (Actually not a limit)
3029 $limits{'max_columns'} = 252; # Max number of columns in table
3030 $limits{'max_tables'} = 65000; # Should be big enough
3031 $limits{'max_text_size'} = 15000; # Max size with default buffers.
3032 $limits{'query_size'} = 1000000; # Max size with default buffers.
3033 $limits{'max_index'} = 65000; # Max number of keys
3034 $limits{'max_index_parts'} = 8; # Max segments/key
3035 $limits{'max_column_name'} = 128; # max table and column name
3037 $limits{'join_optimizer'} = 1; # Can optimize FROM tables
3038 $limits{'load_data_infile'} = 0; # Has load data infile
3039 $limits{'lock_tables'} = 0; # Has lock tables
3040 $limits{'functions'} = 1; # Has simple functions (+/-)
3041 $limits{'group_functions'} = 1; # Have group functions
3042 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings
3043 $limits{'group_distinct_functions'}= 1; # Have count(distinct)
3044 $limits{'select_without_from'}= 0; # Cannot do 'select 1';
3045 $limits{'multi_drop'} = 0; # Drop table cannot take many tables
3046 $limits{'subqueries'} = 1; # Supports sub-queries.
3047 $limits{'left_outer_join'} = 1; # Supports left outer joins
3048 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
3049 $limits{'having_with_alias'} = 0; # Can use aliases in HAVING
3050 $limits{'having_with_group'} = 1; # Can use group functions in HAVING
3051 $limits{'like_with_column'} = 0; # Can use column1 LIKE column2
3052 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1'
3053 $limits{'group_by_position'} = 0; # Cannot use 'GROUP BY 1'
3054 $limits{'alter_table'} = 1; # Have ALTER TABLE
3055 $limits{'alter_add_multi_col'}= 1; # Have ALTER TABLE t add a int,add b int;
3056 $limits{'alter_table_dropcol'}= 1; # Have ALTER TABLE DROP column
3057 $limits{'insert_multi_value'} = 0; # Does not have INSERT ... values (1,2),(3,4)
3059 $limits{'group_func_extra_std'} = 0; # Does not have group function std().
3061 $limits{'func_odbc_mod'} = 0; # Have function mod.
3062 $limits{'func_extra_%'} = 0; # Does not have % as alias for mod()
3063 $limits{'func_odbc_floor'} = 0; # Has func_odbc_floor function
3064 $limits{'func_extra_if'} = 0; # Does not have function if.
3065 $limits{'column_alias'} = 1; # Alias for fields in select statement.
3066 $limits{'NEG'} = 0; # Supports -id
3067 $limits{'func_extra_in_num'} = 0; # Has function in
3068 $limits{'limit'} = 0; # Does not support the limit attribute
3069 $limits{'working_blobs'} = 1; # If big varchar/blobs works
3070 $limits{'order_by_unused'} = 1;
3071 $limits{'working_all_fields'} = 1;
3072 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
3074 return $self;
3078 # Get the version number of the database
3081 sub version
3083 my ($self)=@_;
3084 my ($dbh,$version);
3086 $version='Interbase ?';
3088 $dbh=$self->connect();
3089 eval { $version = $dbh->func('version','ib_database_info')->{'version'}; };
3090 $dbh->disconnect;
3091 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
3092 return $version;
3096 # Connection with optional disabling of logging
3099 sub connect
3101 my ($self)=@_;
3102 my ($dbh);
3103 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
3104 $main::opt_password,{ PrintError => 0, AutoCommit => 1}) ||
3105 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
3107 return $dbh;
3111 # Returns a list of statements to create a table
3112 # The field types are in ANSI SQL format.
3114 # If one uses $main::opt_fast then one is allowed to use
3115 # non standard types to get better speed.
3118 sub create
3120 my($self,$table_name,$fields,$index,$options) = @_;
3121 my($query,@queries,@keys,@indexes);
3123 $query="create table $table_name (";
3124 foreach $field (@$fields)
3126 # $field =~ s/ big_decimal/ decimal/i;
3127 $field =~ s/ double/ double precision/i;
3128 $field =~ s/ tinyint/ smallint/i;
3129 $field =~ s/ mediumint/ integer/i;
3130 $field =~ s/\bint\b/integer/i;
3131 $field =~ s/ float\(\d,\d\)/ float/i;
3132 $field =~ s/ smallint\(\d\)/ smallint/i;
3133 $field =~ s/ integer\(\d\)/ integer/i;
3134 $query.= $field . ',';
3136 foreach $ind (@$index)
3138 if ( $ind =~ /(\bKEY\b)|(\bUNIQUE\b)/i ){
3139 push(@keys,"ALTER TABLE $table_name ADD $ind");
3140 }else{
3141 my @fields = split(' ',$ind);
3142 my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
3143 push(@indexes,$query);
3146 substr($query,-1)=")"; # Remove last ',';
3147 $query.=" $options" if (defined($options));
3148 push(@queries,$query,@keys,@indexes);
3149 return @queries;
3152 sub insert_file {
3153 my($self,$dbname, $file) = @_;
3154 print "insert of an ascii file isn't supported by InterBase\n";
3155 return 0;
3159 # Do any conversions to the ANSI SQL query so that the database can handle it
3162 sub query {
3163 my($self,$sql) = @_;
3164 return $sql;
3167 sub drop_index {
3168 my ($self,$table,$index) = @_;
3169 return "DROP INDEX $index";
3173 # Abort if the server has crashed
3174 # return: 0 if ok
3175 # 1 question should be retried
3178 sub abort_if_fatal_error
3180 return 1 if ($DBI::errstr =~ /Table locked by another cursor/);
3181 return 0;
3184 sub small_rollback_segment
3186 return 1;
3189 sub reconnect_on_errors
3191 return 1;
3194 sub fix_for_insert
3196 my ($self,$cmd) = @_;
3197 return $cmd;
3200 #############################################################################
3201 # Configuration for FrontBase
3202 #############################################################################
3204 package db_FrontBase;
3206 sub new
3208 my ($type,$host,$database)= @_;
3209 my $self= {};
3210 my %limits;
3211 bless $self;
3213 $self->{'cmp_name'} = "FrontBase";
3214 $self->{'data_source'} = "DBI:FB:dbname=$database;host=$host";
3215 $self->{'limits'} = \%limits;
3216 $self->{'blob'} = "varchar(8000000)";
3217 $self->{'text'} = "varchar(8000000)";
3218 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
3219 $self->{'drop_attr'} = ' restrict';
3220 $self->{'transactions'} = 1; # Transactions enabled
3221 $self->{'error_on_execute_means_zero_rows'}=1;
3223 $limits{'max_conditions'} = 5427; # (Actually not a limit)
3224 # The following should be 8192, but is smaller because Frontbase crashes..
3225 $limits{'max_columns'} = 150; # Max number of columns in table
3226 $limits{'max_tables'} = 5000; # 10000 crashed FrontBase
3227 $limits{'max_text_size'} = 65000; # Max size with default buffers.
3228 $limits{'query_size'} = 8000000; # Max size with default buffers.
3229 $limits{'max_index'} = 38; # Max number of keys
3230 $limits{'max_index_parts'} = 20; # Max segments/key
3231 $limits{'max_column_name'} = 128; # max table and column name
3233 $limits{'join_optimizer'} = 1; # Can optimize FROM tables
3234 $limits{'load_data_infile'} = 1; # Has load data infile
3235 $limits{'lock_tables'} = 0; # Has lock tables
3236 $limits{'functions'} = 1; # Has simple functions (+/-)
3237 $limits{'group_functions'} = 1; # Have group functions
3238 $limits{'group_distinct_functions'}= 0; # Have count(distinct)
3239 $limits{'select_without_from'}= 0;
3240 $limits{'multi_drop'} = 0; # Drop table cannot take many tables
3241 $limits{'subqueries'} = 1; # Supports sub-queries.
3242 $limits{'left_outer_join'} = 1; # Supports left outer joins
3243 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
3244 $limits{'having_with_alias'} = 0; # Can use aliases in HAVING
3245 $limits{'having_with_group'} = 0; # Can use group functions in HAVING
3246 $limits{'like_with_column'} = 1; # Can use column1 LIKE column2
3247 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1'
3248 $limits{'group_by_position'} = 0; # Use of 'GROUP BY 1'
3249 $limits{'alter_table'} = 1; # Have ALTER TABLE
3250 $limits{'alter_add_multi_col'}= 0; # Have ALTER TABLE t add a int,add b int;
3251 $limits{'alter_table_dropcol'}= 0; # Have ALTER TABLE DROP column
3252 $limits{'insert_multi_value'} = 1;
3254 $limits{'group_func_extra_std'} = 0; # Does not have group function std().
3256 $limits{'func_odbc_mod'} = 0; # Have function mod.
3257 $limits{'func_extra_%'} = 0; # Does not have % as alias for mod()
3258 $limits{'func_odbc_floor'} = 0; # Has func_odbc_floor function
3259 $limits{'func_extra_if'} = 0; # Does not have function if.
3260 $limits{'column_alias'} = 1; # Alias for fields in select statement.
3261 $limits{'NEG'} = 1; # Supports -id
3262 $limits{'func_extra_in_num'} = 0; # Has function in
3263 $limits{'limit'} = 0; # Does not support the limit attribute
3264 $limits{'insert_select'} = 0;
3265 $limits{'order_by_unused'} = 0;
3267 # We don't get an error for duplicate row in 'test-insert'
3268 $limits{'unique_index'} = 0; # Unique index works or not
3269 # We can't use a blob as a normal string (we got a wierd error)
3270 $limits{'working_blobs'} = 0;
3271 # 'select min(region),max(region) from bench1' kills the server after a while
3272 $limits{'group_func_sql_min_str'} = 0;
3273 # If you do select f1,f2,f3...f200 from table, Frontbase dies.
3274 $limits{'working_all_fields'} = 0;
3275 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
3277 return $self;
3281 # Get the version number of the database
3284 sub version
3286 my ($self)=@_;
3287 my ($dbh,$sth,$version,@row);
3289 # $dbh=$self->connect();
3291 # Pick up SQLGetInfo option SQL_DBMS_VER (18)
3293 #$version = $dbh->func(18, GetInfo);
3294 $version="FrontBase 3.3";
3295 # $dbh->disconnect;
3296 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
3297 return $version;
3301 # Connection with optional disabling of logging
3304 sub connect
3306 my ($self)=@_;
3307 my ($dbh);
3308 $dbh=DBI->connect($self->{'data_source'},
3309 $main::opt_user,
3310 $main::opt_password,
3311 { PrintError => 0 ,
3312 'fb_host'=>$main::opt_host
3313 }) ||
3314 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
3315 $db->{AutoCommit}=1;
3316 # $dbh->do("SET OPTION LOG_OFF=1,UPDATE_LOG=0");
3317 return $dbh;
3321 # Returns a list of statements to create a table
3322 # The field types are in ANSI SQL format.
3324 # If one uses $main::opt_fast then one is allowed to use
3325 # non standard types to get better speed.
3328 sub create
3330 my($self,$table_name,$fields,$index,$options) = @_;
3331 my($query,@queries,@indexes,@keys);
3333 $query="create table $table_name (";
3334 foreach $field (@$fields)
3336 $field =~ s/ blob/ varchar(32000)/i;
3337 $field =~ s/ big_decimal/ float/i;
3338 $field =~ s/ double/ float/i;
3339 $field =~ s/ tinyint/ smallint/i;
3340 $field =~ s/ mediumint/ int/i;
3341 $field =~ s/ integer/ int/i;
3342 $field =~ s/ float\(\d,\d\)/ float/i;
3343 $field =~ s/ smallint\(\d\)/ smallint/i;
3344 $field =~ s/ int\(\d\)/ int/i;
3345 $query.= $field . ',';
3347 foreach $ind (@$index)
3349 # my @index;
3350 if ( $ind =~ /(\bKEY\b)|(\bUNIQUE\b)/i ){
3351 push(@keys,"ALTER TABLE $table_name ADD $ind");
3352 }else{
3353 my @fields = split(' ',$ind);
3354 my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
3355 push(@indexes,$query);
3358 substr($query,-1)=")"; # Remove last ',';
3359 $query.=" $options" if (defined($options));
3360 push(@queries,$query,@keys,@indexes);
3361 return @queries;
3364 sub insert_file {
3365 my($self,$dbname, $file) = @_;
3366 print "insert of an ascii file isn't supported by InterBase\n";
3367 return 0;
3371 # Do any conversions to the ANSI SQL query so that the database can handle it
3374 sub query {
3375 my($self,$sql) = @_;
3376 return $sql;
3379 sub drop_index {
3380 my ($self,$table,$index) = @_;
3381 return "DROP INDEX $index";
3385 # Abort if the server has crashed
3386 # return: 0 if ok
3387 # 1 question should be retried
3390 sub abort_if_fatal_error
3392 return 0 if ($DBI::errstr =~ /No raw data handle/);
3393 return 1;
3396 sub small_rollback_segment
3398 return 0;
3401 sub reconnect_on_errors
3403 return 1;
3406 sub fix_for_insert
3408 my ($self,$cmd) = @_;
3409 return $cmd;
3412 #############################################################################
3413 # Configuration for SAPDB
3414 #############################################################################
3416 package db_sapdb;
3418 sub new
3420 my ($type,$host,$database)= @_;
3421 my $self= {};
3422 my %limits;
3423 bless $self;
3425 $self->{'cmp_name'} = "sapdb";
3426 $self->{'data_source'} = "DBI:SAP_DB:$database";
3427 $self->{'limits'} = \%limits;
3428 $self->{'blob'} = "LONG"; # *
3429 $self->{'text'} = "LONG"; # *
3430 $self->{'double_quotes'} = 1; # Can handle: 'Walker''s'
3431 $self->{'drop_attr'} = "";
3432 $self->{'transactions'} = 1; # Transactions enabled *
3433 $self->{'char_null'} = "";
3434 $self->{'numeric_null'} = "";
3436 $limits{'max_conditions'} = 9999; # (Actually not a limit) *
3437 $limits{'max_columns'} = 1023; # Max number of columns in table *
3438 $limits{'max_tables'} = 65000; # Should be big enough * unlimited actually
3439 $limits{'max_text_size'} = 15000; # Max size with default buffers.
3440 $limits{'query_size'} = 64*1024; # Max size with default buffers. *64 kb by default. May be set by system variable
3441 $limits{'max_index'} = 510; # Max number of keys *
3442 $limits{'max_index_parts'} = 16; # Max segments/key *
3443 $limits{'max_column_name'} = 32; # max table and column name *
3445 $limits{'join_optimizer'} = 1; # Can optimize FROM tables *
3446 $limits{'load_data_infile'} = 0; # Has load data infile *
3447 $limits{'lock_tables'} = 1; # Has lock tables
3448 $limits{'functions'} = 1; # Has simple functions (+/-) *
3449 $limits{'group_functions'} = 1; # Have group functions *
3450 $limits{'group_func_sql_min_str'} = 1; # Can execute MIN() and MAX() on strings *
3451 $limits{'group_distinct_functions'}= 1; # Have count(distinct) *
3452 $limits{'select_without_from'}= 0; # Cannot do 'select 1'; *
3453 $limits{'multi_drop'} = 0; # Drop table cannot take many tables *
3454 $limits{'subqueries'} = 1; # Supports sub-queries. *
3455 $limits{'left_outer_join'} = 1; # Supports left outer joins *
3456 $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
3457 $limits{'having_with_alias'} = 0; # Can use aliases in HAVING *
3458 $limits{'having_with_group'} = 1; # Can use group functions in HAVING *
3459 $limits{'like_with_column'} = 1; # Can use column1 LIKE column2 *
3460 $limits{'order_by_position'} = 1; # Can use 'ORDER BY 1' *
3461 $limits{'group_by_position'} = 0; # Cannot use 'GROUP BY 1' *
3462 $limits{'alter_table'} = 1; # Have ALTER TABLE *
3463 $limits{'alter_add_multi_col'}= 1; # Have ALTER TABLE t add a int,add b int; *
3464 $limits{'alter_table_dropcol'}= 1; # Have ALTER TABLE DROP column *
3465 $limits{'insert_multi_value'} = 0; # INSERT ... values (1,2),(3,4) *
3467 $limits{'group_func_extra_std'} = 0; # Does not have group function std().
3469 $limits{'func_odbc_mod'} = 0; # Have function mod. *
3470 $limits{'func_extra_%'} = 0; # Does not have % as alias for mod() *
3471 $limits{'func_odbc_floor'} = 1; # Has func_odbc_floor function *
3472 $limits{'func_extra_if'} = 0; # Does not have function if. *
3473 $limits{'column_alias'} = 1; # Alias for fields in select statement. *
3474 $limits{'NEG'} = 1; # Supports -id *
3475 $limits{'func_extra_in_num'} = 0; # Has function in *
3476 $limits{'limit'} = 0; # Does not support the limit attribute *
3477 $limits{'working_blobs'} = 1; # If big varchar/blobs works *
3478 $limits{'order_by_unused'} = 1; #
3479 $limits{'working_all_fields'} = 1; #
3480 $limits{'multi_distinct'} = 1; # allows select count(distinct a),count(distinct b)..
3483 return $self;
3487 # Get the version number of the database
3490 sub version
3492 my ($self)=@_;
3493 my ($dbh,$sth,$version,@row);
3495 $dbh=$self->connect();
3496 $sth = $dbh->prepare("SELECT KERNEL FROM VERSIONS") or die $DBI::errstr;
3497 $version="SAP DB (unknown)";
3498 if ($sth->execute && (@row = $sth->fetchrow_array)
3499 && $row[0] =~ /([\d\.]+)/)
3501 $version=$row[0];
3502 $version =~ s/KERNEL/SAP DB/i;
3504 $sth->finish;
3505 $dbh->disconnect;
3506 $version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
3507 return $version;
3511 # Connection with optional disabling of logging
3514 sub connect
3516 my ($self)=@_;
3517 my ($dbh);
3518 $dbh=DBI->connect($self->{'data_source'}, $main::opt_user,
3519 $main::opt_password,{ PrintError => 0, AutoCommit => 1}) ||
3520 die "Got error: '$DBI::errstr' when connecting to " . $self->{'data_source'} ." with user: '$main::opt_user' password: '$main::opt_password'\n";
3522 return $dbh;
3526 # Returns a list of statements to create a table
3527 # The field types are in ANSI SQL format.
3530 sub create
3532 my($self,$table_name,$fields,$index,$options) = @_;
3533 my($query,@queries,$nr);
3534 my @index;
3535 my @keys;
3537 $query="create table $table_name (";
3538 foreach $field (@$fields)
3540 $field =~ s/\bmediumint\b/int/i;
3541 $field =~ s/\btinyint\b/int/i;
3542 $field =~ s/ int\(\d\)/ int/i;
3543 $field =~ s/BLOB/LONG/i;
3544 $field =~ s/INTEGER\s*\(\d+\)/INTEGER/i;
3545 $field =~ s/SMALLINT\s*\(\d+\)/SMALLINT/i;
3546 $field =~ s/FLOAT\s*\((\d+),\d+\)/FLOAT\($1\)/i;
3547 $field =~ s/DOUBLE/FLOAT\(38\)/i;
3548 $field =~ s/DOUBLE\s+PRECISION/FLOAT\(38\)/i;
3549 $query.= $field . ',';
3551 $nr=0;
3552 foreach $ind (@$index)
3554 if ( $ind =~ /\bKEY\b/i ){
3555 push(@keys,"ALTER TABLE $table_name ADD $ind");
3556 } elsif ($ind =~ /^unique.*\(([^\(]*)\)$/i) {
3557 $nr++;
3558 my $query="create unique index ${table_name}_$nr on $table_name ($1)";
3559 push(@index,$query);
3560 }else{
3561 my @fields = split(' ',$ind);
3562 my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
3563 push(@index,$query);
3566 substr($query,-1)=")"; # Remove last ',';
3567 $query.=" $options" if (defined($options));
3568 push(@queries,$query);
3569 push(@queries,@keys);
3570 push(@queries,@index);
3571 return @queries;
3574 sub insert_file {
3575 my($self,$dbname, $file) = @_;
3576 print "insert of an ascii file isn't supported by SAPDB\n";
3577 return 0;
3581 # Do any conversions to the ANSI SQL query so that the database can handle it
3584 sub query {
3585 my($self,$sql) = @_;
3586 return $sql;
3589 sub drop_index {
3590 my ($self,$table,$index) = @_;
3591 return "DROP INDEX $index";
3595 # Abort if the server has crashed
3596 # return: 0 if ok
3597 # 1 question should be retried
3600 sub abort_if_fatal_error
3602 return 0;
3605 sub small_rollback_segment
3607 return 0;
3610 sub reconnect_on_errors
3612 return 0;
3615 sub fix_for_insert
3617 my ($self,$cmd) = @_;
3618 return $cmd;