3
# Copyright (C) 2000-2006 MySQL AB
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
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.
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,
20
# Written by Monty for the TCX/Monty Program/Detron benchmark suite.
21
# Empress and PostgreSQL patches by Luuk de Boer
22
# Extensions for ANSI SQL and Mimer by Bengt Gunne
23
# Some additions and corrections by Matthias Urlich
25
# This programs tries to find all limits for a sql server
26
# It gets the name from what it does to most servers :)
28
# Be sure to use --help before running this!
30
# If you want to add support for another server, add a new package for the
31
# server in server-cfg. You only have to support the 'new' and 'version'
32
# functions. new doesn't need to have any limits if one doesn't want to
37
# CMT includes types and functions which are synonyms for other types
38
# and functions, including those in SQL9x. It should label those synonyms
39
# as such, and clarify ones such as "mediumint" with comments such as
40
# "3-byte int" or "same as xxx".
48
$pwd = cwd(); $pwd = "." if ($pwd eq '');
49
require "$pwd/server-cfg" || die "Can't read Configuration file: $!\n";
51
our $opt_batch_mode=0;
52
our $opt_check_server=0; # Check if server is alive before each query
54
our $opt_config_file="";
55
our $opt_connect_options="";
56
our $opt_database="test";
57
our $opt_db_start_cmd=""; # the db server start command
59
our $opt_dir="limits";
60
our $opt_fix_limit_file=0;
63
our $opt_host="localhost";
64
our $opt_Information=0;
65
our $opt_log_all_queries=0;
66
our $opt_log_queries_to_file="";
72
our $opt_server="mysql";
73
our $opt_sleep=10; # time to sleep while starting the db server
74
our $opt_socket=""; # time to sleep while starting the db server
80
$limit_changed=0; # For configure file
82
$limits{'crash_me_safe'}='yes';
83
$prompts{'crash_me_safe'}='crash me safe';
84
$limits{'operating_system'}= machine();
85
$prompts{'operating_system'}='crash-me tested on';
88
GetOptions("Information","help","server=s","debug","user=s","password=s",
89
"database=s","restart","force","quick","log-all-queries","comment=s",
90
"host=s","fix-limit-file","dir=s","db-start-cmd=s","sleep=s","suffix=s",
91
"batch-mode","config-file=s","log-queries-to-file=s","check-server",
92
"version", "connect-options=s", "machine=s", "socket=s",
93
"verbose!" => \$opt_verbose) || usage();
96
# Find limit using binary search. This is a weighed binary search that
97
# will prefere lower limits to get the server to crash as
98
# few times as possible
101
my ($prompt,$limit,$query)=@_;
102
my ($first,$end,$i,$tmp,@tmp_array, $queries);
104
if (defined($end=$limits{$limit}))
106
print "$end (cache)\n";
109
save_incomplete($limit,$prompt);
110
add_log($limit,"We are trying (example with N=5):");
111
$queries = $query->query(5);
112
if (ref($queries) ne "ARRAY")
114
push(@tmp_array,$queries);
115
$queries= \@tmp_array;
117
foreach $tmp (@$queries)
118
{ add_log($limit,repr_query($tmp)); }
120
if (defined($queries = $query->check_query()))
122
if (ref($queries) ne "ARRAY")
125
push(@tmp_array,$queries);
126
$queries= \@tmp_array;
128
foreach $tmp (@$queries)
129
{ add_log($limit,repr_query($tmp)); }
131
if (defined($query->{'init'}) && !defined($end=$limits{'restart'}{'tohigh'}))
133
if (!safe_query_l($limit,$query->{'init'}))
140
if (!limit_query($query,1)) # This must work
142
print "\nMaybe fatal error: Can't check '$prompt' for limit=1\n".
143
"error: $last_error\n";
148
$first=$limits{'restart'}{'low'} if ($limits{'restart'}{'low'});
150
if (defined($end=$limits{'restart'}{'tohigh'}))
153
print "\nRestarting this with low limit: $first and high limit: $end\n";
154
delete $limits{'restart'};
155
$i=$first+int(($end-$first+4)/5); # Prefere lower on errors
159
$end= $query->max_limit();
160
$i=int(($end+$first)/2);
163
unless(limit_query($query,0+$end)) {
164
while ($first < $end)
166
print "." if ($opt_debug);
167
save_config_data("restart",$i,"") if ($opt_restart);
168
if (limit_query($query,$i))
171
$log_str .= " $i:OK";
172
$i=$first+int(($end-$first+1)/2); # to be a bit faster to go up
177
$log_str .= " $i:FAIL";
178
$i=$first+int(($end-$first+4)/5); # Prefere lower on errors
182
$end+=$query->{'offset'} if ($end && defined($query->{'offset'}));
183
if ($end >= $query->{'max_limit'} &&
184
substr($query->{'max_limit'},0,1) eq '+')
186
$end= $query->{'max_limit'};
189
add_log($limit,$log_str);
190
save_config_data($limit,$end,$prompt);
191
delete $limits{'restart'};
195
usage() if ($opt_help || $opt_Information);
197
version() && exit(0) if ($opt_version);
199
$opt_suffix = '-'.$opt_suffix if (length($opt_suffix) != 0);
200
$opt_config_file = "$pwd/$opt_dir/$opt_server$opt_suffix.cfg"
201
if (length($opt_config_file) == 0);
203
$safe_query_result_log='';
208
if ($opt_fix_limit_file)
210
print "Fixing limit file for $opt_server\n";
213
save_all_config_data();
217
$server=get_server($opt_server,$opt_host,$opt_database,$opt_odbc, machine_part(), $opt_socket, $opt_connect_options);
218
$opt_server=$server->{'cmp_name'};
220
$|=1; # For debugging
222
print "Running $0 $version on '",($server_version=$server->version()),"'\n\n";
223
print "I hope you didn't have anything important running on this server....\n";
225
if ($limit_changed) # Must have been restarted
227
save_config_data('crash_me_safe','no',"crash me safe");
230
if (!$opt_force && !$opt_batch_mode)
236
print "Using --force. I assume you know what you are doing...\n";
240
save_config_data('crash_me_version',$version,"crash me version");
243
save_config_data('server_version',$server_version,"server version");
245
if (length($opt_comment))
247
save_config_data('user_comment',$opt_comment,"comment");
251
if (length($opt_log_queries_to_file))
253
open(LOG,">$opt_log_queries_to_file") ||
254
die "Can't open file $opt_log_queries_to_file\n";
259
# Set up some limits that's regared as unlimited
260
# We don't want to take up all resources from the server...
263
$max_connections="+1000"; # Number of simultaneous connections
264
$max_buffer_size="+16000000"; # size of communication buffer.
265
$max_string_size="+8000000"; # Enough for this test
266
$max_name_length="+512"; # Actually 256, but ...
267
$max_keys="+64"; # Probably too big.
268
$max_join_tables="+64"; # Probably too big.
269
$max_columns="+8192"; # Probably too big.
270
$max_row_length=$max_string_size;
271
$max_key_length="+8192"; # Big enough
272
$max_order_by="+64"; # Big enough
273
$max_expressions="+10000";
274
$max_big_expressions="+100";
275
$max_stacked_expressions="+2000";
276
$query_size=$max_buffer_size;
277
$longreadlen=16000000; # For retrieval buffer
281
# First do some checks that needed for the rest of the benchmark
283
use sigtrap; # Must be removed with perl5.005_2 on Win98
284
$SIG{PIPE} = 'IGNORE';
287
$problem_counter +=1;
288
if ($problem_counter >= 100) {
289
die("Too many problems, try to restart");
297
# Test if the database require RESTRICT/CASCADE after DROP TABLE
300
# Really remove the crash_me table
301
$prompt="drop table require cascade/restrict";
303
$dbh->do("drop table crash_me");
304
$dbh->do("drop table crash_me cascade");
305
if (!safe_query_l('drop_requires_cascade',
306
["create table crash_me (a integer not null)",
307
"drop table crash_me"]))
309
$dbh->do("drop table crash_me cascade");
310
if (safe_query_l('drop_requires_cascade',
311
["create table crash_me (a integer not null)",
312
"drop table crash_me cascade"]))
314
save_config_data('drop_requires_cascade',"yes","$prompt");
315
$drop_attr="cascade";
319
die "Can't create and drop table 'crash_me'\n";
324
save_config_data('drop_requires_cascade',"no","$prompt");
328
# Remove tables from old runs
329
$dbh->do("drop table crash_me $drop_attr");
330
$dbh->do("drop table crash_me2 $drop_attr");
331
$dbh->do("drop table crash_me3 $drop_attr");
332
$dbh->do("drop table crash_q $drop_attr");
333
$dbh->do("drop table crash_q1 $drop_attr");
335
$prompt="Tables without primary key";
336
if (!safe_query_l('no_primary_key',
337
["create table crash_me (a integer not null,b char(10) not null)",
338
"insert into crash_me (a,b) values (1,'a')"]))
340
if (!safe_query_l('no_primary_key',
341
["create table crash_me (a integer not null,b char(10) not null".
342
", primary key (a))",
343
"insert into crash_me (a,b) values (1,'a')"]))
345
die "Can't create table 'crash_me' with one record: $DBI::errstr\n";
347
save_config_data('no_primary_key',"no",$prompt);
351
save_config_data('no_primary_key',"yes",$prompt);
355
# Define strings for character NULL and numeric NULL used in expressions
357
$char_null=$server->{'char_null'};
358
$numeric_null=$server->{'numeric_null'};
359
if ($char_null eq '')
363
if ($numeric_null eq '')
365
$numeric_null="NULL";
368
print "$prompt: $limits{'no_primary_key'}\n";
370
report("SELECT without FROM",'select_without_from',"select 1");
371
if ($limits{'select_without_from'} ne "yes")
373
$end_query=" from crash_me";
374
$check_connect="select a from crash_me";
379
$check_connect="select 1";
382
assert_crash($check_connect);
383
assert_crash("select a from crash_me where b<'b'");
385
report("Select constants",'select_constants',"select 1 $end_query");
386
report("Select table_name.*",'table_wildcard',
387
"select crash_me.* from crash_me");
388
report("Allows \' and \" as string markers",'quote_with_"',
389
'select a from crash_me where b<"c"');
390
check_and_report("Double '' as ' in strings",'double_quotes',[],
391
"select 'Walker''s' $end_query",[],"Walker's",1);
392
check_and_report("Multiple line strings","multi_strings",[],
393
"select a from crash_me where b < 'a'\n'b'",[],"1",0);
394
check_and_report("\" as identifier quote (ANSI SQL)",'quote_ident_with_"',[],
395
'select "A" from crash_me',[],"A",0);
396
check_and_report("\` as identifier quote",'quote_ident_with_`',[],
397
'select `A` from crash_me',[],"1",0);
398
check_and_report("[] as identifier quote",'quote_ident_with_[',[],
399
'select [A] from crash_me',[],"1",0);
400
report('Double "" in identifiers as "','quote_ident_with_dbl_"',
401
'create table crash_me1 ("abc""d" integer)',
402
'drop table crash_me1');
404
report("Column alias","column_alias","select a as ab from crash_me");
405
report("Table alias","table_alias","select b.a from crash_me as b");
406
report("Functions",'functions',"select 1+1 $end_query");
407
report("Group functions",'group_functions',"select count(*) from crash_me");
408
report("Group functions with distinct",'group_distinct_functions',
409
"select count(distinct a) from crash_me");
410
report("Group functions with several distinct",'group_many_distinct_functions',
411
"select count(distinct a), count(distinct b) from crash_me");
412
report("Group by",'group_by',"select a from crash_me group by a");
413
report("Group by position",'group_by_position',
414
"select a from crash_me group by 1");
415
report("Group by alias",'group_by_alias',
416
"select a as ab from crash_me group by ab");
417
report("Group on unused column",'group_on_unused',
418
"select count(*) from crash_me group by a");
420
report("Order by",'order_by',"select a from crash_me order by a");
421
report("Order by position",'order_by_position',
422
"select a from crash_me order by 1");
423
report("Order by function","order_by_function",
424
"select a from crash_me order by a+1");
425
report("Order by on unused column",'order_on_unused',
426
"select b from crash_me order by a");
427
# little bit deprecated
428
#check_and_report("Order by DESC is remembered",'order_by_remember_desc',
429
# ["create table crash_q (s int,s1 int)",
430
# "insert into crash_q values(1,1)",
431
# "insert into crash_q values(3,1)",
432
# "insert into crash_q values(2,1)"],
433
# "select s,s1 from crash_q order by s1 DESC,s",
434
# ["drop table crash_q $drop_attr"],[3,2,1],7,undef(),3);
435
report("Compute",'compute',
436
"select a from crash_me order by a compute sum(a) by a");
437
report("INSERT with Value lists",'insert_multi_value',
438
"create table crash_q (s char(10))",
439
"insert into crash_q values ('a'),('b')",
440
"drop table crash_q $drop_attr");
441
report("INSERT with set syntax",'insert_with_set',
442
"create table crash_q (a integer)",
443
"insert into crash_q SET a=1",
444
"drop table crash_q $drop_attr");
445
report("INSERT with DEFAULT","insert_with_default",
446
"create table crash_me_q (a int)",
447
"insert into crash_me_q (a) values (DEFAULT)",
448
"drop table crash_me_q $drop_attr");
450
report("INSERT with empty value list","insert_with_empty_value_list",
451
"create table crash_me_q (a int)",
452
"insert into crash_me_q (a) values ()",
453
"drop table crash_me_q $drop_attr");
455
report("INSERT DEFAULT VALUES","insert_default_values",
456
"create table crash_me_q (a int)",
457
"insert into crash_me_q DEFAULT VALUES",
458
"drop table crash_me_q $drop_attr");
460
report("allows end ';'","end_colon", "select * from crash_me;");
461
try_and_report("LIMIT number of rows","select_limit",
463
"select * from crash_me limit 1"],
465
"select TOP 1 * from crash_me"]);
466
report("SELECT with LIMIT #,#","select_limit2",
467
"select * from crash_me limit 1,1");
468
report("SELECT with LIMIT # OFFSET #",
469
"select_limit3", "select * from crash_me limit 1 offset 1");
471
# The following alter table commands MUST be kept together!
472
if ($dbh->do("create table crash_q (a integer, b integer,c1 CHAR(10))"))
474
report("Alter table add column",'alter_add_col',
475
"alter table crash_q add d integer");
476
report_one("Alter table add many columns",'alter_add_multi_col',
477
[["alter table crash_q add (f integer,g integer)","yes"],
478
["alter table crash_q add f integer, add g integer","with add"],
479
["alter table crash_q add f integer,g integer","without add"]] );
480
report("Alter table change column",'alter_change_col',
481
"alter table crash_q change a e char(50)");
483
# informix can only change data type with modify
484
report_one("Alter table modify column",'alter_modify_col',
485
[["alter table crash_q modify c1 CHAR(20)","yes"],
486
["alter table crash_q alter c1 CHAR(20)","with alter"]]);
487
report("Alter table alter column default",'alter_alter_col',
488
"alter table crash_q alter b set default 10");
489
report_one("Alter table drop column",'alter_drop_col',
490
[["alter table crash_q drop column b","yes"],
491
["alter table crash_q drop column b restrict",
492
"with restrict/cascade"]]);
493
report("Alter table rename table",'alter_rename_table',
494
"alter table crash_q rename to crash_q1");
496
# Make sure both tables will be dropped, even if rename fails.
497
$dbh->do("drop table crash_q1 $drop_attr");
498
$dbh->do("drop table crash_q $drop_attr");
500
report("rename table","rename_table",
501
"create table crash_q (a integer, b integer,c1 CHAR(10))",
502
"rename table crash_q to crash_q1",
503
"drop table crash_q1 $drop_attr");
504
# Make sure both tables will be dropped, even if rename fails.
505
$dbh->do("drop table crash_q1 $drop_attr");
506
$dbh->do("drop table crash_q $drop_attr");
508
report("truncate","truncate_table",
509
"create table crash_q (a integer, b integer,c1 CHAR(10))",
510
"truncate table crash_q",
511
"drop table crash_q $drop_attr");
513
if ($dbh->do("create table crash_q (a integer, b integer,c1 CHAR(10))") &&
514
$dbh->do("create table crash_q1 (a integer, b integer,c1 CHAR(10) not null)"))
516
report("Alter table add constraint",'alter_add_constraint',
517
"alter table crash_q add constraint c2 check(a > b)");
518
report_one("Alter table drop constraint",'alter_drop_constraint',
519
[["alter table crash_q drop constraint c2","yes"],
520
["alter table crash_q drop constraint c2 restrict",
521
"with restrict/cascade"]]);
522
report("Alter table add unique",'alter_add_unique',
523
"alter table crash_q add constraint u1 unique(c1)");
524
try_and_report("Alter table drop unique",'alter_drop_unique',
526
"alter table crash_q drop constraint u1"],
527
["with constraint and restrict/cascade",
528
"alter table crash_q drop constraint u1 restrict"],
530
"alter table crash_q drop key u1"]);
531
try_and_report("Alter table add primary key",'alter_add_primary_key',
533
"alter table crash_q1 add constraint p1 primary key(c1)"],
534
["with add primary key",
535
"alter table crash_q1 add primary key(c1)"]);
536
report("Alter table add foreign key",'alter_add_foreign_key',
537
"alter table crash_q add constraint f1 foreign key(c1) references crash_q1(c1)");
538
try_and_report("Alter table drop foreign key",'alter_drop_foreign_key',
539
["with drop constraint",
540
"alter table crash_q drop constraint f1"],
541
["with drop constraint and restrict/cascade",
542
"alter table crash_q drop constraint f1 restrict"],
543
["with drop foreign key",
544
"alter table crash_q drop foreign key f1"]);
545
try_and_report("Alter table drop primary key",'alter_drop_primary_key',
547
"alter table crash_q1 drop constraint p1 restrict"],
549
"alter table crash_q1 drop primary key"]);
551
$dbh->do("drop table crash_q $drop_attr");
552
$dbh->do("drop table crash_q1 $drop_attr");
554
check_and_report("Case insensitive compare","case_insensitive_strings",
555
[],"select b from crash_me where b = 'A'",[],'a',1);
556
check_and_report("Ignore end space in compare","ignore_end_space",
557
[],"select b from crash_me where b = 'a '",[],'a',1);
558
check_and_report("Group on column with null values",'group_by_null',
559
["create table crash_q (s char(10))",
560
"insert into crash_q values(null)",
561
"insert into crash_q values(null)"],
562
"select count(*),s from crash_q group by s",
563
["drop table crash_q $drop_attr"],2,0);
566
if (!defined($limits{'having'}))
567
{ # Complicated because of postgreSQL
568
if (!safe_query_result_l("having",
569
"select a from crash_me group by a having a > 0",1,0))
571
if (!safe_query_result_l("having",
572
"select a from crash_me group by a having a < 0",
574
{ save_config_data("having","error",$prompt); }
576
{ save_config_data("having","yes",$prompt); }
579
{ save_config_data("having","no",$prompt); }
581
print "$prompt: $limits{'having'}\n";
583
if ($limits{'having'} eq 'yes')
585
report("Having with group function","having_with_group",
586
"select a from crash_me group by a having count(*) = 1");
589
if ($limits{'column_alias'} eq 'yes')
591
report("Order by alias",'order_by_alias',
592
"select a as ab from crash_me order by ab");
593
if ($limits{'having'} eq 'yes')
595
report("Having on alias","having_with_alias",
596
"select a as ab from crash_me group by a having ab > 0");
599
report("binary numbers (0b1001)","binary_numbers","select 0b1001 $end_query");
600
report("hex numbers (0x41)","hex_numbers","select 0x41 $end_query");
601
report("binary strings (b'0110')","binary_strings","select b'0110' $end_query");
602
report("hex strings (x'1ace')","hex_strings","select x'1ace' $end_query");
604
report_result("Value of logical operation (1=1)","logical_value",
605
"select (1=1) $end_query");
607
report_result("Value of TRUE","value_of_true","select TRUE $end_query");
608
report_result("Value of FALSE","value_of_false","select FALSE $end_query");
610
$logical_value= $limits{'logical_value'};
614
if ($res=safe_query_l('has_true_false',"select (1=1)=true $end_query")) {
618
save_config_data('has_true_false',$result,"TRUE and FALSE");
621
# Check how many connections the server can handle:
622
# We can't test unlimited connections, because this may take down the
626
$prompt="Simultaneous connections (installation default)";
628
if (defined($limits{'connections'}))
630
print "$limits{'connections'}\n";
636
for ($i=1; $i < $max_connections ; $i++)
638
if (!($dbh=DBI->connect($server->{'data_source'},$opt_user,$opt_password,
639
{ PrintError => 0})))
641
print "Last connect error: $DBI::errstr\n" if ($opt_debug);
644
$dbh->{LongReadLen}= $longreadlen; # Set retrieval buffer
645
print "." if ($opt_debug);
649
save_config_data('connections',$i,$prompt);
650
foreach $dbh (@connect)
652
print "#" if ($opt_debug);
653
$dbh->disconnect || warn $dbh->errstr; # close connection
656
$#connect=-1; # Free connections
660
print "Can't connect to server: $DBI::errstr.".
661
" Please start it and try again\n";
664
$dbh=retry_connect();
669
# Check size of communication buffer, strings...
672
$prompt="query size";
674
if (!defined($limits{'query_size'}))
678
$end=$max_buffer_size;
679
$select= $limits{'select_without_from'} eq 'yes' ? 1 : 'a';
681
assert_crash($query . "$select$end_query");
683
$first=$limits{'restart'}{'low'} if ($limits{'restart'}{'low'});
685
if ($limits{'restart'}{'tohigh'})
687
$end = $limits{'restart'}{'tohigh'} - 1;
688
print "\nRestarting this with low limit: $first and high limit: $end\n";
689
delete $limits{'restart'};
690
$first=$first+int(($end-$first+4)/5); # Prefere lower on errors
692
for ($i=$first ; $i < $end ; $i*=2)
694
#printf "Trying query %s %d with %d spaces\n",$query,$select,($i - length($query)-length($end_query) -1);
695
last if (!safe_query($query .
696
(" " x ($i - length($query)-length($end_query) -1))
697
. "$select$end_query"));
699
save_config_data("restart",$i,"") if ($opt_restart);
703
if ($i < $max_buffer_size)
705
while ($first != $end)
707
$i=int(($first+$end+1)/2);
708
if (safe_query($query .
709
(" " x ($i - length($query)-length($end_query) -1)) .
710
"$select$end_query"))
720
save_config_data('query_size',$end,$prompt);
722
$query_size=$limits{'query_size'};
724
print "$limits{'query_size'}\n";
727
# Check for reserved words
730
check_reserved_words($dbh);
733
# Test database types
736
@sql_types=("character(1)","char(1)","char varying(1)", "character varying(1)",
739
"integer","int","smallint",
740
"numeric(9,2)","decimal(6,2)","dec(6,2)",
741
"bit", "bit(2)","bit varying(2)","float","float(8)","real",
742
"double precision", "date","time","timestamp",
743
"interval year", "interval year to month",
745
"interval day", "interval day to hour", "interval day to minute",
746
"interval day to second",
747
"interval hour", "interval hour to minute",
748
"interval hour to second",
749
"interval minute", "interval minute to second",
751
"national character varying(20)",
752
"national character(20)","nchar(1)",
753
"national char varying(20)","nchar varying(20)",
754
"national character varying(20)",
755
"timestamp with time zone");
756
@odbc_types=("binary(1)","varbinary(1)","tinyint","bigint",
758
@extra_types=("blob","byte","long varbinary","image","text","text(10)",
760
"long varchar(1)", "varchar2(257)",
761
"mediumint","middleint","int unsigned",
762
"int1","int2","int3","int4","int8","uint",
763
"money","smallmoney","float4","float8","smallfloat",
764
"float(6,2)","double",
765
"enum('red')","set('red')", "int(5) zerofill", "serial",
766
"char(10) binary","int not null auto_increment,unique(q)",
767
"abstime","year","datetime","smalldatetime","timespan","reltime",
769
"int not null identity,unique(q)",
771
"box","bool","circle","polygon","point","line","lseg","path",
772
"interval", "inet", "cidr", "macaddr",
775
"varchar2(16)","nvarchar2(16)","number(9,2)","number(9)",
776
"number", "long","raw(16)","long raw","rowid","mlslabel","clob",
780
@types=(["sql",\@sql_types],
781
["odbc",\@odbc_types],
782
["extra",\@extra_types]);
784
foreach $types (@types)
786
print "\nSupported $types->[0] types\n";
788
foreach $use_type (@$tmp)
791
$type =~ s/\(.*\)/(1 arg)/;
792
if (index($use_type,",")>= 0)
794
$type =~ s/\(1 arg\)/(2 arg)/;
796
if (($tmp2=index($type,",unique")) >= 0)
798
$type=substr($type,0,$tmp2);
802
$tmp2 =~ s/_not_null//g;
803
report("Type $type","type_$types->[0]_$tmp2",
804
"create table crash_q (q $use_type)",
805
"drop table crash_q $drop_attr");
810
# Test some type limits
814
check_and_report("Remembers end space in char()","remember_end_space",
815
["create table crash_q (a char(10))",
816
"insert into crash_q values('hello ')"],
817
"select a from crash_q where a = 'hello '",
818
["drop table crash_q $drop_attr"],
821
check_and_report("Remembers end space in varchar()",
822
"remember_end_space_varchar",
823
["create table crash_q (a varchar(10))",
824
"insert into crash_q values('hello ')"],
825
"select a from crash_q where a = 'hello '",
826
["drop table crash_q $drop_attr"],
829
if (($limits{'type_extra_float(2_arg)'} eq "yes" ||
830
$limits{'type_sql_decimal(2_arg)'} eq "yes") &&
831
(!defined($limits{'storage_of_float'})))
833
my $type=$limits{'type_extra_float(2_arg)'} eq "yes" ? "float(4,1)" :
835
my $result="undefined";
836
if (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
837
"insert into crash_q values(1.14)"],
838
"select q1 from crash_q",
839
["drop table crash_q $drop_attr"],1.1,0) &&
840
execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
841
"insert into crash_q values(1.16)"],
842
"select q1 from crash_q",
843
["drop table crash_q $drop_attr"],1.1,0))
847
elsif (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
848
"insert into crash_q values(1.14)"],
849
"select q1 from crash_q",
850
["drop table crash_q $drop_attr"],1.1,0) &&
851
execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
852
"insert into crash_q values(1.16)"],
853
"select q1 from crash_q",
854
["drop table crash_q $drop_attr"],1.2,0))
858
elsif (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
859
"insert into crash_q values(1.14)"],
860
"select q1 from crash_q",
861
["drop table crash_q $drop_attr"],1.14,0) &&
862
execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
863
"insert into crash_q values(1.16)"],
864
"select q1 from crash_q",
865
["drop table crash_q $drop_attr"],1.16,0))
869
$prompt="Storage of float values";
870
print "$prompt: $result\n";
871
save_config_data("storage_of_float", $result, $prompt);
874
try_and_report("Type for row id", "rowid",
876
"create table crash_q (a rowid)",
877
"drop table crash_q $drop_attr"],
879
"create table crash_q (a int not null auto_increment".
880
", primary key(a))","drop table crash_q $drop_attr"],
882
"create table crash_q (a oid, primary key(a))",
883
"drop table crash_q $drop_attr"],
885
"create table crash_q (a serial, primary key(a))",
886
"drop table crash_q $drop_attr"]);
888
try_and_report("Automatic row id", "automatic_rowid",
890
"create table crash_q (a int not null, primary key(a))",
891
"insert into crash_q values (1)",
892
"select _rowid from crash_q",
893
"drop table crash_q $drop_attr"]);
900
(["+, -, * and /","+","5*3-4/2+1",14,0],
901
["ANSI SQL SUBSTRING","substring","substring('abcd' from 2 for 2)","bc",1],
902
["BIT_LENGTH","bit_length","bit_length('abc')",24,0],
903
["searched CASE","searched_case",
904
"case when 1 > 2 then 'false' when 2 > 1 then 'true' end", "true",1],
905
["simple CASE","simple_case",
906
"case 2 when 1 then 'false' when 2 then 'true' end", "true",1],
907
["CAST","cast","CAST(1 as CHAR)","1",1],
908
["CHARACTER_LENGTH","character_length","character_length('abcd')","4",0],
909
["CHAR_LENGTH","char_length","char_length(b)","1",0],
910
["CHAR_LENGTH(constant)","char_length(constant)",
911
"char_length('abcd')","4",0],
912
["COALESCE","coalesce","coalesce($char_null,'bcd','qwe')","bcd",1],
913
["CURRENT_DATE","current_date","current_date",0,2],
914
["CURRENT_TIME","current_time","current_time",0,2],
915
["CURRENT_TIMESTAMP","current_timestamp","current_timestamp",0,2],
916
["EXTRACT","extract_sql",
917
"extract(minute from timestamp '2000-02-23 18:43:12.987')",43,0],
918
["LOCALTIME","localtime","localtime",0,2],
919
["LOCALTIMESTAMP","localtimestamp","localtimestamp",0,2],
920
["LOWER","lower","LOWER('ABC')","abc",1],
921
["NULLIF with strings","nullif_string",
922
"NULLIF(NULLIF('first','second'),'first')",undef(),4],
923
["NULLIF with numbers","nullif_num","NULLIF(NULLIF(1,2),1)",undef(),4],
924
["OCTET_LENGTH","octet_length","octet_length('abc')",3,0],
925
["POSITION","position","position('ll' in 'hello')",3,0],
926
["TRIM","trim","trim(trailing from trim(LEADING FROM ' abc '))","abc",3],
927
["UPPER","upper","UPPER('abc')","ABC",1],
928
["concatenation with ||","concat_as_||","'abc' || 'def'","abcdef",1],
932
(["ASCII", "ascii", "ASCII('A')","65",0],
933
["CHAR", "char", "CHAR(65)" ,"A",1],
934
["CONCAT(2 arg)","concat", "concat('a','b')","ab",1],
935
["DIFFERENCE()","difference","difference('abc','abe')",3,0],
936
["INSERT","insert","insert('abcd',2,2,'ef')","aefd",1],
937
["LEFT","left","left('abcd',2)","ab",1],
938
["LTRIM","ltrim","ltrim(' abcd')","abcd",1],
939
["REAL LENGTH","length","length('abcd ')","5",0],
940
["ODBC LENGTH","length_without_space","length('abcd')","4",0],
941
["LOCATE(2 arg)","locate_2","locate('bcd','abcd')","2",0],
942
["LOCATE(3 arg)","locate_3","locate('bcd','abcd',3)","0",0],
943
["LCASE","lcase","lcase('ABC')","abc",1],
944
["REPEAT","repeat","repeat('ab',3)","ababab",1],
945
["REPLACE","replace","replace('abbaab','ab','ba')","bababa",1],
946
["RIGHT","right","right('abcd',2)","cd",1],
947
["RTRIM","rtrim","rtrim(' abcd ')"," abcd",1],
948
["SPACE","space","space(5)"," ",3],
949
["SOUNDEX","soundex","soundex('hello')",0,2],
950
["ODBC SUBSTRING","substring","substring('abcd',3,2)","cd",1],
951
["UCASE","ucase","ucase('abc')","ABC",1],
953
["ABS","abs","abs(-5)",5,0],
954
["ACOS","acos","acos(0)","1.570796",0],
955
["ASIN","asin","asin(1)","1.570796",0],
956
["ATAN","atan","atan(1)","0.785398",0],
957
["ATAN2","atan2","atan2(1,0)","1.570796",0],
958
["CEILING","ceiling","ceiling(-4.5)",-4,0],
959
["COS","cos","cos(0)","1.00000",0],
960
["COT","cot","cot(1)","0.64209262",0],
961
["DEGREES","degrees","degrees(6.283185)","360",0],
962
["EXP","exp","exp(1.0)","2.718282",0],
963
["FLOOR","floor","floor(2.5)","2",0],
964
["LOG","log","log(2)","0.693147",0],
965
["LOG10","log10","log10(10)","1",0],
966
["MOD","mod","mod(11,7)","4",0],
967
["PI","pi","pi()","3.141593",0],
968
["POWER","power","power(2,4)","16",0],
969
["RAND","rand","rand(1)",0,2], # Any value is acceptable
970
["RADIANS","radians","radians(360)","6.283185",0],
971
["ROUND(2 arg)","round","round(5.63,2)","5.6",0],
972
["SIGN","sign","sign(-5)",-1,0],
973
["SIN","sin","sin(1)","0.841471",0],
974
["SQRT","sqrt","sqrt(4)",2,0],
975
["TAN","tan","tan(1)","1.557408",0],
976
["TRUNCATE","truncate","truncate(18.18,-1)",10,0],
977
["NOW","now","now()",0,2], # Any value is acceptable
978
["CURDATE","curdate","curdate()",0,2],
979
["CURTIME","curtime","curtime()",0,2],
980
["TIMESTAMPADD","timestampadd",
981
"timestampadd(SQL_TSI_SECOND,1,'1997-01-01 00:00:00')",
982
"1997-01-01 00:00:01",1],
983
["TIMESTAMPDIFF","timestampdiff",
984
"timestampdiff(SQL_TSI_SECOND,'1997-01-01 00:00:01',".
985
" '1997-01-01 00:00:02')","1",0],
986
["USER()","user()","user()",0,2],
987
["DATABASE","database","database()",0,2],
988
["IFNULL","ifnull","ifnull(2,3)",2,0],
989
["ODBC syntax LEFT & RIGHT", "fn_left",
990
"{ fn LEFT( { fn RIGHT('abcd',2) },1) }","c",1],
995
["& (bitwise and)",'&',"5 & 3",1,0],
996
["| (bitwise or)",'|',"1 | 2",3,0],
997
["<< and >> (bitwise shifts)",'binary_shifts',"(1 << 4) >> 2",4,0],
998
["<> in SELECT","<>","1<>1","0",0],
999
["=","=","(1=1)",1,$logical_value],
1000
["~* (case insensitive compare)","~*","'hi' ~* 'HI'",1,$logical_value],
1001
["AND and OR in SELECT","and_or","1=1 AND 2=2",$logical_value,0],
1002
["AND as '&&'",'&&',"1=1 && 2=2",$logical_value,0],
1003
["ASCII_CHAR", "ascii_char", "ASCII_CHAR(65)","A",1],
1004
["ASCII_CODE", "ascii_code", "ASCII_CODE('A')","65",0],
1005
["ATN2","atn2","atn2(1,0)","1.570796",0],
1006
["BETWEEN in SELECT","between","5 between 4 and 6",$logical_value,0],
1007
["BIT_COUNT","bit_count","bit_count(5)",2,0],
1008
["CEIL","ceil","ceil(-4.5)",-4,0], # oracle
1009
["CHARINDEX","charindex","charindex('a','crash')",3,0],
1010
["CHR", "chr", "CHR(65)" ,"A",1], # oracle
1011
["CONCAT(list)","concat_list", "concat('a','b','c','d')","abcd",1],
1012
["CONVERT","convert","convert(CHAR,5)","5",1],
1013
["COSH","cosh","cosh(0)","1",0], # oracle hyperbolic cosine of n.
1014
["ELT","elt","elt(2,'ONE','TWO','THREE')","TWO",1],
1015
["ENCRYPT","encrypt","encrypt('hello')",0,2],
1016
["FIELD","field","field('IBM','NCA','ICL','SUN','IBM','DIGITAL')",4,0],
1017
["FORMAT","format","format(1234.5555,2)","1,234.56",1],
1018
["GETDATE","getdate","getdate()",0,2],
1019
["GREATEST","greatest","greatest('HARRY','HARRIOT','HAROLD')","HARRY",1],
1020
["IF","if", "if(5,6,7)",6,0],
1021
["IN on numbers in SELECT","in_num","2 in (3,2,5,9,5,1)",$logical_value,0],
1022
["IN on strings in SELECT","in_str","'monty' in ('david','monty','allan')", $logical_value,0],
1023
["INITCAP","initcap","initcap('the soap')","The Soap",1],
1024
# oracle Returns char, with the first letter of each word in uppercase
1025
["INSTR (Oracle syntax)", "instr_oracle", "INSTR('CORPORATE FLOOR','OR',3,2)" ,"14",0], # oracle instring
1026
["INSTRB", "instrb", "INSTRB('CORPORATE FLOOR','OR',5,2)" ,"27",0],
1027
# oracle instring in bytes
1028
["INTERVAL","interval","interval(55,10,20,30,40,50,60,70,80,90,100)",5,0],
1029
["LAST_INSERT_ID","last_insert_id","last_insert_id()",0,2],
1030
["LEAST","least","least('HARRY','HARRIOT','HAROLD')","HAROLD",1],
1032
["LENGTHB","lengthb","lengthb('CANDIDE')","14",0],
1033
# oracle length in bytes
1034
["LIKE ESCAPE in SELECT","like_escape",
1035
"'%' like 'a%' escape 'a'",$logical_value,0],
1036
["LIKE in SELECT","like","'a' like 'a%'",$logical_value,0],
1037
["LN","ln","ln(95)","4.55387689",0],
1038
# oracle natural logarithm of n
1039
["LOCATE as INSTR","instr","instr('hello','ll')",3,0],
1040
["LOG(m,n)","log(m_n)","log(10,100)","2",0],
1041
# oracle logarithm, base m, of n
1042
["LOGN","logn","logn(2)","0.693147",0],
1044
["LPAD","lpad","lpad('hi',4,'??')",'??hi',3],
1045
["MOD as %","%","10%7","3",0],
1046
["NOT BETWEEN in SELECT","not_between","5 not between 4 and 6",0,0],
1047
["NOT LIKE in SELECT","not_like","'a' not like 'a%'",0,0],
1048
["NOT as '!' in SELECT","!","! 1",0,0],
1049
["NOT in SELECT","not","not $false",$logical_value,0],
1050
["ODBC CONVERT","odbc_convert","convert(5,SQL_CHAR)","5",1],
1051
["OR as '||'",'||',"1=0 || 1=1",$logical_value,0],
1052
["PASSWORD","password","password('hello')",0,2],
1053
["PASTE", "paste", "paste('ABCDEFG',3,2,'1234')","AB1234EFG",1],
1054
["PATINDEX","patindex","patindex('%a%','crash')",3,0],
1055
["POW","pow","pow(3,2)",9,0],
1056
["RANGE","range","range(a)","0.0",0],
1057
# informix range(a) = max(a) - min(a)
1058
["REGEXP in SELECT","regexp","'a' regexp '^(a|b)*\$'",$logical_value,0],
1059
["REPLICATE","replicate","replicate('a',5)","aaaaa",1],
1060
["REVERSE","reverse","reverse('abcd')","dcba",1],
1061
["ROOT","root","root(4)",2,0], # informix
1062
["ROUND(1 arg)","round1","round(5.63)","6",0],
1063
["RPAD","rpad","rpad('hi',4,'??')",'hi??',3],
1064
["SINH","sinh","sinh(1)","1.17520119",0], # oracle hyperbolic sine of n
1065
["STR","str","str(123.45,5,1)",123.5,3],
1066
["STRCMP","strcmp","strcmp('abc','adc')",-1,0],
1067
["STUFF","stuff","stuff('abc',2,3,'xyz')",'axyz',3],
1068
["SUBSTRB", "substrb", "SUBSTRB('ABCDEFG',5,4.2)" ,"CD",1],
1069
# oracle substring with bytes
1070
["SUBSTRING as MID","mid","mid('hello',3,2)","ll",1],
1071
["SUBSTRING_INDEX","substring_index",
1072
"substring_index('www.tcx.se','.',-2)", "tcx.se",1],
1073
["SYSDATE","sysdate","sysdate()",0,2],
1074
["TAIL","tail","tail('ABCDEFG',3)","EFG",0],
1075
["TANH","tanh","tanh(1)","0.462117157",0],
1076
# oracle hyperbolic tangent of n
1077
["TRANSLATE","translate","translate('abc','bc','de')",'ade',3],
1078
["TRIM; Leading char extension", "trim_leading_char","trim(LEADING ':' FROM ':abc!')","abc!",3],
1079
["TRIM; Trailing char extension", "trim_trailing_char","trim(TRAILING'!' FROM ':abc!')",":abc",3],
1080
["TRIM; Substring extension",
1081
"trim_substring","trim('cb' FROM 'abccb')","abc",3],
1082
["TRUNC","trunc","trunc(18.18,-1)",10,0], # oracle
1083
["UID","uid","uid",0,2], # oracle uid from user
1084
["UNIX_TIMESTAMP","unix_timestamp","unix_timestamp()",0,2],
1085
["USERENV","userenv","userenv",0,2], # oracle user enviroment
1086
["VERSION","version","version()",0,2],
1087
["automatic num->string convert","auto_num2string","concat('a',2)","a2",1],
1088
["automatic string->num convert","auto_string2num","'1'+2",3,0],
1089
["concatenation with +","concat_as_+","'abc' + 'def'","abcdef",1],
1090
["SUBSTR (2 arg)",'substr2arg',"substr('abcd',2)",'bcd',1], #sapdb func
1091
["SUBSTR (3 arg)",'substr3arg',"substr('abcd',2,2)",'bc',1],
1092
["LFILL (3 arg)",'lfill3arg',"lfill('abcd','.',6)",'..abcd',1],
1093
["RFILL (3 arg)",'rfill3arg',"rfill('abcd','.',6)",'abcd..',1],
1094
["RPAD (4 arg)",'rpad4arg',"rpad('abcd',2,'+-',8)",'abcd+-+-',1],
1095
["LPAD (4 arg)",'rpad4arg',"lpad('abcd',2,'+-',8)",'+-+-abcd',1],
1096
["TRIM (1 arg)",'trim1arg',"trim(' abcd ')",'abcd',1],
1097
["TRIM (2 arg)",'trim2arg',"trim('..abcd..','.')",'abcd',1],
1098
["LTRIM (2 arg)",'ltrim2arg',"ltrim('..abcd..','.')",'abcd..',1],
1099
["RTRIM (2 arg)",'rtrim2arg',"rtrim('..abcd..','.')",'..abcd',1],
1100
["EXPAND",'expand2arg',"expand('abcd',6)",'abcd ',0],
1101
["REPLACE (2 arg) ",'replace2arg',"replace('AbCd','bC')",'Ad',1],
1102
["MAPCHAR",'mapchar',"mapchar('A�')",'Aa',1],
1103
["ALPHA",'alpha',"alpha('A�',2)",'AA',1],
1104
["ASCII in string cast",'ascii_string',"ascii('a')",'97',1],
1105
["EBCDIC in string cast",'ebcdic_string',"ebcdic('a')",'a',1],
1106
["TRUNC (1 arg)",'trunc1arg',"trunc(222.6)",222,0],
1107
["FIXED",'fixed',"fixed(222.6666,10,2)",'222.67',0],
1108
["FLOAT",'float',"float(6666.66,4)",6667,0],
1109
["LENGTH",'length',"length(1)",1,0],
1110
["INDEX",'index',"index('abcdefg','cd',1,1)",3,0],
1111
["MICROSECOND",'microsecond',
1112
"MICROSECOND('19630816200212111111')",'111111',0],
1113
["TIMESTAMP",'timestamp',
1114
"timestamp('19630816','00200212')",'19630816200212000000',0],
1115
["VALUE",'value',"value(NULL,'WALRUS')",'WALRUS',0],
1116
["DECODE",'decode',"DECODE('S-103','T72',1,'S-103',2,'Leopard',3)",2,0],
1117
["NUM",'num',"NUM('2123')",2123,0],
1118
["CHR (any type to string)",'chr_str',"CHR(67)",'67',0],
1119
["HEX",'hex',"HEX('A')",41,0],
1123
@sql_group_functions=
1125
["AVG","avg","avg(a)",1,0],
1126
["COUNT (*)","count_*","count(*)",1,0],
1127
["COUNT column name","count_column","count(a)",1,0],
1128
["COUNT(DISTINCT expr)","count_distinct","count(distinct a)",1,0],
1129
["MAX on numbers","max","max(a)",1,0],
1130
["MAX on strings","max_str","max(b)","a",1],
1131
["MIN on numbers","min","min(a)",1,0],
1132
["MIN on strings","min_str","min(b)","a",1],
1133
["SUM","sum","sum(a)",1,0],
1134
["ANY","any","any(a)",$logical_value,0],
1135
["EVERY","every","every(a)",$logical_value,0],
1136
["SOME","some","some(a)",$logical_value,0],
1139
@extra_group_functions=
1141
["BIT_AND",'bit_and',"bit_and(a)",1,0],
1142
["BIT_OR", 'bit_or', "bit_or(a)",1,0],
1143
["COUNT(DISTINCT expr,expr,...)",
1144
"count_distinct_list","count(distinct a,b)",1,0],
1145
["STD","std","std(a)",0,0],
1146
["STDDEV","stddev","stddev(a)",0,0],
1147
["VARIANCE","variance","variance(a)",0,0],
1152
["= ALL","eq_all","b =all (select b from crash_me)",1,0],
1153
["= ANY","eq_any","b =any (select b from crash_me)",1,0],
1154
["= SOME","eq_some","b =some (select b from crash_me)",1,0],
1155
["BETWEEN","between","5 between 4 and 6",1,0],
1156
["EXISTS","exists","exists (select * from crash_me)",1,0],
1157
["IN on numbers","in_num","2 in (3,2,5,9,5,1)",1,0],
1158
["LIKE ESCAPE","like_escape","b like '%' escape 'a'",1,0],
1159
["LIKE","like","b like 'a%'",1,0],
1160
["MATCH UNIQUE","match_unique",
1161
"1 match unique (select a from crash_me)",1,0],
1162
["MATCH","match","1 match (select a from crash_me)",1,0],
1163
["MATCHES","matches","b matches 'a*'",1,0],
1164
["NOT BETWEEN","not_between","7 not between 4 and 6",1,0],
1165
["NOT EXISTS","not_exists",
1166
"not exists (select * from crash_me where a = 2)",1,0],
1167
["NOT LIKE","not_like","b not like 'b%'",1,0],
1168
["NOT UNIQUE","not_unique",
1169
"not unique (select * from crash_me where a = 2)",1,0],
1170
["UNIQUE","unique","unique (select * from crash_me)",1,0],
1173
@types=(["sql",\@sql_functions,0],
1174
["odbc",\@odbc_functions,0],
1175
["extra",\@extra_functions,0],
1176
["where",\@where_functions,0]);
1178
@group_types=(["sql",\@sql_group_functions,0],
1179
["extra",\@extra_group_functions,0]);
1182
foreach $types (@types)
1184
print "\nSupported $types->[0] functions\n";
1186
foreach $type (@$tmp)
1188
if (defined($limits{"func_$types->[0]_$type->[1]"}))
1192
if ($types->[0] eq "where")
1194
check_and_report("Function $type->[0]","func_$types->[0]_$type->[1]",
1195
[],"select a from crash_me where $type->[2]",[],
1196
$type->[3],$type->[4]);
1198
elsif ($limits{'functions'} eq 'yes')
1200
if (($type->[2] =~ /char_length\(b\)/) && (!$end_query))
1202
my $tmp= $type->[2];
1203
$tmp .= " from crash_me ";
1204
undef($limits{"func_$types->[0]_$type->[1]"});
1205
check_and_report("Function $type->[0]",
1206
"func_$types->[0]_$type->[1]",
1207
[],"select $tmp ",[],
1208
$type->[3],$type->[4]);
1212
undef($limits{"func_$types->[0]_$type->[1]"});
1213
$result = check_and_report("Function $type->[0]",
1214
"func_$types->[0]_$type->[1]",
1215
[],"select $type->[2] $end_query",[],
1216
$type->[3],$type->[4]);
1219
# check without type specifyer
1220
if ($type->[2] =~ /DATE /)
1222
my $tmp= $type->[2];
1224
undef($limits{"func_$types->[0]_$type->[1]"});
1225
$result = check_and_report("Function $type->[0]",
1226
"func_$types->[0]_$type->[1]",
1227
[],"select $tmp $end_query",[],
1228
$type->[3],$type->[4]);
1232
if ($types->[0] eq "odbc" && ! ($type->[2] =~ /\{fn/))
1234
my $tmp= $type->[2];
1235
# Check by converting to ODBC format
1236
undef($limits{"func_$types->[0]_$type->[1]"});
1238
$tmp =~ s/('1997-\d\d-\d\d \d\d:\d\d:\d\d')/{ts $1}/g;
1239
$tmp =~ s/(DATE '1997-\d\d-\d\d')/{d $1}/g;
1240
$tmp =~ s/(TIME '12:13:14')/{t $1}/g;
1243
check_and_report("Function $type->[0]",
1244
"func_$types->[0]_$type->[1]",
1245
[],"select $tmp $end_query",[],
1246
$type->[3],$type->[4]);
1255
if ($limits{'functions'} eq 'yes')
1257
foreach $types (@group_types)
1259
print "\nSupported $types->[0] group functions\n";
1261
foreach $type (@$tmp)
1263
check_and_report("Group function $type->[0]",
1264
"group_func_$types->[0]_$type->[1]",
1265
[],"select $type->[2],a from crash_me group by a",[],
1266
$type->[3],$type->[4]);
1270
report("mixing of integer and float in expression","float_int_expr",
1271
"select 1+1.0 $end_query");
1272
if ($limits{'func_odbc_exp'} eq 'yes')
1274
report("No need to cast from integer to float",
1275
"dont_require_cast_to_float", "select exp(1) $end_query");
1277
check_and_report("Is 1+NULL = NULL","null_num_expr",
1278
[],"select 1+$numeric_null $end_query",[],undef(),4);
1279
$tmp=sql_concat("'a'",$char_null);
1282
check_and_report("Is $tmp = NULL", "null_concat_expr", [],
1283
"select $tmp $end_query",[], undef(),4);
1285
$prompt="Need to cast NULL for arithmetic";
1286
add_log("Need_cast_for_null",
1287
" Check if numeric_null ($numeric_null) is 'NULL'");
1288
save_config_data("Need_cast_for_null",
1289
($numeric_null eq "NULL") ? "no" : "yes",
1300
my $result = 'undefined';
1303
save_incomplete('func_extra_noround','Function NOROUND');
1305
# 1) check if noround() function is supported
1306
$error = safe_query_l('func_extra_noround',"select noround(22.6) $end_query");
1307
if ($error ne 1) # syntax error -- noround is not supported
1311
else # Ok, now check if it really works
1313
$error=safe_query_l('func_extra_noround',
1314
["create table crash_me_nr (a int)",
1315
"insert into crash_me_nr values(noround(10.2))",
1316
"drop table crash_me_nr $drop_attr"]);
1319
$result= "syntax only";
1327
save_config_data('func_extra_noround',$result,"Function NOROUND");
1330
check_parenthesis("func_sql_","CURRENT_USER");
1331
check_parenthesis("func_sql_","SESSION_USER");
1332
check_parenthesis("func_sql_","SYSTEM_USER");
1333
check_parenthesis("func_sql_","USER");
1336
if ($limits{'type_sql_date'} eq 'yes')
1338
# Checking the format of date in result.
1340
safe_query("drop table crash_me_d $drop_attr");
1341
assert_crash("create table crash_me_d (a date)");
1342
# find the example of date
1344
if ($limits{'func_extra_sysdate'} eq 'yes') {
1345
$dateexample=' sysdate() ';
1347
elsif ($limits{'func_sql_current_date'} eq 'yes') {
1348
$dateexample='CURRENT_DATE';
1350
elsif ($limits{'func_odbc_curdate'} eq 'yes') {
1351
$dateexample='curdate()';
1353
elsif ($limits{'func_extra_getdate'} eq 'yes') {
1354
$dateexample='getdate()';
1356
elsif ($limits{'func_odbc_now'} eq 'yes') {
1357
$dateexample='now()';
1360
$dateexample="DATE '1963-08-16'";
1363
my $key = 'date_format_inresult';
1364
my $prompt = "Date format in result";
1365
if (! safe_query_l('date_format_inresult',
1366
"insert into crash_me_d values($dateexample) "))
1368
die "Cannot insert date ($dateexample):".$last_error;
1370
my $sth= $dbh->prepare("select a from crash_me_d");
1371
add_log('date_format_inresult',"< select a from crash_me_d");
1373
$_= $sth->fetchrow_array;
1374
add_log('date_format_inresult',"> $_");
1375
safe_query_l($key,"delete from crash_me_d");
1376
if (/\d{4}-\d{2}-\d{2}/){ save_config_data($key,"iso",$prompt);}
1377
elsif (/\d{2}-\d{2}-\d{2}/){ save_config_data($key,"short iso",$prompt);}
1378
elsif (/\d{2}\.\d{2}\.\d{4}/){ save_config_data($key,"euro",$prompt);}
1379
elsif (/\d{2}\.\d{2}\.\d{2}/){ save_config_data($key,"short euro",$prompt);}
1380
elsif (/\d{2}\/\d{2}\/\d{4}/){ save_config_data($key,"usa",$prompt);}
1381
elsif (/\d{2}\/\d{2}\/\d{2}/){ save_config_data($key,"short usa",$prompt);}
1382
elsif (/\d*/){ save_config_data($key,"YYYYMMDD",$prompt);}
1383
else { save_config_data($key,"unknown",$prompt);};
1386
check_and_report("Supports YYYY-MM-DD (ISO) format","date_format_ISO",
1387
[ "insert into crash_me_d(a) values ('1963-08-16')"],
1388
"select a from crash_me_d",
1389
["delete from crash_me_d"],
1390
make_date_r(1963,8,16),1);
1392
check_and_report("Supports DATE 'YYYY-MM-DD' (ISO) format",
1393
"date_format_ISO_with_date",
1394
[ "insert into crash_me_d(a) values (DATE '1963-08-16')"],
1395
"select a from crash_me_d",
1396
["delete from crash_me_d"],
1397
make_date_r(1963,8,16),1);
1399
check_and_report("Supports DD.MM.YYYY (EUR) format","date_format_EUR",
1400
[ "insert into crash_me_d(a) values ('16.08.1963')"],
1401
"select a from crash_me_d",
1402
["delete from crash_me_d"],
1403
make_date_r(1963,8,16),1);
1404
check_and_report("Supports DATE 'DD.MM.YYYY' (EUR) format",
1405
"date_format_EUR_with_date",
1406
[ "insert into crash_me_d(a) values (DATE '16.08.1963')"],
1407
"select a from crash_me_d",
1408
["delete from crash_me_d"],
1409
make_date_r(1963,8,16),1);
1411
check_and_report("Supports YYYYMMDD format",
1412
"date_format_YYYYMMDD",
1413
[ "insert into crash_me_d(a) values ('19630816')"],
1414
"select a from crash_me_d",
1415
["delete from crash_me_d"],
1416
make_date_r(1963,8,16),1);
1417
check_and_report("Supports DATE 'YYYYMMDD' format",
1418
"date_format_YYYYMMDD_with_date",
1419
[ "insert into crash_me_d(a) values (DATE '19630816')"],
1420
"select a from crash_me_d",
1421
["delete from crash_me_d"],
1422
make_date_r(1963,8,16),1);
1424
check_and_report("Supports MM/DD/YYYY format",
1426
[ "insert into crash_me_d(a) values ('08/16/1963')"],
1427
"select a from crash_me_d",
1428
["delete from crash_me_d"],
1429
make_date_r(1963,8,16),1);
1430
check_and_report("Supports DATE 'MM/DD/YYYY' format",
1431
"date_format_USA_with_date",
1432
[ "insert into crash_me_d(a) values (DATE '08/16/1963')"],
1433
"select a from crash_me_d",
1434
["delete from crash_me_d"],
1435
make_date_r(1963,8,16),1);
1440
check_and_report("Supports 0000-00-00 dates","date_zero",
1441
["create table crash_me2 (a date not null)",
1442
"insert into crash_me2 values (".make_date(0,0,0).")"],
1443
"select a from crash_me2",
1444
["drop table crash_me2 $drop_attr"],
1445
make_date_r(0,0,0),1);
1447
check_and_report("Supports 0001-01-01 dates","date_one",
1448
["create table crash_me2 (a date not null)",
1449
"insert into crash_me2 values (".make_date(1,1,1).")"],
1450
"select a from crash_me2",
1451
["drop table crash_me2 $drop_attr"],
1452
make_date_r(1,1,1),1);
1454
check_and_report("Supports 9999-12-31 dates","date_last",
1455
["create table crash_me2 (a date not null)",
1456
"insert into crash_me2 values (".make_date(9999,12,31).")"],
1457
"select a from crash_me2",
1458
["drop table crash_me2 $drop_attr"],
1459
make_date_r(9999,12,31),1);
1461
check_and_report("Supports 'infinity dates","date_infinity",
1462
["create table crash_me2 (a date not null)",
1463
"insert into crash_me2 values ('infinity')"],
1464
"select a from crash_me2",
1465
["drop table crash_me2 $drop_attr"],
1468
if (!defined($limits{'date_with_YY'}))
1470
check_and_report("Supports YY-MM-DD dates","date_with_YY",
1471
["create table crash_me2 (a date not null)",
1472
"insert into crash_me2 values ('98-03-03')"],
1473
"select a from crash_me2",
1474
["drop table crash_me2 $drop_attr"],
1475
make_date_r(1998,3,3),5);
1476
if ($limits{'date_with_YY'} eq "yes")
1478
undef($limits{'date_with_YY'});
1479
check_and_report("Supports YY-MM-DD 2000 compilant dates",
1481
["create table crash_me2 (a date not null)",
1482
"insert into crash_me2 values ('10-03-03')"],
1483
"select a from crash_me2",
1484
["drop table crash_me2 $drop_attr"],
1485
make_date_r(2010,3,3),5);
1494
save_incomplete('func_odbc_week','WEEK');
1495
$error = safe_query_result_l('func_odbc_week',
1496
"select week(".make_date(1997,2,1).") $end_query",5,0);
1497
# actually this query must return 4 or 5 in the $last_result,
1498
# $error can be 1 (not supported at all) , -1 ( probably USA weeks)
1499
# and 0 - EURO weeks
1501
if ($last_result == 4) {
1505
add_log('func_odbc_week',
1506
" must return 4 or 5, but $last_result");
1508
} elsif ($error == 0) {
1512
save_config_data('func_odbc_week',$result,"WEEK");
1515
my $insert_query ='insert into crash_me_d values('.
1516
make_date(1997,2,1).')';
1517
safe_query($insert_query);
1520
["DAYNAME","dayname","dayname(a)","",2],
1521
["MONTH","month","month(a)","",2],
1522
["MONTHNAME","monthname","monthname(a)","",2],
1523
["DAYOFMONTH","dayofmonth","dayofmonth(a)",1,0],
1524
["DAYOFWEEK","dayofweek","dayofweek(a)",7,0],
1525
["DAYOFYEAR","dayofyear","dayofyear(a)",32,0],
1526
["QUARTER","quarter","quarter(a)",1,0],
1527
["YEAR","year","year(a)",1997,0]))
1529
$prompt='Function '.$fn->[0];
1530
$key='func_odbc_'.$fn->[1];
1531
add_log($key,"< ".$insert_query);
1532
check_and_report($prompt,$key,
1533
[],"select ".$fn->[2]." from crash_me_d",[],
1538
safe_query(['delete from crash_me_d',
1539
'insert into crash_me_d values('.make_date(1963,8,16).')']);
1541
["DATEADD","dateadd","dateadd(day,3,make_date(1997,11,30))",0,2],
1542
["MDY","mdy","mdy(7,1,1998)","make_date_r(1998,07,01)",0], # informix
1543
["DATEDIFF","datediff",
1544
"datediff(month,'Oct 21 1997','Nov 30 1997')",0,2],
1545
["DATENAME","datename","datename(month,'Nov 30 1997')",0,2],
1546
["DATEPART","datepart","datepart(month,'July 20 1997')",0,2],
1547
["DATE_FORMAT","date_format",
1548
"date_format('1997-01-02 03:04:05','M W D Y y m d h i s w')", 0,2],
1549
["FROM_DAYS","from_days",
1550
"from_days(729024)","make_date_r(1996,1,1)",1],
1551
["FROM_UNIXTIME","from_unixtime","from_unixtime(0)",0,2],
1552
["MONTHS_BETWEEN","months_between",
1553
"months_between(make_date(1997,2,2),make_date(1997,1,1))",
1554
"1.03225806",0], # oracle number of months between 2 dates
1555
["PERIOD_ADD","period_add","period_add(9602,-12)",199502,0],
1556
["PERIOD_DIFF","period_diff","period_diff(199505,199404)",13,0],
1557
["WEEKDAY","weekday","weekday(make_date(1997,11,29))",5,0],
1558
["ADDDATE",'adddate',
1559
"ADDDATE(make_date(2002,12,01),3)",'make_date_r(2002,12,04)',0],
1560
["SUBDATE",'subdate',
1561
"SUBDATE(make_date(2002,12,04),3)",'make_date_r(2002,12,01)',0],
1562
["DATEDIFF (2 arg)",'datediff2arg',
1563
"DATEDIFF(make_date(2002,12,04),make_date(2002,12,01))",'3',0],
1564
["WEEKOFYEAR",'weekofyear',
1565
"WEEKOFYEAR(make_date(1963,08,16))",'33',0],
1566
# table crash_me_d must contain record with 1963-08-16 (for CHAR)
1567
["CHAR (conversation date)",'char_date',
1568
"CHAR(a,EUR)",'16.08.1963',0],
1569
["MAKEDATE",'makedate',"MAKEDATE(1963,228)"
1570
,'make_date_r(1963,08,16)',0],
1571
["TO_DAYS","to_days",
1572
"to_days(make_date(1996,01,01))",729024,0],
1573
["ADD_MONTHS","add_months",
1574
"add_months(make_date(1997,01,01),1)","make_date_r(1997,02,01)",0],
1575
# oracle the date plus n months
1576
["LAST_DAY","last_day",
1577
"last_day(make_date(1997,04,01))","make_date_r(1997,04,30)",0],
1578
# oracle last day of month of date
1579
["DATE",'date',"date(make_date(1963,8,16))",
1580
'make_date_r(1963,8,16)',0],
1581
["DAY",'day',"DAY(make_date(2002,12,01))",1,0]))
1583
$prompt='Function '.$fn->[0];
1584
$key='func_extra_'.$fn->[1];
1585
my $qry="select ".$fn->[2]." from crash_me_d";
1586
while( $qry =~ /^(.*)make_date\((\d+),(\d+),(\d+)\)(.*)$/)
1588
my $dt= &make_date($2,$3,$4);
1591
my $result=$fn->[3];
1592
while( $result =~ /^(.*)make_date_r\((\d+),(\d+),(\d+)\)(.*)$/)
1594
my $dt= &make_date_r($2,$3,$4);
1597
check_and_report($prompt,$key,
1604
safe_query("drop table crash_me_d $drop_attr");
1608
if ($limits{'type_sql_time'} eq 'yes')
1610
# Checking the format of date in result.
1612
safe_query("drop table crash_me_t $drop_attr");
1613
assert_crash("create table crash_me_t (a time)");
1614
# find the example of time
1616
if ($limits{'func_sql_current_time'} eq 'yes') {
1617
$timeexample='CURRENT_TIME';
1619
elsif ($limits{'func_odbc_curtime'} eq 'yes') {
1620
$timeexample='curtime()';
1622
elsif ($limits{'func_sql_localtime'} eq 'yes') {
1623
$timeexample='localtime';
1625
elsif ($limits{'func_odbc_now'} eq 'yes') {
1626
$timeexample='now()';
1629
$timeexample="'02:55:12'";
1632
my $key = 'time_format_inresult';
1633
my $prompt = "Time format in result";
1634
if (! safe_query_l('time_format_inresult',
1635
"insert into crash_me_t values($timeexample) "))
1637
die "Cannot insert time ($timeexample):".$last_error;
1639
my $sth= $dbh->prepare("select a from crash_me_t");
1640
add_log('time_format_inresult',"< select a from crash_me_t");
1642
$_= $sth->fetchrow_array;
1643
add_log('time_format_inresult',"> $_");
1644
safe_query_l($key,"delete from crash_me_t");
1645
if (/\d{2}:\d{2}:\d{2}/){ save_config_data($key,"iso",$prompt);}
1646
elsif (/\d{2}\.\d{2}\.\d{2}/){ save_config_data($key,"euro",$prompt);}
1647
elsif (/\d{2}:\d{2}\s+(AM|PM)/i){ save_config_data($key,"usa",$prompt);}
1648
elsif (/\d{8}$/){ save_config_data($key,"HHHHMMSS",$prompt);}
1649
elsif (/\d{4}$/){ save_config_data($key,"HHMMSS",$prompt);}
1650
else { save_config_data($key,"unknown",$prompt);};
1653
check_and_report("Supports HH:MM:SS (ISO) time format","time_format_ISO",
1654
[ "insert into crash_me_t(a) values ('20:08:16')"],
1655
"select a from crash_me_t",
1656
["delete from crash_me_t"],
1657
make_time_r(20,8,16),1);
1659
check_and_report("Supports HH.MM.SS (EUR) time format","time_format_EUR",
1660
[ "insert into crash_me_t(a) values ('20.08.16')"],
1661
"select a from crash_me_t",
1662
["delete from crash_me_t"],
1663
make_time_r(20,8,16),1);
1665
check_and_report("Supports HHHHmmSS time format",
1666
"time_format_HHHHMMSS",
1667
[ "insert into crash_me_t(a) values ('00200816')"],
1668
"select a from crash_me_t",
1669
["delete from crash_me_t"],
1670
make_time_r(20,8,16),1);
1672
check_and_report("Supports HHmmSS time format",
1673
"time_format_HHHHMMSS",
1674
[ "insert into crash_me_t(a) values ('200816')"],
1675
"select a from crash_me_t",
1676
["delete from crash_me_t"],
1677
make_time_r(20,8,16),1);
1679
check_and_report("Supports HH:MM:SS (AM|PM) time format",
1681
[ "insert into crash_me_t(a) values ('08:08:16 PM')"],
1682
"select a from crash_me_t",
1683
["delete from crash_me_t"],
1684
make_time_r(20,8,16),1);
1686
my $insert_query ='insert into crash_me_t values('.
1687
make_time(20,8,16).')';
1688
safe_query($insert_query);
1691
["HOUR","hour","hour('".make_time(12,13,14)."')",12,0],
1692
["ANSI HOUR","hour_time","hour(TIME '".make_time(12,13,14)."')",12,0],
1693
["MINUTE","minute","minute('".make_time(12,13,14)."')",13,0],
1694
["SECOND","second","second('".make_time(12,13,14)."')",14,0]
1698
$prompt='Function '.$fn->[0];
1699
$key='func_odbc_'.$fn->[1];
1700
add_log($key,"< ".$insert_query);
1701
check_and_report($prompt,$key,
1702
[],"select ".$fn->[2]." $end_query",[],
1707
# safe_query(['delete from crash_me_t',
1708
# 'insert into crash_me_t values('.make_time(20,8,16).')']);
1710
["TIME_TO_SEC","time_to_sec","time_to_sec('".
1711
make_time(1,23,21)."')","5001",0],
1712
["SEC_TO_TIME","sec_to_time","sec_to_time(5001)",
1713
make_time_r(01,23,21),1],
1714
["ADDTIME",'addtime',"ADDTIME('".make_time(20,2,12).
1715
"','".make_time(0,0,3)."')",make_time_r(20,2,15),0],
1716
["SUBTIME",'subtime',"SUBTIME('".make_time(20,2,15)
1717
."','".make_time(0,0,3)."')",make_time_r(20,2,12),0],
1718
["TIMEDIFF",'timediff',"TIMEDIFF('".make_time(20,2,15)."','".
1719
make_time(20,2,12)."')",make_time_r(0,0,3),0],
1720
["MAKETIME",'maketime',"MAKETIME(20,02,12)",make_time_r(20,2,12),0],
1721
["TIME",'time',"time('".make_time(20,2,12)."')",make_time_r(20,2,12),0]
1724
$prompt='Function '.$fn->[0];
1725
$key='func_extra_'.$fn->[1];
1726
my $qry="select ".$fn->[2]." $end_query";
1727
my $result=$fn->[3];
1728
check_and_report($prompt,$key,
1735
safe_query("drop table crash_me_t $drop_attr");
1740
# NOT id BETWEEN a and b
1741
if ($limits{'func_where_not_between'} eq 'yes')
1743
my $result = 'error';
1745
my $key='not_id_between';
1746
my $prompt='NOT ID BETWEEN interprets as ID NOT BETWEEN';
1748
save_incomplete($key,$prompt);
1749
safe_query_l($key,["create table crash_me_b (i int)",
1750
"insert into crash_me_b values(2)",
1751
"insert into crash_me_b values(5)"]);
1752
$err =safe_query_result_l($key,
1753
"select i from crash_me_b where not i between 1 and 3",
1756
if (not defined($last_result)) {
1763
safe_query_l($key,["drop table crash_me_b"]);
1764
save_config_data($key,$result,$prompt);
1771
report("LIKE on numbers","like_with_number",
1772
"create table crash_q (a int,b int)",
1773
"insert into crash_q values(10,10)",
1774
"select * from crash_q where a like '10'",
1775
"drop table crash_q $drop_attr");
1777
report("column LIKE column","like_with_column",
1778
"create table crash_q (a char(10),b char(10))",
1779
"insert into crash_q values('abc','abc')",
1780
"select * from crash_q where a like b",
1781
"drop table crash_q $drop_attr");
1783
report("update of column= -column","NEG",
1784
"create table crash_q (a integer)",
1785
"insert into crash_q values(10)",
1786
"update crash_q set a=-a",
1787
"drop table crash_q $drop_attr");
1789
if ($limits{'func_odbc_left'} eq 'yes' ||
1790
$limits{'func_odbc_substring'} eq 'yes')
1792
my $type= ($limits{'func_odbc_left'} eq 'yes' ?
1793
"left(a,4)" : "substring(a for 4)");
1795
check_and_report("String functions on date columns","date_as_string",
1796
["create table crash_me2 (a date not null)",
1797
"insert into crash_me2 values ('1998-03-03')"],
1798
"select $type from crash_me2",
1799
["drop table crash_me2 $drop_attr"],
1804
$tmp=sql_concat("b","b");
1807
check_and_report("char are space filled","char_is_space_filled",
1808
[],"select $tmp from crash_me where b = 'a '",[],
1812
if (!defined($limits{'multi_table_update'}))
1814
if (check_and_report("Update with many tables","multi_table_update",
1815
["create table crash_q (a integer,b char(10))",
1816
"insert into crash_q values(1,'c')",
1817
"update crash_q left join crash_me on crash_q.a=crash_me.a set crash_q.b=crash_me.b"],
1818
"select b from crash_q",
1819
["drop table crash_q $drop_attr"],
1822
check_and_report("Update with many tables","multi_table_update",
1823
["create table crash_q (a integer,b char(10))",
1824
"insert into crash_q values(1,'c')",
1825
"update crash_q,crash_me set crash_q.b=crash_me.b ".
1826
"where crash_q.a=crash_me.a"],
1827
"select b from crash_q",
1828
["drop table crash_q $drop_attr"],
1834
report("DELETE FROM table1,table2...","multi_table_delete",
1835
"create table crash_q (a integer,b char(10))",
1836
"insert into crash_q values(1,'c')",
1837
"delete crash_q.* from crash_q,crash_me where crash_q.a=crash_me.a",
1838
"drop table crash_q $drop_attr");
1840
check_and_report("Update with sub select","select_table_update",
1841
["create table crash_q (a integer,b char(10))",
1842
"insert into crash_q values(1,'c')",
1843
"update crash_q set b= ".
1844
"(select b from crash_me where crash_q.a = crash_me.a)"],
1845
"select b from crash_q",
1846
["drop table crash_q $drop_attr"],
1849
check_and_report("Calculate 1--1","minus_neg",[],
1850
"select a--1 from crash_me",[],0,2);
1852
report("ANSI SQL simple joins","simple_joins",
1853
"select crash_me.a from crash_me, crash_me t0");
1856
# Check max string size, and expression limits
1859
foreach $type (('mediumtext','text','text()','blob','long'))
1861
if ($limits{"type_extra_$type"} eq 'yes')
1867
if (defined($found))
1869
$found =~ s/\(\)/\(%d\)/;
1870
find_limit("max text or blob size","max_text_size",
1871
new query_many(["create table crash_q (q $found)",
1872
"insert into crash_q values ('%s')"],
1873
"select * from crash_q","%s",
1874
["drop table crash_q $drop_attr"],
1875
min($max_string_size,$limits{'query_size'}-30)));
1879
# It doesn't make lots of sense to check for string lengths much bigger than
1880
# what can be stored...
1882
find_limit(($prompt="constant string size in where"),"where_string_size",
1883
new query_repeat([],"select a from crash_me where b >='",
1885
if ($limits{'where_string_size'} == 10)
1887
save_config_data('where_string_size','nonstandard',$prompt);
1890
if ($limits{'select_constants'} eq 'yes')
1892
find_limit("constant string size in SELECT","select_string_size",
1893
new query_repeat([],"select '","","","a","","'$end_query"));
1896
goto no_functions if ($limits{'functions'} ne "yes");
1898
if ($limits{'func_odbc_repeat'} eq 'yes')
1900
find_limit("return string size from function","repeat_string_size",
1902
"select repeat('a',%d) $end_query","%s",
1904
$max_string_size,0));
1907
$tmp=find_limit("simple expressions","max_expressions",
1908
new query_repeat([],"select 1","","","+1","",$end_query,
1909
undef(),$max_expressions));
1913
$tmp= "(1" . ( '+1' x ($tmp-10) ) . ")";
1914
find_limit("big expressions", "max_big_expressions",
1915
new query_repeat([],"select 0","","","+$tmp","",$end_query,
1916
undef(),$max_big_expressions));
1919
find_limit("stacked expressions", "max_stack_expression",
1920
new query_repeat([],"select 1","","","+(1",")",$end_query,
1921
undef(),$max_stacked_expressions));
1925
if (!defined($limits{'max_conditions'}))
1927
find_limit("OR and AND in WHERE","max_conditions",
1928
new query_repeat([],
1929
"select a from crash_me where a=1 and b='a'","",
1930
"", " or a=%d and b='%d'","","","",
1931
[],($query_size-42)/29,undef,2));
1932
$limits{'max_conditions'}*=2;
1934
# The 42 is the length of the constant part.
1935
# The 29 is the length of the variable part, plus two seven-digit numbers.
1937
find_limit("tables in join", "join_tables",
1938
new query_repeat([],
1939
"select crash_me.a",",t%d.a","from crash_me",
1940
",crash_me t%d","","",[],$max_join_tables,undef,
1943
# Different CREATE TABLE options
1945
report("primary key in create table",'primary_key_in_create',
1946
"create table crash_q (q integer not null,primary key (q))",
1947
"drop table crash_q $drop_attr");
1949
report("unique in create table",'unique_in_create',
1950
"create table crash_q (q integer not null,unique (q))",
1951
"drop table crash_q $drop_attr");
1953
if ($limits{'unique_in_create'} eq 'yes')
1955
report("unique null in create",'unique_null_in_create',
1956
"create table crash_q (q integer,unique (q))",
1957
"insert into crash_q (q) values (NULL)",
1958
"insert into crash_q (q) values (NULL)",
1959
"insert into crash_q (q) values (1)",
1960
"drop table crash_q $drop_attr");
1963
report("default value for column",'create_default',
1964
"create table crash_q (q integer default 10 not null)",
1965
"drop table crash_q $drop_attr");
1967
report("default value function for column",'create_default_func',
1968
"create table crash_q (q integer not null,q1 integer default (1+1))",
1969
"drop table crash_q $drop_attr");
1971
report("temporary tables",'temporary_table',
1972
"create temporary table crash_q (q integer not null)",
1973
"drop table crash_q $drop_attr");
1975
report_one("create table from select",'create_table_select',
1976
[["create table crash_q SELECT * from crash_me","yes"],
1977
["create table crash_q AS SELECT * from crash_me","with AS"]]);
1978
$dbh->do("drop table crash_q $drop_attr");
1980
report("index in create table",'index_in_create',
1981
"create table crash_q (q integer not null,index (q))",
1982
"drop table crash_q $drop_attr");
1984
# The following must be executed as we need the value of end_drop_keyword
1986
if (!(defined($limits{'create_index'}) && defined($limits{'drop_index'})))
1988
if ($res=safe_query_l('create_index',"create index crash_q on crash_me (a)"))
1992
$end_drop_keyword="";
1993
if (!safe_query_l('drop_index',"drop index crash_q"))
1995
# Can't drop the standard way; Check if mSQL
1996
if (safe_query_l('drop_index',"drop index crash_q from crash_me"))
1998
$drop_res="with 'FROM'"; # Drop is not ANSI SQL
1999
$end_drop_keyword="drop index %i from %t";
2001
# else check if Access or MySQL
2002
elsif (safe_query_l('drop_index',"drop index crash_q on crash_me"))
2004
$drop_res="with 'ON'"; # Drop is not ANSI SQL
2005
$end_drop_keyword="drop index %i on %t";
2007
# else check if MS-SQL
2008
elsif (safe_query_l('drop_index',"drop index crash_me.crash_q"))
2010
$drop_res="with 'table.index'"; # Drop is not ANSI SQL
2011
$end_drop_keyword="drop index %t.%i";
2016
# Old MySQL 3.21 supports only the create index syntax
2017
# This means that the second create doesn't give an error.
2018
$res=safe_query_l('create_index',["create index crash_q on crash_me (a)",
2019
"create index crash_q on crash_me (a)",
2020
"drop index crash_q"]);
2021
$res= $res ? 'ignored' : 'yes';
2026
$drop_res=$res='no';
2028
save_config_data('create_index',$res,"create index");
2029
save_config_data('drop_index',$drop_res,"drop index");
2031
print "create index: $limits{'create_index'}\n";
2032
print "drop index: $limits{'drop_index'}\n";
2035
# check if we can have 'NULL' as a key
2036
check_and_report("null in index","null_in_index",
2037
[create_table("crash_q",["a char(10)"],["(a)"]),
2038
"insert into crash_q values (NULL)"],
2039
"select * from crash_q",
2040
["drop table crash_q $drop_attr"],
2043
if ($limits{'unique_in_create'} eq 'yes')
2045
report("null in unique index",'null_in_unique',
2046
create_table("crash_q",["q integer"],["unique(q)"]),
2047
"insert into crash_q (q) values(NULL)",
2048
"insert into crash_q (q) values(NULL)",
2049
"drop table crash_q $drop_attr");
2050
report("null combination in unique index",'nulls_in_unique',
2051
create_table("crash_q",["q integer,q1 integer"],["unique(q,q1)"]),
2052
"insert into crash_q (q,q1) values(1,NULL)",
2053
"insert into crash_q (q,q1) values(1,NULL)",
2054
"drop table crash_q $drop_attr");
2057
if ($limits{'null_in_unique'} eq 'yes')
2059
report("null in unique index",'multi_null_in_unique',
2060
create_table("crash_q",["q integer, x integer"],["unique(q)"]),
2061
"insert into crash_q(x) values(1)",
2062
"insert into crash_q(x) values(2)",
2063
"drop table crash_q $drop_attr");
2066
if ($limits{'create_index'} ne 'no')
2068
$end_drop=$end_drop_keyword;
2069
$end_drop =~ s/%i/crash_q/;
2070
$end_drop =~ s/%t/crash_me/;
2071
report("index on column part (extension)","index_parts",,
2072
"create index crash_q on crash_me (b(5))",
2074
$end_drop=$end_drop_keyword;
2075
$end_drop =~ s/%i/crash_me/;
2076
$end_drop =~ s/%t/crash_me/;
2077
report("different namespace for index",
2079
"create index crash_me on crash_me (b)",
2083
if (!report("case independent table names","table_name_case",
2084
"create table crash_q (q integer)",
2085
"drop table CRASH_Q $drop_attr"))
2087
safe_query("drop table crash_q $drop_attr");
2090
if (!report("case independent field names","field_name_case",
2091
"create table crash_q (q integer)",
2092
"insert into crash_q(Q) values (1)",
2093
"drop table crash_q $drop_attr"))
2095
safe_query("drop table crash_q $drop_attr");
2098
if (!report("drop table if exists","drop_if_exists",
2099
"create table crash_q (q integer)",
2100
"drop table if exists crash_q $drop_attr"))
2102
safe_query("drop table crash_q $drop_attr");
2105
report("create table if not exists","create_if_not_exists",
2106
"create table crash_q (q integer)",
2107
"create table if not exists crash_q (q integer)");
2108
safe_query("drop table crash_q $drop_attr");
2111
# test of different join types
2114
assert_crash("create table crash_me2 (a integer not null,b char(10) not null,".
2116
assert_crash("insert into crash_me2 (a,b,c1) values (1,'b',1)");
2117
assert_crash("create table crash_me3 (a integer not null,b char(10) not null)");
2118
assert_crash("insert into crash_me3 (a,b) values (1,'b')");
2120
report("inner join","inner_join",
2121
"select crash_me.a from crash_me inner join crash_me2 ON ".
2122
"crash_me.a=crash_me2.a");
2123
report("left outer join","left_outer_join",
2124
"select crash_me.a from crash_me left join crash_me2 ON ".
2125
"crash_me.a=crash_me2.a");
2126
report("natural left outer join","natural_left_outer_join",
2127
"select c1 from crash_me natural left join crash_me2");
2128
report("left outer join using","left_outer_join_using",
2129
"select c1 from crash_me left join crash_me2 using (a)");
2130
report("left outer join odbc style","odbc_left_outer_join",
2131
"select crash_me.a from { oj crash_me left outer join crash_me2 ON".
2132
" crash_me.a=crash_me2.a }");
2133
report("right outer join","right_outer_join",
2134
"select crash_me.a from crash_me right join crash_me2 ON ".
2135
"crash_me.a=crash_me2.a");
2136
report("full outer join","full_outer_join",
2137
"select crash_me.a from crash_me full join crash_me2 ON "."
2138
crash_me.a=crash_me2.a");
2139
report("cross join (same as from a,b)","cross_join",
2140
"select crash_me.a from crash_me cross join crash_me3");
2141
report("natural join","natural_join",
2142
"select * from crash_me natural join crash_me3");
2143
report("union","union",
2144
"select * from crash_me union select a,b from crash_me3");
2145
report("union all","union_all",
2146
"select * from crash_me union all select a,b from crash_me3");
2147
report("intersect","intersect",
2148
"select * from crash_me intersect select * from crash_me3");
2149
report("intersect all","intersect_all",
2150
"select * from crash_me intersect all select * from crash_me3");
2151
report("except","except",
2152
"select * from crash_me except select * from crash_me3");
2153
report("except all","except_all",
2154
"select * from crash_me except all select * from crash_me3");
2155
report("except","except",
2156
"select * from crash_me except select * from crash_me3");
2157
report("except all","except_all",
2158
"select * from crash_me except all select * from crash_me3");
2159
report("minus","minus",
2160
"select * from crash_me minus select * from crash_me3"); # oracle ...
2162
report("natural join (incompatible lists)","natural_join_incompat",
2163
"select c1 from crash_me natural join crash_me2");
2164
report("union (incompatible lists)","union_incompat",
2165
"select * from crash_me union select a,b from crash_me2");
2166
report("union all (incompatible lists)","union_all_incompat",
2167
"select * from crash_me union all select a,b from crash_me2");
2168
report("intersect (incompatible lists)","intersect_incompat",
2169
"select * from crash_me intersect select * from crash_me2");
2170
report("intersect all (incompatible lists)","intersect_all_incompat",
2171
"select * from crash_me intersect all select * from crash_me2");
2172
report("except (incompatible lists)","except_incompat",
2173
"select * from crash_me except select * from crash_me2");
2174
report("except all (incompatible lists)","except_all_incompat",
2175
"select * from crash_me except all select * from crash_me2");
2176
report("except (incompatible lists)","except_incompat",
2177
"select * from crash_me except select * from crash_me2");
2178
report("except all (incompatible lists)","except_all_incompat",
2179
"select * from crash_me except all select * from crash_me2");
2180
report("minus (incompatible lists)","minus_incompat",
2181
"select * from crash_me minus select * from crash_me2"); # oracle ...
2183
assert_crash("drop table crash_me2 $drop_attr");
2184
assert_crash("drop table crash_me3 $drop_attr");
2186
# somethings to be added here ....
2187
# FOR UNION - INTERSECT - EXCEPT -> CORRESPONDING [ BY ]
2189
# >ALL | ANY | SOME - EXISTS - UNIQUE
2191
if (report("subqueries","subqueries",
2192
"select a from crash_me where crash_me.a in ".
2193
"(select max(a) from crash_me)"))
2195
$tmp=new query_repeat([],"select a from crash_me","","",
2196
" where a in (select a from crash_me",")",
2197
"",[],$max_join_tables);
2198
find_limit("recursive subqueries", "recursive_subqueries",$tmp);
2201
report("insert INTO ... SELECT ...","insert_select",
2202
"create table crash_q (a int)",
2203
"insert into crash_q (a) SELECT crash_me.a from crash_me",
2204
"drop table crash_q $drop_attr");
2206
if (!defined($limits{"transactions"}))
2209
$limit="transactions";
2210
$limit_r="rollback_metadata";
2212
foreach $type (('', 'type=bdb', 'type=innodb', 'type=gemini'))
2214
undef($limits{$limit});
2215
if (!report_trans($limit,
2216
[create_table("crash_q",["a integer not null"],[],
2218
"insert into crash_q values (1)"],
2219
"select * from crash_q",
2220
"drop table crash_q $drop_attr"
2223
report_rollback($limit_r,
2224
[create_table("crash_q",["a integer not null"],[],
2226
"insert into crash_q values (1)",
2227
"drop table crash_q $drop_attr" );
2231
print "$limits{$limit}\n";
2232
print "$limit_r: $limits{$limit_r}\n";
2235
report("atomic updates","atomic_updates",
2236
create_table("crash_q",["a integer not null"],["primary key (a)"]),
2237
"insert into crash_q values (2)",
2238
"insert into crash_q values (3)",
2239
"insert into crash_q values (1)",
2240
"update crash_q set a=a+1",
2241
"drop table crash_q $drop_attr");
2243
if ($limits{'atomic_updates'} eq 'yes')
2245
report_fail("atomic_updates_with_rollback","atomic_updates_with_rollback",
2246
create_table("crash_q",["a integer not null"],
2247
["primary key (a)"]),
2248
"insert into crash_q values (2)",
2249
"insert into crash_q values (3)",
2250
"insert into crash_q values (1)",
2251
"update crash_q set a=a+1 where a < 3",
2252
"drop table crash_q $drop_attr");
2255
# To add with the views:
2256
# DROP VIEW - CREAT VIEW *** [ WITH [ CASCADE | LOCAL ] CHECK OPTION ]
2257
report("views","views",
2258
"create view crash_q as select a from crash_me",
2259
"drop view crash_q $drop_attr");
2263
my $result = 'undefined';
2265
print "foreign keys: ";
2266
save_incomplete('foreign_key','foreign keys');
2268
# 1) check if foreign keys are supported
2269
safe_query_l('foreign_key',
2270
create_table("crash_me_qf",
2271
["a integer not null"],
2272
["primary key (a)"]));
2273
$error= safe_query_l('foreign_key',
2274
create_table("crash_me_qf2",
2275
["a integer not null",
2276
"foreign key (a) references crash_me_qf (a)"],
2279
if ($error == 1) # OK -- syntax is supported
2282
# now check if foreign key really works
2283
safe_query_l('foreign_key', "insert into crash_me_qf values (1)");
2284
if (safe_query_l('foreign_key', "insert into crash_me_qf2 values (2)") eq 1)
2286
$result = 'syntax only';
2297
safe_query_l('foreign_key', "drop table crash_me_qf2 $drop_attr");
2298
safe_query_l('foreign_key', "drop table crash_me_qf $drop_attr");
2300
save_config_data('foreign_key',$result,"foreign keys");
2303
if ($limits{'foreign_key'} eq 'yes')
2305
report("allows to update of foreign key values",'foreign_update',
2306
"create table crash_me1 (a int not null primary key)",
2307
"create table crash_me2 (a int not null," .
2308
" foreign key (a) references crash_me1 (a))",
2309
"insert into crash_me1 values (1)",
2310
"insert into crash_me2 values (1)",
2311
"update crash_me1 set a = 2", ## <- must fail
2312
"drop table crash_me2 $drop_attr",
2313
"drop table crash_me1 $drop_attr"
2317
report("Create SCHEMA","create_schema",
2318
"create schema crash_schema create table crash_q (a int) ".
2319
"create table crash_q2(b int)",
2320
"drop schema crash_schema cascade");
2322
if ($limits{'foreign_key'} eq 'yes')
2324
if ($limits{'create_schema'} eq 'yes')
2326
report("Circular foreign keys","foreign_key_circular",
2327
"create schema crash_schema create table crash_q ".
2328
"(a int primary key, b int, foreign key (b) references ".
2329
"crash_q2(a)) create table crash_q2(a int, b int, ".
2330
"primary key(a), foreign key (b) references crash_q(a))",
2331
"drop schema crash_schema cascade");
2335
if ($limits{'func_sql_character_length'} eq 'yes')
2337
my $result = 'error';
2339
my $key = 'length_of_varchar_field';
2340
my $prompt='CHARACTER_LENGTH(varchar_field)';
2341
print $prompt," = ";
2342
if (!defined($limits{$key})) {
2343
save_incomplete($key,$prompt);
2345
"CREATE TABLE crash_me1 (S1 VARCHAR(100))",
2346
"INSERT INTO crash_me1 VALUES ('X')"
2348
my $recset = get_recordset($key,
2349
"SELECT CHARACTER_LENGTH(S1) FROM crash_me1");
2350
print_recordset($key,$recset);
2351
if (defined($recset)){
2352
if ( $recset->[0][0] eq 1 ) {
2353
$result = 'actual length';
2354
} elsif( $recset->[0][0] eq 100 ) {
2355
$result = 'defined length';
2358
add_log($key,$DBI::errstr);
2360
safe_query_l($key, "drop table crash_me1 $drop_attr");
2361
save_config_data($key,$result,$prompt);
2363
$result = $limits{$key};
2369
check_constraint("Column constraints","constraint_check",
2370
"create table crash_q (a int check (a>0))",
2371
"insert into crash_q values(0)",
2372
"drop table crash_q $drop_attr");
2375
check_constraint("Table constraints","constraint_check_table",
2376
"create table crash_q (a int ,b int, check (a>b))",
2377
"insert into crash_q values(0,0)",
2378
"drop table crash_q $drop_attr");
2380
check_constraint("Named constraints","constraint_check_named",
2381
"create table crash_q (a int ,b int, constraint abc check (a>b))",
2382
"insert into crash_q values(0,0)",
2383
"drop table crash_q $drop_attr");
2386
report("NULL constraint (SyBase style)","constraint_null",
2387
"create table crash_q (a int null)",
2388
"drop table crash_q $drop_attr");
2390
report("Triggers (ANSI SQL)","psm_trigger",
2391
"create table crash_q (a int ,b int)",
2392
"create trigger crash_trigger after insert on crash_q referencing ".
2393
"new table as new_a when (localtime > time '18:00:00') ".
2395
"insert into crash_q values(1,2)",
2396
"drop trigger crash_trigger",
2397
"drop table crash_q $drop_attr");
2399
report("PSM procedures (ANSI SQL)","psm_procedures",
2400
"create table crash_q (a int,b int)",
2401
"create procedure crash_proc(in a1 int, in b1 int) language ".
2402
"sql modifies sql data begin declare c1 int; set c1 = a1 + b1;".
2403
" insert into crash_q(a,b) values (a1,c1); end",
2404
"call crash_proc(1,10)",
2405
"drop procedure crash_proc",
2406
"drop table crash_q $drop_attr");
2408
report("PSM modules (ANSI SQL)","psm_modules",
2409
"create table crash_q (a int,b int)",
2410
"create module crash_m declare procedure ".
2411
"crash_proc(in a1 int, in b1 int) language sql modifies sql ".
2412
"data begin declare c1 int; set c1 = a1 + b1; ".
2413
"insert into crash_q(a,b) values (a1,c1); end; ".
2414
"declare procedure crash_proc2(INOUT a int, in b int) ".
2415
"contains sql set a = b + 10; end module",
2416
"call crash_proc(1,10)",
2417
"drop module crash_m cascade",
2418
"drop table crash_q cascade $drop_attr");
2420
report("PSM functions (ANSI SQL)","psm_functions",
2421
"create table crash_q (a int)",
2422
"create function crash_func(in a1 int, in b1 int) returns int".
2423
" language sql deterministic contains sql ".
2424
" begin return a1 * b1; end",
2425
"insert into crash_q values(crash_func(2,4))",
2426
"select a,crash_func(a,2) from crash_q",
2427
"drop function crash_func cascade",
2428
"drop table crash_q $drop_attr");
2430
report("Domains (ANSI SQL)","domains",
2431
"create domain crash_d as varchar(10) default 'Empty' ".
2432
"check (value <> 'abcd')",
2433
"create table crash_q(a crash_d, b int)",
2434
"insert into crash_q(a,b) values('xyz',10)",
2435
"insert into crash_q(b) values(10)",
2436
"drop table crash_q $drop_attr",
2437
"drop domain crash_d");
2440
if (!defined($limits{'lock_tables'}))
2442
report("lock table","lock_tables",
2443
"lock table crash_me READ",
2445
if ($limits{'lock_tables'} eq 'no')
2447
delete $limits{'lock_tables'};
2448
report("lock table","lock_tables",
2449
"lock table crash_me IN SHARE MODE");
2453
if (!report("many tables to drop table","multi_drop",
2454
"create table crash_q (a int)",
2455
"create table crash_q2 (a int)",
2456
"drop table crash_q,crash_q2 $drop_attr"))
2458
$dbh->do("drop table crash_q $drop_attr");
2459
$dbh->do("drop table crash_q2 $drop_attr");
2462
if (!report("drop table with cascade/restrict","drop_restrict",
2463
"create table crash_q (a int)",
2464
"drop table crash_q restrict"))
2466
$dbh->do("drop table crash_q $drop_attr");
2470
report("-- as comment (ANSI)","comment_--",
2471
"select * from crash_me -- Testing of comments");
2472
report("// as comment","comment_//",
2473
"select * from crash_me // Testing of comments");
2474
report("# as comment","comment_#",
2475
"select * from crash_me # Testing of comments");
2476
report("/* */ as comment","comment_/**/",
2477
"select * from crash_me /* Testing of comments */");
2480
# Check things that fails one some servers
2483
# Empress can't insert empty strings in a char() field
2484
report("insert empty string","insert_empty_string",
2485
create_table("crash_q",["a char(10) not null,b char(10)"],[]),
2486
"insert into crash_q values ('','')",
2487
"drop table crash_q $drop_attr");
2489
report("Having with alias","having_with_alias",
2490
create_table("crash_q",["a integer"],[]),
2491
"insert into crash_q values (10)",
2492
"select sum(a) as b from crash_q group by a having b > 0",
2493
"drop table crash_q $drop_attr");
2499
find_limit("table name length","max_table_name",
2500
new query_many(["create table crash_q%s (q integer)",
2501
"insert into crash_q%s values(1)"],
2502
"select * from crash_q%s",1,
2503
["drop table crash_q%s $drop_attr"],
2504
$max_name_length,7,1));
2506
find_limit("column name length","max_column_name",
2507
new query_many(["create table crash_q (q%s integer)",
2508
"insert into crash_q (q%s) values(1)"],
2509
"select q%s from crash_q",1,
2510
["drop table crash_q $drop_attr"],
2511
$max_name_length,1));
2513
if ($limits{'column_alias'} eq 'yes')
2515
find_limit("select alias name length","max_select_alias_name",
2516
new query_many(undef,
2517
"select b as %s from crash_me",undef,
2518
undef, $max_name_length));
2521
find_limit("table alias name length","max_table_alias_name",
2522
new query_many(undef,
2523
"select %s.b from crash_me %s",
2525
undef, $max_name_length));
2527
$end_drop_keyword = "drop index %i" if (!$end_drop_keyword);
2528
$end_drop=$end_drop_keyword;
2529
$end_drop =~ s/%i/crash_q%s/;
2530
$end_drop =~ s/%t/crash_me/;
2532
if ($limits{'create_index'} ne 'no')
2534
find_limit("index name length","max_index_name",
2535
new query_many(["create index crash_q%s on crash_me (a)"],
2538
$max_name_length,7));
2541
find_limit("max char() size","max_char_size",
2542
new query_many(["create table crash_q (q char(%d))",
2543
"insert into crash_q values ('%s')"],
2544
"select * from crash_q","%s",
2545
["drop table crash_q $drop_attr"],
2546
min($max_string_size,$limits{'query_size'})));
2548
if ($limits{'type_sql_varchar(1_arg)'} eq 'yes')
2550
find_limit("max varchar() size","max_varchar_size",
2551
new query_many(["create table crash_q (q varchar(%d))",
2552
"insert into crash_q values ('%s')"],
2553
"select * from crash_q","%s",
2554
["drop table crash_q $drop_attr"],
2555
min($max_string_size,$limits{'query_size'})));
2559
foreach $type (('mediumtext','text','text()','blob','long'))
2561
if ($limits{"type_extra_$type"} eq 'yes')
2567
if (defined($found))
2569
$found =~ s/\(\)/\(%d\)/;
2570
find_limit("max text or blob size","max_text_size",
2571
new query_many(["create table crash_q (q $found)",
2572
"insert into crash_q values ('%s')"],
2573
"select * from crash_q","%s",
2574
["drop table crash_q $drop_attr"],
2575
min($max_string_size,$limits{'query_size'}-30)));
2579
$tmp=new query_repeat([],"create table crash_q (a integer","","",
2580
",a%d integer","",")",["drop table crash_q $drop_attr"],
2583
find_limit("Columns in table","max_columns",$tmp);
2585
# Make a field definition to be used when testing keys
2587
$key_definitions="q0 integer not null";
2589
for ($i=1; $i < min($limits{'max_columns'},$max_keys) ; $i++)
2591
$key_definitions.=",q$i integer not null";
2592
$key_fields.=",q$i";
2594
$key_values="1," x $i;
2597
if ($limits{'unique_in_create'} eq 'yes')
2599
find_limit("unique indexes","max_unique_index",
2600
new query_table("create table crash_q (q integer",
2601
",q%d integer not null,unique (q%d)",")",
2602
["insert into crash_q (q,%f) values (1,%v)"],
2603
"select q from crash_q",1,
2604
"drop table crash_q $drop_attr",
2607
find_limit("index parts","max_index_parts",
2608
new query_table("create table crash_q ".
2609
"($key_definitions,unique (q0",
2611
["insert into crash_q ($key_fields) values ($key_values)"],
2612
"select q0 from crash_q",1,
2613
"drop table crash_q $drop_attr",
2616
find_limit("max index part length","max_index_part_length",
2617
new query_many(["create table crash_q (q char(%d) not null,".
2619
"insert into crash_q (q) values ('%s')"],
2620
"select q from crash_q","%s",
2621
["drop table crash_q $drop_attr"],
2622
$limits{'max_char_size'},0));
2624
if ($limits{'type_sql_varchar(1_arg)'} eq 'yes')
2626
find_limit("index varchar part length","max_index_varchar_part_length",
2627
new query_many(["create table crash_q (q varchar(%d) not null,".
2629
"insert into crash_q (q) values ('%s')"],
2630
"select q from crash_q","%s",
2631
["drop table crash_q $drop_attr"],
2632
$limits{'max_varchar_size'},0));
2637
if ($limits{'create_index'} ne 'no')
2639
if ($limits{'create_index'} eq 'ignored' ||
2640
$limits{'unique_in_create'} eq 'yes')
2641
{ # This should be true
2642
add_log('max_index',
2643
" max_unique_index=$limits{'max_unique_index'} ,".
2644
"so max_index must be same");
2645
save_config_data('max_index',$limits{'max_unique_index'},"max index");
2646
print "indexes: $limits{'max_index'}\n";
2650
if (!defined($limits{'max_index'}))
2652
safe_query_l('max_index',"create table crash_q ($key_definitions)");
2653
for ($i=1; $i <= min($limits{'max_columns'},$max_keys) ; $i++)
2655
last if (!safe_query_l('max_index',
2656
"create index crash_q$i on crash_q (q$i)"));
2658
save_config_data('max_index',$i == $max_keys ? $max_keys : $i,
2662
$end_drop=$end_drop_keyword;
2663
$end_drop =~ s/%i/crash_q$i/;
2664
$end_drop =~ s/%t/crash_q/;
2665
assert_crash($end_drop);
2667
assert_crash("drop table crash_q $drop_attr");
2669
print "indexs: $limits{'max_index'}\n";
2670
if (!defined($limits{'max_unique_index'}))
2672
safe_query_l('max_unique_index',
2673
"create table crash_q ($key_definitions)");
2674
for ($i=0; $i < min($limits{'max_columns'},$max_keys) ; $i++)
2676
last if (!safe_query_l('max_unique_index',
2677
"create unique index crash_q$i on crash_q (q$i)"));
2679
save_config_data('max_unique_index',$i == $max_keys ? $max_keys : $i,
2680
"max unique index");
2683
$end_drop=$end_drop_keyword;
2684
$end_drop =~ s/%i/crash_q$i/;
2685
$end_drop =~ s/%t/crash_q/;
2686
assert_crash($end_drop);
2688
assert_crash("drop table crash_q $drop_attr");
2690
print "unique indexes: $limits{'max_unique_index'}\n";
2691
if (!defined($limits{'max_index_parts'}))
2693
safe_query_l('max_index_parts',
2694
"create table crash_q ($key_definitions)");
2695
$end_drop=$end_drop_keyword;
2696
$end_drop =~ s/%i/crash_q1%d/;
2697
$end_drop =~ s/%t/crash_q/;
2698
find_limit("index parts","max_index_parts",
2699
new query_table("create index crash_q1%d on crash_q (q0",
2705
assert_crash("drop table crash_q $drop_attr");
2709
print "index parts: $limits{'max_index_parts'}\n";
2711
$end_drop=$end_drop_keyword;
2712
$end_drop =~ s/%i/crash_q2%d/;
2713
$end_drop =~ s/%t/crash_me/;
2715
find_limit("index part length","max_index_part_length",
2716
new query_many(["create table crash_q (q char(%d))",
2717
"create index crash_q2%d on crash_q (q)",
2718
"insert into crash_q values('%s')"],
2719
"select q from crash_q",
2722
"drop table crash_q $drop_attr"],
2723
min($limits{'max_char_size'},"+8192")));
2727
find_limit("index length","max_index_length",
2728
new query_index_length("create table crash_q ",
2729
"drop table crash_q $drop_attr",
2732
find_limit("max table row length (without blobs)","max_row_length",
2733
new query_row_length("crash_q ",
2735
"drop table crash_q $drop_attr",
2736
min($max_row_length,
2737
$limits{'max_columns'}*
2738
min($limits{'max_char_size'},255))));
2740
find_limit("table row length with nulls (without blobs)",
2741
"max_row_length_with_null",
2742
new query_row_length("crash_q ",
2744
"drop table crash_q $drop_attr",
2745
$limits{'max_row_length'}*2));
2747
find_limit("number of columns in order by","columns_in_order_by",
2748
new query_many(["create table crash_q (%F)",
2749
"insert into crash_q values(%v)",
2750
"insert into crash_q values(%v)"],
2751
"select * from crash_q order by %f",
2753
["drop table crash_q $drop_attr"],
2756
find_limit("number of columns in group by","columns_in_group_by",
2757
new query_many(["create table crash_q (%F)",
2758
"insert into crash_q values(%v)",
2759
"insert into crash_q values(%v)"],
2760
"select %f from crash_q group by %f",
2762
["drop table crash_q $drop_attr"],
2767
# Safe arithmetic test
2769
$prompt="safe decimal arithmetic";
2770
$key="safe_decimal_arithmetic";
2771
if (!defined($limits{$key}))
2774
save_incomplete($key,$prompt);
2775
if (!safe_query_l($key,$server->create("crash_me_a",
2776
["a decimal(10,2)","b decimal(10,2)"])))
2778
print DBI->errstr();
2779
die "Can't create table 'crash_me_a' $DBI::errstr\n";
2782
if (!safe_query_l($key,
2783
["insert into crash_me_a (a,b) values (11.4,18.9)"]))
2785
die "Can't insert into table 'crash_me_a' a record: $DBI::errstr\n";
2788
$arithmetic_safe = 'no';
2789
$arithmetic_safe = 'yes'
2790
if ( (safe_query_result_l($key,
2791
'select count(*) from crash_me_a where a+b=30.3',1,0) == 0)
2792
and (safe_query_result_l($key,
2793
'select count(*) from crash_me_a where a+b-30.3 = 0',1,0) == 0)
2794
and (safe_query_result_l($key,
2795
'select count(*) from crash_me_a where a+b-30.3 < 0',0,0) == 0)
2796
and (safe_query_result_l($key,
2797
'select count(*) from crash_me_a where a+b-30.3 > 0',0,0) == 0));
2798
save_config_data($key,$arithmetic_safe,$prompt);
2799
print "$arithmetic_safe\n";
2800
assert_crash("drop table crash_me_a $drop_attr");
2804
print "$prompt=$limits{$key} (cached)\n";
2807
# Check where is null values in sorted recordset
2808
if (!safe_query($server->create("crash_me_n",["i integer","r integer"])))
2810
print DBI->errstr();
2811
die "Can't create table 'crash_me_n' $DBI::errstr\n";
2814
safe_query_l("position_of_null",["insert into crash_me_n (i) values(1)",
2815
"insert into crash_me_n values(2,2)",
2816
"insert into crash_me_n values(3,3)",
2817
"insert into crash_me_n values(4,4)",
2818
"insert into crash_me_n (i) values(5)"]);
2820
$key = "position_of_null";
2821
$prompt ="Where is null values in sorted recordset";
2822
if (!defined($limits{$key}))
2824
save_incomplete($key,$prompt);
2826
$sth=$dbh->prepare("select r from crash_me_n order by r ");
2828
add_log($key,"< select r from crash_me_n order by r ");
2829
$limit= detect_null_position($key,$sth);
2832
save_config_data($key,$limit,$prompt);
2834
print "$prompt=$limits{$key} (cache)\n";
2837
$key = "position_of_null_desc";
2838
$prompt ="Where is null values in sorted recordset (DESC)";
2839
if (!defined($limits{$key}))
2841
save_incomplete($key,$prompt);
2843
$sth=$dbh->prepare("select r from crash_me_n order by r desc");
2845
add_log($key,"< select r from crash_me_n order by r desc");
2846
$limit= detect_null_position($key,$sth);
2849
save_config_data($key,$limit,$prompt);
2851
print "$prompt=$limits{$key} (cache)\n";
2855
assert_crash("drop table crash_me_n $drop_attr");
2859
$key = 'sorted_group_by';
2860
$prompt = 'Group by always sorted';
2861
if (!defined($limits{$key}))
2863
save_incomplete($key,$prompt);
2866
"create table crash_me_t1 (a int not null, b int not null)",
2867
"insert into crash_me_t1 values (1,1)",
2868
"insert into crash_me_t1 values (1,2)",
2869
"insert into crash_me_t1 values (3,1)",
2870
"insert into crash_me_t1 values (3,2)",
2871
"insert into crash_me_t1 values (2,2)",
2872
"insert into crash_me_t1 values (2,1)",
2873
"create table crash_me_t2 (a int not null, b int not null)",
2874
"create index crash_me_t2_ind on crash_me_t2 (a)",
2875
"insert into crash_me_t2 values (1,3)",
2876
"insert into crash_me_t2 values (3,1)",
2877
"insert into crash_me_t2 values (2,2)",
2878
"insert into crash_me_t2 values (1,1)"]);
2880
my $bigqry = "select crash_me_t1.a,crash_me_t2.b from ".
2881
"crash_me_t1,crash_me_t2 where crash_me_t1.a=crash_me_t2.a ".
2882
"group by crash_me_t1.a,crash_me_t2.b";
2885
my $rs = get_recordset($key,$bigqry);
2886
print_recordset($key,$rs);
2887
if ( defined ($rs)) {
2888
if (compare_recordset($key,$rs,[[1,1],[1,3],[2,2],[3,1]]) eq 0)
2893
add_log($key,"error: ".$DBI::errstr);
2897
safe_query_l($key,["drop table crash_me_t1",
2898
"drop table crash_me_t2"]);
2899
save_config_data($key,$limit,$prompt);
2902
print "$prompt=$limits{$key} (cashed)\n";
2910
$dbh->do("drop table crash_me $drop_attr"); # Remove temporary table
2912
print "crash-me safe: $limits{'crash_me_safe'}\n";
2913
print "reconnected $reconnect_count times\n";
2915
$dbh->disconnect || warn $dbh->errstr;
2916
save_all_config_data();
2922
$dbh->do("drop table crash_me $drop_attr"); # Remove temporary table
2924
print "crash-me safe: $limits{'crash_me_safe'}\n";
2925
print "reconnected $reconnect_count times\n";
2927
$dbh->disconnect || warn $dbh->errstr;
2928
save_all_config_data();
2931
# Check where is nulls in the sorted result (for)
2932
# it expects exactly 5 rows in the result
2934
sub detect_null_position
2938
my ($z,$r1,$r2,$r3,$r4,$r5);
2939
$r1 = $sth->fetchrow_array; add_log($key,"> $r1");
2940
$r2 = $sth->fetchrow_array; add_log($key,"> $r2");
2941
$r3 = $sth->fetchrow_array; add_log($key,"> $r3");
2942
$r4 = $sth->fetchrow_array; add_log($key,"> $r4");
2943
$r5 = $sth->fetchrow_array; add_log($key,"> $r5");
2944
return "first" if ( !defined($r1) && !defined($r2) && defined($r3));
2945
return "last" if ( !defined($r5) && !defined($r4) && defined($r3));
2949
sub check_parenthesis {
2953
my $param_name=$prefix.lc($fn);
2956
save_incomplete($param_name,$fn);
2957
$r = safe_query("select $fn $end_query");
2958
add_log($param_name,$safe_query_log);
2964
$r = safe_query("select $fn() $end_query");
2965
add_log($param_name,$safe_query_log);
2968
$result="with_parenthesis";
2972
save_config_data($param_name,$result,$fn);
2975
sub check_constraint {
2981
save_incomplete($key,$prompt);
2985
$t=safe_query($create);
2986
add_log($key,$safe_query_log);
2990
$t= safe_query($check);
2991
add_log($key,$safe_query_log);
2998
add_log($key,$safe_query_log);
3000
save_config_data($key,$res,$prompt);
3008
$_ = $limits{'time_format_inresult'};
3009
return sprintf "%02d:%02d:%02d", ($hour%24),$minute,$second if (/^iso$/);
3010
return sprintf "%02d.%02d.%02d", ($hour%24),$minute,$second if (/^euro/);
3011
return sprintf "%02d:%02d %s",
3012
($hour >= 13? ($hour-12) : $hour),$minute,($hour >=13 ? 'PM':'AM')
3014
return sprintf "%02d%02d%02d", ($hour%24),$minute,$second if (/^HHMMSS/);
3015
return sprintf "%04d%02d%02d", ($hour%24),$minute,$second if (/^HHHHMMSS/);
3016
return "UNKNOWN FORMAT";
3023
return sprintf "%02d:%02d:%02d", ($hour%24),$minute,$second
3024
if ($limits{'time_format_ISO'} eq "yes");
3025
return sprintf "%02d.%02d.%02d", ($hour%24),$minute,$second
3026
if ($limits{'time_format_EUR'} eq "yes");
3027
return sprintf "%02d:%02d %s",
3028
($hour >= 13? ($hour-12) : $hour),$minute,($hour >=13 ? 'PM':'AM')
3029
if ($limits{'time_format_USA'} eq "yes");
3030
return sprintf "%02d%02d%02d", ($hour%24),$minute,$second
3031
if ($limits{'time_format_HHMMSS'} eq "yes");
3032
return sprintf "%04d%02d%02d", ($hour%24),$minute,$second
3033
if ($limits{'time_format_HHHHMMSS'} eq "yes");
3034
return "UNKNOWN FORMAT";
3041
$_ = $limits{'date_format_inresult'};
3042
return sprintf "%02d-%02d-%02d", ($year%100),$month,$day if (/^short iso$/);
3043
return sprintf "%04d-%02d-%02d", $year,$month,$day if (/^iso/);
3044
return sprintf "%02d.%02d.%02d", $day,$month,($year%100) if (/^short euro/);
3045
return sprintf "%02d.%02d.%04d", $day,$month,$year if (/^euro/);
3046
return sprintf "%02d/%02d/%02d", $month,$day,($year%100) if (/^short usa/);
3047
return sprintf "%02d/%02d/%04d", $month,$day,$year if (/^usa/);
3048
return sprintf "%04d%02d%02d", $year,$month,$day if (/^YYYYMMDD/);
3049
return "UNKNOWN FORMAT";
3057
return sprintf "'%04d-%02d-%02d'", $year,$month,$day
3058
if ($limits{'date_format_ISO'} eq 'yes');
3059
return sprintf "DATE '%04d-%02d-%02d'", $year,$month,$day
3060
if ($limits{'date_format_ISO_with_date'} eq 'yes');
3061
return sprintf "'%02d.%02d.%04d'", $day,$month,$year
3062
if ($limits{'date_format_EUR'} eq 'yes');
3063
return sprintf "DATE '%02d.%02d.%04d'", $day,$month,$year
3064
if ($limits{'date_format_EUR_with_date'} eq 'yes');
3065
return sprintf "'%02d/%02d/%04d'", $month,$day,$year
3066
if ($limits{'date_format_USA'} eq 'yes');
3067
return sprintf "DATE '%02d/%02d/%04d'", $month,$day,$year
3068
if ($limits{'date_format_USA_with_date'} eq 'yes');
3069
return sprintf "'%04d%02d%02d'", $year,$month,$day
3070
if ($limits{'date_format_YYYYMMDD'} eq 'yes');
3071
return sprintf "DATE '%04d%02d%02d'", $year,$month,$day
3072
if ($limits{'date_format_YYYYMMDD_with_date'} eq 'yes');
3073
return "UNKNOWN FORMAT";
3077
sub print_recordset{
3078
my ($key,$recset) = @_;
3080
foreach $rec (@$recset)
3082
add_log($key, " > ".join(',', map(repr($_), @$rec)));
3087
# read result recordset from sql server.
3088
# returns arrayref to (arrayref to) values
3089
# or undef (in case of sql errors)
3092
my ($key,$query) = @_;
3093
add_log($key, "< $query");
3094
return $dbh->selectall_arrayref($query);
3097
# function for comparing recordset (that was returned by get_recordset)
3098
# and arrayref of (arrayref of) values.
3100
# returns : zero if recordset equal that array, 1 if it doesn't equal
3103
# $key - current operation (for logging)
3104
# $recset - recordset
3105
# $mustbe - array of values that we expect
3107
# example: $a=get_recordset('some_parameter','select a,b from c');
3108
# if (compare_recordset('some_parameter',$a,[[1,1],[1,2],[1,3]]) neq 0)
3110
# print "unexpected result\n";
3113
sub compare_recordset {
3114
my ($key,$recset,$mustbe) = @_;
3115
my ($rec,$recno,$fldno,$fcount);
3116
add_log($key,"\n Check recordset:");
3118
foreach $rec (@$recset)
3120
add_log($key," " . join(',', map(repr($_),@$rec)) . " expected: " .
3121
join(',', map(repr($_), @{$mustbe->[$recno]} ) ));
3124
foreach $fldno (0 .. $fcount )
3126
if ($mustbe->[$recno][$fldno] ne $rec->[$fldno])
3128
add_log($key," Recordset doesn't correspond with template");
3134
add_log($key," Recordset corresponds with template");
3139
# converts inner perl value to printable representation
3140
# for example: undef maps to 'NULL',
3141
# string -> 'string'
3146
return "'$s'"if ($s =~ /\D/);
3147
return 'NULL'if ( not defined($s));
3154
print "$0 Ver $version\n";
3163
This program tries to find all limits and capabilities for a SQL
3164
server. As it will use the server in some 'unexpected' ways, one
3165
shouldn\'t have anything important running on it at the same time this
3166
program runs! There is a slight chance that something unexpected may
3169
As all used queries are legal according to some SQL standard. any
3170
reasonable SQL server should be able to run this test without any
3173
All questions is cached in $opt_dir/'server_name'[-suffix].cfg that
3174
future runs will use limits found in previous runs. Remove this file
3175
if you want to find the current limits for your version of the
3178
This program uses some table names while testing things. If you have any
3179
tables with the name of 'crash_me' or 'crash_qxxxx' where 'x' is a number,
3180
they will be deleted by this test!
3182
$0 takes the following options:
3184
--help or --Information
3188
Don\'t ask any questions, quit on errors.
3191
Do a new connection to the server every time crash-me checks if the server
3192
is alive. This can help in cases where the server starts returning wrong
3193
data because of an earlier select.
3195
--comment='some comment'
3196
Add this comment to the crash-me limit file
3198
--config-file='filename'
3199
Read limit results from specific file
3201
--connect-options='some connect options'
3202
Add options, which uses at DBI connect.
3203
For example --connect-options=mysql_read_default_file=/etc/my.cnf.
3205
--database='database' (Default $opt_database)
3206
Create test tables in this database.
3209
Lots of printing to help debugging if something goes wrong.
3212
Save crash-me output in this directory
3215
Reformat the crash-me limit file. crash-me is not run!
3218
Start test at once, without a warning screen and without questions.
3219
This is a option for the very brave.
3220
Use this in your cron scripts to test your database every night.
3223
Prints all queries that are executed. Mostly used for debugging crash-me.
3225
--log-queries-to-file='filename'
3226
Log full queries to file.
3228
--host='hostname' (Default $opt_host)
3229
Run tests on this host.
3231
--password='password'
3232
Password for the current user.
3235
Save states during each limit tests. This will make it possible to continue
3236
by restarting with the same options if there is some bug in the DBI or
3237
DBD driver that caused $0 to die!
3239
--server='server name' (Default $opt_server)
3240
Run the test on the given server.
3241
Known servers names are: Access, Adabas, AdabasD, Empress, Oracle,
3242
Informix, DB2, Mimer, mSQL, MS-SQL, MySQL, Pg, Solid or Sybase.
3243
For others $0 can\'t report the server version.
3245
--suffix='suffix' (Default '')
3246
Add suffix to the output filename. For instance if you run crash-me like
3247
"crash-me --suffix="myisam",
3248
then output filename will look "mysql-myisam.cfg".
3251
User name to log into the SQL server.
3253
--db-start-cmd='command to restart server'
3254
Automaticly restarts server with this command if the database server dies.
3256
--sleep='time in seconds' (Default $opt_sleep)
3257
Wait this long before restarting server.
3261
Log into the result file queries performed for determination parameter value
3272
print "\nNOTE: You should be familiar with '$0 --help' before continuing!\n\n";
3273
if (lc($opt_server) eq "mysql")
3277
This test should not crash MySQL if it was distributed together with the
3278
running MySQL version.
3279
If this is the case you can probably continue without having to worry about
3280
destroying something.
3283
elsif (lc($opt_server) eq "msql")
3286
This test will take down mSQL repeatedly while finding limits.
3287
To make this test easier, start mSQL in another terminal with something like:
3289
while (true); do /usr/local/mSQL/bin/msql2d ; done
3291
You should be sure that no one is doing anything important with mSQL and that
3292
you have privileges to restart it!
3293
It may take awhile to determinate the number of joinable tables, so prepare to
3297
elsif (lc($opt_server) eq "solid")
3300
This test will take down Solid server repeatedly while finding limits.
3301
You should be sure that no one is doing anything important with Solid
3302
and that you have privileges to restart it!
3304
If you are running Solid without logging and/or backup YOU WILL LOSE!
3305
Solid does not write data from the cache often enough. So if you continue
3306
you may lose tables and data that you entered hours ago!
3308
Solid will also take a lot of memory running this test. You will nead
3311
When doing the connect test Solid server or the perl api will hang when
3312
freeing connections. Kill this program and restart it to continue with the
3313
test. You don\'t have to use --restart for this case.
3317
print "\nWhen DBI/Solid dies you should run this program repeatedly\n";
3318
print "with --restart until all tests have completed\n";
3321
elsif (lc($opt_server) eq "pg")
3324
This test will crash postgreSQL when calculating the number of joinable tables!
3325
You should be sure that no one is doing anything important with postgreSQL
3326
and that you have privileges to restart it!
3332
This test may crash $opt_server repeatedly while finding limits!
3333
You should be sure that no one is doing anything important with $opt_server
3334
and that you have privileges to restart it!
3339
Some of the tests you are about to execute may require a lot of
3340
memory. Your tests WILL adversely affect system performance. It\'s
3341
not uncommon that either this crash-me test program, or the actual
3342
database back-end, will DIE with an out-of-memory error. So might
3343
any other program on your system if it requests more memory at the
3346
Note also that while crash-me tries to find limits for the database server
3347
it will make a lot of queries that can\'t be categorized as \'normal\'. It\'s
3348
not unlikely that crash-me finds some limit bug in your server so if you
3349
run this test you have to be prepared that your server may die during it!
3351
We, the creators of this utility, are not responsible in any way if your
3352
database server unexpectedly crashes while this program tries to find the
3353
limitations of your server. By accepting the following question with \'yes\',
3354
you agree to the above!
3356
You have been warned!
3361
# No default reply here so no one can blame us for starting the test
3366
print "Start test (yes/no) ? ";
3367
$tmp=<STDIN>; chomp($tmp); $tmp=lc($tmp);
3368
last if ($tmp =~ /^yes$/i);
3369
exit 1 if ($tmp =~ /^n/i);
3376
# my @name = POSIX::uname();
3377
# my $name= $name[0] . " " . $name[2] . " " . $name[4];
3383
# Help functions that we need
3393
if (($dbh=DBI->connect($server->{'data_source'},$opt_user,$opt_password,
3394
{ PrintError => 0, AutoCommit => 1})))
3396
$dbh->{LongReadLen}= 16000000; # Set max retrieval buffer
3399
print "Error: $DBI::errstr; $server->{'data_source'} ".
3400
" - '$opt_user' - '$opt_password'\n";
3401
print "I got the above error when connecting to $opt_server\n";
3402
if (defined($object) && defined($object->{'limit'}))
3404
print "This check was done with limit: $object->{'limit'}.".
3405
"\nNext check will be done with a smaller limit!\n";
3408
save_config_data('crash_me_safe','no',"crash me safe");
3409
if ($opt_db_start_cmd)
3411
print "Restarting the db server with:\n'$opt_db_start_cmd'\n";
3412
system("$opt_db_start_cmd");
3413
print "Waiting $opt_sleep seconds so the server can initialize\n";
3418
exit(1) if ($opt_batch_mode);
3419
print "Can you check/restart it so I can continue testing?\n";
3422
print "Continue test (yes/no) ? [yes] ";
3423
$tmp=<STDIN>; chomp($tmp); $tmp=lc($tmp);
3424
$tmp = "yes" if ($tmp eq "");
3425
last if (index("yes",$tmp) >= 0);
3426
exit 1 if (index("no",$tmp) >= 0);
3434
# Test connecting a couple of times before giving an error
3435
# This is needed to get the server time to free old connections
3436
# after the connect test
3442
for ($i=0 ; $i < 10 ; $i++)
3444
if (($dbh=DBI->connect($server->{'data_source'},$opt_user,$opt_password,
3445
{ PrintError => 0, AutoCommit => 1})))
3447
$dbh->{LongReadLen}= 16000000; # Set max retrieval buffer
3452
return safe_connect();
3456
# Check if the server is up and running. If not, ask the user to restart it
3463
print "Checking connection\n" if ($opt_log_all_queries);
3464
# The following line will not work properly with interbase
3465
if ($opt_check_server && defined($check_connect) && $dbh->{AutoCommit} != 0)
3469
$dbh=safe_connect($object);
3472
return if (defined($check_connect) && defined($dbh->do($check_connect)));
3473
$dbh->disconnect || warn $dbh->errstr;
3474
print "\nreconnecting\n" if ($opt_debug);
3477
$dbh=safe_connect($object);
3481
# print query if debugging
3485
if (length($query) > 130)
3487
$query=substr($query,0,120) . "...(" . (length($query)-120) . ")";
3495
$last_error=$DBI::errstr;
3498
if (length($query) > 130)
3500
$query=substr($query,0,120) . "...(" . (length($query)-120) . ")";
3502
printf "\nGot error from query: '%s'\n%s\n",$query,$DBI::errstr;
3507
# Do one or many queries. Return 1 if all was ok
3508
# Note that all rows are executed
3509
# (to ensure that we execute drop table commands)
3515
my $r = safe_query($q);
3516
add_log($key,$safe_query_log);
3523
my($query,$ok,$retry_ok,$retry,@tmp,$sth);
3526
if (ref($queries) ne "ARRAY")
3528
push(@tmp,$queries);
3531
foreach $query (@$queries)
3533
printf "query1: %-80.80s ...(%d - %d)\n",$query,
3534
length($query),$retry_limit if ($opt_log_all_queries);
3535
print LOG "$query;\n" if ($opt_log);
3536
$safe_query_log .= "< $query\n";
3537
if (length($query) > $query_size)
3540
$safe_query_log .= "Query is too long\n";
3545
for ($retry=0; $retry < $retry_limit ; $retry++)
3547
if (! ($sth=$dbh->prepare($query)))
3549
print_query($query);
3550
$safe_query_log .= "> couldn't prepare:". $dbh->errstr. "\n";
3551
$retry=100 if (!$server->abort_if_fatal_error());
3552
# Force a reconnect because of Access drop table bug!
3553
if ($retry == $retry_limit-2)
3555
print "Forcing disconnect to retry query\n" if ($opt_debug);
3556
$dbh->disconnect || warn $dbh->errstr;
3558
check_connect(); # Check that server is still up
3562
if (!$sth->execute())
3564
print_query($query);
3565
$safe_query_log .= "> execute error:". $dbh->errstr. "\n";
3566
$retry=100 if (!$server->abort_if_fatal_error());
3567
# Force a reconnect because of Access drop table bug!
3568
if ($retry == $retry_limit-2)
3570
print "Forcing disconnect to retry query\n" if ($opt_debug);
3571
$dbh->disconnect || warn $dbh->errstr;
3573
check_connect(); # Check that server is still up
3577
$retry = $retry_limit;
3579
$safe_query_log .= "> OK\n";
3584
$ok=0 if (!$retry_ok);
3585
if ($query =~ /create/i && $server->reconnect_on_errors())
3587
print "Forcing disconnect to retry query\n" if ($opt_debug);
3588
$dbh->disconnect || warn $dbh->errstr;
3589
$dbh=safe_connect();
3595
sub check_reserved_words
3599
my ($answer, $prompt, $config, $keyword_type);
3601
my @keywords_ext = ( "ansi-92/99", "ansi92", "ansi99", "extra");
3603
my %reserved_words = (
3604
'ABSOLUTE' => 0, 'ACTION' => 0, 'ADD' => 0,
3605
'AFTER' => 0, 'ALIAS' => 0, 'ALL' => 0,
3606
'ALLOCATE' => 0, 'ALTER' => 0, 'AND' => 0,
3607
'ANY' => 0, 'ARE' => 0, 'AS' => 0,
3608
'ASC' => 0, 'ASSERTION' => 0, 'AT' => 0,
3609
'AUTHORIZATION' => 0, 'BEFORE' => 0, 'BEGIN' => 0,
3610
'BIT' => 0, 'BOOLEAN' => 0, 'BOTH' => 0,
3611
'BREADTH' => 0, 'BY' => 0, 'CALL' => 0,
3612
'CASCADE' => 0, 'CASCADED' => 0, 'CASE' => 0,
3613
'CAST' => 0, 'CATALOG' => 0, 'CHAR' => 0,
3614
'CHARACTER' => 0, 'CHECK' => 0, 'CLOSE' => 0,
3615
'COLLATE' => 0, 'COLLATION' => 0, 'COLUMN' => 0,
3616
'COMMIT' => 0, 'COMPLETION' => 0, 'CONNECT' => 0,
3617
'CONNECTION' => 0, 'CONSTRAINT' => 0, 'CONSTRAINTS' => 0,
3618
'CONTINUE' => 0, 'CORRESPONDING' => 0, 'CREATE' => 0,
3619
'CROSS' => 0, 'CURRENT' => 0, 'CURRENT_DATE' => 0,
3620
'CURRENT_TIME' => 0,'CURRENT_TIMESTAMP' => 0, 'CURRENT_USER' => 0,
3621
'CURSOR' => 0, 'CYCLE' => 0, 'DATA' => 0,
3622
'DATE' => 0, 'DAY' => 0, 'DEALLOCATE' => 0,
3623
'DEC' => 0, 'DECIMAL' => 0, 'DECLARE' => 0,
3624
'DEFAULT' => 0, 'DEFERRABLE' => 0, 'DEFERRED' => 0,
3625
'DELETE' => 0, 'DEPTH' => 0, 'DESC' => 0,
3626
'DESCRIBE' => 0, 'DESCRIPTOR' => 0, 'DIAGNOSTICS' => 0,
3627
'DICTIONARY' => 0, 'DISCONNECT' => 0, 'DISTINCT' => 0,
3628
'DOMAIN' => 0, 'DOUBLE' => 0, 'DROP' => 0,
3629
'EACH' => 0, 'ELSE' => 0, 'ELSEIF' => 0,
3630
'END' => 0, 'END-EXEC' => 0, 'EQUALS' => 0,
3631
'ESCAPE' => 0, 'EXCEPT' => 0, 'EXCEPTION' => 0,
3632
'EXEC' => 0, 'EXECUTE' => 0, 'EXTERNAL' => 0,
3633
'FALSE' => 0, 'FETCH' => 0, 'FIRST' => 0,
3634
'FLOAT' => 0, 'FOR' => 0, 'FOREIGN' => 0,
3635
'FOUND' => 0, 'FROM' => 0, 'FULL' => 0,
3636
'GENERAL' => 0, 'GET' => 0, 'GLOBAL' => 0,
3637
'GO' => 0, 'GOTO' => 0, 'GRANT' => 0,
3638
'GROUP' => 0, 'HAVING' => 0, 'HOUR' => 0,
3639
'IDENTITY' => 0, 'IF' => 0, 'IGNORE' => 0,
3640
'IMMEDIATE' => 0, 'IN' => 0, 'INDICATOR' => 0,
3641
'INITIALLY' => 0, 'INNER' => 0, 'INPUT' => 0,
3642
'INSERT' => 0, 'INT' => 0, 'INTEGER' => 0,
3643
'INTERSECT' => 0, 'INTERVAL' => 0, 'INTO' => 0,
3644
'IS' => 0, 'ISOLATION' => 0, 'JOIN' => 0,
3645
'KEY' => 0, 'LANGUAGE' => 0, 'LAST' => 0,
3646
'LEADING' => 0, 'LEAVE' => 0, 'LEFT' => 0,
3647
'LESS' => 0, 'LEVEL' => 0, 'LIKE' => 0,
3648
'LIMIT' => 0, 'LOCAL' => 0, 'LOOP' => 0,
3649
'MATCH' => 0, 'MINUTE' => 0, 'MODIFY' => 0,
3650
'MODULE' => 0, 'MONTH' => 0, 'NAMES' => 0,
3651
'NATIONAL' => 0, 'NATURAL' => 0, 'NCHAR' => 0,
3652
'NEW' => 0, 'NEXT' => 0, 'NO' => 0,
3653
'NONE' => 0, 'NOT' => 0, 'NULL' => 0,
3654
'NUMERIC' => 0, 'OBJECT' => 0, 'OF' => 0,
3655
'OFF' => 0, 'OLD' => 0, 'ON' => 0,
3656
'ONLY' => 0, 'OPEN' => 0, 'OPERATION' => 0,
3657
'OPTION' => 0, 'OR' => 0, 'ORDER' => 0,
3658
'OUTER' => 0, 'OUTPUT' => 0, 'PAD' => 0,
3659
'PARAMETERS' => 0, 'PARTIAL' => 0, 'PRECISION' => 0,
3660
'PREORDER' => 0, 'PREPARE' => 0, 'PRESERVE' => 0,
3661
'PRIMARY' => 0, 'PRIOR' => 0, 'PRIVILEGES' => 0,
3662
'PROCEDURE' => 0, 'PUBLIC' => 0, 'READ' => 0,
3663
'REAL' => 0, 'RECURSIVE' => 0, 'REF' => 0,
3664
'REFERENCES' => 0, 'REFERENCING' => 0, 'RELATIVE' => 0,
3665
'RESIGNAL' => 0, 'RESTRICT' => 0, 'RETURN' => 0,
3666
'RETURNS' => 0, 'REVOKE' => 0, 'RIGHT' => 0,
3667
'ROLE' => 0, 'ROLLBACK' => 0, 'ROUTINE' => 0,
3668
'ROW' => 0, 'ROWS' => 0, 'SAVEPOINT' => 0,
3669
'SCHEMA' => 0, 'SCROLL' => 0, 'SEARCH' => 0,
3670
'SECOND' => 0, 'SECTION' => 0, 'SELECT' => 0,
3671
'SEQUENCE' => 0, 'SESSION' => 0, 'SESSION_USER' => 0,
3672
'SET' => 0, 'SIGNAL' => 0, 'SIZE' => 0,
3673
'SMALLINT' => 0, 'SOME' => 0, 'SPACE' => 0,
3674
'SQL' => 0, 'SQLEXCEPTION' => 0, 'SQLSTATE' => 0,
3675
'SQLWARNING' => 0, 'STRUCTURE' => 0, 'SYSTEM_USER' => 0,
3676
'TABLE' => 0, 'TEMPORARY' => 0, 'THEN' => 0,
3677
'TIME' => 0, 'TIMESTAMP' => 0, 'TIMEZONE_HOUR' => 0,
3678
'TIMEZONE_MINUTE' => 0, 'TO' => 0, 'TRAILING' => 0,
3679
'TRANSACTION' => 0, 'TRANSLATION' => 0, 'TRIGGER' => 0,
3680
'TRUE' => 0, 'UNDER' => 0, 'UNION' => 0,
3681
'UNIQUE' => 0, 'UNKNOWN' => 0, 'UPDATE' => 0,
3682
'USAGE' => 0, 'USER' => 0, 'USING' => 0,
3683
'VALUE' => 0, 'VALUES' => 0, 'VARCHAR' => 0,
3684
'VARIABLE' => 0, 'VARYING' => 0, 'VIEW' => 0,
3685
'WHEN' => 0, 'WHENEVER' => 0, 'WHERE' => 0,
3686
'WHILE' => 0, 'WITH' => 0, 'WITHOUT' => 0,
3687
'WORK' => 0, 'WRITE' => 0, 'YEAR' => 0,
3690
'ASYNC' => 1, 'AVG' => 1, 'BETWEEN' => 1,
3691
'BIT_LENGTH' => 1,'CHARACTER_LENGTH' => 1, 'CHAR_LENGTH' => 1,
3692
'COALESCE' => 1, 'CONVERT' => 1, 'COUNT' => 1,
3693
'EXISTS' => 1, 'EXTRACT' => 1, 'INSENSITIVE' => 1,
3694
'LOWER' => 1, 'MAX' => 1, 'MIN' => 1,
3695
'NULLIF' => 1, 'OCTET_LENGTH' => 1, 'OID' => 1,
3696
'OPERATORS' => 1, 'OTHERS' => 1, 'OVERLAPS' => 1,
3697
'PENDANT' => 1, 'POSITION' => 1, 'PRIVATE' => 1,
3698
'PROTECTED' => 1, 'REPLACE' => 1, 'SENSITIVE' => 1,
3699
'SIMILAR' => 1, 'SQLCODE' => 1, 'SQLERROR' => 1,
3700
'SUBSTRING' => 1, 'SUM' => 1, 'TEST' => 1,
3701
'THERE' => 1, 'TRANSLATE' => 1, 'TRIM' => 1,
3702
'TYPE' => 1, 'UPPER' => 1, 'VIRTUAL' => 1,
3703
'VISIBLE' => 1, 'WAIT' => 1,
3705
'ADMIN' => 2, 'AGGREGATE' => 2, 'ARRAY' => 2,
3706
'BINARY' => 2, 'BLOB' => 2, 'CLASS' => 2,
3707
'CLOB' => 2, 'CONDITION' => 2, 'CONSTRUCTOR' => 2,
3708
'CONTAINS' => 2, 'CUBE' => 2, 'CURRENT_PATH' => 2,
3709
'CURRENT_ROLE' => 2, 'DATALINK' => 2, 'DEREF' => 2,
3710
'DESTROY' => 2, 'DESTRUCTOR' => 2, 'DETERMINISTIC' => 2,
3711
'DO' => 2, 'DYNAMIC' => 2, 'EVERY' => 2,
3712
'EXIT' => 2, 'EXPAND' => 2, 'EXPANDING' => 2,
3713
'FREE' => 2, 'FUNCTION' => 2, 'GROUPING' => 2,
3714
'HANDLER' => 2, 'HAST' => 2, 'HOST' => 2,
3715
'INITIALIZE' => 2, 'INOUT' => 2, 'ITERATE' => 2,
3716
'LARGE' => 2, 'LATERAL' => 2, 'LOCALTIME' => 2,
3717
'LOCALTIMESTAMP' => 2, 'LOCATOR' => 2, 'MEETS' => 2,
3718
'MODIFIES' => 2, 'NCLOB' => 2, 'NORMALIZE' => 2,
3719
'ORDINALITY' => 2, 'OUT' => 2, 'PARAMETER' => 2,
3720
'PATH' => 2, 'PERIOD' => 2, 'POSTFIX' => 2,
3721
'PRECEDES' => 2, 'PREFIX' => 2, 'READS' => 2,
3722
'REDO' => 2, 'REPEAT' => 2, 'RESULT' => 2,
3723
'ROLLUP' => 2, 'SETS' => 2, 'SPECIFIC' => 2,
3724
'SPECIFICTYPE' => 2, 'START' => 2, 'STATE' => 2,
3725
'STATIC' => 2, 'SUCCEEDS' => 2, 'TERMINATE' => 2,
3726
'THAN' => 2, 'TREAT' => 2, 'UNDO' => 2,
3729
'ACCESS' => 3, 'ANALYZE' => 3, 'AUDIT' => 3,
3730
'AUTO_INCREMENT' => 3, 'BACKUP' => 3, 'BDB' => 3,
3731
'BERKELEYDB' => 3, 'BIGINT' => 3, 'BREAK' => 3,
3732
'BROWSE' => 3, 'BTREE' => 3, 'BULK' => 3,
3733
'CHANGE' => 3, 'CHECKPOINT' => 3, 'CLUSTER' => 3,
3734
'CLUSTERED' => 3, 'COLUMNS' => 3, 'COMMENT' => 3,
3735
'COMPRESS' => 3, 'COMPUTE' => 3, 'CONTAINSTABLE' => 3,
3736
'DATABASE' => 3, 'DATABASES' => 3, 'DAY_HOUR' => 3,
3737
'DAY_MINUTE' => 3, 'DAY_SECOND' => 3, 'DBCC' => 3,
3738
'DELAYED' => 3, 'DENY' => 3, 'DISK' => 3,
3739
'DISTINCTROW' => 3, 'DISTRIBUTED' => 3, 'DUMMY' => 3,
3740
'DUMP' => 3, 'ENCLOSED' => 3, 'ERRLVL' => 3,
3741
'ERRORS' => 3, 'ESCAPED' => 3, 'EXCLUSIVE' => 3,
3742
'EXPLAIN' => 3, 'FIELDS' => 3, 'FILE' => 3,
3743
'FILLFACTOR' => 3, 'FREETEXT' => 3, 'FREETEXTTABLE' => 3,
3744
'FULLTEXT' => 3, 'GEOMETRY' => 3, 'HASH' => 3,
3745
'HIGH_PRIORITY' => 3, 'HOLDLOCK' => 3, 'HOUR_MINUTE' => 3,
3746
'HOUR_SECOND' => 3, 'IDENTIFIED' => 3, 'IDENTITYCOL' => 3,
3747
'IDENTITY_INSERT' => 3, 'INCREMENT' => 3, 'INDEX' => 3,
3748
'INFILE' => 3, 'INITIAL' => 3, 'INNODB' => 3,
3749
'KEYS' => 3, 'KILL' => 3, 'LINENO' => 3,
3750
'LINES' => 3, 'LOAD' => 3, 'LOCK' => 3,
3751
'LONG' => 3, 'LONGBLOB' => 3, 'LONGTEXT' => 3,
3752
'LOW_PRIORITY' => 3, 'MASTER_SERVER_ID' => 3, 'MAXEXTENTS' => 3,
3753
'MEDIUMBLOB' => 3, 'MEDIUMINT' => 3, 'MEDIUMTEXT' => 3,
3754
'MIDDLEINT' => 3, 'MINUS' => 3, 'MINUTE_SECOND' => 3,
3755
'MLSLABEL' => 3, 'MODE' => 3, 'MRG_MYISAM' => 3,
3756
'NOAUDIT' => 3, 'NOCHECK' => 3, 'NOCOMPRESS' => 3,
3757
'NONCLUSTERED' => 3, 'NOWAIT' => 3, 'NUMBER' => 3,
3758
'OFFLINE' => 3, 'OFFSETS' => 3, 'ONLINE' => 3,
3759
'OPENDATASOURCE' => 3, 'OPENQUERY' => 3, 'OPENROWSET' => 3,
3760
'OPENXML' => 3, 'OPTIMIZE' => 3, 'OPTIONALLY' => 3,
3761
'OUTFILE' => 3, 'OVER' => 3, 'PCTFREE' => 3,
3762
'PERCENT' => 3, 'PLAN' => 3, 'PRINT' => 3,
3763
'PROC' => 3, 'PURGE' => 3, 'RAISERROR' => 3,
3764
'RAW' => 3, 'READTEXT' => 3, 'RECONFIGURE' => 3,
3765
'REGEXP' => 3, 'RENAME' => 3, 'REPLICATION' => 3,
3766
'REQUIRE' => 3, 'RESOURCE' => 3, 'RESTORE' => 3,
3767
'RLIKE' => 3, 'ROWCOUNT' => 3, 'ROWGUIDCOL' => 3,
3768
'ROWID' => 3, 'ROWNUM' => 3, 'RTREE' => 3,
3769
'RULE' => 3, 'SAVE' => 3, 'SETUSER' => 3,
3770
'SHARE' => 3, 'SHOW' => 3, 'SHUTDOWN' => 3,
3771
'SONAME' => 3, 'SPATIAL' => 3, 'SQL_BIG_RESULT' => 3,
3772
'SQL_CALC_FOUND_ROWS' => 3,'SQL_SMALL_RESULT' => 3, 'SSL' => 3,
3773
'STARTING' => 3, 'STATISTICS' => 3, 'STRAIGHT_JOIN' => 3,
3774
'STRIPED' => 3, 'SUCCESSFUL' => 3, 'SYNONYM' => 3,
3775
'SYSDATE' => 3, 'TABLES' => 3, 'TERMINATED' => 3,
3776
'TEXTSIZE' => 3, 'TINYBLOB' => 3, 'TINYINT' => 3,
3777
'TINYTEXT' => 3, 'TOP' => 3, 'TRAN' => 3,
3778
'TRUNCATE' => 3, 'TSEQUAL' => 3, 'TYPES' => 3,
3779
'UID' => 3, 'UNLOCK' => 3, 'UNSIGNED' => 3,
3780
'UPDATETEXT' => 3, 'USE' => 3, 'USER_RESOURCES' => 3,
3781
'VALIDATE' => 3, 'VARBINARY' => 3, 'VARCHAR2' => 3,
3782
'WAITFOR' => 3, 'WARNINGS' => 3, 'WRITETEXT' => 3,
3783
'XOR' => 3, 'YEAR_MONTH' => 3, 'ZEROFILL' => 3
3787
safe_query("drop table crash_me10 $drop_attr");
3789
foreach my $keyword (sort {$a cmp $b} keys %reserved_words)
3791
$keyword_type= $reserved_words{$keyword};
3793
$prompt= "Keyword ".$keyword;
3794
$config= "reserved_word_".$keywords_ext[$keyword_type]."_".lc($keyword);
3796
report_fail($prompt,$config,
3797
"create table crash_me10 ($keyword int not null)",
3798
"drop table crash_me10 $drop_attr"
3804
# Do a query on a query package object.
3809
my($object,$limit)=@_;
3810
my ($query,$result,$retry,$sth);
3812
$query=$object->query($limit);
3813
$result=safe_query($query);
3819
if (defined($query=$object->check_query()))
3821
for ($retry=0 ; $retry < $retry_limit ; $retry++)
3823
printf "query2: %-80.80s\n",$query if ($opt_log_all_queries);
3824
print LOG "$query;\n" if ($opt_log);
3825
if (($sth= $dbh->prepare($query)))
3829
$result= $object->check($sth);
3834
print_query($query);
3839
print_query($query);
3841
$retry=100 if (!$server->abort_if_fatal_error()); # No need to continue
3842
if ($retry == $retry_limit-2)
3844
print "Forcing discoennect to retry query\n" if ($opt_debug);
3845
$dbh->disconnect || warn $dbh->errstr;
3847
check_connect($object); # Check that server is still up
3849
$result=0; # Query failed
3852
return $result; # Server couldn't handle the query
3858
my ($prompt,$limit,@queries)=@_;
3860
if (!defined($limits{$limit}))
3862
#print "Found limits for $prompt $limit\n";
3863
my $queries_result = safe_query(\@queries);
3864
add_log($limit, $safe_query_log);
3866
if ( $queries_result) {
3867
$report_result= "yes";
3868
add_log($limit,"As far as all queries returned OK, result is YES");
3870
$report_result= "no";
3871
add_log($limit,"As far as some queries didnt return OK, result is NO");
3873
save_config_data($limit,$report_result,$prompt);
3875
print "REPORT $prompt $limits{$limit}\n";
3876
return $limits{$limit} ne "no";
3881
my ($prompt,$limit,@queries)=@_;
3883
if (!defined($limits{$limit}))
3885
my $queries_result = safe_query(\@queries);
3886
add_log($limit, $safe_query_log);
3888
if ( $queries_result) {
3889
$report_result= "no";
3890
add_log($limit,"As far as all queries returned OK, result is NO");
3892
$report_result= "yes";
3893
add_log($limit,"As far as some queries didnt return OK, result is YES");
3895
save_config_data($limit,$report_result,$prompt);
3897
print "$limits{$limit}\n";
3898
return $limits{$limit} ne "no";
3902
# Return true if one of the queries is ok
3906
my ($prompt,$limit,$queries)=@_;
3907
my ($query,$res,$result);
3909
if (!defined($limits{$limit}))
3911
save_incomplete($limit,$prompt);
3913
foreach $query (@$queries)
3915
if (safe_query_l($limit,$query->[0]))
3917
$result= $query->[1];
3921
save_config_data($limit,$result,$prompt);
3923
print "$limits{$limit}\n";
3924
return $limits{$limit} ne "no";
3928
# Execute query and save result as limit value.
3932
my ($prompt,$limit,$query)=@_;
3935
if (!defined($limits{$limit}))
3937
save_incomplete($limit,$prompt);
3938
$error=safe_query_result($query,"1",2);
3939
add_log($limit,$safe_query_result_log);
3940
save_config_data($limit,$error ? "not supported" :$last_result,$prompt);
3942
print "$limits{$limit}\n";
3943
return $limits{$limit} ne "not supported";
3948
my ($limit,$queries,$check,$clear)=@_;
3949
if (!defined($limits{$limit}))
3951
save_incomplete($limit,$prompt);
3952
eval {undef($dbh->{AutoCommit})};
3955
if (safe_query(\@$queries))
3958
$dbh->{AutoCommit} = 1;
3959
if (safe_query_result($check,"","")) {
3960
add_log($limit,$safe_query_result_log);
3961
save_config_data($limit,"yes",$limit);
3965
add_log($limit,$safe_query_log);
3966
save_config_data($limit,"error",$limit);
3968
$dbh->{AutoCommit} = 1;
3972
add_log($limit,"Couldnt undef autocommit ?? ");
3973
save_config_data($limit,"no",$limit);
3977
return $limits{$limit} ne "yes";
3982
my ($limit,$queries,$check,$clear)=@_;
3983
if (!defined($limits{$limit}))
3985
save_incomplete($limit,$prompt);
3986
eval {undef($dbh->{AutoCommit})};
3989
if (safe_query(\@$queries))
3991
add_log($limit,$safe_query_log);
3994
$dbh->{AutoCommit} = 1;
3995
if (safe_query($check)) {
3996
add_log($limit,$safe_query_log);
3997
save_config_data($limit,"no",$limit);
3999
add_log($limit,$safe_query_log);
4000
save_config_data($limit,"yes",$limit);
4004
add_log($limit,$safe_query_log);
4005
save_config_data($limit,"error",$limit);
4010
add_log($limit,'Couldnt undef Autocommit??');
4011
save_config_data($limit,"error",$limit);
4015
$dbh->{AutoCommit} = 1;
4016
return $limits{$limit} ne "yes";
4020
sub check_and_report
4022
my ($prompt,$limit,$pre,$query,$post,$answer,$string_type,$skip_prompt,
4025
$function=0 if (!defined($function));
4027
print "$prompt: " if (!defined($skip_prompt));
4028
if (!defined($limits{$limit}))
4030
save_incomplete($limit,$prompt);
4031
$tmp=1-safe_query(\@$pre);
4032
add_log($limit,$safe_query_log);
4035
$tmp=safe_query_result($query,$answer,$string_type) ;
4036
add_log($limit,$safe_query_result_log);
4038
safe_query(\@$post);
4039
add_log($limit,$safe_query_log);
4040
delete $limits{$limit};
4041
if ($function == 3) # Report error as 'no'.
4046
if ($function == 0 ||
4047
$tmp != 0 && $function == 1 ||
4048
$tmp == 0 && $function== 2)
4050
save_config_data($limit, $tmp == 0 ? "yes" : $tmp == 1 ? "no" : "error",
4052
print "$limits{$limit}\n";
4053
return $function == 0 ? $limits{$limit} eq "yes" : 0;
4055
return 1; # more things to check
4057
print "$limits{$limit}\n";
4058
return 0 if ($function);
4059
return $limits{$limit} eq "yes";
4065
my ($prompt,$limit,@tests)=@_;
4066
my ($tmp,$test,$type);
4070
if (!defined($limits{$limit}))
4072
save_incomplete($limit,$prompt);
4073
$type="no"; # Not supported
4074
foreach $test (@tests)
4076
my $tmp_type= shift(@$test);
4077
if (safe_query_l($limit,\@$test))
4084
save_config_data($limit, $type, $prompt);
4086
print "$limits{$limit}\n";
4087
return $limits{$limit} ne "no";
4091
# Just execute the query and check values; Returns 1 if ok
4094
sub execute_and_check
4096
my ($key,$pre,$query,$post,$answer,$string_type)=@_;
4099
$tmp=safe_query_l($key,\@$pre);
4101
$tmp=safe_query_result_l($key,$query,$answer,$string_type) == 0 if ($tmp);
4102
safe_query_l($key,\@$post);
4107
# returns 0 if ok, 1 if error, -1 if wrong answer
4108
# Sets $last_result to value of query
4109
sub safe_query_result_l{
4110
my ($key,$query,$answer,$result_type)=@_;
4111
my $r = safe_query_result($query,$answer,$result_type);
4112
add_log($key,$safe_query_result_log);
4116
sub safe_query_result
4118
# result type can be
4119
# 8 (must be empty), 2 (Any value), 0 (number)
4120
# 1 (char, endspaces can differ), 3 (exact char), 4 (NULL)
4121
# 5 (char with prefix), 6 (exact, errors are ignored)
4122
# 7 (array of numbers)
4123
my ($query,$answer,$result_type)=@_;
4124
my ($sth,$row,$result,$retry);
4125
undef($last_result);
4126
$safe_query_result_log="";
4128
printf "\nquery3: %-80.80s\n",$query if ($opt_log_all_queries);
4129
print LOG "$query;\n" if ($opt_log);
4130
$safe_query_result_log="<".$query."\n";
4132
for ($retry=0; $retry < $retry_limit ; $retry++)
4134
if (!($sth=$dbh->prepare($query)))
4136
print_query($query);
4137
$safe_query_result_log .= "> prepare failed:".$dbh->errstr."\n";
4139
if ($server->abort_if_fatal_error())
4141
check_connect(); # Check that server is still up
4144
check_connect(); # Check that server is still up
4149
print_query($query);
4150
$safe_query_result_log .= "> execute failed:".$dbh->errstr."\n";
4151
if ($server->abort_if_fatal_error())
4153
check_connect(); # Check that server is still up
4156
check_connect(); # Check that server is still up
4164
if (!($row=$sth->fetchrow_arrayref))
4166
print "\nquery: $query didn't return any result\n" if ($opt_debug);
4167
$safe_query_result_log .= "> didn't return any result:".$dbh->errstr."\n";
4169
return ($result_type == 8) ? 0 : 1;
4171
if ($result_type == 8)
4177
$last_result= $row->[0]; # Save for report_result;
4178
$safe_query_result_log .= ">".$last_result."\n";
4180
# if ($result_type == 2) We accept any return value as answer
4182
if ($result_type == 0) # Compare numbers
4184
$row->[0] =~ s/,/./; # Fix if ',' is used instead of '.'
4185
if ($row->[0] != $answer && (abs($row->[0]- $answer)/
4186
(abs($row->[0]) + abs($answer))) > 0.01)
4189
$safe_query_result_log .=
4190
"We expected '$answer' but got '$last_result' \n";
4193
elsif ($result_type == 1) # Compare where end space may differ
4195
$row->[0] =~ s/\s+$//;
4196
if ($row->[0] ne $answer)
4199
$safe_query_result_log .=
4200
"We expected '$answer' but got '$last_result' \n";
4203
elsif ($result_type == 3) # This should be a exact match
4205
if ($row->[0] ne $answer)
4208
$safe_query_result_log .=
4209
"We expected '$answer' but got '$last_result' \n";
4212
elsif ($result_type == 4) # If results should be NULL
4214
if (defined($row->[0]))
4217
$safe_query_result_log .=
4218
"We expected NULL but got '$last_result' \n";
4221
elsif ($result_type == 5) # Result should have given prefix
4223
if (length($row->[0]) < length($answer) &&
4224
substr($row->[0],1,length($answer)) ne $answer)
4227
$safe_query_result_log .=
4228
"Result must have prefix '$answer', but '$last_result' \n";
4231
elsif ($result_type == 6) # Exact match but ignore errors
4233
if ($row->[0] ne $answer)
4235
$safe_query_result_log .=
4236
"We expected '$answer' but got '$last_result' \n";
4239
elsif ($result_type == 7) # Compare against array of numbers
4241
if ($row->[0] != $answer->[0])
4243
$safe_query_result_log .= "must be '$answer->[0]' \n";
4250
while (($row=$sth->fetchrow_arrayref))
4252
$safe_query_result_log .= ">$row\n";
4254
$value=shift(@$answer);
4255
if (!defined($value))
4257
print "\nquery: $query returned to many results\n"
4259
$safe_query_result_log .= "It returned to many results \n";
4263
if ($row->[0] != $value)
4265
$safe_query_result_log .= "Must return $value here \n";
4270
if ($#$answer != -1)
4272
print "\nquery: $query returned too few results\n"
4274
$safe_query_result_log .= "It returned too few results \n";
4280
print "\nquery: '$query' returned '$row->[0]' instead of '$answer'\n"
4281
if ($opt_debug && $result && $result_type != 7);
4286
# Check that the query works!
4293
if (!safe_query($query))
4295
$query=join("; ",@$query) if (ref($query) eq "ARRAY");
4296
print "\nFatal error:\nquery: '$query'\nerror: $DBI::errstr\n";
4302
sub read_config_data
4304
my ($key,$limit,$prompt);
4305
if (-e $opt_config_file)
4307
open(CONFIG_FILE,"+<$opt_config_file") ||
4308
die "Can't open configure file $opt_config_file\n";
4309
print "Reading old values from cache: $opt_config_file\n";
4313
open(CONFIG_FILE,"+>>$opt_config_file") ||
4314
die "Can't create configure file $opt_config_file: $!\n";
4319
while (<CONFIG_FILE>)
4322
if (/^(\S+)=([^\#]*[^\#\s])\s*(\# .*)*$/)
4324
$key=$1; $limit=$2 ; $prompt=$3;
4325
if (!$opt_quick || $limit =~ /\d/ || $key =~ /crash_me/)
4327
if ($key !~ /restart/i)
4329
$limits{$key}=$limit eq "null"? undef : $limit;
4330
$prompts{$key}=length($prompt) ? substr($prompt,2) : "";
4332
delete $limits{'restart'};
4337
if ($limit > $limits{'restart'}{'tohigh'})
4339
$limits{'restart'}{'low'} = $limits{'restart'}{'tohigh'};
4341
$limits{'restart'}{'tohigh'} = $limit;
4345
elsif (/\s*###(.*)$/) # log line
4347
# add log line for previously read key
4348
$log{$last_read} .= "$1\n";
4350
elsif (!/^\s*$/ && !/^\#/)
4352
die "Wrong config row: $_\n";
4358
sub save_config_data
4360
my ($key,$limit,$prompt)=@_;
4361
$prompts{$key}=$prompt;
4362
return if (defined($limits{$key}) && $limits{$key} eq $limit);
4363
if (!defined($limit) || $limit eq "")
4365
# die "Undefined limit for $key\n";
4368
print CONFIG_FILE "$key=$limit\t# $prompt\n";
4369
$limits{$key}=$limit;
4371
# now write log lines (immediatelly after limits)
4373
my $last_line_was_empty=0;
4374
foreach $line (split /\n/, $log{$key})
4376
print CONFIG_FILE " ###$line\n"
4377
unless ( ($last_line_was_empty eq 1)
4378
&& ($line =~ /^\s+$/) );
4379
$last_line_was_empty= ($line =~ /^\s+$/)?1:0;
4382
if (($opt_restart && $limits{'operating_system'} =~ /windows/i) ||
4383
($limits{'operating_system'} =~ /NT/))
4385
# If perl crashes in windows, everything is lost (Wonder why? :)
4387
open(CONFIG_FILE,"+>>$opt_config_file") ||
4388
die "Can't reopen configure file $opt_config_file: $!\n";
4396
$log{$key} .= $line . "\n" if ($opt_verbose);;
4399
sub save_all_config_data
4403
return if (!$limit_changed);
4404
open(CONFIG_FILE,">$opt_config_file") ||
4405
die "Can't create configure file $opt_config_file: $!\n";
4409
delete $limits{'restart'};
4412
"#This file is automaticly generated by crash-me $version\n\n";
4413
foreach $key (sort keys %limits)
4415
$tmp="$key=$limits{$key}";
4416
print CONFIG_FILE $tmp . ("\t" x (int((32-min(length($tmp),32)+7)/8)+1)) .
4417
"# $prompts{$key}\n";
4420
my $last_line_was_empty=0;
4421
foreach $line (split /\n/, $log{$key})
4423
print CONFIG_FILE " ###$line\n" unless
4424
( ($last_line_was_empty eq 1) && ($line =~ /^\s*$/));
4425
$last_line_was_empty= ($line =~ /^\s*$/)?1:0;
4432
# Save 'incomplete' in the limits file to be able to continue if
4433
# crash-me dies because of a bug in perl/DBI
4437
my ($limit,$prompt)= @_;
4438
save_config_data($limit,"incompleted",$prompt) if ($opt_restart);
4444
my ($sth,$limit)=@_;
4447
return 0 if (!($row=$sth->fetchrow_arrayref));
4448
return (defined($row->[0]) && ('a' x $limit) eq $row->[0]) ? 1 : 0;
4456
for ($i=1 ; $i <= $#_; $i++)
4458
$min=$_[$i] if ($min > $_[$i]);
4466
return "$a || $b" if ($limits{'func_sql_concat_as_||'} eq 'yes');
4467
return "concat($a,$b)" if ($limits{'func_odbc_concat'} eq 'yes');
4468
return "$a + $b" if ($limits{'func_extra_concat_as_+'} eq 'yes');
4473
# Returns a list of statements to create a table in a portable manner
4474
# but still utilizing features in the databases.
4479
my($table_name,$fields,$index,$extra) = @_;
4480
my($query,$nr,$parts,@queries,@index);
4482
$extra="" if (!defined($extra));
4484
$query="create table $table_name (";
4486
foreach $field (@$fields)
4488
$query.= $field . ',';
4490
foreach $index (@$index)
4492
$index =~ /\(([^\(]*)\)$/i;
4494
if ($index =~ /^primary key/)
4496
if ($limits{'primary_key_in_create'} eq 'yes')
4498
$query.= $index . ',';
4503
"create unique index ${table_name}_prim on $table_name ($parts)");
4506
elsif ($index =~ /^unique/)
4508
if ($limits{'unique_in_create'} eq 'yes')
4510
$query.= "unique ($parts),";
4516
"create unique index ${table_name}_$nr on $table_name ($parts)");
4522
if ($limits{'index_in_create'} eq 'yes')
4524
$query.= "index ($parts),";
4530
"create index ${table_name}_$nr on $table_name ($1)");
4535
$query.= ") $extra";
4536
unshift(@queries,$query);
4542
# This is used by some query packages to change:
4545
# %v -> "1,1,1,1,1" where there are 'limit' number of ones
4546
# %f -> q1,q2,q3....
4547
# %F -> q1 integer,q2 integer,q3 integer....
4551
my ($query,$limit)=@_;
4554
return $query if !(defined($query));
4555
$query =~ s/%d/$limit/g;
4558
$repeat= 'a' x $limit;
4559
$query =~ s/%s/$repeat/g;
4563
$repeat= '1,' x $limit;
4565
$query =~ s/%v/$repeat/g;
4570
for ($i=1 ; $i <= $limit ; $i++)
4575
$query =~ s/%f/$repeat/g;
4580
for ($i=1 ; $i <= $limit ; $i++)
4582
$repeat.="q$i integer,";
4585
$query =~ s/%F/$repeat/g;
4592
# Different query packages
4595
package query_repeat;
4599
my ($type,$init,$query,$add1,$add_mid,$add,$add_end,$end_query,$cleanup,
4600
$max_limit, $check, $offset)=@_;
4602
if (defined($init) && $#$init != -1)
4604
$self->{'init'}=$init;
4606
$self->{'query'}=$query;
4607
$self->{'add1'}=$add1;
4608
$self->{'add_mid'}=$add_mid;
4609
$self->{'add'}=$add;
4610
$self->{'add_end'}=$add_end;
4611
$self->{'end_query'}=$end_query;
4612
$self->{'cleanup'}=$cleanup;
4613
$self->{'max_limit'}=(defined($max_limit) ? $max_limit : $main::query_size);
4614
$self->{'check'}=$check;
4615
$self->{'offset'}=$offset;
4616
$self->{'printf'}= ($add =~ /%d/);
4622
my ($self,$limit)=@_;
4623
if (!$self->{'printf'})
4625
return $self->{'query'} . ($self->{'add'} x $limit) .
4626
($self->{'add_end'} x $limit) . $self->{'end_query'};
4628
my ($tmp,$tmp2,$tmp3,$i);
4629
$tmp=$self->{'query'};
4630
if ($self->{'add1'})
4632
for ($i=0; $i < $limit ; $i++)
4634
$tmp3 = $self->{'add1'};
4639
$tmp .= " ".$self->{'add_mid'};
4642
for ($i=0; $i < $limit ; $i++)
4644
$tmp2 = $self->{'add'};
4650
($self->{'add_end'} x $limit) . $self->{'end_query'});
4657
$tmp=int(($main::limits{"query_size"}-length($self->{'query'})
4658
-length($self->{'add_mid'})-length($self->{'end_query'}))/
4659
(length($self->{'add1'})+
4660
length($self->{'add'})+length($self->{'add_end'})));
4661
return main::min($self->{'max_limit'},$tmp);
4668
my($tmp,$statement);
4669
$tmp=$self->{'cleanup'};
4670
foreach $statement (@$tmp)
4672
main::safe_query($statement) if (defined($statement) && length($statement));
4679
my $check=$self->{'check'};
4680
return &$check($sth,$self->{'limit'}) if (defined($check));
4694
my ($type,$query,$end_query,$cleanup,$max_limit,$check)=@_;
4696
$self->{'query'}=$query;
4697
$self->{'end_query'}=$end_query;
4698
$self->{'cleanup'}=$cleanup;
4699
$self->{'max_limit'}=$max_limit;
4700
$self->{'check'}=$check;
4707
$self->{'limit'}=$i;
4708
return "$self->{'query'}$i$self->{'end_query'}";
4714
return $self->{'max_limit'};
4721
foreach $statement ($self->{'$cleanup'})
4723
main::safe_query($statement) if (defined($statement) && length($statement));
4731
my $check=$self->{'check'};
4732
return &$check($sth,$self->{'limit'}) if (defined($check));
4742
# This package is used when testing CREATE TABLE!
4745
package query_table;
4749
my ($type,$query, $add, $end_query, $extra_init, $safe_query, $check,
4750
$cleanup, $max_limit, $offset)=@_;
4752
$self->{'query'}=$query;
4753
$self->{'add'}=$add;
4754
$self->{'end_query'}=$end_query;
4755
$self->{'extra_init'}=$extra_init;
4756
$self->{'safe_query'}=$safe_query;
4757
$self->{'check'}=$check;
4758
$self->{'cleanup'}=$cleanup;
4759
$self->{'max_limit'}=$max_limit;
4760
$self->{'offset'}=$offset;
4767
my ($self,$limit)=@_;
4768
$self->{'limit'}=$limit;
4769
$self->cleanup(); # Drop table before create
4771
my ($tmp,$tmp2,$i,$query,@res);
4772
$tmp =$self->{'query'};
4773
$tmp =~ s/%d/$limit/g;
4774
for ($i=1; $i <= $limit ; $i++)
4776
$tmp2 = $self->{'add'};
4780
push(@res,$tmp . $self->{'end_query'});
4781
$tmp=$self->{'extra_init'};
4782
foreach $query (@$tmp)
4784
push(@res,main::fix_query($query,$limit));
4793
return $self->{'max_limit'};
4800
return main::fix_query($self->{'safe_query'},$self->{'limit'});
4806
my $check=$self->{'check'};
4807
return 0 if (!($row=$sth->fetchrow_arrayref));
4808
if (defined($check))
4810
return (defined($row->[0]) &&
4811
$row->[0] eq main::fix_query($check,$self->{'limit'})) ? 1 : 0;
4817
# Remove table before and after create table query
4822
main::safe_query(main::fix_query($self->{'cleanup'},$self->{'limit'}));
4826
# Package to do many queries with %d, and %s substitution
4833
my ($type,$query,$safe_query,$check_result,$cleanup,$max_limit,$offset,
4836
$self->{'query'}=$query;
4837
$self->{'safe_query'}=$safe_query;
4838
$self->{'check'}=$check_result;
4839
$self->{'cleanup'}=$cleanup;
4840
$self->{'max_limit'}=$max_limit;
4841
$self->{'offset'}=$offset;
4842
$self->{'safe_cleanup'}=$safe_cleanup;
4849
my ($self,$limit)=@_;
4850
my ($queries,$query,@res);
4851
$self->{'limit'}=$limit;
4852
$self->cleanup() if (defined($self->{'safe_cleanup'}));
4853
$queries=$self->{'query'};
4854
foreach $query (@$queries)
4856
push(@res,main::fix_query($query,$limit));
4864
return main::fix_query($self->{'safe_query'},$self->{'limit'});
4870
my($tmp,$statement);
4871
return if (!defined($self->{'cleanup'}));
4872
$tmp=$self->{'cleanup'};
4873
foreach $statement (@$tmp)
4875
if (defined($statement) && length($statement))
4877
main::safe_query(main::fix_query($statement,$self->{'limit'}));
4887
return 0 if (!($row=$sth->fetchrow_arrayref));
4888
$check=$self->{'check'};
4889
if (defined($check))
4891
return (defined($row->[0]) &&
4892
$row->[0] eq main::fix_query($check,$self->{'limit'})) ? 1 : 0;
4900
return $self->{'max_limit'};
4904
# Used to find max supported row length
4907
package query_row_length;
4911
my ($type,$create,$null,$drop,$max_limit)=@_;
4913
$self->{'table_name'}=$create;
4914
$self->{'null'}=$null;
4915
$self->{'cleanup'}=$drop;
4916
$self->{'max_limit'}=$max_limit;
4923
my ($self,$limit)=@_;
4924
my ($res,$values,$size,$length,$i);
4925
$self->{'limit'}=$limit;
4928
$size=main::min($main::limits{'max_char_size'},255);
4929
$size = 255 if (!$size); # Safety
4930
for ($length=$i=0; $length + $size <= $limit ; $length+=$size, $i++)
4932
$res.= "q$i char($size) $self->{'null'},";
4933
$values.="'" . ('a' x $size) . "',";
4935
if ($length < $limit)
4937
$size=$limit-$length;
4938
$res.= "q$i char($size) $self->{'null'},";
4939
$values.="'" . ('a' x $size) . "',";
4943
return ["create table " . $self->{'table_name'} . " ($res)",
4944
"insert into " . $self->{'table_name'} . " values ($values)"];
4950
return $self->{'max_limit'};
4956
main::safe_query($self->{'cleanup'});
4971
# Used to find max supported index length
4974
package query_index_length;
4978
my ($type,$create,$drop,$max_limit)=@_;
4980
$self->{'create'}=$create;
4981
$self->{'cleanup'}=$drop;
4982
$self->{'max_limit'}=$max_limit;
4989
my ($self,$limit)=@_;
4990
my ($res,$size,$length,$i,$parts,$values);
4991
$self->{'limit'}=$limit;
4993
$res=$parts=$values="";
4994
$size=main::min($main::limits{'max_index_part_length'},
4995
$main::limits{'max_char_size'});
4996
$size=1 if ($size == 0); # Avoid infinite loop errors
4997
for ($length=$i=0; $length + $size <= $limit ; $length+=$size, $i++)
4999
$res.= "q$i char($size) not null,";
5001
$values.= "'" . ('a' x $size) . "',";
5003
if ($length < $limit)
5005
$size=$limit-$length;
5006
$res.= "q$i char($size) not null,";
5008
$values.= "'" . ('a' x $size) . "',";
5013
if ($main::limits{'unique_in_create'} eq 'yes')
5015
return [$self->{'create'} . "($res,unique ($parts))",
5016
"insert into crash_q values($values)"];
5018
return [$self->{'create'} . "($res)",
5019
"create index crash_q_index on crash_q ($parts)",
5020
"insert into crash_q values($values)"];
5026
return $self->{'max_limit'};
5032
main::safe_query($self->{'cleanup'});
5049
# OID test instead of / in addition to _rowid