crash-me
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:155k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. #!/usr/bin/perl
  2. # -*- perl -*-
  3. # Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  4. #
  5. # This library is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU Library General Public
  7. # License as published by the Free Software Foundation; either
  8. # version 2 of the License, or (at your option) any later version.
  9. #
  10. # This library is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. # Library General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU Library General Public
  16. # License along with this library; if not, write to the Free
  17. # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  18. # MA 02111-1307, USA
  19. # Written by Monty for the TCX/Monty Program/Detron benchmark suite.
  20. # Empress and PostgreSQL patches by Luuk de Boer
  21. # Extensions for ANSI SQL and Mimer by Bengt Gunne
  22. # Some additions and corrections by Matthias Urlich
  23. #
  24. # This programs tries to find all limits for a sql server
  25. # It gets the name from what it does to most servers :)
  26. #
  27. # Be sure to use --help before running this!
  28. #
  29. # If you want to add support for another server, add a new package for the
  30. # server in server-cfg.  You only have to support the 'new' and 'version'
  31. # functions. new doesn't need to have any limits if one doesn't want to
  32. # use the benchmarks.
  33. #
  34. # TODO:
  35. # CMT includes types and functions which are synonyms for other types
  36. # and functions, including those in SQL9x. It should label those synonyms
  37. # as such, and clarify ones such as "mediumint" with comments such as
  38. # "3-byte int" or "same as xxx".
  39. $version="1.61";
  40. use Cwd;
  41. use DBI;
  42. use Getopt::Long;
  43. use POSIX;
  44. $pwd = cwd(); $pwd = "." if ($pwd eq '');
  45. require "$pwd/server-cfg" || die "Can't read Configuration file: $!n";
  46. $opt_server="mysql"; $opt_host="localhost"; $opt_database="test";
  47. $opt_dir="limits";
  48. $opt_user=$opt_password="";$opt_verbose=1;
  49. $opt_debug=$opt_help=$opt_Information=$opt_restart=$opt_force=$opt_quick=0;
  50. $opt_log_all_queries=$opt_fix_limit_file=$opt_batch_mode=$opt_version=0;
  51. $opt_db_start_cmd="";           # the db server start command
  52. $opt_check_server=0; # Check if server is alive before each query
  53. $opt_sleep=10;                  # time to sleep while starting the db server
  54. $limit_changed=0;               # For configure file
  55. $reconnect_count=0;
  56. $opt_suffix="";
  57. $opt_comment=$opt_config_file=$opt_log_queries_to_file="";
  58. $limits{'crash_me_safe'}='yes';
  59. $prompts{'crash_me_safe'}='crash me safe';
  60. $limits{'operating_system'}= machine();
  61. $prompts{'operating_system'}='crash-me tested on';
  62. $retry_limit=3;
  63. GetOptions("Information","help","server=s","debug","user=s","password=s",
  64. "database=s","restart","force","quick","log-all-queries","comment=s",
  65. "host=s","fix-limit-file","dir=s","db-start-cmd=s","sleep=s","suffix=s",
  66. "batch-mode","config-file=s","log-queries-to-file=s","check-server",
  67. "version",
  68. "verbose!" => $opt_verbose) || usage();
  69. usage() if ($opt_help || $opt_Information);
  70. version() && exit(0) if ($opt_version);
  71. $opt_suffix = '-'.$opt_suffix if (length($opt_suffix) != 0);
  72. $opt_config_file = "$pwd/$opt_dir/$opt_server$opt_suffix.cfg"
  73.   if (length($opt_config_file) == 0);
  74. $log_prefix='   ###';  # prefix for log lines in result file
  75. $safe_query_log='';
  76. $safe_query_result_log='';
  77. $log{"crash-me"}="";
  78. #!!!
  79. if ($opt_fix_limit_file)
  80. {
  81.   print "Fixing limit file for $opt_servern";
  82.   read_config_data();
  83.   $limit_changed=1;
  84.   save_all_config_data();
  85.   exit 0;
  86. }
  87. $server=get_server($opt_server,$opt_host,$opt_database);
  88. $opt_server=$server->{'cmp_name'};
  89. $|=1;                           # For debugging
  90. print "Running $0 $version on '",($server_version=$server->version()),"'nn";
  91. print "I hope you didn't have anything important running on this server....n";
  92. read_config_data();
  93. if ($limit_changed)             # Must have been restarted
  94. {
  95.   save_config_data('crash_me_safe','no',"crash me safe");
  96. }
  97. if (!$opt_force && !$opt_batch_mode)
  98. {
  99.   server_info();
  100. }
  101. else
  102. {
  103.   print "Using --force.  I assume you know what you are doing...n";
  104. }
  105. print "n";
  106. save_config_data('crash_me_version',$version,"crash me version");
  107. if ($server_version)
  108. {
  109.   save_config_data('server_version',$server_version,"server version");
  110. }
  111. if (length($opt_comment))
  112. {
  113.   save_config_data('user_comment',$opt_comment,"comment");
  114. }
  115. $opt_log=0;
  116. if (length($opt_log_queries_to_file))
  117. {
  118.   open(LOG,">$opt_log_queries_to_file") || 
  119.     die "Can't open file $opt_log_queries_to_filen";
  120.   $opt_log=1;
  121. }
  122. #
  123. # Set up some limits that's regared as unlimited
  124. # We don't want to take up all resources from the server...
  125. #
  126. $max_connections="+1000";       # Number of simultaneous connections
  127. $max_buffer_size="+16000000";   # size of communication buffer.
  128. $max_string_size="+8000000";    # Enough for this test
  129. $max_name_length="+512";        # Actually 256, but ...
  130. $max_keys="+64";                # Probably too big.
  131. $max_join_tables="+64";         # Probably too big.
  132. $max_columns="+8192";           # Probably too big.
  133. $max_row_length=$max_string_size;
  134. $max_key_length="+8192";        # Big enough
  135. $max_order_by="+64"; # Big enough
  136. $max_expressions="+10000";
  137. $max_big_expressions="+100";
  138. $max_stacked_expressions="+2000";
  139. $query_size=$max_buffer_size;
  140. $longreadlen=16000000; # For retrieval buffer
  141. #
  142. # First do some checks that needed for the rest of the benchmark
  143. #
  144. use sigtrap;        # Must be removed with perl5.005_2 on Win98
  145. $SIG{PIPE} = 'IGNORE';
  146. $problem_counter=0;
  147. $SIG{SEGV} = sub {
  148.   $problem_counter +=1;
  149.   if ($problem_counter >= 100) {
  150.     die("Too many problems, try to restart");
  151.   } else {
  152.     warn('SEGFAULT');
  153.   };    
  154. };
  155. $dbh=safe_connect();
  156. #
  157. # Test if the database require RESTRICT/CASCADE after DROP TABLE
  158. #
  159. # Really remove the crash_me table
  160. $prompt="drop table require cascade/restrict";
  161. $drop_attr="";
  162. $dbh->do("drop table crash_me");
  163. $dbh->do("drop table crash_me cascade");
  164. if (!safe_query_l('drop_requires_cascade',
  165.          ["create table crash_me (a integer not null)",
  166.  "drop table crash_me"]))
  167. {
  168.   $dbh->do("drop table crash_me cascade");  
  169.   if (safe_query_l('drop_requires_cascade',
  170.         ["create table crash_me (a integer not null)",
  171.   "drop table crash_me cascade"]))
  172.   {
  173.     save_config_data('drop_requires_cascade',"yes","$prompt");
  174.     $drop_attr="cascade";
  175.   }
  176.   else
  177.   {
  178.     die "Can't create and drop table 'crash_me'n";
  179.   }
  180. }
  181. else
  182. {
  183.   save_config_data('drop_requires_cascade',"no","$prompt");
  184.   $drop_attr="";
  185. }
  186. # Remove tables from old runs
  187. $dbh->do("drop table crash_me $drop_attr");
  188. $dbh->do("drop table crash_me2 $drop_attr");
  189. $dbh->do("drop table crash_me3 $drop_attr");
  190. $dbh->do("drop table crash_q $drop_attr");
  191. $dbh->do("drop table crash_q1 $drop_attr");
  192. $prompt="Tables without primary key";
  193. if (!safe_query_l('no_primary_key',
  194.       ["create table crash_me (a integer not null,b char(10) not null)",
  195.  "insert into crash_me (a,b) values (1,'a')"]))
  196. {
  197.   if (!safe_query_l('no_primary_key',
  198.       ["create table crash_me (a integer not null,b char(10) not null".
  199.         ", primary key (a))",
  200.  "insert into crash_me (a,b) values (1,'a')"]))
  201.   {
  202.     die "Can't create table 'crash_me' with one record: $DBI::errstrn";
  203.   }
  204.   save_config_data('no_primary_key',"no",$prompt);
  205. }
  206. else
  207. {
  208.   save_config_data('no_primary_key',"yes",$prompt);
  209. }
  210. #
  211. #  Define strings for character NULL and numeric NULL used in expressions
  212. #
  213. $char_null=$server->{'char_null'};
  214. $numeric_null=$server->{'numeric_null'};
  215. if ($char_null eq '')
  216. {
  217.   $char_null="NULL";
  218. }
  219. if ($numeric_null eq '')
  220. {
  221.   $numeric_null="NULL";
  222. }
  223. print "$prompt: $limits{'no_primary_key'}n";
  224. report("SELECT without FROM",'select_without_from',"select 1");
  225. if ($limits{'select_without_from'} ne "yes")
  226. {
  227.   $end_query=" from crash_me";
  228.   $check_connect="select a from crash_me";
  229. }
  230. else
  231. {
  232.   $end_query="";
  233.   $check_connect="select 1";
  234. }
  235. assert($check_connect);
  236. assert("select a from crash_me where b<'b'");
  237. report("Select constants",'select_constants',"select 1 $end_query");
  238. report("Select table_name.*",'table_wildcard',
  239.        "select crash_me.* from crash_me");
  240. report("Allows ' and " as string markers",'quote_with_"',
  241.        'select a from crash_me where b<"c"');
  242. check_and_report("Double '' as ' in strings",'double_quotes',[],
  243.  "select 'Walker''s' $end_query",[],"Walker's",1);
  244. check_and_report("Multiple line strings","multi_strings",[],
  245.  "select a from crash_me where b < 'a'n'b'",[],"1",0);
  246. check_and_report("" as identifier quote (ANSI SQL)",'quote_ident_with_"',[],
  247.  'select "A" from crash_me',[],"1",0);
  248. check_and_report("` as identifier quote",'quote_ident_with_`',[],
  249.  'select `A` from crash_me',[],"1",0);
  250. check_and_report("[] as identifier quote",'quote_ident_with_[',[],
  251.  'select [A] from crash_me',[],"1",0);
  252. report('Double "" in identifiers as "','quote_ident_with_dbl_"',
  253.         'create table crash_me1 ("abc""d" integer)',
  254. 'drop table crash_me1');  
  255. report("Column alias","column_alias","select a as ab from crash_me");
  256. report("Table alias","table_alias","select b.a from crash_me as b");
  257. report("Functions",'functions',"select 1+1 $end_query");
  258. report("Group functions",'group_functions',"select count(*) from crash_me");
  259. report("Group functions with distinct",'group_distinct_functions',
  260.        "select count(distinct a) from crash_me");
  261. report("Group functions with several distinct",'group_many_distinct_functions',
  262.        "select count(distinct a), count(distinct b) from crash_me");
  263. report("Group by",'group_by',"select a from crash_me group by a");
  264. report("Group by position",'group_by_position',
  265.        "select a from crash_me group by 1");
  266. report("Group by alias",'group_by_alias',
  267.        "select a as ab from crash_me group by ab");
  268. report("Group on unused column",'group_on_unused',
  269.        "select count(*) from crash_me group by a");
  270. report("Order by",'order_by',"select a from crash_me order by a");
  271. report("Order by position",'order_by_position',
  272.        "select a from crash_me order by 1");
  273. report("Order by function","order_by_function",
  274.        "select a from crash_me order by a+1");
  275. report("Order by on unused column",'order_on_unused',
  276.        "select b from crash_me order by a");
  277. # little bit deprecated
  278. #check_and_report("Order by DESC is remembered",'order_by_remember_desc',
  279. #  ["create table crash_q (s int,s1 int)",
  280. #   "insert into crash_q values(1,1)",
  281. #   "insert into crash_q values(3,1)",
  282. #   "insert into crash_q values(2,1)"],
  283. #  "select s,s1 from crash_q order by s1 DESC,s",
  284. #  ["drop table crash_q $drop_attr"],[3,2,1],7,undef(),3);
  285. report("Compute",'compute',
  286.        "select a from crash_me order by a compute sum(a) by a");
  287. report("INSERT with Value lists",'insert_multi_value',
  288.        "create table crash_q (s char(10))",
  289.        "insert into crash_q values ('a'),('b')",
  290.        "drop table crash_q $drop_attr");
  291. report("INSERT with set syntax",'insert_with_set',
  292.        "create table crash_q (a integer)",
  293.        "insert into crash_q SET a=1",
  294.        "drop table crash_q $drop_attr");
  295. report("INSERT with DEFAULT","insert_with_default",
  296.        "create table crash_me_q (a int)",
  297.        "insert into crash_me_q (a) values (DEFAULT)",
  298.        "drop table crash_me_q $drop_attr");
  299. report("INSERT with empty value list","insert_with_empty_value_list",
  300.        "create table crash_me_q (a int)",
  301.        "insert into crash_me_q (a) values ()",
  302.        "drop table crash_me_q $drop_attr");
  303. report("INSERT DEFAULT VALUES","insert_default_values",
  304.        "create table crash_me_q (a int)",
  305.        "insert into crash_me_q  DEFAULT VALUES",
  306.        "drop table crash_me_q $drop_attr");
  307.        
  308. report("allows end ';'","end_colon", "select * from crash_me;");
  309. try_and_report("LIMIT number of rows","select_limit",
  310.        ["with LIMIT",
  311. "select * from crash_me limit 1"],
  312.        ["with TOP",
  313. "select TOP 1 * from crash_me"]);
  314. report("SELECT with LIMIT #,#","select_limit2", 
  315.       "select * from crash_me limit 1,1");
  316. report("SELECT with LIMIT # OFFSET #",
  317.       "select_limit3", "select * from crash_me limit 1 offset 1");
  318. # The following alter table commands MUST be kept together!
  319. if ($dbh->do("create table crash_q (a integer, b integer,c1 CHAR(10))"))
  320. {
  321.   report("Alter table add column",'alter_add_col',
  322.  "alter table crash_q add d integer");
  323.   report_one("Alter table add many columns",'alter_add_multi_col',
  324.      [["alter table crash_q add (f integer,g integer)","yes"],
  325.       ["alter table crash_q add f integer, add g integer","with add"],
  326.       ["alter table crash_q add f integer,g integer","without add"]] );
  327.   report("Alter table change column",'alter_change_col',
  328.  "alter table crash_q change a e char(50)");
  329.   # informix can only change data type with modify
  330.   report_one("Alter table modify column",'alter_modify_col',
  331.      [["alter table crash_q modify c1 CHAR(20)","yes"],
  332.       ["alter table crash_q alter c1 CHAR(20)","with alter"]]);
  333.   report("Alter table alter column default",'alter_alter_col',
  334.  "alter table crash_q alter b set default 10");
  335.   report_one("Alter table drop column",'alter_drop_col',
  336.      [["alter table crash_q drop column b","yes"],
  337.       ["alter table crash_q drop column b restrict",
  338.       "with restrict/cascade"]]);
  339.   report("Alter table rename table",'alter_rename_table',
  340.  "alter table crash_q rename to crash_q1");
  341. }
  342. # Make sure both tables will be dropped, even if rename fails.
  343. $dbh->do("drop table crash_q1 $drop_attr");
  344. $dbh->do("drop table crash_q $drop_attr");
  345. report("rename table","rename_table",
  346.        "create table crash_q (a integer, b integer,c1 CHAR(10))",
  347.        "rename table crash_q to crash_q1",
  348.        "drop table crash_q1 $drop_attr");
  349. # Make sure both tables will be dropped, even if rename fails.
  350. $dbh->do("drop table crash_q1 $drop_attr");
  351. $dbh->do("drop table crash_q $drop_attr");
  352. report("truncate","truncate_table",
  353.        "create table crash_q (a integer, b integer,c1 CHAR(10))",
  354.        "truncate table crash_q",
  355.        "drop table crash_q $drop_attr");
  356. if ($dbh->do("create table crash_q (a integer, b integer,c1 CHAR(10))") &&
  357.  $dbh->do("create table crash_q1 (a integer, b integer,c1 CHAR(10) not null)"))
  358. {
  359.   report("Alter table add constraint",'alter_add_constraint',
  360.  "alter table crash_q add constraint c2 check(a > b)");
  361.   report_one("Alter table drop constraint",'alter_drop_constraint',
  362.      [["alter table crash_q drop constraint c2","yes"],
  363.       ["alter table crash_q drop constraint c2 restrict",
  364.       "with restrict/cascade"]]);
  365.   report("Alter table add unique",'alter_add_unique',
  366.  "alter table crash_q add constraint u1 unique(c1)");
  367.   try_and_report("Alter table drop unique",'alter_drop_unique',
  368.  ["with constraint",
  369.   "alter table crash_q drop constraint u1"],
  370.  ["with constraint and restrict/cascade",
  371.   "alter table crash_q drop constraint u1 restrict"],
  372.  ["with drop key",
  373.   "alter table crash_q drop key u1"]);
  374.   try_and_report("Alter table add primary key",'alter_add_primary_key',
  375.  ["with constraint",
  376.   "alter table crash_q1 add constraint p1 primary key(c1)"],
  377.  ["with add primary key",
  378.   "alter table crash_q1 add primary key(c1)"]);
  379.   report("Alter table add foreign key",'alter_add_foreign_key',
  380.  "alter table crash_q add constraint f1 foreign key(c1) references crash_q1(c1)");
  381.   try_and_report("Alter table drop foreign key",'alter_drop_foreign_key',
  382.  ["with drop constraint",
  383.   "alter table crash_q drop constraint f1"],
  384.  ["with drop constraint and restrict/cascade",
  385.   "alter table crash_q drop constraint f1 restrict"],
  386.  ["with drop foreign key",
  387.   "alter table crash_q drop foreign key f1"]);
  388.   try_and_report("Alter table drop primary key",'alter_drop_primary_key',
  389.  ["drop constraint",
  390.   "alter table crash_q1 drop constraint p1 restrict"],
  391.  ["drop primary key",
  392.   "alter table crash_q1 drop primary key"]);
  393. }
  394. $dbh->do("drop table crash_q $drop_attr");
  395. $dbh->do("drop table crash_q1 $drop_attr");
  396. check_and_report("Case insensitive compare","case_insensitive_strings",
  397.  [],"select b from crash_me where b = 'A'",[],'a',1);
  398. check_and_report("Ignore end space in compare","ignore_end_space",
  399.  [],"select b from crash_me where b = 'a '",[],'a',1);
  400. check_and_report("Group on column with null values",'group_by_null',
  401.  ["create table crash_q (s char(10))",
  402.   "insert into crash_q values(null)",
  403.   "insert into crash_q values(null)"],
  404.  "select count(*),s from crash_q group by s",
  405.  ["drop table crash_q $drop_attr"],2,0);
  406. $prompt="Having";
  407. if (!defined($limits{'having'}))
  408. {                               # Complicated because of postgreSQL
  409.   if (!safe_query_result_l("having",
  410.       "select a from crash_me group by a having a > 0",1,0))
  411.   {
  412.     if (!safe_query_result_l("having",
  413.            "select a from crash_me group by a having a < 0",
  414.     1,0))
  415.     { save_config_data("having","error",$prompt); }
  416.     else
  417.     { save_config_data("having","yes",$prompt); }
  418.   }
  419.   else
  420.   { save_config_data("having","no",$prompt); }
  421. }
  422. print "$prompt: $limits{'having'}n";
  423. if ($limits{'having'} eq 'yes')
  424. {
  425.   report("Having with group function","having_with_group",
  426.  "select a from crash_me group by a having count(*) = 1");
  427. }
  428. if ($limits{'column_alias'} eq 'yes')
  429. {
  430.   report("Order by alias",'order_by_alias',
  431.  "select a as ab from crash_me order by ab");
  432.   if ($limits{'having'} eq 'yes')
  433.   {
  434.     report("Having on alias","having_with_alias",
  435.    "select a as ab from crash_me group by a having ab > 0");
  436.   }
  437. }
  438. report("binary numbers (0b1001)","binary_numbers","select 0b1001 $end_query");
  439. report("hex numbers (0x41)","hex_numbers","select 0x41 $end_query");
  440. report("binary strings (b'0110')","binary_strings","select b'0110' $end_query");
  441. report("hex strings (x'1ace')","hex_strings","select x'1ace' $end_query");
  442. report_result("Value of logical operation (1=1)","logical_value",
  443.       "select (1=1) $end_query");
  444. report_result("Value of TRUE","value_of_true","select TRUE $end_query");
  445. report_result("Value of FALSE","value_of_false","select FALSE $end_query");
  446. $logical_value= $limits{'logical_value'};
  447. $false=0;
  448. $result="no";
  449. if ($res=safe_query_l('has_true_false',"select (1=1)=true $end_query")) {
  450.   $false="false";
  451.   $result="yes";
  452. }
  453. save_config_data('has_true_false',$result,"TRUE and FALSE");
  454. #
  455. # Check how many connections the server can handle:
  456. # We can't test unlimited connections, because this may take down the
  457. # server...
  458. #
  459. $prompt="Simultaneous connections (installation default)";
  460. print "$prompt: ";
  461. if (defined($limits{'connections'}))
  462. {
  463.   print "$limits{'connections'}n";
  464. }
  465. else
  466. {
  467.   @connect=($dbh);
  468.   for ($i=1; $i < $max_connections ; $i++)
  469.   {
  470.     if (!($dbh=DBI->connect($server->{'data_source'},$opt_user,$opt_password,
  471.   { PrintError => 0})))
  472.     {
  473.       print "Last connect error: $DBI::errstrn" if ($opt_debug);
  474.       last;
  475.     }
  476.     $dbh->{LongReadLen}= $longreadlen; # Set retrieval buffer
  477.     print "." if ($opt_debug);
  478.     push(@connect,$dbh);
  479.   }
  480.   print "$in";
  481.   save_config_data('connections',$i,$prompt);
  482.   foreach $dbh (@connect)
  483.   {
  484.     print "#" if ($opt_debug);
  485.     $dbh->disconnect || warn $dbh->errstr;           # close connection
  486.   }
  487.   $#connect=-1;                 # Free connections
  488.   if ($i == 0)
  489.   {
  490.     print "Can't connect to server: $DBI::errstr.".
  491.           "  Please start it and try againn";
  492.     exit 1;
  493.   }
  494.   $dbh=retry_connect();
  495. }
  496. #
  497. # Check size of communication buffer, strings...
  498. #
  499. $prompt="query size";
  500. print "$prompt: ";
  501. if (!defined($limits{'query_size'}))
  502. {
  503.   $query="select ";
  504.   $first=64;
  505.   $end=$max_buffer_size;
  506.   $select= $limits{'select_without_from'} eq 'yes' ? 1 : 'a';
  507.   assert($query . "$select$end_query");
  508.   $first=$limits{'restart'}{'low'} if ($limits{'restart'}{'low'});
  509.   if ($limits{'restart'}{'tohigh'})
  510.   {
  511.     $end = $limits{'restart'}{'tohigh'} - 1;
  512.     print "nRestarting this with low limit: $first and high limit: $endn";
  513.     delete $limits{'restart'};
  514.     $first=$first+int(($end-$first+4)/5);           # Prefere lower on errors
  515.   }
  516.   for ($i=$first ; $i < $end ; $i*=2)
  517.   {
  518.     last if (!safe_query($query . 
  519.             (" " x ($i - length($query)-length($end_query) -1)) 
  520.       . "$select$end_query"));
  521.     $first=$i;
  522.     save_config_data("restart",$i,"") if ($opt_restart);
  523.   }
  524.   $end=$i;
  525.   if ($i < $max_buffer_size)
  526.   {
  527.     while ($first != $end)
  528.     {
  529.       $i=int(($first+$end+1)/2);
  530.       if (safe_query($query .
  531.      (" " x ($i - length($query)-length($end_query) -1)) .
  532.      "$select$end_query"))
  533.       {
  534. $first=$i;
  535.       }
  536.       else
  537.       {
  538. $end=$i-1;
  539.       }
  540.     }
  541.   }
  542.   save_config_data('query_size',$end,$prompt);
  543. }
  544. $query_size=$limits{'query_size'};
  545. print "$limits{'query_size'}n";
  546. #
  547. # Check for reserved words
  548. #
  549. check_reserved_words($dbh);
  550. #
  551. # Test database types
  552. #
  553. @sql_types=("character(1)","char(1)","char varying(1)", "character varying(1)",
  554.     "boolean",
  555.     "varchar(1)",
  556.     "integer","int","smallint",
  557.     "numeric(9,2)","decimal(6,2)","dec(6,2)",
  558.     "bit", "bit(2)","bit varying(2)","float","float(8)","real",
  559.     "double precision", "date","time","timestamp",
  560.     "interval year", "interval year to month",
  561.             "interval month",
  562.             "interval day", "interval day to hour", "interval day to minute",
  563.             "interval day to second",
  564.             "interval hour", "interval hour to minute",
  565.     "interval hour to second",
  566.             "interval minute", "interval minute to second",
  567.             "interval second",
  568.     "national character varying(20)",
  569.     "national character(20)","nchar(1)",
  570.     "national char varying(20)","nchar varying(20)",
  571.     "national character varying(20)",
  572.     "timestamp with time zone");
  573. @odbc_types=("binary(1)","varbinary(1)","tinyint","bigint",
  574.      "datetime");
  575. @extra_types=("blob","byte","long varbinary","image","text","text(10)",
  576.       "mediumtext",
  577.       "long varchar(1)", "varchar2(257)",
  578.       "mediumint","middleint","int unsigned",
  579.       "int1","int2","int3","int4","int8","uint",
  580.       "money","smallmoney","float4","float8","smallfloat",
  581.       "float(6,2)","double",
  582.       "enum('red')","set('red')", "int(5) zerofill", "serial",
  583.       "char(10) binary","int not null auto_increment,unique(q)",
  584.       "abstime","year","datetime","smalldatetime","timespan","reltime",
  585.       # Sybase types
  586.       "int not null identity,unique(q)",
  587.       # postgres types
  588.       "box","bool","circle","polygon","point","line","lseg","path",
  589.       "interval", "inet", "cidr", "macaddr",
  590.       # oracle types
  591.       "varchar2(16)","nvarchar2(16)","number(9,2)","number(9)",
  592.       "number", "long","raw(16)","long raw","rowid","mlslabel","clob",
  593.       "nclob","bfile"
  594.       );
  595. @types=(["sql",@sql_types],
  596. ["odbc",@odbc_types],
  597. ["extra",@extra_types]);
  598. foreach $types (@types)
  599. {
  600.   print "nSupported $types->[0] typesn";
  601.   $tmp=@$types->[1];
  602.   foreach $use_type (@$tmp)
  603.   {
  604.     $type=$use_type;
  605.     $type =~ s/(.*)/(1 arg)/;
  606.     if (index($use_type,",")>= 0)
  607.     {
  608.       $type =~ s/(1 arg)/(2 arg)/;
  609.     }
  610.     if (($tmp2=index($type,",unique")) >= 0)
  611.     {
  612.       $type=substr($type,0,$tmp2);
  613.     }
  614.     $tmp2=$type;
  615.     $tmp2 =~ s/ /_/g;
  616.     $tmp2 =~ s/_not_null//g;
  617.     report("Type $type","type_$types->[0]_$tmp2",
  618.    "create table crash_q (q $use_type)",
  619.    "drop table crash_q $drop_attr");
  620.   }
  621. }
  622. #
  623. # Test some type limits
  624. #
  625. check_and_report("Remembers end space in char()","remember_end_space",
  626.  ["create table crash_q (a char(10))",
  627.   "insert into crash_q values('hello ')"],
  628.  "select a from crash_q where a = 'hello '",
  629.  ["drop table crash_q $drop_attr"],
  630.  'hello ',6);
  631. check_and_report("Remembers end space in varchar()",
  632.  "remember_end_space_varchar",
  633.  ["create table crash_q (a varchar(10))",
  634.   "insert into crash_q values('hello ')"],
  635.  "select a from crash_q where a = 'hello '",
  636.  ["drop table crash_q $drop_attr"],
  637.  'hello ',6);
  638. if (($limits{'type_extra_float(2_arg)'} eq "yes" ||
  639.     $limits{'type_sql_decimal(2_arg)'} eq "yes") &&
  640.     (!defined($limits{'storage_of_float'})))
  641. {
  642.   my $type=$limits{'type_extra_float(2_arg)'} eq "yes" ? "float(4,1)" :
  643.     "decimal(4,1)";
  644.   my $result="undefined";
  645.   if (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
  646.  "insert into crash_q values(1.14)"],
  647. "select q1 from crash_q",
  648. ["drop table crash_q $drop_attr"],1.1,0) &&
  649.       execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
  650.  "insert into crash_q values(1.16)"],
  651. "select q1 from crash_q",
  652. ["drop table crash_q $drop_attr"],1.1,0))
  653.   {
  654.     $result="truncate";
  655.   }
  656.   elsif (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
  657.     "insert into crash_q values(1.14)"],
  658.    "select q1 from crash_q",
  659.    ["drop table crash_q $drop_attr"],1.1,0) &&
  660.  execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
  661.     "insert into crash_q values(1.16)"],
  662.    "select q1 from crash_q",
  663.    ["drop table crash_q $drop_attr"],1.2,0))
  664.   {
  665.     $result="round";
  666.   }
  667.   elsif (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
  668.     "insert into crash_q values(1.14)"],
  669.    "select q1 from crash_q",
  670.    ["drop table crash_q $drop_attr"],1.14,0) &&
  671.  execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
  672.     "insert into crash_q values(1.16)"],
  673.    "select q1 from crash_q",
  674.    ["drop table crash_q $drop_attr"],1.16,0))
  675.   {
  676.     $result="exact";
  677.   }
  678.   $prompt="Storage of float values";
  679.   print "$prompt: $resultn";
  680.   save_config_data("storage_of_float", $result, $prompt);
  681. }
  682. try_and_report("Type for row id", "rowid",
  683.        ["rowid",
  684. "create table crash_q (a rowid)",
  685. "drop table crash_q $drop_attr"],
  686.        ["auto_increment",
  687. "create table crash_q (a int not null auto_increment".
  688. ", primary key(a))","drop table crash_q $drop_attr"],
  689.        ["oid",
  690. "create table crash_q (a oid, primary key(a))",
  691. "drop table crash_q $drop_attr"],
  692.        ["serial",
  693. "create table crash_q (a serial, primary key(a))",
  694. "drop table crash_q $drop_attr"]);
  695. try_and_report("Automatic row id", "automatic_rowid",
  696.        ["_rowid",
  697. "create table crash_q (a int not null, primary key(a))",
  698. "insert into crash_q values (1)",
  699. "select _rowid from crash_q",
  700. "drop table crash_q $drop_attr"]);
  701. #
  702. # Test functions
  703. #
  704. @sql_functions=
  705.   (["+, -, * and /","+","5*3-4/2+1",14,0],
  706.    ["ANSI SQL SUBSTRING","substring","substring('abcd' from 2 for 2)","bc",1],
  707.    ["BIT_LENGTH","bit_length","bit_length('abc')",24,0],
  708.    ["searched CASE","searched_case",
  709.      "case when 1 > 2 then 'false' when 2 > 1 then 'true' end", "true",1],
  710.    ["simple CASE","simple_case",
  711.      "case 2 when 1 then 'false' when 2 then 'true' end", "true",1],
  712.    ["CAST","cast","CAST(1 as CHAR)","1",1],
  713.    ["CHARACTER_LENGTH","character_length","character_length('abcd')","4",0],
  714.    ["CHAR_LENGTH","char_length","char_length(b)","10",0],
  715.    ["CHAR_LENGTH(constant)","char_length(constant)",
  716.      "char_length('abcd')","4",0],
  717.    ["COALESCE","coalesce","coalesce($char_null,'bcd','qwe')","bcd",1],
  718.    ["CURRENT_DATE","current_date","current_date",0,2],
  719.    ["CURRENT_TIME","current_time","current_time",0,2],
  720.    ["CURRENT_TIMESTAMP","current_timestamp","current_timestamp",0,2],
  721.    ["EXTRACT","extract_sql",
  722.      "extract(minute from timestamp '2000-02-23 18:43:12.987')",43,0],
  723.    ["LOCALTIME","localtime","localtime",0,2],
  724.    ["LOCALTIMESTAMP","localtimestamp","localtimestamp",0,2],
  725.    ["LOWER","lower","LOWER('ABC')","abc",1],
  726.    ["NULLIF with strings","nullif_string",
  727.        "NULLIF(NULLIF('first','second'),'first')",undef(),4],
  728.    ["NULLIF with numbers","nullif_num","NULLIF(NULLIF(1,2),1)",undef(),4],
  729.    ["OCTET_LENGTH","octet_length","octet_length('abc')",3,0],
  730.    ["POSITION","position","position('ll' in 'hello')",3,0],
  731.    ["TRIM","trim","trim(trailing from trim(LEADING FROM ' abc '))","abc",3],
  732.    ["UPPER","upper","UPPER('abc')","ABC",1],
  733.    ["concatenation with ||","concat_as_||","'abc' || 'def'","abcdef",1],
  734.    );
  735. @odbc_functions=
  736.   (["ASCII", "ascii", "ASCII('A')","65",0],
  737.    ["CHAR", "char", "CHAR(65)"  ,"A",1],
  738.    ["CONCAT(2 arg)","concat", "concat('a','b')","ab",1],
  739.    ["DIFFERENCE()","difference","difference('abc','abe')",3,0],
  740.    ["INSERT","insert","insert('abcd',2,2,'ef')","aefd",1],
  741.    ["LEFT","left","left('abcd',2)","ab",1],
  742.    ["LTRIM","ltrim","ltrim('   abcd')","abcd",1],
  743.    ["REAL LENGTH","length","length('abcd ')","5",0],
  744.    ["ODBC LENGTH","length_without_space","length('abcd ')","4",0],
  745.    ["LOCATE(2 arg)","locate_2","locate('bcd','abcd')","2",0],
  746.    ["LOCATE(3 arg)","locate_3","locate('bcd','abcd',3)","0",0],
  747.    ["LCASE","lcase","lcase('ABC')","abc",1],
  748.    ["REPEAT","repeat","repeat('ab',3)","ababab",1],
  749.    ["REPLACE","replace","replace('abbaab','ab','ba')","bababa",1],
  750.    ["RIGHT","right","right('abcd',2)","cd",1],
  751.    ["RTRIM","rtrim","rtrim(' abcd  ')"," abcd",1],
  752.    ["SPACE","space","space(5)","     ",3],
  753.    ["SOUNDEX","soundex","soundex('hello')",0,2],
  754.    ["ODBC SUBSTRING","substring","substring('abcd',3,2)","cd",1],
  755.    ["UCASE","ucase","ucase('abc')","ABC",1],
  756.    ["ABS","abs","abs(-5)",5,0],
  757.    ["ACOS","acos","acos(0)","1.570796",0],
  758.    ["ASIN","asin","asin(1)","1.570796",0],
  759.    ["ATAN","atan","atan(1)","0.785398",0],
  760.    ["ATAN2","atan2","atan2(1,0)","1.570796",0],
  761.    ["CEILING","ceiling","ceiling(-4.5)",-4,0],
  762.    ["COS","cos","cos(0)","1.00000",0],
  763.    ["COT","cot","cot(1)","0.64209262",0],
  764.    ["DEGREES","degrees","degrees(6.283185)","360",0],
  765.    ["EXP","exp","exp(1.0)","2.718282",0],
  766.    ["FLOOR","floor","floor(2.5)","2",0],
  767.    ["LOG","log","log(2)","0.693147",0],
  768.    ["LOG10","log10","log10(10)","1",0],
  769.    ["MOD","mod","mod(11,7)","4",0],
  770.    ["PI","pi","pi()","3.141593",0],
  771.    ["POWER","power","power(2,4)","16",0],
  772.    ["RAND","rand","rand(1)",0,2],       # Any value is acceptable
  773.    ["RADIANS","radians","radians(360)","6.283185",0],
  774.    ["ROUND(2 arg)","round","round(5.63,2)","5.6",0],
  775.    ["SIGN","sign","sign(-5)",-1,0],
  776.    ["SIN","sin","sin(1)","0.841471",0],
  777.    ["SQRT","sqrt","sqrt(4)",2,0],
  778.    ["TAN","tan","tan(1)","1.557408",0],
  779.    ["TRUNCATE","truncate","truncate(18.18,-1)",10,0],
  780.    ["NOW","now","now()",0,2],           # Any value is acceptable
  781.    ["CURDATE","curdate","curdate()",0,2],
  782.    ["CURTIME","curtime","curtime()",0,2],
  783.    ["TIMESTAMPADD","timestampadd",
  784.     "timestampadd(SQL_TSI_SECOND,1,'1997-01-01 00:00:00')",
  785.     "1997-01-01 00:00:01",1],
  786.    ["TIMESTAMPDIFF","timestampdiff",
  787.     "timestampdiff(SQL_TSI_SECOND,'1997-01-01 00:00:02',".
  788.      " '1997-01-01 00:00:01')","1",0],
  789.    ["USER()","user()","user()",0,2],
  790.    ["DATABASE","database","database()",0,2],
  791.    ["IFNULL","ifnull","ifnull(2,3)",2,0],
  792.    ["ODBC syntax LEFT & RIGHT", "fn_left",
  793.     "{ fn LEFT( { fn RIGHT('abcd',2) },1) }","c",1],
  794.    );
  795. @extra_functions=
  796.   (
  797.    ["& (bitwise and)",'&',"5 & 3",1,0],
  798.    ["| (bitwise or)",'|',"1 | 2",3,0],
  799.    ["<< and >> (bitwise shifts)",'binary_shifts',"(1 << 4) >> 2",4,0],
  800.    ["<> in SELECT","<>","1<>1","0",0],
  801.    ["=","=","(1=1)",1,$logical_value],
  802.    ["~* (case insensitive compare)","~*","'hi' ~* 'HI'",1,$logical_value],
  803.    ["AND and OR in SELECT","and_or","1=1 AND 2=2",$logical_value,0],
  804.    ["AND as '&&'",'&&',"1=1 && 2=2",$logical_value,0],
  805.    ["ASCII_CHAR", "ascii_char", "ASCII_CHAR(65)","A",1],
  806.    ["ASCII_CODE", "ascii_code", "ASCII_CODE('A')","65",0],
  807.    ["ATN2","atn2","atn2(1,0)","1.570796",0],
  808.    ["BETWEEN in SELECT","between","5 between 4 and 6",$logical_value,0],
  809.    ["BIT_COUNT","bit_count","bit_count(5)",2,0],
  810.    ["CEIL","ceil","ceil(-4.5)",-4,0], # oracle
  811.    ["CHARINDEX","charindex","charindex('a','crash')",3,0],
  812.    ["CHR", "chr", "CHR(65)"  ,"A",1], # oracle
  813.    ["CONCAT(list)","concat_list", "concat('a','b','c','d')","abcd",1],
  814.    ["CONVERT","convert","convert(CHAR,5)","5",1],
  815.    ["COSH","cosh","cosh(0)","1",0], # oracle hyperbolic cosine of n.
  816.    ["ELT","elt","elt(2,'ONE','TWO','THREE')","TWO",1],
  817.    ["ENCRYPT","encrypt","encrypt('hello')",0,2],
  818.    ["FIELD","field","field('IBM','NCA','ICL','SUN','IBM','DIGITAL')",4,0],
  819.    ["FORMAT","format","format(1234.5555,2)","1,234.56",1],
  820.    ["GETDATE","getdate","getdate()",0,2],
  821.    ["GREATEST","greatest","greatest('HARRY','HARRIOT','HAROLD')","HARRY",1],
  822.    ["IF","if", "if(5,6,7)",6,0],
  823.    ["IN on numbers in SELECT","in_num","2 in (3,2,5,9,5,1)",$logical_value,0],
  824.    ["IN on strings in SELECT","in_str","'monty' in ('david','monty','allan')", $logical_value,0],
  825.    ["INITCAP","initcap","initcap('the soap')","The Soap",1], 
  826.        # oracle Returns char, with the first letter of each word in uppercase
  827.    ["INSTR (Oracle syntax)", "instr_oracle", "INSTR('CORPORATE FLOOR','OR',3,2)"  ,"14",0], # oracle instring
  828.    ["INSTRB", "instrb", "INSTRB('CORPORATE FLOOR','OR',5,2)"  ,"27",0], 
  829.       # oracle instring in bytes
  830.    ["INTERVAL","interval","interval(55,10,20,30,40,50,60,70,80,90,100)",5,0],
  831.    ["LAST_INSERT_ID","last_insert_id","last_insert_id()",0,2],
  832.    ["LEAST","least","least('HARRY','HARRIOT','HAROLD')","HAROLD",1], 
  833.       # oracle
  834.    ["LENGTHB","lengthb","lengthb('CANDIDE')","14",0], 
  835.       # oracle length in bytes
  836.    ["LIKE ESCAPE in SELECT","like_escape",
  837.      "'%' like 'a%' escape 'a'",$logical_value,0],
  838.    ["LIKE in SELECT","like","'a' like 'a%'",$logical_value,0],
  839.    ["LN","ln","ln(95)","4.55387689",0], 
  840.       # oracle natural logarithm of n
  841.    ["LOCATE as INSTR","instr","instr('hello','ll')",3,0],
  842.    ["LOG(m,n)","log(m_n)","log(10,100)","2",0], 
  843.       # oracle logarithm, base m, of n
  844.    ["LOGN","logn","logn(2)","0.693147",0], 
  845.       # informix
  846.    ["LPAD","lpad","lpad('hi',4,'??')",'??hi',3],
  847.    ["MOD as %","%","10%7","3",0],
  848.    ["NOT BETWEEN in SELECT","not_between","5 not between 4 and 6",0,0],
  849.    ["NOT LIKE in SELECT","not_like","'a' not like 'a%'",0,0],
  850.    ["NOT as '!' in SELECT","!","! 1",0,0],
  851.    ["NOT in SELECT","not","not $false",$logical_value,0],
  852.    ["ODBC CONVERT","odbc_convert","convert(5,SQL_CHAR)","5",1],
  853.    ["OR as '||'",'||',"1=0 || 1=1",$logical_value,0],
  854.    ["PASSWORD","password","password('hello')",0,2],
  855.    ["PASTE", "paste", "paste('ABCDEFG',3,2,'1234')","AB1234EFG",1],
  856.    ["PATINDEX","patindex","patindex('%a%','crash')",3,0],
  857.    ["POW","pow","pow(3,2)",9,0],
  858.    ["RANGE","range","range(a)","0.0",0], 
  859.        # informix range(a) = max(a) - min(a)
  860.    ["REGEXP in SELECT","regexp","'a' regexp '^(a|b)*$'",$logical_value,0],
  861.    ["REPLICATE","replicate","replicate('a',5)","aaaaa",1],
  862.    ["REVERSE","reverse","reverse('abcd')","dcba",1],
  863.    ["ROOT","root","root(4)",2,0], # informix
  864.    ["ROUND(1 arg)","round1","round(5.63)","6",0],
  865.    ["RPAD","rpad","rpad('hi',4,'??')",'hi??',3],
  866.    ["SINH","sinh","sinh(1)","1.17520119",0], # oracle hyperbolic sine of n
  867.    ["STR","str","str(123.45,5,1)",123.5,3],
  868.    ["STRCMP","strcmp","strcmp('abc','adc')",-1,0],
  869.    ["STUFF","stuff","stuff('abc',2,3,'xyz')",'axyz',3],
  870.    ["SUBSTRB", "substrb", "SUBSTRB('ABCDEFG',5,4.2)"  ,"CD",1], 
  871.       # oracle substring with bytes
  872.    ["SUBSTRING as MID","mid","mid('hello',3,2)","ll",1],
  873.    ["SUBSTRING_INDEX","substring_index",
  874.      "substring_index('www.tcx.se','.',-2)", "tcx.se",1],
  875.    ["SYSDATE","sysdate","sysdate()",0,2],
  876.    ["TAIL","tail","tail('ABCDEFG',3)","EFG",0],
  877.    ["TANH","tanh","tanh(1)","0.462117157",0], 
  878.       # oracle hyperbolic tangent of n
  879.    ["TRANSLATE","translate","translate('abc','bc','de')",'ade',3],
  880.    ["TRIM; Many char extension",
  881.      "trim_many_char","trim(':!' FROM ':abc!')","abc",3],
  882.    ["TRIM; Substring extension",
  883.      "trim_substring","trim('cb' FROM 'abccb')","abc",3],
  884.    ["TRUNC","trunc","trunc(18.18,-1)",10,0], # oracle
  885.    ["UID","uid","uid",0,2], # oracle uid from user
  886.    ["UNIX_TIMESTAMP","unix_timestamp","unix_timestamp()",0,2],
  887.    ["USERENV","userenv","userenv",0,2], # oracle user enviroment
  888.    ["VERSION","version","version()",0,2],
  889.    ["automatic num->string convert","auto_num2string","concat('a',2)","a2",1],
  890.    ["automatic string->num convert","auto_string2num","'1'+2",3,0],
  891.    ["concatenation with +","concat_as_+","'abc' + 'def'","abcdef",1],
  892.    ["SUBSTR (2 arg)",'substr2arg',"substr('abcd',2)",'bcd',1],  #sapdb func
  893.    ["SUBSTR (3 arg)",'substr3arg',"substr('abcd',2,2)",'bc',1],
  894.    ["LFILL (3 arg)",'lfill3arg',"lfill('abcd','.',6)",'..abcd',1],
  895.    ["RFILL (3 arg)",'rfill3arg',"rfill('abcd','.',6)",'abcd..',1],
  896.    ["RPAD (4 arg)",'rpad4arg',"rpad('abcd',2,'+-',8)",'abcd+-+-',1],
  897.    ["LPAD (4 arg)",'rpad4arg',"lpad('abcd',2,'+-',8)",'+-+-abcd',1],
  898.    ["TRIM (1 arg)",'trim1arg',"trim(' abcd ')",'abcd',1],
  899.    ["TRIM (2 arg)",'trim2arg',"trim('..abcd..','.')",'abcd',1],
  900.    ["LTRIM (2 arg)",'ltrim2arg',"ltrim('..abcd..','.')",'abcd..',1],
  901.    ["RTRIM (2 arg)",'rtrim2arg',"rtrim('..abcd..','.')",'..abcd',1],
  902.    ["EXPAND",'expand2arg',"expand('abcd',6)",'abcd  ',0],
  903.    ["REPLACE (2 arg) ",'replace2arg',"replace('AbCd','bC')",'Ad',1],
  904.    ["MAPCHAR",'mapchar',"mapchar('A