crash-me
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:155k
- #!/usr/bin/perl
- # -*- perl -*-
- # Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
- #
- # This library is free software; you can redistribute it and/or
- # modify it under the terms of the GNU Library General Public
- # License as published by the Free Software Foundation; either
- # version 2 of the License, or (at your option) any later version.
- #
- # This library is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- # Library General Public License for more details.
- #
- # You should have received a copy of the GNU Library General Public
- # License along with this library; if not, write to the Free
- # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- # MA 02111-1307, USA
- # Written by Monty for the TCX/Monty Program/Detron benchmark suite.
- # Empress and PostgreSQL patches by Luuk de Boer
- # Extensions for ANSI SQL and Mimer by Bengt Gunne
- # Some additions and corrections by Matthias Urlich
- #
- # This programs tries to find all limits for a sql server
- # It gets the name from what it does to most servers :)
- #
- # Be sure to use --help before running this!
- #
- # If you want to add support for another server, add a new package for the
- # server in server-cfg. You only have to support the 'new' and 'version'
- # functions. new doesn't need to have any limits if one doesn't want to
- # use the benchmarks.
- #
- # TODO:
- # CMT includes types and functions which are synonyms for other types
- # and functions, including those in SQL9x. It should label those synonyms
- # as such, and clarify ones such as "mediumint" with comments such as
- # "3-byte int" or "same as xxx".
- $version="1.61";
- use Cwd;
- use DBI;
- use Getopt::Long;
- use POSIX;
- $pwd = cwd(); $pwd = "." if ($pwd eq '');
- require "$pwd/server-cfg" || die "Can't read Configuration file: $!n";
- $opt_server="mysql"; $opt_host="localhost"; $opt_database="test";
- $opt_dir="limits";
- $opt_user=$opt_password="";$opt_verbose=1;
- $opt_debug=$opt_help=$opt_Information=$opt_restart=$opt_force=$opt_quick=0;
- $opt_log_all_queries=$opt_fix_limit_file=$opt_batch_mode=$opt_version=0;
- $opt_db_start_cmd=""; # the db server start command
- $opt_check_server=0; # Check if server is alive before each query
- $opt_sleep=10; # time to sleep while starting the db server
- $limit_changed=0; # For configure file
- $reconnect_count=0;
- $opt_suffix="";
- $opt_comment=$opt_config_file=$opt_log_queries_to_file="";
- $limits{'crash_me_safe'}='yes';
- $prompts{'crash_me_safe'}='crash me safe';
- $limits{'operating_system'}= machine();
- $prompts{'operating_system'}='crash-me tested on';
- $retry_limit=3;
- GetOptions("Information","help","server=s","debug","user=s","password=s",
- "database=s","restart","force","quick","log-all-queries","comment=s",
- "host=s","fix-limit-file","dir=s","db-start-cmd=s","sleep=s","suffix=s",
- "batch-mode","config-file=s","log-queries-to-file=s","check-server",
- "version",
- "verbose!" => $opt_verbose) || usage();
- usage() if ($opt_help || $opt_Information);
- version() && exit(0) if ($opt_version);
- $opt_suffix = '-'.$opt_suffix if (length($opt_suffix) != 0);
- $opt_config_file = "$pwd/$opt_dir/$opt_server$opt_suffix.cfg"
- if (length($opt_config_file) == 0);
- $log_prefix=' ###'; # prefix for log lines in result file
- $safe_query_log='';
- $safe_query_result_log='';
- $log{"crash-me"}="";
- #!!!
- if ($opt_fix_limit_file)
- {
- print "Fixing limit file for $opt_servern";
- read_config_data();
- $limit_changed=1;
- save_all_config_data();
- exit 0;
- }
- $server=get_server($opt_server,$opt_host,$opt_database);
- $opt_server=$server->{'cmp_name'};
- $|=1; # For debugging
- print "Running $0 $version on '",($server_version=$server->version()),"'nn";
- print "I hope you didn't have anything important running on this server....n";
- read_config_data();
- if ($limit_changed) # Must have been restarted
- {
- save_config_data('crash_me_safe','no',"crash me safe");
- }
- if (!$opt_force && !$opt_batch_mode)
- {
- server_info();
- }
- else
- {
- print "Using --force. I assume you know what you are doing...n";
- }
- print "n";
- save_config_data('crash_me_version',$version,"crash me version");
- if ($server_version)
- {
- save_config_data('server_version',$server_version,"server version");
- }
- if (length($opt_comment))
- {
- save_config_data('user_comment',$opt_comment,"comment");
- }
- $opt_log=0;
- if (length($opt_log_queries_to_file))
- {
- open(LOG,">$opt_log_queries_to_file") ||
- die "Can't open file $opt_log_queries_to_filen";
- $opt_log=1;
- }
- #
- # Set up some limits that's regared as unlimited
- # We don't want to take up all resources from the server...
- #
- $max_connections="+1000"; # Number of simultaneous connections
- $max_buffer_size="+16000000"; # size of communication buffer.
- $max_string_size="+8000000"; # Enough for this test
- $max_name_length="+512"; # Actually 256, but ...
- $max_keys="+64"; # Probably too big.
- $max_join_tables="+64"; # Probably too big.
- $max_columns="+8192"; # Probably too big.
- $max_row_length=$max_string_size;
- $max_key_length="+8192"; # Big enough
- $max_order_by="+64"; # Big enough
- $max_expressions="+10000";
- $max_big_expressions="+100";
- $max_stacked_expressions="+2000";
- $query_size=$max_buffer_size;
- $longreadlen=16000000; # For retrieval buffer
- #
- # First do some checks that needed for the rest of the benchmark
- #
- use sigtrap; # Must be removed with perl5.005_2 on Win98
- $SIG{PIPE} = 'IGNORE';
- $problem_counter=0;
- $SIG{SEGV} = sub {
- $problem_counter +=1;
- if ($problem_counter >= 100) {
- die("Too many problems, try to restart");
- } else {
- warn('SEGFAULT');
- };
- };
- $dbh=safe_connect();
- #
- # Test if the database require RESTRICT/CASCADE after DROP TABLE
- #
- # Really remove the crash_me table
- $prompt="drop table require cascade/restrict";
- $drop_attr="";
- $dbh->do("drop table crash_me");
- $dbh->do("drop table crash_me cascade");
- if (!safe_query_l('drop_requires_cascade',
- ["create table crash_me (a integer not null)",
- "drop table crash_me"]))
- {
- $dbh->do("drop table crash_me cascade");
- if (safe_query_l('drop_requires_cascade',
- ["create table crash_me (a integer not null)",
- "drop table crash_me cascade"]))
- {
- save_config_data('drop_requires_cascade',"yes","$prompt");
- $drop_attr="cascade";
- }
- else
- {
- die "Can't create and drop table 'crash_me'n";
- }
- }
- else
- {
- save_config_data('drop_requires_cascade',"no","$prompt");
- $drop_attr="";
- }
- # Remove tables from old runs
- $dbh->do("drop table crash_me $drop_attr");
- $dbh->do("drop table crash_me2 $drop_attr");
- $dbh->do("drop table crash_me3 $drop_attr");
- $dbh->do("drop table crash_q $drop_attr");
- $dbh->do("drop table crash_q1 $drop_attr");
- $prompt="Tables without primary key";
- if (!safe_query_l('no_primary_key',
- ["create table crash_me (a integer not null,b char(10) not null)",
- "insert into crash_me (a,b) values (1,'a')"]))
- {
- if (!safe_query_l('no_primary_key',
- ["create table crash_me (a integer not null,b char(10) not null".
- ", primary key (a))",
- "insert into crash_me (a,b) values (1,'a')"]))
- {
- die "Can't create table 'crash_me' with one record: $DBI::errstrn";
- }
- save_config_data('no_primary_key',"no",$prompt);
- }
- else
- {
- save_config_data('no_primary_key',"yes",$prompt);
- }
- #
- # Define strings for character NULL and numeric NULL used in expressions
- #
- $char_null=$server->{'char_null'};
- $numeric_null=$server->{'numeric_null'};
- if ($char_null eq '')
- {
- $char_null="NULL";
- }
- if ($numeric_null eq '')
- {
- $numeric_null="NULL";
- }
- print "$prompt: $limits{'no_primary_key'}n";
- report("SELECT without FROM",'select_without_from',"select 1");
- if ($limits{'select_without_from'} ne "yes")
- {
- $end_query=" from crash_me";
- $check_connect="select a from crash_me";
- }
- else
- {
- $end_query="";
- $check_connect="select 1";
- }
- assert($check_connect);
- assert("select a from crash_me where b<'b'");
- report("Select constants",'select_constants',"select 1 $end_query");
- report("Select table_name.*",'table_wildcard',
- "select crash_me.* from crash_me");
- report("Allows ' and " as string markers",'quote_with_"',
- 'select a from crash_me where b<"c"');
- check_and_report("Double '' as ' in strings",'double_quotes',[],
- "select 'Walker''s' $end_query",[],"Walker's",1);
- check_and_report("Multiple line strings","multi_strings",[],
- "select a from crash_me where b < 'a'n'b'",[],"1",0);
- check_and_report("" as identifier quote (ANSI SQL)",'quote_ident_with_"',[],
- 'select "A" from crash_me',[],"1",0);
- check_and_report("` as identifier quote",'quote_ident_with_`',[],
- 'select `A` from crash_me',[],"1",0);
- check_and_report("[] as identifier quote",'quote_ident_with_[',[],
- 'select [A] from crash_me',[],"1",0);
- report('Double "" in identifiers as "','quote_ident_with_dbl_"',
- 'create table crash_me1 ("abc""d" integer)',
- 'drop table crash_me1');
- report("Column alias","column_alias","select a as ab from crash_me");
- report("Table alias","table_alias","select b.a from crash_me as b");
- report("Functions",'functions',"select 1+1 $end_query");
- report("Group functions",'group_functions',"select count(*) from crash_me");
- report("Group functions with distinct",'group_distinct_functions',
- "select count(distinct a) from crash_me");
- report("Group functions with several distinct",'group_many_distinct_functions',
- "select count(distinct a), count(distinct b) from crash_me");
- report("Group by",'group_by',"select a from crash_me group by a");
- report("Group by position",'group_by_position',
- "select a from crash_me group by 1");
- report("Group by alias",'group_by_alias',
- "select a as ab from crash_me group by ab");
- report("Group on unused column",'group_on_unused',
- "select count(*) from crash_me group by a");
- report("Order by",'order_by',"select a from crash_me order by a");
- report("Order by position",'order_by_position',
- "select a from crash_me order by 1");
- report("Order by function","order_by_function",
- "select a from crash_me order by a+1");
- report("Order by on unused column",'order_on_unused',
- "select b from crash_me order by a");
- # little bit deprecated
- #check_and_report("Order by DESC is remembered",'order_by_remember_desc',
- # ["create table crash_q (s int,s1 int)",
- # "insert into crash_q values(1,1)",
- # "insert into crash_q values(3,1)",
- # "insert into crash_q values(2,1)"],
- # "select s,s1 from crash_q order by s1 DESC,s",
- # ["drop table crash_q $drop_attr"],[3,2,1],7,undef(),3);
- report("Compute",'compute',
- "select a from crash_me order by a compute sum(a) by a");
- report("INSERT with Value lists",'insert_multi_value',
- "create table crash_q (s char(10))",
- "insert into crash_q values ('a'),('b')",
- "drop table crash_q $drop_attr");
- report("INSERT with set syntax",'insert_with_set',
- "create table crash_q (a integer)",
- "insert into crash_q SET a=1",
- "drop table crash_q $drop_attr");
- report("INSERT with DEFAULT","insert_with_default",
- "create table crash_me_q (a int)",
- "insert into crash_me_q (a) values (DEFAULT)",
- "drop table crash_me_q $drop_attr");
- report("INSERT with empty value list","insert_with_empty_value_list",
- "create table crash_me_q (a int)",
- "insert into crash_me_q (a) values ()",
- "drop table crash_me_q $drop_attr");
- report("INSERT DEFAULT VALUES","insert_default_values",
- "create table crash_me_q (a int)",
- "insert into crash_me_q DEFAULT VALUES",
- "drop table crash_me_q $drop_attr");
-
- report("allows end ';'","end_colon", "select * from crash_me;");
- try_and_report("LIMIT number of rows","select_limit",
- ["with LIMIT",
- "select * from crash_me limit 1"],
- ["with TOP",
- "select TOP 1 * from crash_me"]);
- report("SELECT with LIMIT #,#","select_limit2",
- "select * from crash_me limit 1,1");
- report("SELECT with LIMIT # OFFSET #",
- "select_limit3", "select * from crash_me limit 1 offset 1");
- # The following alter table commands MUST be kept together!
- if ($dbh->do("create table crash_q (a integer, b integer,c1 CHAR(10))"))
- {
- report("Alter table add column",'alter_add_col',
- "alter table crash_q add d integer");
- report_one("Alter table add many columns",'alter_add_multi_col',
- [["alter table crash_q add (f integer,g integer)","yes"],
- ["alter table crash_q add f integer, add g integer","with add"],
- ["alter table crash_q add f integer,g integer","without add"]] );
- report("Alter table change column",'alter_change_col',
- "alter table crash_q change a e char(50)");
- # informix can only change data type with modify
- report_one("Alter table modify column",'alter_modify_col',
- [["alter table crash_q modify c1 CHAR(20)","yes"],
- ["alter table crash_q alter c1 CHAR(20)","with alter"]]);
- report("Alter table alter column default",'alter_alter_col',
- "alter table crash_q alter b set default 10");
- report_one("Alter table drop column",'alter_drop_col',
- [["alter table crash_q drop column b","yes"],
- ["alter table crash_q drop column b restrict",
- "with restrict/cascade"]]);
- report("Alter table rename table",'alter_rename_table',
- "alter table crash_q rename to crash_q1");
- }
- # Make sure both tables will be dropped, even if rename fails.
- $dbh->do("drop table crash_q1 $drop_attr");
- $dbh->do("drop table crash_q $drop_attr");
- report("rename table","rename_table",
- "create table crash_q (a integer, b integer,c1 CHAR(10))",
- "rename table crash_q to crash_q1",
- "drop table crash_q1 $drop_attr");
- # Make sure both tables will be dropped, even if rename fails.
- $dbh->do("drop table crash_q1 $drop_attr");
- $dbh->do("drop table crash_q $drop_attr");
- report("truncate","truncate_table",
- "create table crash_q (a integer, b integer,c1 CHAR(10))",
- "truncate table crash_q",
- "drop table crash_q $drop_attr");
- if ($dbh->do("create table crash_q (a integer, b integer,c1 CHAR(10))") &&
- $dbh->do("create table crash_q1 (a integer, b integer,c1 CHAR(10) not null)"))
- {
- report("Alter table add constraint",'alter_add_constraint',
- "alter table crash_q add constraint c2 check(a > b)");
- report_one("Alter table drop constraint",'alter_drop_constraint',
- [["alter table crash_q drop constraint c2","yes"],
- ["alter table crash_q drop constraint c2 restrict",
- "with restrict/cascade"]]);
- report("Alter table add unique",'alter_add_unique',
- "alter table crash_q add constraint u1 unique(c1)");
- try_and_report("Alter table drop unique",'alter_drop_unique',
- ["with constraint",
- "alter table crash_q drop constraint u1"],
- ["with constraint and restrict/cascade",
- "alter table crash_q drop constraint u1 restrict"],
- ["with drop key",
- "alter table crash_q drop key u1"]);
- try_and_report("Alter table add primary key",'alter_add_primary_key',
- ["with constraint",
- "alter table crash_q1 add constraint p1 primary key(c1)"],
- ["with add primary key",
- "alter table crash_q1 add primary key(c1)"]);
- report("Alter table add foreign key",'alter_add_foreign_key',
- "alter table crash_q add constraint f1 foreign key(c1) references crash_q1(c1)");
- try_and_report("Alter table drop foreign key",'alter_drop_foreign_key',
- ["with drop constraint",
- "alter table crash_q drop constraint f1"],
- ["with drop constraint and restrict/cascade",
- "alter table crash_q drop constraint f1 restrict"],
- ["with drop foreign key",
- "alter table crash_q drop foreign key f1"]);
- try_and_report("Alter table drop primary key",'alter_drop_primary_key',
- ["drop constraint",
- "alter table crash_q1 drop constraint p1 restrict"],
- ["drop primary key",
- "alter table crash_q1 drop primary key"]);
- }
- $dbh->do("drop table crash_q $drop_attr");
- $dbh->do("drop table crash_q1 $drop_attr");
- check_and_report("Case insensitive compare","case_insensitive_strings",
- [],"select b from crash_me where b = 'A'",[],'a',1);
- check_and_report("Ignore end space in compare","ignore_end_space",
- [],"select b from crash_me where b = 'a '",[],'a',1);
- check_and_report("Group on column with null values",'group_by_null',
- ["create table crash_q (s char(10))",
- "insert into crash_q values(null)",
- "insert into crash_q values(null)"],
- "select count(*),s from crash_q group by s",
- ["drop table crash_q $drop_attr"],2,0);
- $prompt="Having";
- if (!defined($limits{'having'}))
- { # Complicated because of postgreSQL
- if (!safe_query_result_l("having",
- "select a from crash_me group by a having a > 0",1,0))
- {
- if (!safe_query_result_l("having",
- "select a from crash_me group by a having a < 0",
- 1,0))
- { save_config_data("having","error",$prompt); }
- else
- { save_config_data("having","yes",$prompt); }
- }
- else
- { save_config_data("having","no",$prompt); }
- }
- print "$prompt: $limits{'having'}n";
- if ($limits{'having'} eq 'yes')
- {
- report("Having with group function","having_with_group",
- "select a from crash_me group by a having count(*) = 1");
- }
- if ($limits{'column_alias'} eq 'yes')
- {
- report("Order by alias",'order_by_alias',
- "select a as ab from crash_me order by ab");
- if ($limits{'having'} eq 'yes')
- {
- report("Having on alias","having_with_alias",
- "select a as ab from crash_me group by a having ab > 0");
- }
- }
- report("binary numbers (0b1001)","binary_numbers","select 0b1001 $end_query");
- report("hex numbers (0x41)","hex_numbers","select 0x41 $end_query");
- report("binary strings (b'0110')","binary_strings","select b'0110' $end_query");
- report("hex strings (x'1ace')","hex_strings","select x'1ace' $end_query");
- report_result("Value of logical operation (1=1)","logical_value",
- "select (1=1) $end_query");
- report_result("Value of TRUE","value_of_true","select TRUE $end_query");
- report_result("Value of FALSE","value_of_false","select FALSE $end_query");
- $logical_value= $limits{'logical_value'};
- $false=0;
- $result="no";
- if ($res=safe_query_l('has_true_false',"select (1=1)=true $end_query")) {
- $false="false";
- $result="yes";
- }
- save_config_data('has_true_false',$result,"TRUE and FALSE");
- #
- # Check how many connections the server can handle:
- # We can't test unlimited connections, because this may take down the
- # server...
- #
- $prompt="Simultaneous connections (installation default)";
- print "$prompt: ";
- if (defined($limits{'connections'}))
- {
- print "$limits{'connections'}n";
- }
- else
- {
- @connect=($dbh);
- for ($i=1; $i < $max_connections ; $i++)
- {
- if (!($dbh=DBI->connect($server->{'data_source'},$opt_user,$opt_password,
- { PrintError => 0})))
- {
- print "Last connect error: $DBI::errstrn" if ($opt_debug);
- last;
- }
- $dbh->{LongReadLen}= $longreadlen; # Set retrieval buffer
- print "." if ($opt_debug);
- push(@connect,$dbh);
- }
- print "$in";
- save_config_data('connections',$i,$prompt);
- foreach $dbh (@connect)
- {
- print "#" if ($opt_debug);
- $dbh->disconnect || warn $dbh->errstr; # close connection
- }
- $#connect=-1; # Free connections
- if ($i == 0)
- {
- print "Can't connect to server: $DBI::errstr.".
- " Please start it and try againn";
- exit 1;
- }
- $dbh=retry_connect();
- }
- #
- # Check size of communication buffer, strings...
- #
- $prompt="query size";
- print "$prompt: ";
- if (!defined($limits{'query_size'}))
- {
- $query="select ";
- $first=64;
- $end=$max_buffer_size;
- $select= $limits{'select_without_from'} eq 'yes' ? 1 : 'a';
- assert($query . "$select$end_query");
- $first=$limits{'restart'}{'low'} if ($limits{'restart'}{'low'});
- if ($limits{'restart'}{'tohigh'})
- {
- $end = $limits{'restart'}{'tohigh'} - 1;
- print "nRestarting this with low limit: $first and high limit: $endn";
- delete $limits{'restart'};
- $first=$first+int(($end-$first+4)/5); # Prefere lower on errors
- }
- for ($i=$first ; $i < $end ; $i*=2)
- {
- last if (!safe_query($query .
- (" " x ($i - length($query)-length($end_query) -1))
- . "$select$end_query"));
- $first=$i;
- save_config_data("restart",$i,"") if ($opt_restart);
- }
- $end=$i;
- if ($i < $max_buffer_size)
- {
- while ($first != $end)
- {
- $i=int(($first+$end+1)/2);
- if (safe_query($query .
- (" " x ($i - length($query)-length($end_query) -1)) .
- "$select$end_query"))
- {
- $first=$i;
- }
- else
- {
- $end=$i-1;
- }
- }
- }
- save_config_data('query_size',$end,$prompt);
- }
- $query_size=$limits{'query_size'};
- print "$limits{'query_size'}n";
- #
- # Check for reserved words
- #
- check_reserved_words($dbh);
- #
- # Test database types
- #
- @sql_types=("character(1)","char(1)","char varying(1)", "character varying(1)",
- "boolean",
- "varchar(1)",
- "integer","int","smallint",
- "numeric(9,2)","decimal(6,2)","dec(6,2)",
- "bit", "bit(2)","bit varying(2)","float","float(8)","real",
- "double precision", "date","time","timestamp",
- "interval year", "interval year to month",
- "interval month",
- "interval day", "interval day to hour", "interval day to minute",
- "interval day to second",
- "interval hour", "interval hour to minute",
- "interval hour to second",
- "interval minute", "interval minute to second",
- "interval second",
- "national character varying(20)",
- "national character(20)","nchar(1)",
- "national char varying(20)","nchar varying(20)",
- "national character varying(20)",
- "timestamp with time zone");
- @odbc_types=("binary(1)","varbinary(1)","tinyint","bigint",
- "datetime");
- @extra_types=("blob","byte","long varbinary","image","text","text(10)",
- "mediumtext",
- "long varchar(1)", "varchar2(257)",
- "mediumint","middleint","int unsigned",
- "int1","int2","int3","int4","int8","uint",
- "money","smallmoney","float4","float8","smallfloat",
- "float(6,2)","double",
- "enum('red')","set('red')", "int(5) zerofill", "serial",
- "char(10) binary","int not null auto_increment,unique(q)",
- "abstime","year","datetime","smalldatetime","timespan","reltime",
- # Sybase types
- "int not null identity,unique(q)",
- # postgres types
- "box","bool","circle","polygon","point","line","lseg","path",
- "interval", "inet", "cidr", "macaddr",
- # oracle types
- "varchar2(16)","nvarchar2(16)","number(9,2)","number(9)",
- "number", "long","raw(16)","long raw","rowid","mlslabel","clob",
- "nclob","bfile"
- );
- @types=(["sql",@sql_types],
- ["odbc",@odbc_types],
- ["extra",@extra_types]);
- foreach $types (@types)
- {
- print "nSupported $types->[0] typesn";
- $tmp=@$types->[1];
- foreach $use_type (@$tmp)
- {
- $type=$use_type;
- $type =~ s/(.*)/(1 arg)/;
- if (index($use_type,",")>= 0)
- {
- $type =~ s/(1 arg)/(2 arg)/;
- }
- if (($tmp2=index($type,",unique")) >= 0)
- {
- $type=substr($type,0,$tmp2);
- }
- $tmp2=$type;
- $tmp2 =~ s/ /_/g;
- $tmp2 =~ s/_not_null//g;
- report("Type $type","type_$types->[0]_$tmp2",
- "create table crash_q (q $use_type)",
- "drop table crash_q $drop_attr");
- }
- }
- #
- # Test some type limits
- #
- check_and_report("Remembers end space in char()","remember_end_space",
- ["create table crash_q (a char(10))",
- "insert into crash_q values('hello ')"],
- "select a from crash_q where a = 'hello '",
- ["drop table crash_q $drop_attr"],
- 'hello ',6);
- check_and_report("Remembers end space in varchar()",
- "remember_end_space_varchar",
- ["create table crash_q (a varchar(10))",
- "insert into crash_q values('hello ')"],
- "select a from crash_q where a = 'hello '",
- ["drop table crash_q $drop_attr"],
- 'hello ',6);
- if (($limits{'type_extra_float(2_arg)'} eq "yes" ||
- $limits{'type_sql_decimal(2_arg)'} eq "yes") &&
- (!defined($limits{'storage_of_float'})))
- {
- my $type=$limits{'type_extra_float(2_arg)'} eq "yes" ? "float(4,1)" :
- "decimal(4,1)";
- my $result="undefined";
- if (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
- "insert into crash_q values(1.14)"],
- "select q1 from crash_q",
- ["drop table crash_q $drop_attr"],1.1,0) &&
- execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
- "insert into crash_q values(1.16)"],
- "select q1 from crash_q",
- ["drop table crash_q $drop_attr"],1.1,0))
- {
- $result="truncate";
- }
- elsif (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
- "insert into crash_q values(1.14)"],
- "select q1 from crash_q",
- ["drop table crash_q $drop_attr"],1.1,0) &&
- execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
- "insert into crash_q values(1.16)"],
- "select q1 from crash_q",
- ["drop table crash_q $drop_attr"],1.2,0))
- {
- $result="round";
- }
- elsif (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
- "insert into crash_q values(1.14)"],
- "select q1 from crash_q",
- ["drop table crash_q $drop_attr"],1.14,0) &&
- execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
- "insert into crash_q values(1.16)"],
- "select q1 from crash_q",
- ["drop table crash_q $drop_attr"],1.16,0))
- {
- $result="exact";
- }
- $prompt="Storage of float values";
- print "$prompt: $resultn";
- save_config_data("storage_of_float", $result, $prompt);
- }
- try_and_report("Type for row id", "rowid",
- ["rowid",
- "create table crash_q (a rowid)",
- "drop table crash_q $drop_attr"],
- ["auto_increment",
- "create table crash_q (a int not null auto_increment".
- ", primary key(a))","drop table crash_q $drop_attr"],
- ["oid",
- "create table crash_q (a oid, primary key(a))",
- "drop table crash_q $drop_attr"],
- ["serial",
- "create table crash_q (a serial, primary key(a))",
- "drop table crash_q $drop_attr"]);
- try_and_report("Automatic row id", "automatic_rowid",
- ["_rowid",
- "create table crash_q (a int not null, primary key(a))",
- "insert into crash_q values (1)",
- "select _rowid from crash_q",
- "drop table crash_q $drop_attr"]);
- #
- # Test functions
- #
- @sql_functions=
- (["+, -, * and /","+","5*3-4/2+1",14,0],
- ["ANSI SQL SUBSTRING","substring","substring('abcd' from 2 for 2)","bc",1],
- ["BIT_LENGTH","bit_length","bit_length('abc')",24,0],
- ["searched CASE","searched_case",
- "case when 1 > 2 then 'false' when 2 > 1 then 'true' end", "true",1],
- ["simple CASE","simple_case",
- "case 2 when 1 then 'false' when 2 then 'true' end", "true",1],
- ["CAST","cast","CAST(1 as CHAR)","1",1],
- ["CHARACTER_LENGTH","character_length","character_length('abcd')","4",0],
- ["CHAR_LENGTH","char_length","char_length(b)","10",0],
- ["CHAR_LENGTH(constant)","char_length(constant)",
- "char_length('abcd')","4",0],
- ["COALESCE","coalesce","coalesce($char_null,'bcd','qwe')","bcd",1],
- ["CURRENT_DATE","current_date","current_date",0,2],
- ["CURRENT_TIME","current_time","current_time",0,2],
- ["CURRENT_TIMESTAMP","current_timestamp","current_timestamp",0,2],
- ["EXTRACT","extract_sql",
- "extract(minute from timestamp '2000-02-23 18:43:12.987')",43,0],
- ["LOCALTIME","localtime","localtime",0,2],
- ["LOCALTIMESTAMP","localtimestamp","localtimestamp",0,2],
- ["LOWER","lower","LOWER('ABC')","abc",1],
- ["NULLIF with strings","nullif_string",
- "NULLIF(NULLIF('first','second'),'first')",undef(),4],
- ["NULLIF with numbers","nullif_num","NULLIF(NULLIF(1,2),1)",undef(),4],
- ["OCTET_LENGTH","octet_length","octet_length('abc')",3,0],
- ["POSITION","position","position('ll' in 'hello')",3,0],
- ["TRIM","trim","trim(trailing from trim(LEADING FROM ' abc '))","abc",3],
- ["UPPER","upper","UPPER('abc')","ABC",1],
- ["concatenation with ||","concat_as_||","'abc' || 'def'","abcdef",1],
- );
- @odbc_functions=
- (["ASCII", "ascii", "ASCII('A')","65",0],
- ["CHAR", "char", "CHAR(65)" ,"A",1],
- ["CONCAT(2 arg)","concat", "concat('a','b')","ab",1],
- ["DIFFERENCE()","difference","difference('abc','abe')",3,0],
- ["INSERT","insert","insert('abcd',2,2,'ef')","aefd",1],
- ["LEFT","left","left('abcd',2)","ab",1],
- ["LTRIM","ltrim","ltrim(' abcd')","abcd",1],
- ["REAL LENGTH","length","length('abcd ')","5",0],
- ["ODBC LENGTH","length_without_space","length('abcd ')","4",0],
- ["LOCATE(2 arg)","locate_2","locate('bcd','abcd')","2",0],
- ["LOCATE(3 arg)","locate_3","locate('bcd','abcd',3)","0",0],
- ["LCASE","lcase","lcase('ABC')","abc",1],
- ["REPEAT","repeat","repeat('ab',3)","ababab",1],
- ["REPLACE","replace","replace('abbaab','ab','ba')","bababa",1],
- ["RIGHT","right","right('abcd',2)","cd",1],
- ["RTRIM","rtrim","rtrim(' abcd ')"," abcd",1],
- ["SPACE","space","space(5)"," ",3],
- ["SOUNDEX","soundex","soundex('hello')",0,2],
- ["ODBC SUBSTRING","substring","substring('abcd',3,2)","cd",1],
- ["UCASE","ucase","ucase('abc')","ABC",1],
- ["ABS","abs","abs(-5)",5,0],
- ["ACOS","acos","acos(0)","1.570796",0],
- ["ASIN","asin","asin(1)","1.570796",0],
- ["ATAN","atan","atan(1)","0.785398",0],
- ["ATAN2","atan2","atan2(1,0)","1.570796",0],
- ["CEILING","ceiling","ceiling(-4.5)",-4,0],
- ["COS","cos","cos(0)","1.00000",0],
- ["COT","cot","cot(1)","0.64209262",0],
- ["DEGREES","degrees","degrees(6.283185)","360",0],
- ["EXP","exp","exp(1.0)","2.718282",0],
- ["FLOOR","floor","floor(2.5)","2",0],
- ["LOG","log","log(2)","0.693147",0],
- ["LOG10","log10","log10(10)","1",0],
- ["MOD","mod","mod(11,7)","4",0],
- ["PI","pi","pi()","3.141593",0],
- ["POWER","power","power(2,4)","16",0],
- ["RAND","rand","rand(1)",0,2], # Any value is acceptable
- ["RADIANS","radians","radians(360)","6.283185",0],
- ["ROUND(2 arg)","round","round(5.63,2)","5.6",0],
- ["SIGN","sign","sign(-5)",-1,0],
- ["SIN","sin","sin(1)","0.841471",0],
- ["SQRT","sqrt","sqrt(4)",2,0],
- ["TAN","tan","tan(1)","1.557408",0],
- ["TRUNCATE","truncate","truncate(18.18,-1)",10,0],
- ["NOW","now","now()",0,2], # Any value is acceptable
- ["CURDATE","curdate","curdate()",0,2],
- ["CURTIME","curtime","curtime()",0,2],
- ["TIMESTAMPADD","timestampadd",
- "timestampadd(SQL_TSI_SECOND,1,'1997-01-01 00:00:00')",
- "1997-01-01 00:00:01",1],
- ["TIMESTAMPDIFF","timestampdiff",
- "timestampdiff(SQL_TSI_SECOND,'1997-01-01 00:00:02',".
- " '1997-01-01 00:00:01')","1",0],
- ["USER()","user()","user()",0,2],
- ["DATABASE","database","database()",0,2],
- ["IFNULL","ifnull","ifnull(2,3)",2,0],
- ["ODBC syntax LEFT & RIGHT", "fn_left",
- "{ fn LEFT( { fn RIGHT('abcd',2) },1) }","c",1],
- );
- @extra_functions=
- (
- ["& (bitwise and)",'&',"5 & 3",1,0],
- ["| (bitwise or)",'|',"1 | 2",3,0],
- ["<< and >> (bitwise shifts)",'binary_shifts',"(1 << 4) >> 2",4,0],
- ["<> in SELECT","<>","1<>1","0",0],
- ["=","=","(1=1)",1,$logical_value],
- ["~* (case insensitive compare)","~*","'hi' ~* 'HI'",1,$logical_value],
- ["AND and OR in SELECT","and_or","1=1 AND 2=2",$logical_value,0],
- ["AND as '&&'",'&&',"1=1 && 2=2",$logical_value,0],
- ["ASCII_CHAR", "ascii_char", "ASCII_CHAR(65)","A",1],
- ["ASCII_CODE", "ascii_code", "ASCII_CODE('A')","65",0],
- ["ATN2","atn2","atn2(1,0)","1.570796",0],
- ["BETWEEN in SELECT","between","5 between 4 and 6",$logical_value,0],
- ["BIT_COUNT","bit_count","bit_count(5)",2,0],
- ["CEIL","ceil","ceil(-4.5)",-4,0], # oracle
- ["CHARINDEX","charindex","charindex('a','crash')",3,0],
- ["CHR", "chr", "CHR(65)" ,"A",1], # oracle
- ["CONCAT(list)","concat_list", "concat('a','b','c','d')","abcd",1],
- ["CONVERT","convert","convert(CHAR,5)","5",1],
- ["COSH","cosh","cosh(0)","1",0], # oracle hyperbolic cosine of n.
- ["ELT","elt","elt(2,'ONE','TWO','THREE')","TWO",1],
- ["ENCRYPT","encrypt","encrypt('hello')",0,2],
- ["FIELD","field","field('IBM','NCA','ICL','SUN','IBM','DIGITAL')",4,0],
- ["FORMAT","format","format(1234.5555,2)","1,234.56",1],
- ["GETDATE","getdate","getdate()",0,2],
- ["GREATEST","greatest","greatest('HARRY','HARRIOT','HAROLD')","HARRY",1],
- ["IF","if", "if(5,6,7)",6,0],
- ["IN on numbers in SELECT","in_num","2 in (3,2,5,9,5,1)",$logical_value,0],
- ["IN on strings in SELECT","in_str","'monty' in ('david','monty','allan')", $logical_value,0],
- ["INITCAP","initcap","initcap('the soap')","The Soap",1],
- # oracle Returns char, with the first letter of each word in uppercase
- ["INSTR (Oracle syntax)", "instr_oracle", "INSTR('CORPORATE FLOOR','OR',3,2)" ,"14",0], # oracle instring
- ["INSTRB", "instrb", "INSTRB('CORPORATE FLOOR','OR',5,2)" ,"27",0],
- # oracle instring in bytes
- ["INTERVAL","interval","interval(55,10,20,30,40,50,60,70,80,90,100)",5,0],
- ["LAST_INSERT_ID","last_insert_id","last_insert_id()",0,2],
- ["LEAST","least","least('HARRY','HARRIOT','HAROLD')","HAROLD",1],
- # oracle
- ["LENGTHB","lengthb","lengthb('CANDIDE')","14",0],
- # oracle length in bytes
- ["LIKE ESCAPE in SELECT","like_escape",
- "'%' like 'a%' escape 'a'",$logical_value,0],
- ["LIKE in SELECT","like","'a' like 'a%'",$logical_value,0],
- ["LN","ln","ln(95)","4.55387689",0],
- # oracle natural logarithm of n
- ["LOCATE as INSTR","instr","instr('hello','ll')",3,0],
- ["LOG(m,n)","log(m_n)","log(10,100)","2",0],
- # oracle logarithm, base m, of n
- ["LOGN","logn","logn(2)","0.693147",0],
- # informix
- ["LPAD","lpad","lpad('hi',4,'??')",'??hi',3],
- ["MOD as %","%","10%7","3",0],
- ["NOT BETWEEN in SELECT","not_between","5 not between 4 and 6",0,0],
- ["NOT LIKE in SELECT","not_like","'a' not like 'a%'",0,0],
- ["NOT as '!' in SELECT","!","! 1",0,0],
- ["NOT in SELECT","not","not $false",$logical_value,0],
- ["ODBC CONVERT","odbc_convert","convert(5,SQL_CHAR)","5",1],
- ["OR as '||'",'||',"1=0 || 1=1",$logical_value,0],
- ["PASSWORD","password","password('hello')",0,2],
- ["PASTE", "paste", "paste('ABCDEFG',3,2,'1234')","AB1234EFG",1],
- ["PATINDEX","patindex","patindex('%a%','crash')",3,0],
- ["POW","pow","pow(3,2)",9,0],
- ["RANGE","range","range(a)","0.0",0],
- # informix range(a) = max(a) - min(a)
- ["REGEXP in SELECT","regexp","'a' regexp '^(a|b)*$'",$logical_value,0],
- ["REPLICATE","replicate","replicate('a',5)","aaaaa",1],
- ["REVERSE","reverse","reverse('abcd')","dcba",1],
- ["ROOT","root","root(4)",2,0], # informix
- ["ROUND(1 arg)","round1","round(5.63)","6",0],
- ["RPAD","rpad","rpad('hi',4,'??')",'hi??',3],
- ["SINH","sinh","sinh(1)","1.17520119",0], # oracle hyperbolic sine of n
- ["STR","str","str(123.45,5,1)",123.5,3],
- ["STRCMP","strcmp","strcmp('abc','adc')",-1,0],
- ["STUFF","stuff","stuff('abc',2,3,'xyz')",'axyz',3],
- ["SUBSTRB", "substrb", "SUBSTRB('ABCDEFG',5,4.2)" ,"CD",1],
- # oracle substring with bytes
- ["SUBSTRING as MID","mid","mid('hello',3,2)","ll",1],
- ["SUBSTRING_INDEX","substring_index",
- "substring_index('www.tcx.se','.',-2)", "tcx.se",1],
- ["SYSDATE","sysdate","sysdate()",0,2],
- ["TAIL","tail","tail('ABCDEFG',3)","EFG",0],
- ["TANH","tanh","tanh(1)","0.462117157",0],
- # oracle hyperbolic tangent of n
- ["TRANSLATE","translate","translate('abc','bc','de')",'ade',3],
- ["TRIM; Many char extension",
- "trim_many_char","trim(':!' FROM ':abc!')","abc",3],
- ["TRIM; Substring extension",
- "trim_substring","trim('cb' FROM 'abccb')","abc",3],
- ["TRUNC","trunc","trunc(18.18,-1)",10,0], # oracle
- ["UID","uid","uid",0,2], # oracle uid from user
- ["UNIX_TIMESTAMP","unix_timestamp","unix_timestamp()",0,2],
- ["USERENV","userenv","userenv",0,2], # oracle user enviroment
- ["VERSION","version","version()",0,2],
- ["automatic num->string convert","auto_num2string","concat('a',2)","a2",1],
- ["automatic string->num convert","auto_string2num","'1'+2",3,0],
- ["concatenation with +","concat_as_+","'abc' + 'def'","abcdef",1],
- ["SUBSTR (2 arg)",'substr2arg',"substr('abcd',2)",'bcd',1], #sapdb func
- ["SUBSTR (3 arg)",'substr3arg',"substr('abcd',2,2)",'bc',1],
- ["LFILL (3 arg)",'lfill3arg',"lfill('abcd','.',6)",'..abcd',1],
- ["RFILL (3 arg)",'rfill3arg',"rfill('abcd','.',6)",'abcd..',1],
- ["RPAD (4 arg)",'rpad4arg',"rpad('abcd',2,'+-',8)",'abcd+-+-',1],
- ["LPAD (4 arg)",'rpad4arg',"lpad('abcd',2,'+-',8)",'+-+-abcd',1],
- ["TRIM (1 arg)",'trim1arg',"trim(' abcd ')",'abcd',1],
- ["TRIM (2 arg)",'trim2arg',"trim('..abcd..','.')",'abcd',1],
- ["LTRIM (2 arg)",'ltrim2arg',"ltrim('..abcd..','.')",'abcd..',1],
- ["RTRIM (2 arg)",'rtrim2arg',"rtrim('..abcd..','.')",'..abcd',1],
- ["EXPAND",'expand2arg',"expand('abcd',6)",'abcd ',0],
- ["REPLACE (2 arg) ",'replace2arg',"replace('AbCd','bC')",'Ad',1],
- ["MAPCHAR",'mapchar',"mapchar('A