📄 mysqltest.c
字号:
}#endif/* Source and execute the given file SYNOPSIS do_source() query called command DESCRIPTION source <file_name> Open the file <file_name> and execute it*/int do_source(struct st_query *query){ char *p= query->first_argument, *name; if (!*p) die("Missing file name in source"); name= p; while (*p && !my_isspace(charset_info,*p)) p++; if (*p) *p++= 0; query->last_argument= p; /* If this file has already been sourced, don't source it again. It's already available in the q_lines cache. */ if (parser.current_line < (parser.read_lines - 1)) return 0; return open_file(name);}#ifdef __WIN__/* Variables used for temuprary sh files used for emulating Unix on Windows */char tmp_sh_name[64], tmp_sh_cmd[70];static void init_tmp_sh_file(){ /* Format a name for the tmp sh file that is unique for this process */ my_snprintf(tmp_sh_name, sizeof(tmp_sh_name), "tmp_%d.sh", getpid()); /* Format the command to execute in order to run the script */ my_snprintf(tmp_sh_cmd, sizeof(tmp_sh_cmd), "sh %s", tmp_sh_name);}static void free_tmp_sh_file(){ my_delete(tmp_sh_name, MYF(0));}#endifFILE* my_popen(DYNAMIC_STRING* ds_cmd, const char* mode){#ifdef __WIN__ /* Dump the command into a sh script file and execute with popen */ str_to_file(tmp_sh_name, ds_cmd->str, ds_cmd->length); return popen(tmp_sh_cmd, mode);#else return popen(ds_cmd->str, mode);#endif}/* Execute given command. SYNOPSIS do_exec() query called command DESCRIPTION exec <command> Execute the text between exec and end of line in a subprocess. The error code returned from the subprocess is checked against the expected error array, previously set with the --error command. It can thus be used to execute a command that shall fail. NOTE Although mysqltest is executed from cygwin shell, the command will be executed in "cmd.exe". Thus commands like "rm" etc can NOT be used, use system for those commands.*/static void do_exec(struct st_query *query){ int error; char buf[1024]; FILE *res_file; char *cmd= query->first_argument; DYNAMIC_STRING ds_cmd; DBUG_ENTER("do_exec"); DBUG_PRINT("enter", ("cmd: '%s'", cmd)); while (*cmd && my_isspace(charset_info, *cmd)) cmd++; if (!*cmd) die("Missing argument in exec"); query->last_argument= query->end; init_dynamic_string(&ds_cmd, 0, strlen(cmd)+256, 256); /* Eval the command, thus replacing all environment variables */ do_eval(&ds_cmd, cmd, TRUE); cmd= ds_cmd.str; DBUG_PRINT("info", ("Executing '%s' as '%s'", query->first_argument, cmd)); if (!(res_file= my_popen(&ds_cmd, "r")) && query->abort_on_error) die("popen(\"%s\", \"r\") failed", query->first_argument); while (fgets(buf, sizeof(buf), res_file)) { if (disable_result_log) { buf[strlen(buf)-1]=0; DBUG_PRINT("exec_result",("%s", buf)); } else { replace_dynstr_append(&ds_res, buf); } } error= pclose(res_file); if (error != 0) { uint status= WEXITSTATUS(error), i; my_bool ok= 0; if (query->abort_on_error) die("command \"%s\" failed", query->first_argument); DBUG_PRINT("info", ("error: %d, status: %d", error, status)); for (i= 0; i < query->expected_errors; i++) { DBUG_PRINT("info", ("expected error: %d", query->expected_errno[i].code.errnum)); if ((query->expected_errno[i].type == ERR_ERRNO) && (query->expected_errno[i].code.errnum == status)) { ok= 1; DBUG_PRINT("info", ("command \"%s\" failed with expected error: %d", query->first_argument, status)); } } if (!ok) die("command \"%s\" failed with wrong error: %d", query->first_argument, status); } else if (query->expected_errno[0].type == ERR_ERRNO && query->expected_errno[0].code.errnum != 0) { /* Error code we wanted was != 0, i.e. not an expected success */ die("command \"%s\" succeeded - should have failed with errno %d...", query->first_argument, query->expected_errno[0].code.errnum); } free_replace(); DBUG_VOID_RETURN;}/* Set variable from the result of a query SYNOPSIS var_query_set() var variable to set from query query start of query string to execute query_end end of the query string to execute DESCRIPTION let @<var_name> = `<query>` Execute the query and assign the first row of result to var as a tab separated strings Also assign each column of the result set to variable "$<var_name>_<column_name>" Thus the tab separated output can be read from $<var_name> and and each individual column can be read as $<var_name>_<col_name>*/int var_query_set(VAR* var, const char *query, const char** query_end){ char* end = (char*)((query_end && *query_end) ? *query_end : query + strlen(query)); MYSQL_RES *res; MYSQL_ROW row; MYSQL* mysql = &cur_con->mysql; LINT_INIT(res); while (end > query && *end != '`') --end; if (query == end) die("Syntax error in query, missing '`'"); ++query; if (mysql_real_query(mysql, query, (int)(end - query)) || !(res = mysql_store_result(mysql))) { *end = 0; die("Error running query '%s': %d: %s", query, mysql_errno(mysql) ,mysql_error(mysql)); } if ((row = mysql_fetch_row(res)) && row[0]) { /* Concatenate all row results with tab in between to allow us to work with results from many columns (for example from SHOW VARIABLES) */ DYNAMIC_STRING result; uint i; ulong *lengths; char *end; MYSQL_FIELD *fields= mysql_fetch_fields(res); init_dynamic_string(&result, "", 16384, 65536); lengths= mysql_fetch_lengths(res); for (i=0; i < mysql_num_fields(res); i++) { if (row[0]) {#ifdef NOT_YET /* Add to <var_name>_<col_name> */ uint j; char var_col_name[MAX_VAR_NAME]; uint length= snprintf(var_col_name, MAX_VAR_NAME, "$%s_%s", var->name, fields[i].name); /* Convert characters not allowed in variable names to '_' */ for (j= 1; j < length; j++) { if (!my_isvar(charset_info,var_col_name[j])) var_col_name[j]= '_'; } var_set(var_col_name, var_col_name + length, row[i], row[i] + lengths[i]);#endif /* Add column to tab separated string */ dynstr_append_mem(&result, row[i], lengths[i]); } dynstr_append_mem(&result, "\t", 1); } end= result.str + result.length-1; eval_expr(var, result.str, (const char**) &end); dynstr_free(&result); } else eval_expr(var, "", 0); mysql_free_result(res); return 0;}void var_copy(VAR *dest, VAR *src){ dest->int_val= src->int_val; dest->int_dirty= src->int_dirty; /* Alloc/realloc data for str_val in dest */ if (dest->alloced_len < src->alloced_len && !(dest->str_val= dest->str_val ? my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME)) : my_malloc(src->alloced_len, MYF(MY_WME)))) die("Out of memory"); else dest->alloced_len= src->alloced_len; /* Copy str_val data to dest */ dest->str_val_len= src->str_val_len; if (src->str_val_len) memcpy(dest->str_val, src->str_val, src->str_val_len);}int eval_expr(VAR* v, const char *p, const char** p_end){ VAR* vp; if (*p == '$') { if ((vp = var_get(p,p_end,0,0))) { var_copy(v, vp); return 0; } } else if (*p == '`') { return var_query_set(v, p, p_end); } else { int new_val_len = (p_end && *p_end) ? (int) (*p_end - p) : (int) strlen(p); if (new_val_len + 1 >= v->alloced_len) { v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ? MIN_VAR_ALLOC : new_val_len + 1; if (!(v->str_val = v->str_val ? my_realloc(v->str_val, v->alloced_len+1, MYF(MY_WME)) : my_malloc(v->alloced_len+1, MYF(MY_WME)))) die("Out of memory"); } v->str_val_len = new_val_len; memcpy(v->str_val, p, new_val_len); v->str_val[new_val_len] = 0; v->int_val=atoi(p); v->int_dirty=0; return 0; } die("Invalid expr: %s", p); return 1;}enum enum_operator{ DO_DEC, DO_INC};/* Decrease or increase the value of a variable SYNOPSIS do_modify_var() query called command operator operation to perform on the var DESCRIPTION dec $var_name inc $var_name*/int do_modify_var(struct st_query *query, enum enum_operator operator){ const char *p= query->first_argument; VAR* v; if (!*p) die("Missing argument to %.*s", query->first_word_len, query->query); if (*p != '$') die("The argument to %.*s must be a variable (start with $)", query->first_word_len, query->query); v= var_get(p, &p, 1, 0); switch (operator) { case DO_DEC: v->int_val--; break; case DO_INC: v->int_val++; break; default: die("Invalid operator to do_modify_var"); break; } v->int_dirty= 1; query->last_argument= (char*)++p; return 0;}/* Wrapper for 'system' function NOTE If mysqltest is executed from cygwin shell, the command will be executed in the "windows command interpreter" cmd.exe and we prepend "sh" to make it be executed by cygwins "bash". Thus commands like "rm", "mkdir" as well as shellscripts can executed by "system" in Windows.*/int my_system(DYNAMIC_STRING* ds_cmd){#ifdef __WIN__ /* Dump the command into a sh script file and execute with system */ str_to_file(tmp_sh_name, ds_cmd->str, ds_cmd->length); return system(tmp_sh_cmd);#else return system(ds_cmd->str);#endif}/* SYNOPSIS do_system command called command DESCRIPTION system <command> Eval the query to expand any $variables in the command. Execute the command with the "system" command.*/void do_system(struct st_query *command){ DYNAMIC_STRING ds_cmd; DBUG_ENTER("do_system"); if (strlen(command->first_argument) == 0) die("Missing arguments to system, nothing to do!"); init_dynamic_string(&ds_cmd, 0, strlen(command->first_argument) + 64, 256); /* Eval the system command, thus replacing all environment variables */ do_eval(&ds_cmd, command->first_argument, TRUE); DBUG_PRINT("info", ("running system command '%s' as '%s'", command->first_argument, ds_cmd.str)); if (my_system(&ds_cmd)) { if (command->abort_on_error) die("system command '%s' failed", command->first_argument); /* If ! abort_on_error, log message and continue */ dynstr_append(&ds_res, "system command '"); replace_dynstr_append(&ds_res, command->first_argument); dynstr_append(&ds_res, "' failed\n"); } command->last_argument= command->end; DBUG_VOID_RETURN;}/* Print the content between echo and <delimiter> to result file. Evaluate all variables in the string before printing, allow for variable names to be escaped using \ SYNOPSIS do_echo() q called command DESCRIPTION echo text Print the text after echo until end of command to result file echo $<var_name> Print the content of the variable <var_name> to result file echo Some text $<var_name> Print "Some text" plus the content of the variable <var_name> to result file echo Some text \$<var_name> Print "Some text" plus $<var_name> to result file*/int do_echo(struct st_query *command){ DYNAMIC_STRING *ds, ds_echo; ds= &ds_res; init_dynamic_string(&ds_echo, "", 256, 256); do_eval(&ds_echo, command->first_argument, FALSE); dynstr_append_mem(ds, ds_echo.str, ds_echo.length); dynstr_append_mem(ds, "\n", 1); dynstr_free(&ds_echo); command->last_argument= command->end; return 0;}int do_sync_with_master2(long offset){ MYSQL_RES* res; MYSQL_ROW row; MYSQL* mysql= &cur_con->mysql; char query_buf[FN_REFLEN+128]; int tries= 0; int rpl_parse; if (!master_pos.file[0]) die("Calling 'sync_with_master' without calling 'save_master_pos'"); rpl_parse= mysql_rpl_parse_enabled(mysql); mysql_disable_rpl_parse(mysql); sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file, master_pos.pos + offset);wait_for_position: if (mysql_query(mysql, query_buf)) die("failed in %s: %d: %s", query_buf, mysql_errno(mysql), mysql_error(mysql)); if (!(res= mysql_store_result(mysql))) die("mysql_store_result() returned NULL for '%s'", query_buf); if (!(row= mysql_fetch_row(res))) die("empty result in %s", query_buf); if (!row[0]) { /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -