~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to tests/sql-bench/server-cfg

  • Committer: patrick crews
  • Date: 2011-06-07 18:45:15 UTC
  • mto: This revision was merged to the branch mainline in revision 2329.
  • Revision ID: gleebix@gmail.com-20110607184515-vwzakr741grhr2yl
Initial work for sql-bench mode.  Added sql-bench to the tree.  Test script for running entire suite added

Show diffs side-by-side

added added

removed removed

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