From: Bjorn Munch Date: October 6 2010 9:15am Subject: bzr commit into mysql-5.5-mtr branch (bjorn.munch:3097) Bug#57276 List-Archive: http://lists.mysql.com/commits/120073 X-Bug: 57276 Message-Id: <201010060915.o969F6i4021707@khepri15.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1382358468==" --===============1382358468== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/bm136801/my/ifexpr-55/ based on revid:bjorn.munch@stripped 3097 Bjorn Munch 2010-10-06 Bug #57276 mysqltest: add support for simple compares in if/while conditions Added more parsing in do_block() Limitations: left operand must be variable, white space must surround operator Also changed var_set_int from 57036 to var_check_int Added tests to mysqltest.test Some tests can now be simplified but will take this later modified: client/mysqltest.cc mysql-test/r/mysqltest.result mysql-test/t/mysqltest.test === modified file 'client/mysqltest.cc' --- a/client/mysqltest.cc 2010-09-30 10:53:36 +0000 +++ b/client/mysqltest.cc 2010-10-06 09:11:03 +0000 @@ -479,7 +479,8 @@ VAR* var_init(VAR* v, const char *name, int val_len); VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw, my_bool ignore_not_existing); -void eval_expr(VAR* v, const char *p, const char** p_end); +void eval_expr(VAR* v, const char *p, const char** p_end, + my_bool open_end=FALSE); my_bool match_delimiter(int c, const char *delim, uint length); void dump_result_to_reject_file(char *buf, int size); void dump_warning_messages(); @@ -1959,9 +1960,11 @@ static void var_free(void *v) C_MODE_END -void var_set_int(VAR *v, const char *str) +void var_check_int(VAR *v) { char *endptr; + char *str= v->str_val; + /* Initially assume not a number */ v->int_val= 0; v->is_int= false; @@ -2008,7 +2011,7 @@ VAR *var_init(VAR *v, const char *name, memcpy(tmp_var->str_val, val, val_len); tmp_var->str_val[val_len]= 0; } - var_set_int(tmp_var, val); + var_check_int(tmp_var); tmp_var->name_len = name_len; tmp_var->str_val_len = val_len; tmp_var->alloced_len = val_alloc_len; @@ -2459,7 +2462,7 @@ void var_copy(VAR *dest, VAR *src) } -void eval_expr(VAR *v, const char *p, const char **p_end) +void eval_expr(VAR *v, const char *p, const char **p_end, my_bool open_end) { DBUG_ENTER("eval_expr"); @@ -2477,7 +2480,7 @@ void eval_expr(VAR *v, const char *p, co /* Make sure there was just a $variable and nothing else */ const char* end= *p_end + 1; - if (end < expected_end) + if (end < expected_end && !open_end) die("Found junk '%.*s' after $variable in expression", (int)(expected_end - end - 1), end); @@ -2524,7 +2527,7 @@ void eval_expr(VAR *v, const char *p, co v->str_val_len = new_val_len; memcpy(v->str_val, p, new_val_len); v->str_val[new_val_len] = 0; - var_set_int(v, p); + var_check_int(v); } DBUG_VOID_RETURN; } @@ -5417,6 +5420,40 @@ int do_done(struct st_command *command) return 0; } +/* Operands available in if or while conditions */ + +enum block_op { + EQ_OP, + NE_OP, + GT_OP, + GE_OP, + LT_OP, + LE_OP, + ILLEG_OP +}; + + +enum block_op find_operand(const char *start) +{ + char first= *start; + char next= *(start+1); + + if (first == '=' && next == '=') + return EQ_OP; + if (first == '!' && next == '=') + return NE_OP; + if (first == '>' && next == '=') + return GE_OP; + if (first == '>' && next == ' ') + return GT_OP; + if (first == '<' && next == '=') + return LE_OP; + if (first == '<' && next == ' ') + return LT_OP; + + return ILLEG_OP; +} + /* Process start of a "if" or "while" statement @@ -5442,6 +5479,13 @@ int do_done(struct st_command *command) A '!' can be used before the to indicate it should be executed if it evaluates to zero. + can also be a simple comparison condition: + + + + The left hand side must be a variable, the right hand side can be a + variable, number, string or `query`. Operands are ==, !=, <, <=, >, >=. + == and != can be used for strings, all can be used for numerical values. */ void do_block(enum block_cmd cmd, struct st_command* command) @@ -5477,6 +5521,9 @@ void do_block(enum block_cmd cmd, struct if (!expr_start++) die("missing '(' in %s", cmd_name); + while (my_isspace(charset_info, *expr_start)) + expr_start++; + /* Check for ! */ if (*expr_start == '!') { @@ -5495,14 +5542,84 @@ void do_block(enum block_cmd cmd, struct die("Missing '{' after %s. Found \"%s\"", cmd_name, p); var_init(&v,0,0,0,0); - eval_expr(&v, expr_start, &expr_end); + /* If expression starts with a variable, it may be a compare condition */ + + if (*expr_start == '$') + { + const char *curr_ptr= expr_end; + eval_expr(&v, expr_start, &curr_ptr, TRUE); + while (my_isspace(charset_info, *++curr_ptr)) ; + /* If there was nothing past the variable, skip condition part */ + if (curr_ptr == expr_end) + goto NO_COMPARE; + + enum block_op operand= find_operand(curr_ptr); + if (operand == ILLEG_OP) + die("Found junk '%.*s' after $variable in condition", + (int)(expr_end - curr_ptr), curr_ptr); + + /* We could silently allow this, but may be confusing */ + if (not_expr) + die("Negation and comparison should not be combined, please rewrite"); + + curr_ptr++; + while (my_isspace(charset_info, *++curr_ptr)) ; + + VAR v2; + var_init(&v2,0,0,0,0); + eval_expr(&v2, curr_ptr, &expr_end); + + if ((operand!=EQ_OP && operand!=NE_OP) && ! (v.is_int && v2.is_int)) + die ("Cannot use inequality operand on non-numeric values"); + + /* Now we overwrite the first variable with the value of 0 or 1 */ + + switch (operand) + { + case EQ_OP: + if (v.is_int) + v.int_val= (v2.is_int && v2.int_val == v.int_val); + else + v.int_val= !strcmp (v.str_val, v2.str_val); + break; + + case NE_OP: + if (v.is_int) + v.int_val= ! (v2.is_int && v2.int_val == v.int_val); + else + v.int_val= !! strcmp (v.str_val, v2.str_val); + break; + + case LT_OP: + v.int_val= (v.int_val < v2.int_val); + break; + case LE_OP: + v.int_val= (v.int_val <= v2.int_val); + break; + case GT_OP: + v.int_val= (v.int_val > v2.int_val); + break; + case GE_OP: + v.int_val= (v.int_val >= v2.int_val); + break; + } + + v.is_int= TRUE; + } else + { + if (*expr_start != '`' && ! my_isdigit(charset_info, *expr_start)) + die("Expression in if/while must beging with $, ` or a number"); + eval_expr(&v, expr_start, &expr_end); + } + + NO_COMPARE: /* Define inner block */ cur_block++; cur_block->cmd= cmd; - if (v.int_val) + if (v.is_int) { - cur_block->ok= TRUE; + cur_block->ok= (v.int_val != 0); } else /* Any non-empty string which does not begin with 0 is also TRUE */ { === modified file 'mysql-test/r/mysqltest.result' --- a/mysql-test/r/mysqltest.result 2010-09-28 14:00:11 +0000 +++ b/mysql-test/r/mysqltest.result 2010-10-06 09:11:03 +0000 @@ -401,8 +401,31 @@ true-outer Counter is greater than 0, (counter=10) Counter is not 0, (counter=0) Counter is true, (counter=alpha) -Beta is true while with string, only once +5<7 +5<6 +5>=5 +5>3 +5==5 +5!=8 +5==3+2 +5 == 5 +hello == hello +hello == hello +hello != goodbye +two words +two words are two words +right answer +anything goes +mysqltest: At line 2: Cannot use inequality operand on non-numeric values +mysqltest: At line 2: Found junk '<> 6' after $variable in condition +mysqltest: At line 2: Expression in if/while must beging with $, ` or a number +counter is 2 +counter is 3 +counter is 4 +counter is 5 +counter is 6 +counter is 7 1 Testing while with not mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest_while.inc": At line 64: Nesting too deeply @@ -807,8 +830,6 @@ dir-list.txt SELECT 'c:\\a.txt' AS col; col z -hej -mysqltest: At line 1: Found junk ' != 143' after $variable in expression select 1; 1 1 === modified file 'mysql-test/t/mysqltest.test' --- a/mysql-test/t/mysqltest.test 2010-09-28 14:00:11 +0000 +++ b/mysql-test/t/mysqltest.test 2010-10-06 09:11:03 +0000 @@ -1163,10 +1163,11 @@ if ($counter) { echo oops, -0 is true; } -if (beta) -{ - echo Beta is true; -} +# This is no longer allowed, as a precaution against mistyped conditionals +# if (beta) +# { +# echo Beta is true; +# } let $counter=gamma; while ($counter) { @@ -1175,6 +1176,152 @@ while ($counter) } # ---------------------------------------------------------------------------- +# Test if with compare conditions +# ---------------------------------------------------------------------------- + +let $ifvar= 5; +let $ifvar2= 6; + +if ($ifvar < 7) +{ + echo 5<7; +} +if ($ifvar < $ifvar2) +{ + echo 5<6; +} +if ($ifvar <= 4) +{ + echo 5<=4; +} +if ($ifvar >= 5) +{ + echo 5>=5; +} +if ($ifvar > 3) +{ + echo 5>3; +} +if ($ifvar == 4) +{ + echo 5==4; +} +if ($ifvar == 5) +{ + echo 5==5; +} +if ($ifvar != 8) +{ + echo 5!=8; +} +if ($ifvar == `SELECT 3+2`) +{ + echo 5==3+2; +} +if ($ifvar == 5) +{ + echo 5 == 5; +} +let $ifvar= hello; +if ($ifvar == hello there) +{ + echo hello == hello there; +} +if ($ifvar == hello) +{ + echo hello == hello; +} +if ($ifvar == hell) +{ + echo hello == hell; +} +if ($ifvar == hello) +{ + echo hello == hello; +} +if ($ifvar != goodbye) +{ + echo hello != goodbye; +} + +let $ifvar= two words; +if ($ifvar == two words) +{ + echo two words; +} +if ($ifvar == `SELECT 'two words'`) +{ + echo two words are two words; +} +if (42) +{ + echo right answer; +} +if (0) +{ + echo wrong answer; +} +if (`SELECT 'something'`) +{ + echo anything goes; +} + +--write_file $MYSQL_TMP_DIR/mysqltest.sql +let $var= 5; +if ($var >= four) +{ + echo 5>=four; +} +EOF +--error 1 +--exec $MYSQL_TEST < $MYSQL_TMP_DIR/mysqltest.sql 2>&1 +remove_file $MYSQL_TMP_DIR/mysqltest.sql; + +--write_file $MYSQL_TMP_DIR/mysqltest.sql +let $var= 5; +if ($var <> 6) +{ + echo 5<>6; +} +EOF +--error 1 +--exec $MYSQL_TEST < $MYSQL_TMP_DIR/mysqltest.sql 2>&1 +remove_file $MYSQL_TMP_DIR/mysqltest.sql; + +--write_file $MYSQL_TMP_DIR/mysqltest.sql +let $var= text; +if (var == text) +{ + echo Oops I forgot the $; +} +EOF +--error 1 +--exec $MYSQL_TEST < $MYSQL_TMP_DIR/mysqltest.sql 2>&1 +remove_file $MYSQL_TMP_DIR/mysqltest.sql; + +# ---------------------------------------------------------------------------- +# Test while with compare conditions +# ---------------------------------------------------------------------------- + +let $counter= 2; + +while ($counter < 5) +{ + echo counter is $counter; + inc $counter; +} +let $ifvar=; +while ($ifvar != stop) +{ + if ($counter >= 7) + { + let $ifvar= stop; + } + echo counter is $counter; + inc $counter; +} + +# ---------------------------------------------------------------------------- # Test while, { and } # ---------------------------------------------------------------------------- @@ -2529,26 +2676,6 @@ rmdir $MYSQLTEST_VARDIR/tmp/testdir; --replace_result c:\\a.txt z SELECT 'c:\\a.txt' AS col; -# -# Bug#32307 mysqltest - does not detect illegal if syntax -# - -let $test= 1; -if ($test){ - echo hej; -} - ---write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql -if ($mysql_errno != 1436) -{ - echo ^ Should not be allowed! -} -EOF ---error 1 ---exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1 -remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql; - - # ---------------------------------------------------------------------------- # Test that -- is not allowed as comment, only as mysqltest builtin command # ---------------------------------------------------------------------------- --===============1382358468== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/bjorn.munch@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: bjorn.munch@stripped # target_branch: file:///home/bm136801/my/ifexpr-55/ # testament_sha1: 749884940258435cd0a6ab97369b0cae10471ab6 # timestamp: 2010-10-06 11:15:06 +0200 # base_revision_id: bjorn.munch@stripped\ # q19eozae1v9mate8 # # Begin bundle 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 --===============1382358468==--