diff options
144 files changed, 4506 insertions, 1997 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index e7152099ed3..f09109774f9 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -98,12 +98,14 @@ kaj@work.mysql.com kent@mysql.com konstantin@mysql.com kostja@oak.local +lars@mysql.com lenz@kallisto.mysql.com lenz@mysql.com magnus@neptunus.(none) magnus@shellback.(none) marko@hundin.mysql.fi matt@mysql.com +matthias@three.local.lan miguel@hegel.(none) miguel@hegel.br miguel@hegel.local diff --git a/Docs/Support/texi2html b/Docs/Support/texi2html index 8067d8f72ce..f13c006c7dc 100755 --- a/Docs/Support/texi2html +++ b/Docs/Support/texi2html @@ -1,4 +1,4 @@ -#!PATH_TO_PERL -*- perl -*- +#!/usr/bin/perl # Add path to perl on the previous line and make this executable # if you want to use this as a normal script. 'di '; @@ -12,7 +12,7 @@ #-############################################################################## # @(#)texi2html 1.52 971230 Written (mainly) by Lionel Cons, Lionel.Cons@cern.ch -# Enhanced by David Axmark, david@detron.se +# Enhanced by David Axmark # The man page for this program is included at the end of this file and can be # viewed using the command 'nroff -man texi2html'. @@ -40,8 +40,7 @@ $NODESRE = '[^@{}:\'`"]+'; # RE for a list of node names $XREFRE = '[^@{}]+'; # RE for a xref (should use NODERE) $ERROR = "***"; # prefix for errors and warnings -$THISPROG = "texi2html 1.52 (hacked by david\@detron.se)"; # program name and version -$HOMEPAGE = "http://www.mathematik.uni-kl.de/~obachman/Texi2html/"; # program home page +$THISPROG = "texi2html 1.52 (with additions by MySQL AB)"; # program name and version $TODAY = &pretty_date; # like "20 September 1993" $SPLITTAG = "<!-- SPLIT HERE -->\n"; # tag to know where to split $PROTECTTAG = "_ThisIsProtected_"; # tag to recognize protected sections @@ -114,10 +113,12 @@ $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//E # %accent_map = ( '"', 'uml', + '\'', 'acute', + ',{', 'cedil', '~', 'tilde', '^', 'circ', '`', 'grave', - '\'', 'acute', + 'ringaccent{', 'ring', ); # @@ -125,7 +126,7 @@ $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//E # %simple_map = ( # cf. makeinfo.c - "*", "<BR>", # HTML+ + "*", "<br />", # HTML+ " ", " ", "\n", "\n", "|", "", @@ -134,6 +135,8 @@ $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//E "!", "!", "?", "?", ".", ".", + # @- means "allow word break", not — + "-", "", ); # @@ -141,9 +144,10 @@ $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//E # %things_map = ( 'TeX', 'TeX', - 'br', '<P>', # paragraph break + 'br', '<p>', # paragraph break 'bullet', '*', 'copyright', '(C)', + 'registeredsymbol', '(R)', 'dots', '...', 'equiv', '==', 'error', 'error-->', @@ -161,27 +165,28 @@ $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//E %style_map = ( 'asis', '', 'b', 'B', - 'cite', 'CITE', - 'code', 'CODE', + 'cite', 'cite', + 'code', 'code', + 'command', 'code', 'ctrl', '&do_ctrl', # special case - 'dfn', 'STRONG', # DFN tag is illegal in the standard + 'dfn', 'strong', # DFN tag is illegal in the standard 'dmn', '', # useless 'email', '&fix_email', # special - 'emph', 'EM', - 'file', '"TT', # will put quotes, cf. &apply_style - 'i', 'I', - 'kbd', 'KBD', - 'key', 'KBD', + 'emph', 'em', + 'file', '"tt', # will put quotes, cf. &apply_style + 'i', 'i', + 'kbd', 'kbd', + 'key', 'kbd', 'r', '', # unsupported - 'samp', '"SAMP', # will put quotes, cf. &apply_style + 'samp', '"samp', # will put quotes, cf. &apply_style 'sc', '&do_sc', # special case - 'strong', 'STRONG', - 't', 'TT', + 'strong', 'strong', + 't', 'tt', 'titlefont', '', # useless 'image', '&fix_image', # Image 'url', '&fix_url', # URL 'uref', '&fix_uref', # URL Reference - 'var', 'VAR', + 'var', 'var', 'w', '', # unsupported ); @@ -317,6 +322,7 @@ $usage = <<EOT; This is $THISPROG To convert a Texinfo file to HMTL: $0 [options] file where options can be: +-acc : convert @"-like accents to &entities; -expandinfo : use \@ifinfo sections, not \@iftex -glossary : handle a glossary -invisible name: use 'name' as an invisible anchor @@ -445,11 +451,15 @@ $html_num = 0; if ($use_iso) { $things_map{'bullet'} = "•"; $things_map{'copyright'} = "©"; + $things_map{'registeredsymbol'} = "®"; $things_map{'dots'} = "…"; $things_map{'equiv'} = "≡"; $things_map{'expansion'} = "→"; $things_map{'point'} = "∗"; $things_map{'result'} = "⇒"; + $things_map{'ss'} = "ß"; + $things_map{'o'} = "ø"; + $things_map{'O'} = "Ø"; } # @@ -505,23 +515,27 @@ $html_element = ''; # current HTML element # watch out for regexps, / and escaped characters! $subst_code = ''; foreach (keys(%simple_map)) { - ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars - $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n"; + $re = quotemeta $_; # protect regexp chars + $sub = quotemeta $simple_map{$_}; + $subst_code .= "s/\\\@$re/$sub/g;\n"; } foreach (keys(%things_map)) { - $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n"; + $re = quotemeta $_; # protect regexp chars + $sub = quotemeta $things_map{$_}; + $subst_code .= "s/\\\@$re\\{\\}/$sub/g;\n"; } if ($use_acc) { # accentuated characters foreach (keys(%accent_map)) { + my $brace = /{$/ ? '}' : ''; if ($_ eq "`") { $subst_code .= "s/$;3"; } elsif ($_ eq "'") { $subst_code .= "s/$;4"; } else { - $subst_code .= "s/\\\@\\$_"; + $subst_code .= "s/\\\@\\Q$_\\E"; } - $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n"; + $subst_code .= "(\\w)$brace/&\${1}$accent_map{$_};/gi;\n"; } } eval("sub simple_substitutions { $subst_code }"); @@ -703,7 +717,7 @@ READ_LINE: while ($_ = &next_line) s/{[^{}]+}//g); print "# Multitable with $multitable_cols columns\n" if $debug and $DEBUG_USER; - push(@lines, &debug("<TABLE BORDER WIDTH=\"100%\">\n", __LINE__)); + push(@lines, &debug("<TABLE BORDER>\n", __LINE__)); } else { warn "$ERROR Bad table line: $_"; } @@ -873,7 +887,7 @@ READ_LINE: while ($_ = &next_line) &simple_substitutions; s/\@value{($VARRE)}/$value{$1}/eg; s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4 - s|\s+\@tab\s*| </TD><TD> |g if ($in_multitable); + s/(^|\s+)\@tab\s*/ <\/TD><TD> /g if ($in_multitable); # # analyze the tag again @@ -885,7 +899,7 @@ READ_LINE: while ($_ = &next_line) $name =~ s/\s+$//; $level = $sec2level{$tag}; $name = &update_sec_num($tag, $level) . " $name" - if $number_sections && $tag !~ /^unnumbered/; + if $number_sections && $tag !~ /^unnumbered/ && $tag ne 'subsubheading'; if ($tag =~ /heading$/) { push(@lines, &html_debug("\n", __LINE__)); if ($html_element ne 'body') { @@ -1079,7 +1093,7 @@ EOC push(@lines, &debug("</TD></TR>\n", __LINE__)) unless $html_element eq 'TABLE'; &html_pop_if('TR'); - $what =~ s|\s+\@tab\s*| </TD><TD> |g; + $what =~ s/(^|\s+)\@tab\s*/ <\/TD><TD> /g; push(@lines, &debug("<TR><TD>$what\n", __LINE__)); &html_push('TR'); if ($deferred_ref) @@ -1463,11 +1477,7 @@ print "# end of pass 4\n" if $verbose; # # #---############################################################################ -$header = <<EOT; -<!-- This HTML file has been created by $THISPROG - from $docu on $TODAY --> -EOT - + $header = ''; $full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document"; $title = $value{'_settitle'} || $full_title; $_ = &substitute_style($full_title); @@ -1815,8 +1825,10 @@ sub fix_image die "error in image: '$text'" unless defined($1); $arg1 = $1; $arg1 =~ s/@@/@/g; - $ext = "jpg" if -f "$arg1.jpg"; - $ext = "gif" if -f "$arg1.gif"; + foreach (@include_dirs) { + $ext = "jpg" if -f "$_/$arg1.jpg"; + $ext = "gif" if -f "$_/$arg1.gif"; + } if (defined($ext)) { "<IMG SRC=\"$arg1.$ext\">"; @@ -2010,7 +2022,7 @@ sub print_toplevel_header { local($_); - &print_header; # pass given arg... + &print_header unless $opt_empty_headers; # pass given arg... print FILE $full_title; if ($value{'_subtitle'}) { $value{'_subtitle'} =~ s/\n+$//; @@ -2042,13 +2054,7 @@ EOT sub print_toplevel_footer { - &print_ruler; - print FILE <<EOT; -This document was generated on $TODAY using the -<A HREF=\"$HOMEPAGE\">texi2html</A> -translator version 1.52 (extended by davida\@detron.se).</P> -EOT - &print_footer; + &print_footer unless $opt_empty_headers; } sub protect_texi @@ -2065,8 +2071,10 @@ sub protect_html { local($what) = @_; # protect & < > - # Avoid loop in & replacement. This instead bugs out for &# in text.. - $what =~ s/\&([^#]|$)/\&\#38;$1/g; + # hack for the two entity-like variable reference in existing examples + $what =~ s/\&(length|ts);/\&\#38;$1;/g; + # this leaves alone entities, but encodes standalone ampersands + $what =~ s/\&(?!([a-z0-9]+|#\d+);)/\&\#38;/ig; $what =~ s/\</\&\#60;/g; $what =~ s/\>/\&\#62;/g; # but recognize some HTML things diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 8182b95fb83..c670b84db44 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -81,8 +81,13 @@ static struct my_option my_long_options[] = "To check several databases. Note the difference in usage; In this case no tables are given. All name arguments are regarded as databasenames.", (gptr*) &opt_databases, (gptr*) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef DBUG_OFF + {"debug", '#', "This is a non-debug version. Catch this and exit.", + 0, 0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, +#else {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"default-character-set", OPT_DEFAULT_CHARSET, "Set the default character set.", (gptr*) &default_charset, (gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/client/mysqltest.c b/client/mysqltest.c index 420d5316cd4..8e89352c8e8 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -42,7 +42,7 @@ **********************************************************************/ -#define MTEST_VERSION "2.3" +#define MTEST_VERSION "2.4" #include <my_global.h> #include <mysql_embed.h> @@ -243,6 +243,7 @@ VAR var_reg[10]; HASH var_hash; my_bool disable_query_log=0, disable_result_log=0, disable_warnings=0; my_bool disable_info= 1; /* By default off */ +my_bool abort_on_error= 1; struct connection cons[MAX_CONS]; struct connection* cur_con, *next_con, *cons_end; @@ -274,6 +275,7 @@ Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS, Q_ENABLE_INFO, Q_DISABLE_INFO, Q_ENABLE_METADATA, Q_DISABLE_METADATA, Q_EXEC, Q_DELIMITER, +Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR, Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS, Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL, Q_START_TIMER, Q_END_TIMER, @@ -353,6 +355,8 @@ const char *command_names[]= "disable_metadata", "exec", "delimiter", + "disable_abort_on_error", + "enable_abort_on_error", "vertical_results", "horizontal_results", "query_vertical", @@ -741,7 +745,7 @@ err: DBUG_RETURN(0); } -static VAR* var_obtain(char* name, int len) +static VAR *var_obtain(const char* name, int len) { VAR* v; if ((v = (VAR*)hash_search(&var_hash, name, len))) @@ -751,28 +755,33 @@ static VAR* var_obtain(char* name, int len) return v; } -int var_set(char* var_name, char* var_name_end, char* var_val, - char* var_val_end) +int var_set(const char *var_name, const char *var_name_end, + const char *var_val, const char *var_val_end) { int digit; VAR* v; + DBUG_ENTER("var_set"); + DBUG_PRINT("enter", ("var_name: '%.*s' = '%.*s' (length: %d)", + (int) (var_name_end - var_name), var_name, + (int) (var_val_end - var_val), var_val, + (int) (var_val_end - var_val))); + if (*var_name++ != '$') - { - --var_name; - *var_name_end = 0; - die("Variable name in %s does not start with '$'", var_name); - } + { + var_name--; + die("Variable name in %s does not start with '$'", var_name); + } digit = *var_name - '0'; if (!(digit < 10 && digit >= 0)) - { - v = var_obtain(var_name, var_name_end - var_name); - } + { + v = var_obtain(var_name, (uint) (var_name_end - var_name)); + } else - v = var_reg + digit; - + v = var_reg + digit; return eval_expr(v, var_val, (const char**)&var_val_end); } + int open_file(const char* name) { char buff[FN_REFLEN]; @@ -1241,6 +1250,22 @@ int do_let(struct st_query* q) return var_set(var_name, var_name_end, var_val_start, q->end); } + +/* + Store an integer (typically the returncode of the last SQL) + statement in the mysqltest builtin variable $mysql_errno, by + simulating of a user statement "let $mysql_errno= <integer>" +*/ + +int var_set_errno(int sql_errno) +{ + const char *var_name= "$mysql_errno"; + char var_val[21]; + uint length= my_sprintf(var_val, (var_val, "%d", sql_errno)); + return var_set(var_name, var_name + 12, var_val, var_val + length); +} + + int do_rpl_probe(struct st_query* q __attribute__((unused))) { DBUG_ENTER("do_rpl_probe"); @@ -1249,12 +1274,14 @@ int do_rpl_probe(struct st_query* q __attribute__((unused))) DBUG_RETURN(0); } + int do_enable_rpl_parse(struct st_query* q __attribute__((unused))) { mysql_enable_rpl_parse(&cur_con->mysql); return 0; } + int do_disable_rpl_parse(struct st_query* q __attribute__((unused))) { mysql_disable_rpl_parse(&cur_con->mysql); @@ -1998,7 +2025,7 @@ int read_query(struct st_query** q_ptr) memcpy((gptr) q->expected_errno, (gptr) global_expected_errno, sizeof(global_expected_errno)); q->expected_errors= global_expected_errors; - q->abort_on_error= global_expected_errors == 0; + q->abort_on_error= (global_expected_errors == 0 && abort_on_error); bzero((gptr) global_expected_errno, sizeof(global_expected_errno)); global_expected_errors=0; if (p[0] == '-' && p[1] == '-') @@ -2407,7 +2434,7 @@ static int run_query(MYSQL *mysql, struct st_query *q, int flags) if (ps_protocol_enabled && disable_info && (flags & QUERY_SEND) && (flags & QUERY_REAP) && ps_match_re(q->query)) - return run_query_stmt (mysql, q, flags); + return run_query_stmt(mysql, q, flags); return run_query_normal(mysql, q, flags); } @@ -2644,6 +2671,13 @@ end: dynstr_free(&ds_tmp); if (q->type == Q_EVAL) dynstr_free(&eval_query); + + /* + We save the return code (mysql_errno(mysql)) from the last call sent + to the server into the mysqltest builtin variable $mysql_errno. This + variable then can be used from the test case itself. + */ + var_set_errno(mysql_errno(mysql)); DBUG_RETURN(error); } @@ -2993,6 +3027,7 @@ end: dynstr_free(&ds_tmp); if (q->type == Q_EVAL) dynstr_free(&eval_query); + var_set_errno(mysql_stmt_errno(stmt)); mysql_stmt_close(stmt); DBUG_RETURN(error); } @@ -3300,7 +3335,7 @@ static VAR* var_from_env(const char *name, const char *def_val) if (!(tmp = getenv(name))) tmp = def_val; - v = var_init(0, name, 0, tmp, 0); + v = var_init(0, name, strlen(name), tmp, strlen(tmp)); my_hash_insert(&var_hash, (byte*)v); return v; } @@ -3396,6 +3431,13 @@ int main(int argc, char **argv) init_var_hash(&cur_con->mysql); + /* + Initialize $mysql_errno with -1, so we can + - distinguish it from valid values ( >= 0 ) and + - detect if there was never a command sent to the server + */ + var_set_errno(-1); + while (!abort_flag && !read_query(&q)) { int current_line_inc = 1, processed = 0; @@ -3415,6 +3457,8 @@ int main(int argc, char **argv) case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break; case Q_ENABLE_QUERY_LOG: disable_query_log=0; break; case Q_DISABLE_QUERY_LOG: disable_query_log=1; break; + case Q_ENABLE_ABORT_ON_ERROR: abort_on_error=1; break; + case Q_DISABLE_ABORT_ON_ERROR: abort_on_error=0; break; case Q_ENABLE_RESULT_LOG: disable_result_log=0; break; case Q_DISABLE_RESULT_LOG: disable_result_log=1; break; case Q_ENABLE_WARNINGS: disable_warnings=0; break; diff --git a/configure.in b/configure.in index 754494f7d70..d1f683fcfec 100644 --- a/configure.in +++ b/configure.in @@ -974,8 +974,11 @@ case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc in CFLAGS="$CFLAGS -DBIG_TABLES" CXXFLAGS="$CXXFLAGS -DBIG_TABLES" ;; + *) ;; +esac +case $SYSTEM_TYPE-$ac_cv_prog_gcc in # workaround for Sun Forte compile problem for ndb - *solaris2.10*-sparc-no) + *solaris*-no) ndb_cxxflags_fix="$ndb_cxxflags_fix -instances=static" ;; *) ;; @@ -1036,8 +1039,8 @@ case $SYSTEM_TYPE in ;; *hpux11.*) echo "Enabling workarounds for hpux 11" - CFLAGS="$CFLAGS -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT" - CXXFLAGS="$CXXFLAGS -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT" + CFLAGS="$CFLAGS -DHPUX11 -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT" + CXXFLAGS="$CXXFLAGS -DHPUX11 -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT" if test "$with_named_thread" = "no" then echo "Using --with-named-thread=-lpthread" @@ -1143,9 +1146,10 @@ dnl Is this the right match for DEC OSF on alpha? fi echo "Adding defines for OSF1" # gethostbyname_r is deprecated and doesn't work ok on OSF1 - CFLAGS="$CFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R" - CXXFLAGS="$CXXFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R" - ndb_cxxflags_fix="$ndb_cxxflags_fix -I/usr/include.dtk" + CFLAGS="$CFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R -DSNPRINTF_RETURN_TRUNC" + CXXFLAGS="$CXXFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R -DSNPRINTF_RETURN_TRUNC" + # fix to handle include of <stdint.h> correctly on OSF1 with cxx compiler + CXXFLAGS="$CXXFLAGS -I/usr/include/cxx -I/usr/include/cxx_cname -I/usr/include -I/usr/include.dtk" ;; *netware*) # No need for curses library so set it to null @@ -1916,7 +1920,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \ getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \ getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \ localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \ - mkstemp mlockall perror poll pread pthread_attr_create clock_gettime \ + mkstemp mlockall perror poll pread pthread_attr_create \ pthread_attr_getstacksize pthread_attr_setprio pthread_attr_setschedparam \ pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \ pthread_key_delete pthread_rwlock_rdlock pthread_setprio \ @@ -1925,6 +1929,18 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \ snprintf socket stpcpy strcasecmp strerror strnlen strpbrk strstr strtol \ strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr) +# +# +# +case "$target" in + *-*-aix4*) + # (grr) aix 4.3 has a stub for clock_gettime, (returning ENOSYS) + # and using AC_TRY_RUN is hard when cross-compiling + ;; + *) AC_CHECK_FUNCS(clock_gettime) + ;; +esac + # isinf() could be a function or a macro (HPUX) AC_MSG_CHECKING(for isinf with <math.h>) AC_TRY_LINK([#include <math.h>], [float f = 0.0; isinf(f)], diff --git a/include/my_list.h b/include/my_list.h index 789bbb50f97..f786621e311 100644 --- a/include/my_list.h +++ b/include/my_list.h @@ -33,8 +33,8 @@ extern LIST *list_delete(LIST *root,LIST *element); extern LIST *list_cons(void *data,LIST *root); extern LIST *list_reverse(LIST *root); extern void list_free(LIST *root,unsigned int free_data); -extern unsigned int list_length(LIST *list); -extern int list_walk(LIST *list,list_walk_action action,gptr argument); +extern unsigned int list_length(LIST *); +extern int list_walk(LIST *,list_walk_action action,gptr argument); #define rest(a) ((a)->next) #define list_push(a,b) (a)=list_cons((b),(a)) diff --git a/include/mysql.h b/include/mysql.h index 87c01c9903f..0a7ab09c57b 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -653,23 +653,6 @@ typedef struct st_mysql_methods #endif } MYSQL_METHODS; -#ifdef HAVE_DEPRECATED_411_API -/* Deprecated calls (since MySQL 4.1.2) */ - -/* Use mysql_stmt_init + mysql_stmt_prepare instead */ -MYSQL_STMT * STDCALL mysql_prepare(MYSQL * mysql, const char *query, - unsigned long length); -#define mysql_execute mysql_stmt_execute -#define mysql_fetch mysql_stmt_fetch -#define mysql_fetch_column mysql_stmt_fetch_column -#define mysql_bind_param mysql_stmt_bind_param -#define mysql_bind_result mysql_stmt_bind_result -#define mysql_param_count mysql_stmt_param_count -#define mysql_param_result mysql_stmt_param_metadata -#define mysql_get_metadata mysql_stmt_result_metadata -#define mysql_send_long_data mysql_stmt_send_long_data - -#endif /* HAVE_DEPRECATED_411_API */ MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql); int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, diff --git a/include/mysql_com.h b/include/mysql_com.h index 09ee5b22286..92a67ac0279 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -312,13 +312,7 @@ void my_net_local_init(NET *net); void net_end(NET *net); void net_clear(NET *net); my_bool net_realloc(NET *net, unsigned long length); - -#ifndef EMBEDDED_LIBRARY /* To be removed by HF */ my_bool net_flush(NET *net); -#else -#define net_flush(A) -#endif - my_bool my_net_write(NET *net,const char *packet,unsigned long len); my_bool net_write_command(NET *net,unsigned char command, const char *header, unsigned long head_len, diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c index 137964b26c1..cbdc0aab53c 100644 --- a/innobase/dict/dict0crea.c +++ b/innobase/dict/dict0crea.c @@ -1067,6 +1067,12 @@ dict_create_or_check_foreign_constraint_tables(void) there are 2 secondary indexes on SYS_FOREIGN, and they are defined just like below */ + /* NOTE: when designing InnoDB's foreign key support in 2001, we made + an error and made the table names and the foreign key id of type + 'CHAR' (internally, really a VARCHAR). We should have made the type + VARBINARY, like in other InnoDB system tables, to get a clean + design. */ + str = "PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n" "BEGIN\n" @@ -1284,9 +1290,17 @@ loop: fputs(".\nA foreign key constraint of name ", ef); ut_print_name(ef, trx, foreign->id); fputs("\nalready exists." - " (Note that internally InnoDB adds 'databasename/'\n" + " (Note that internally InnoDB adds 'databasename/'\n" "in front of the user-defined constraint name).\n", ef); + fputs("Note that InnoDB's FOREIGN KEY system tables store\n" + "constraint names as case-insensitive, with the\n" + "MySQL standard latin1_swedish_ci collation. If you\n" + "create tables or databases whose names differ only in\n" + "the character case, then collisions in constraint\n" + "names can occur. Workaround: name your constraints\n" + "explicitly with unique names.\n", + ef); mutex_exit(&dict_foreign_err_mutex); diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index c3d0d8d9ac1..bc08fc2437e 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -156,7 +156,7 @@ dict_index_build_internal_non_clust( dict_index_t* index); /* in: user representation of a non-clustered index */ /************************************************************************** -Removes a foreign constraint struct from the dictionet cache. */ +Removes a foreign constraint struct from the dictionary cache. */ static void dict_foreign_remove_from_cache( @@ -606,7 +606,7 @@ dict_table_get_on_id( dict_table_t* table; if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0 - || trx->dict_operation) { + || trx->dict_operation_lock_mode == RW_X_LATCH) { /* It is a system table which will always exist in the table cache: we avoid acquiring the dictionary mutex, because if we are doing a rollback to handle an error in TABLE diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index d430eadc97b..8fc6eb9141e 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -19,7 +19,9 @@ Created 4/24/1996 Heikki Tuuri #include "mach0data.h" #include "dict0dict.h" #include "dict0boot.h" +#include "rem0cmp.h" #include "srv0start.h" +#include "srv0srv.h" /************************************************************************ Finds the first table name in the given database. */ @@ -123,6 +125,13 @@ dict_print(void) ulint len; mtr_t mtr; + /* Enlarge the fatal semaphore wait timeout during the InnoDB table + monitor printout */ + + mutex_enter(&kernel_mutex); + srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */ + mutex_exit(&kernel_mutex); + mutex_enter(&(dict_sys->mutex)); mtr_start(&mtr); @@ -145,6 +154,12 @@ loop: mutex_exit(&(dict_sys->mutex)); + /* Restore the fatal semaphore wait timeout */ + + mutex_enter(&kernel_mutex); + srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */ + mutex_exit(&kernel_mutex); + return; } @@ -1242,12 +1257,26 @@ loop: rec = btr_pcur_get_rec(&pcur); field = rec_get_nth_field(rec, 0, &len); - /* Check if the table name in record is the one searched for */ - if (len != ut_strlen(table_name) - || 0 != ut_memcmp(field, table_name, len)) { + /* Check if the table name in the record is the one searched for; the + following call does the comparison in the latin1_swedish_ci + charset-collation, in a case-insensitive way. */ + if (0 != cmp_data_data(dfield_get_type(dfield), + dfield_get_data(dfield), dfield_get_len(dfield), + field, len)) { + goto load_next_index; } + + /* Since table names in SYS_FOREIGN are stored in a case-insensitive + order, we have to check that the table name matches also in a binary + string comparison. On Unix, MySQL allows table names that only differ + in character case. */ + + if (0 != ut_memcmp(field, table_name, len)) { + + goto next_rec; + } if (rec_get_deleted_flag(rec)) { diff --git a/innobase/eval/eval0eval.c b/innobase/eval/eval0eval.c index ebb6cb1b7d9..5b2d1f857b1 100644 --- a/innobase/eval/eval0eval.c +++ b/innobase/eval/eval0eval.c @@ -627,7 +627,11 @@ eval_concat( } /********************************************************************* -Evaluates a predefined function node. */ +Evaluates a predefined function node. If the first argument is an integer, +this function looks at the second argument which is the integer length in +bytes, and converts the integer to a VARCHAR. +If the first argument is of some other type, this function converts it to +BINARY. */ UNIV_INLINE void eval_to_binary( @@ -638,12 +642,24 @@ eval_to_binary( que_node_t* arg2; dfield_t* dfield; byte* str1; + ulint len; ulint len1; arg1 = func_node->args; str1 = dfield_get_data(que_node_get_val(arg1)); + if (dtype_get_mtype(que_node_get_data_type(arg1)) != DATA_INT) { + + len = dfield_get_len(que_node_get_val(arg1)); + + dfield = que_node_get_val(func_node); + + dfield_set_data(dfield, str1, len); + + return; + } + arg2 = que_node_get_next(arg1); len1 = (ulint)eval_node_get_int_val(arg2); diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index b3c8ade2414..2191cdc0ee6 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/innobase/ibuf/ibuf0ibuf.c @@ -2866,6 +2866,8 @@ ibuf_delete_rec( #ifdef UNIV_IBUF_DEBUG ibuf_count_set(space, page_no, ibuf_count_get(space, page_no) - 1); +#else + UT_NOT_USED(space); #endif ibuf_data_sizes_update(ibuf_data, root, mtr); @@ -3267,11 +3269,11 @@ leave_loop: ibuf_data->n_merged_recs += n_inserts; mutex_exit(&ibuf_mutex); - + /* fprintf(stderr, "InnoDB: Discarded %lu ibuf entries for space %lu\n", (ulong) n_inserts, (ulong) space); - + */ ibuf_exit(); mem_heap_free(heap); diff --git a/innobase/pars/pars0pars.c b/innobase/pars/pars0pars.c index 846cb060a7e..16d630dd318 100644 --- a/innobase/pars/pars0pars.c +++ b/innobase/pars/pars0pars.c @@ -259,9 +259,13 @@ pars_resolve_func_data_type( dtype_set(que_node_get_data_type(node), DATA_VARCHAR, DATA_ENGLISH, 0, 0); } else if (func == PARS_TO_BINARY_TOKEN) { - ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT); - dtype_set(que_node_get_data_type(node), DATA_VARCHAR, + if (dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT) { + dtype_set(que_node_get_data_type(node), DATA_VARCHAR, DATA_ENGLISH, 0, 0); + } else { + dtype_set(que_node_get_data_type(node), DATA_BINARY, + 0, 0, 0); + } } else if (func == PARS_TO_NUMBER_TOKEN) { ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_VARCHAR); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 241ddc310e8..f356ef8081e 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -2314,7 +2314,8 @@ row_drop_table_for_mysql( "WHILE found = 1 LOOP\n" " SELECT ID INTO foreign_id\n" " FROM SYS_FOREIGN\n" - " WHERE FOR_NAME = table_name;\n" + " WHERE FOR_NAME = table_name\n" + " AND TO_BINARY(FOR_NAME) = TO_BINARY(table_name);\n" " IF (SQL % NOTFOUND) THEN\n" " found := 0;\n" " ELSE" @@ -2769,7 +2770,8 @@ row_rename_table_for_mysql( "WHILE found = 1 LOOP\n" " SELECT ID INTO foreign_id\n" " FROM SYS_FOREIGN\n" - " WHERE FOR_NAME = old_table_name;\n" + " WHERE FOR_NAME = old_table_name\n" + " AND TO_BINARY(FOR_NAME) = TO_BINARY(old_table_name);\n" " IF (SQL % NOTFOUND) THEN\n" " found := 0;\n" " ELSE\n" @@ -2802,7 +2804,8 @@ row_rename_table_for_mysql( " END IF;\n" "END LOOP;\n" "UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n" - "WHERE REF_NAME = old_table_name;\n"; + "WHERE REF_NAME = old_table_name\n" + " AND TO_BINARY(REF_NAME) = TO_BINARY(old_table_name);\n"; static const char str5[] = "END;\n"; @@ -3012,7 +3015,11 @@ row_rename_table_for_mysql( if (err != DB_SUCCESS) { if (err == DB_DUPLICATE_KEY) { ut_print_timestamp(stderr); - fputs(" InnoDB: Error: table ", stderr); + fputs( + " InnoDB: Error; possible reasons:\n" + "InnoDB: 1) Table rename would cause two FOREIGN KEY constraints\n" + "InnoDB: to have the same internal name in case-insensitive comparison.\n" + "InnoDB: 2) table ", stderr); ut_print_name(stderr, trx, new_name); fputs(" exists in the InnoDB internal data\n" "InnoDB: dictionary though MySQL is trying rename table ", stderr); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 35d01b5bcec..44be120e9ed 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1887,22 +1887,6 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) DBUG_RETURN(0); } -#ifdef HAVE_DEPRECATED_411_API -MYSQL_STMT * STDCALL mysql_prepare(MYSQL *mysql, const char *query, - unsigned long query_length) -{ - MYSQL_STMT *stmt; - DBUG_ENTER("mysql_prepare"); - - stmt= mysql_stmt_init(mysql); - if (stmt && mysql_stmt_prepare(stmt, query, query_length)) - { - mysql_stmt_close(stmt); - DBUG_RETURN(0); - } - DBUG_RETURN(stmt); -} -#endif /* Allocate memory and init prepared statement structure. diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 4da388af1c7..1df518a2712 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -2037,7 +2037,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT* sort_param.keyinfo->seg->charset->mbmaxlen; sort_info.max_records= - (ha_rows) (sort_info.filelength/ft_max_word_len_for_sort+1); + (ha_rows) (sort_info.filelength/ft_min_word_len+1); sort_param.key_read=sort_ft_key_read; sort_param.key_write=sort_ft_key_write; diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index cad7be2e802..fe285198641 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -354,8 +354,12 @@ static void usage(void) puts("Description, check and repair of MyISAM tables."); puts("Used without options all tables on the command will be checked for errors"); printf("Usage: %s [OPTIONS] tables[.MYI]\n", my_progname_short); - printf("\nGlobal options:\n\ - -#, --debug=... Output debug log. Often this is 'd:t:o,filename'.\n\ + printf("\nGlobal options:\n"); +#ifndef DBUG_OFF + printf("\ + -#, --debug=... Output debug log. Often this is 'd:t:o,filename'.\n"); +#endif + printf("\ -?, --help Display this help and exit.\n\ -O, --set-variable var=option.\n\ Change the value of a variable. Please note that\n\ diff --git a/mysql-test/include/ps_modify.inc b/mysql-test/include/ps_modify.inc index 372fc12b722..04b9734240b 100644 --- a/mysql-test/include/ps_modify.inc +++ b/mysql-test/include/ps_modify.inc @@ -321,8 +321,11 @@ select a,b from t1 where a >= 1000 order by a ; delete from t1 where a >= 1000 ; ## replace ---error 1295 prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' '; +execute stmt1; +execute stmt1; +execute stmt1; + ## multi table statements diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 07bc256eb2b..0d467e0a734 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -996,9 +996,11 @@ start_master() if [ -n "$1" ] ; then id=`$EXPR $1 + 101`; this_master_myport=`$EXPR $MASTER_MYPORT + $1` + NOT_FIRST_MASTER_EXTRA_OPTS="--skip-innodb" else id=1; this_master_myport=$MASTER_MYPORT + NOT_FIRST_MASTER_EXTRA_OPTS="" fi if [ -z "$DO_BENCH" ] then @@ -1022,7 +1024,8 @@ start_master() --open-files-limit=1024 \ $MASTER_40_ARGS \ $SMALL_SERVER \ - $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT" + $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \ + $NOT_FIRST_MASTER_EXTRA_OPTS" else master_args="--no-defaults --log-bin=$MYSQL_TEST_DIR/var/log/master-bin$1 \ --server-id=$id --rpl-recovery-rank=1 \ @@ -1041,7 +1044,8 @@ start_master() --innodb_data_file_path=ibdata1:50M \ $MASTER_40_ARGS \ $SMALL_SERVER \ - $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT" + $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \ + $NOT_FIRST_MASTER_EXTRA_OPTS" fi CUR_MYERR=$MASTER_MYERR diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh index 294d32ac4be..d7b115d71b6 100644 --- a/mysql-test/ndb/ndbcluster.sh +++ b/mysql-test/ndb/ndbcluster.sh @@ -146,7 +146,7 @@ fi rm -f "$cfgfile" 2>&1 | cat > /dev/null rm -f "$fs_ndb/$cfgfile" 2>&1 | cat > /dev/null -if ( cd "$fs_ndb" ; $exec_mgmtsrvr -c config.ini ) ; then :; else +if ( cd "$fs_ndb" ; $exec_mgmtsrvr -f config.ini ) ; then :; else echo "Unable to start $exec_mgmtsrvr from `pwd`" exit 1 fi @@ -212,8 +212,8 @@ if [ -f "$fs_ndb/$pidfile" ] ; then attempt=`expr $attempt + 1` done if [ "$kill_pids" != "" ] ; then - echo "Failed to shutdown ndbcluster, executing kill -9 "$kill_pids - kill -9 $kill_pids + echo "Failed to shutdown ndbcluster, executing kill "$kill_pids + kill $kill_pids fi rm "$fs_ndb/$pidfile" fi diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index 78d15c21301..7d5f9d5b59a 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -174,3 +174,69 @@ Warnings: Warning 1265 Data truncated for column 'a' at row 1 Warning 1265 Data truncated for column 'b' at row 1 drop table t1; +set names koi8r; +create table t1 (a char(10) character set cp1251); +insert into t1 values (_koi8r'×ÁÓÑ'); +select * from t1 where a=_koi8r'×ÁÓÑ'; +a +×ÁÓÑ +select * from t1 where a=concat(_koi8r'×ÁÓÑ'); +ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (koi8r_general_ci,COERCIBLE) for operation '=' +select * from t1 where a=_latin1'×ÁÓÑ'; +ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE) for operation '=' +drop table t1; +set names latin1; +set names koi8r; +create table t1 (c1 char(10) character set cp1251); +insert into t1 values ('ß'); +select c1 from t1 where c1 between 'ß' and 'ß'; +c1 +ß +select ifnull(c1,'ß'), ifnull(null,c1) from t1; +ifnull(c1,'ß') ifnull(null,c1) +ß ß +select if(1,c1,'ö'), if(0,c1,'ö') from t1; +if(1,c1,'ö') if(0,c1,'ö') +ß ö +select coalesce('ö',c1), coalesce(null,c1) from t1; +coalesce('ö',c1) coalesce(null,c1) +ö ß +select least(c1,'ö'), greatest(c1,'ö') from t1; +least(c1,'ö') greatest(c1,'ö') +ö ß +select locate(c1,'ß'), locate('ß',c1) from t1; +locate(c1,'ß') locate('ß',c1) +1 1 +select field(c1,'ß'),field('ß',c1) from t1; +field(c1,'ß') field('ß',c1) +1 1 +select concat(c1,'ö'), concat('ö',c1) from t1; +concat(c1,'ö') concat('ö',c1) +ßö öß +select concat_ws(c1,'ö','ß'), concat_ws('ö',c1,'ß') from t1; +concat_ws(c1,'ö','ß') concat_ws('ö',c1,'ß') +ößß ßöß +select replace(c1,'ß','ö'), replace('ß',c1,'ö') from t1; +replace(c1,'ß','ö') replace('ß',c1,'ö') +ö ö +select substring_index(c1,'öößß',2) from t1; +substring_index(c1,'öößß',2) +ß +select elt(1,c1,'ö'),elt(1,'ö',c1) from t1; +elt(1,c1,'ö') elt(1,'ö',c1) +ß ö +select make_set(3,c1,'ö'), make_set(3,'ö',c1) from t1; +make_set(3,c1,'ö') make_set(3,'ö',c1) +ß,ö ö,ß +select insert(c1,1,2,'ö'),insert('ö',1,2,c1) from t1; +insert(c1,1,2,'ö') insert('ö',1,2,c1) +ö ß +select trim(c1 from 'ß'),trim('ß' from c1) from t1; +trim(c1 from 'ß') trim('ß' from c1) + +select lpad(c1,3,'ö'), lpad('ö',3,c1) from t1; +lpad(c1,3,'ö') lpad('ö',3,c1) +ööß ßßö +select rpad(c1,3,'ö'), rpad('ö',3,c1) from t1; +rpad(c1,3,'ö') rpad('ö',3,c1) +ßöö ößß diff --git a/mysql-test/r/ctype_sjis.result b/mysql-test/r/ctype_sjis.result index b0edbed1a41..944fa0602a9 100644 --- a/mysql-test/r/ctype_sjis.result +++ b/mysql-test/r/ctype_sjis.result @@ -60,3 +60,14 @@ hex(c) 9353 9373 drop table t1; +SET NAMES sjis; +CREATE TABLE t1 ( +c char(16) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=sjis; +insert into t1 values(0xb1),(0xb2),(0xb3); +select hex(c) from t1; +hex(c) +B1 +B2 +B3 +drop table t1; diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 3f4766830b0..ba2403bac21 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -330,6 +330,9 @@ t1_id name t2_id t1_id name select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode); t2_id t1_id name drop table t1,t2; +create table t1 (a text, fulltext key (a)); +insert into t1 select "xxxx yyyy zzzz"; +drop table t1; SET NAMES latin1; CREATE TABLE t1 (t text character set utf8 not null, fulltext(t)); INSERT t1 VALUES ('Mit freundlichem Grüß'), ('aus Osnabrück'); diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index c013a01b51b..ee0a30e27d0 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -581,3 +581,77 @@ t1 CREATE TABLE `t1` ( `POINT(1,3)` longblob NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +CREATE TABLE `t1` (`object_id` bigint(20) unsigned NOT NULL default '0', `geo` +geometry NOT NULL default '') ENGINE=MyISAM ; +insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363 +36.305435,-114.992394 36.305202,-114.991219 36.305975,-114.991163 +36.306845,-114.989432 36.309452,-114.978275 36.312642,-114.977363 +36.311978,-114.975327 36.312344,-114.96502 36.31597,-114.963364 +36.313629,-114.961723 36.313721,-114.956398 36.316057,-114.951882 +36.320979,-114.947073 36.323475,-114.945207 36.326451,-114.945207 +36.326451,-114.944132 36.326061,-114.94003 36.326588,-114.924017 +36.334484,-114.923281 36.334146,-114.92564 36.331504,-114.94072 +36.319282,-114.945348 36.314812,-114.948091 36.314762,-114.951755 +36.316211,-114.952446 36.313883,-114.952644 36.309488,-114.944725 +36.313083,-114.93706 36.32043,-114.932478 36.323497,-114.924556 +36.327708,-114.922608 36.329715,-114.92009 36.328695,-114.912105 +36.323566,-114.901647 36.317952,-114.897436 36.313968,-114.895344 +36.309573,-114.891699 36.304398,-114.890569 36.303551,-114.886356 +36.302702,-114.885141 36.301351,-114.885709 36.297391,-114.892499 +36.290893,-114.902142 36.288974,-114.904941 36.288838,-114.905308 +36.289845,-114.906325 36.290395,-114.909916 36.289549,-114.914527 +36.287535,-114.918797 36.284423,-114.922982 36.279731,-114.924113 +36.277282,-114.924057 36.275817,-114.927733 36.27053,-114.929354 +36.269029,-114.929354 36.269029,-114.950856 36.268715,-114.950768 +36.264324,-114.960206 36.264293,-114.960301 36.268943,-115.006662 +36.268929,-115.008583 36.265619,-115.00665 36.264247,-115.006659 +36.246873,-115.006659 36.246873,-115.006838 36.247697,-115.010764 +36.247774,-115.015609 36.25113,-115.015765 36.254505,-115.029517 +36.254619,-115.038573 36.249317,-115.038573 36.249317,-115.023403 +36.25841,-115.023873 36.258994,-115.031845 36.259829,-115.03183 +36.261053,-115.025561 36.261095,-115.036417 36.274632,-115.033729 +36.276041,-115.032217 36.274851,-115.029845 36.273959,-115.029934 +36.274966,-115.025763 36.274896,-115.025406 36.281044,-115.028731 +36.284471,-115.036497 36.290377,-115.042071 36.291039,-115.026759 +36.298478,-115.008995 36.301966,-115.006363 36.305435),(-115.079835 +36.244369,-115.079735 36.260186,-115.076435 36.262369,-115.069758 +36.265,-115.070235 36.268757,-115.064542 36.268655,-115.061843 +36.269857,-115.062676 36.270693,-115.06305 36.272344,-115.059051 +36.281023,-115.05918 36.283008,-115.060591 36.285246,-115.061913 +36.290022,-115.062499 36.306353,-115.062499 36.306353,-115.060918 +36.30642,-115.06112 36.289779,-115.05713 36.2825,-115.057314 +36.279446,-115.060779 36.274659,-115.061366 36.27209,-115.057858 +36.26557,-115.055805 36.262883,-115.054688 36.262874,-115.047335 +36.25037,-115.044234 36.24637,-115.052434 36.24047,-115.061734 +36.23507,-115.061934 36.22677,-115.061934 36.22677,-115.061491 +36.225267,-115.062024 36.218194,-115.060134 36.218278,-115.060133 +36.210771,-115.057833 36.210771,-115.057433 36.196271,-115.062233 +36.196271,-115.062233 36.190371,-115.062233 36.190371,-115.065533 +36.190371,-115.071333 36.188571,-115.098331 36.188275,-115.098331 +36.188275,-115.098435 36.237569,-115.097535 36.240369,-115.097535 +36.240369,-115.093235 36.240369,-115.089135 36.240469,-115.083135 +36.240569,-115.083135 36.240569,-115.079835 +36.244369)))')),('85998',GeomFromText('MULTIPOLYGON(((-115.333107 +36.264587,-115.333168 36.280638,-115.333168 36.280638,-115.32226 +36.280643,-115.322538 36.274311,-115.327222 36.274258,-115.32733 +36.263026,-115.330675 36.262984,-115.332132 36.264673,-115.333107 +36.264587),(-115.247239 36.247066,-115.247438 36.218267,-115.247438 +36.218267,-115.278525 36.219263,-115.278525 36.219263,-115.301545 +36.219559,-115.332748 36.219197,-115.332757 36.220041,-115.332757 +36.220041,-115.332895 36.233514,-115.349023 36.233479,-115.351489 +36.234475,-115.353681 36.237021,-115.357106 36.239789,-115.36519 +36.243331,-115.368156 36.243487,-115.367389 36.244902,-115.364553 +36.246014,-115.359219 36.24616,-115.356186 36.248025,-115.353347 +36.248004,-115.350813 36.249507,-115.339673 36.25387,-115.333069 +36.255018,-115.333069 36.255018,-115.333042 36.247767,-115.279039 +36.248666,-115.263639 36.247466,-115.263839 36.252766,-115.261439 +36.252666,-115.261439 36.247366,-115.247239 36.247066)))')); +select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from +t1 where object_id=85998; +object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo)) +85998 MULTIPOLYGON 0 POINT(115.31877315203 -36.237472821022) +select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from +t1 where object_id=85984; +object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo)) +85984 MULTIPOLYGON 0 POINT(-114.87787186923 36.33101763469) +drop table t1; diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 4e30d5bc110..d75dbd5d00c 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -1,14 +1,12 @@ +select -1 as "before_use_test" ; +before_use_test +-1 select otto from (select 1 as otto) as t1; otto 1 select otto from (select 1 as otto) as t1; otto 1 -select otto from (select 1 as otto) as t1; -otto -1 -select friedrich from (select 1 as otto) as t1; -ERROR 42S22: Unknown column 'friedrich' in 'field list' select friedrich from (select 1 as otto) as t1; ERROR 42S22: Unknown column 'friedrich' in 'field list' select otto from (select 1 as otto) as t1; @@ -21,3 +19,126 @@ select friedrich from (select 1 as otto) as t1; ERROR 42S22: Unknown column 'friedrich' in 'field list' select friedrich from (select 1 as otto) as t1; ERROR 42S22: Unknown column 'friedrich' in 'field list' +select otto from (select 1 as otto) as t1; +otto +1 +select 0 as "after_successful_stmt_errno" ; +after_successful_stmt_errno +0 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +select 1064 as "after_wrong_syntax_errno" ; +after_wrong_syntax_errno +1064 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +select 1064 as "after_let_var_equal_value" ; +after_let_var_equal_value +1064 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +set @my_var= 'abc' ; +select 0 as "after_set_var_equal_value" ; +after_set_var_equal_value +0 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +select 1064 as "after_disable_warnings_command" ; +after_disable_warnings_command +1064 +drop table if exists t1 ; +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +drop table if exists t1 ; +select 0 as "after_disable_warnings" ; +after_disable_warnings +0 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +select 3 from t1 ; +ERROR 42S02: Table 'test.t1' doesn't exist +select 1146 as "after_minus_masked" ; +after_minus_masked +1146 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +select 3 from t1 ; +ERROR 42S02: Table 'test.t1' doesn't exist +select 1146 as "after_!_masked" ; +after_!_masked +1146 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +select -1 as "after_let_errno_equal_value" ; +after_let_errno_equal_value +-1 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +prepare stmt from "select 3 from t1" ; +ERROR 42S02: Table 'test.t1' doesn't exist +select 1146 as "after_failing_prepare" ; +after_failing_prepare +1146 +create table t1 ( f1 char(10)); +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +prepare stmt from "select 3 from t1" ; +select 0 as "after_successful_prepare" ; +after_successful_prepare +0 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +execute stmt; +3 +select 0 as "after_successful_execute" ; +after_successful_execute +0 +drop table t1; +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +execute stmt; +ERROR 42S02: Table 'test.t1' doesn't exist +select 1146 as "after_failing_execute" ; +after_failing_execute +1146 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +execute __stmt_; +ERROR HY000: Unknown prepared statement handler (__stmt_) given to EXECUTE +select 1243 as "after_failing_execute" ; +after_failing_execute +1243 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +deallocate prepare stmt; +select 0 as "after_successful_deallocate" ; +after_successful_deallocate +0 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +deallocate prepare __stmt_; +ERROR HY000: Unknown prepared statement handler (__stmt_) given to DEALLOCATE PREPARE +select 1243 as "after_failing_deallocate" ; +after_failing_deallocate +1243 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +select 1064 as "after_--disable_abort_on_error" ; +after_--disable_abort_on_error +1064 +select 3 from t1 ; +ERROR 42S02: Table 'test.t1' doesn't exist +select 3 from t1 ; +ERROR 42S02: Table 'test.t1' doesn't exist +select 3 from t1 ; +ERROR 42S02: Table 'test.t1' doesn't exist +select 1146 as "after_!errno_masked_error" ; +after_!errno_masked_error +1146 +garbage ; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +select 1064 as "after_--enable_abort_on_error" ; +after_--enable_abort_on_error +1064 +select 3 from t1 ; +ERROR 42S02: Table 'test.t1' doesn't exist diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result index abe1b98b536..604084a72c2 100644 --- a/mysql-test/r/ndb_basic.result +++ b/mysql-test/r/ndb_basic.result @@ -414,3 +414,150 @@ select * from t1 where b IS NOT NULL; a b 1 drop table t1; +create table t1 ( +c1 int, +c2 int, +c3 int, +c4 int, +c5 int, +c6 int, +c7 int, +c8 int, +c9 int, +c10 int, +c11 int, +c12 int, +c13 int, +c14 int, +c15 int, +c16 int, +c17 int, +c18 int, +c19 int, +c20 int, +c21 int, +c22 int, +c23 int, +c24 int, +c25 int, +c26 int, +c27 int, +c28 int, +c29 int, +c30 int, +c31 int, +c32 int, +c33 int, +c34 int, +c35 int, +c36 int, +c37 int, +c38 int, +c39 int, +c40 int, +c41 int, +c42 int, +c43 int, +c44 int, +c45 int, +c46 int, +c47 int, +c48 int, +c49 int, +c50 int, +c51 int, +c52 int, +c53 int, +c54 int, +c55 int, +c56 int, +c57 int, +c58 int, +c59 int, +c60 int, +c61 int, +c62 int, +c63 int, +c64 int, +c65 int, +c66 int, +c67 int, +c68 int, +c69 int, +c70 int, +c71 int, +c72 int, +c73 int, +c74 int, +c75 int, +c76 int, +c77 int, +c78 int, +c79 int, +c80 int, +c81 int, +c82 int, +c83 int, +c84 int, +c85 int, +c86 int, +c87 int, +c88 int, +c89 int, +c90 int, +c91 int, +c92 int, +c93 int, +c94 int, +c95 int, +c96 int, +c97 int, +c98 int, +c99 int, +c100 int, +c101 int, +c102 int, +c103 int, +c104 int, +c105 int, +c106 int, +c107 int, +c108 int, +c109 int, +c110 int, +c111 int, +c112 int, +c113 int, +c114 int, +c115 int, +c116 int, +c117 int, +c118 int, +c119 int, +c120 int, +c121 int, +c122 int, +c123 int, +c124 int, +c125 int, +c126 int, +c127 int, +c128 int, +primary key(c1)) engine=ndb; +drop table t1; +create table t1 ( +a1234567890123456789012345678901234567890 int primary key, +a12345678901234567890123456789a1234567890 int, +index(a12345678901234567890123456789a1234567890) +) engine=ndb; +show tables; +Tables_in_test +t1 +insert into t1 values (1,1),(2,1),(3,1),(4,1),(5,2),(6,1),(7,1); +explain select * from t1 where a12345678901234567890123456789a1234567890=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a12345678901234567890123456789a1234567890 a12345678901234567890123456789a1234567890 5 const 10 Using where +select * from t1 where a12345678901234567890123456789a1234567890=2; +a1234567890123456789012345678901234567890 a12345678901234567890123456789a1234567890 +5 2 +drop table t1; diff --git a/mysql-test/r/ndb_blob.result b/mysql-test/r/ndb_blob.result index 25da313c67e..44109dabbc8 100644 --- a/mysql-test/r/ndb_blob.result +++ b/mysql-test/r/ndb_blob.result @@ -1,25 +1,5 @@ drop table if exists t1; -drop database if exists mysqltest; -create table t1 ( -a int not null primary key, -b tinytext -) engine=ndbcluster; -insert into t1 values(1, 'x'); -update t1 set b = 'y'; -select * from t1; -a b -1 y -delete from t1; -drop table t1; -create table t1 ( -a int not null primary key, -b text not null -) engine=ndbcluster; -insert into t1 values(1, ''); -select * from t1; -a b -1 -drop table t1; +drop database if exists test2; set autocommit=0; create table t1 ( a int not null primary key, @@ -102,6 +82,53 @@ commit; select count(*) from t1; count(*) 0 +replace t1 set a=1,b=@b1,c=111,d=@d1; +replace t1 set a=2,b=@b2,c=222,d=@d2; +commit; +explain select * from t1 where a = 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 +select a,length(b),substr(b,1+2*900,2),length(d),substr(d,1+3*900,3) +from t1 where a=1; +a length(b) substr(b,1+2*900,2) length(d) substr(d,1+3*900,3) +1 2256 b1 3000 dd1 +select a,length(b),substr(b,1+2*9000,2),length(d),substr(d,1+3*9000,3) +from t1 where a=2; +a length(b) substr(b,1+2*9000,2) length(d) substr(d,1+3*9000,3) +2 20000 b2 30000 dd2 +replace t1 set a=1,b=@b2,c=111,d=@d2; +replace t1 set a=2,b=@b1,c=222,d=@d1; +commit; +select a,length(b),substr(b,1+2*9000,2),length(d),substr(d,1+3*9000,3) +from t1 where a=1; +a length(b) substr(b,1+2*9000,2) length(d) substr(d,1+3*9000,3) +1 20000 b2 30000 dd2 +select a,length(b),substr(b,1+2*900,2),length(d),substr(d,1+3*900,3) +from t1 where a=2; +a length(b) substr(b,1+2*900,2) length(d) substr(d,1+3*900,3) +2 2256 b1 3000 dd1 +replace t1 set a=1,b=concat(@b2,@b2),c=111,d=concat(@d2,@d2); +replace t1 set a=2,b=concat(@b1,@b1),c=222,d=concat(@d1,@d1); +commit; +select a,length(b),substr(b,1+4*9000,2),length(d),substr(d,1+6*9000,3) +from t1 where a=1; +a length(b) substr(b,1+4*9000,2) length(d) substr(d,1+6*9000,3) +1 40000 b2 60000 dd2 +select a,length(b),substr(b,1+4*900,2),length(d),substr(d,1+6*900,3) +from t1 where a=2; +a length(b) substr(b,1+4*900,2) length(d) substr(d,1+6*900,3) +2 4512 b1 6000 dd1 +replace t1 set a=1,b='xyz',c=111,d=null; +commit; +select a,b from t1 where d is null; +a b +1 xyz +delete from t1 where a=1; +delete from t1 where a=2; +commit; +select count(*) from t1; +count(*) +0 insert into t1 values(1,@b1,111,@d1); insert into t1 values(2,@b2,222,@d2); commit; @@ -241,90 +268,6 @@ a b c d 7 7xb7 777 7xdd7 8 8xb8 888 8xdd8 9 9xb9 999 9xdd9 -select * from t1 order by a; -a b c d -1 1xb1 111 1xdd1 -2 2xb2 222 2xdd2 -3 3xb3 333 3xdd3 -4 4xb4 444 4xdd4 -5 5xb5 555 5xdd5 -6 6xb6 666 6xdd6 -7 7xb7 777 7xdd7 -8 8xb8 888 8xdd8 -9 9xb9 999 9xdd9 -alter table t1 add x int; -select * from t1 order by a; -a b c d x -1 1xb1 111 1xdd1 NULL -2 2xb2 222 2xdd2 NULL -3 3xb3 333 3xdd3 NULL -4 4xb4 444 4xdd4 NULL -5 5xb5 555 5xdd5 NULL -6 6xb6 666 6xdd6 NULL -7 7xb7 777 7xdd7 NULL -8 8xb8 888 8xdd8 NULL -9 9xb9 999 9xdd9 NULL -alter table t1 drop x; -select * from t1 order by a; -a b c d -1 1xb1 111 1xdd1 -2 2xb2 222 2xdd2 -3 3xb3 333 3xdd3 -4 4xb4 444 4xdd4 -5 5xb5 555 5xdd5 -6 6xb6 666 6xdd6 -7 7xb7 777 7xdd7 -8 8xb8 888 8xdd8 -9 9xb9 999 9xdd9 -create database mysqltest; -use mysqltest; -CREATE TABLE t2 ( -a bigint unsigned NOT NULL PRIMARY KEY, -b int unsigned not null, -c int unsigned -) engine=ndbcluster; -insert into t2 values (1,1,1),(2,2,2); -select * from test.t1,t2 where test.t1.a = t2.a order by test.t1.a; -a b c d a b c -1 1xb1 111 1xdd1 1 1 1 -2 2xb2 222 2xdd2 2 2 2 -drop table t2; -use test; -select * from t1 order by a; -a b c d -1 1xb1 111 1xdd1 -2 2xb2 222 2xdd2 -3 3xb3 333 3xdd3 -4 4xb4 444 4xdd4 -5 5xb5 555 5xdd5 -6 6xb6 666 6xdd6 -7 7xb7 777 7xdd7 -8 8xb8 888 8xdd8 -9 9xb9 999 9xdd9 -alter table t1 add x int; -select * from t1 order by a; -a b c d x -1 1xb1 111 1xdd1 NULL -2 2xb2 222 2xdd2 NULL -3 3xb3 333 3xdd3 NULL -4 4xb4 444 4xdd4 NULL -5 5xb5 555 5xdd5 NULL -6 6xb6 666 6xdd6 NULL -7 7xb7 777 7xdd7 NULL -8 8xb8 888 8xdd8 NULL -9 9xb9 999 9xdd9 NULL -alter table t1 drop x; -select * from t1 order by a; -a b c d -1 1xb1 111 1xdd1 -2 2xb2 222 2xdd2 -3 3xb3 333 3xdd3 -4 4xb4 444 4xdd4 -5 5xb5 555 5xdd5 -6 6xb6 666 6xdd6 -7 7xb7 777 7xdd7 -8 8xb8 888 8xdd8 -9 9xb9 999 9xdd9 delete from t1 where c >= 100; commit; select count(*) from t1; @@ -375,8 +318,128 @@ rollback; select count(*) from t1; count(*) 0 +insert into t1 values(1,'b1',111,'dd1'); +insert into t1 values(2,'b2',222,'dd2'); +insert into t1 values(3,'b3',333,'dd3'); +insert into t1 values(4,'b4',444,'dd4'); +insert into t1 values(5,'b5',555,'dd5'); +insert into t1 values(6,'b6',666,'dd6'); +insert into t1 values(7,'b7',777,'dd7'); +insert into t1 values(8,'b8',888,'dd8'); +insert into t1 values(9,'b9',999,'dd9'); +commit; +select * from t1 order by a; +a b c d +1 b1 111 dd1 +2 b2 222 dd2 +3 b3 333 dd3 +4 b4 444 dd4 +5 b5 555 dd5 +6 b6 666 dd6 +7 b7 777 dd7 +8 b8 888 dd8 +9 b9 999 dd9 +alter table t1 add x int; +select * from t1 order by a; +a b c d x +1 b1 111 dd1 NULL +2 b2 222 dd2 NULL +3 b3 333 dd3 NULL +4 b4 444 dd4 NULL +5 b5 555 dd5 NULL +6 b6 666 dd6 NULL +7 b7 777 dd7 NULL +8 b8 888 dd8 NULL +9 b9 999 dd9 NULL +alter table t1 drop x; +select * from t1 order by a; +a b c d +1 b1 111 dd1 +2 b2 222 dd2 +3 b3 333 dd3 +4 b4 444 dd4 +5 b5 555 dd5 +6 b6 666 dd6 +7 b7 777 dd7 +8 b8 888 dd8 +9 b9 999 dd9 +create database test2; +use test2; +CREATE TABLE t2 ( +a bigint unsigned NOT NULL PRIMARY KEY, +b int unsigned not null, +c int unsigned +) engine=ndbcluster; +insert into t2 values (1,1,1),(2,2,2); +select * from test.t1,t2 where test.t1.a = t2.a order by test.t1.a; +a b c d a b c +1 b1 111 dd1 1 1 1 +2 b2 222 dd2 2 2 2 +drop table t2; +use test; +select * from t1 order by a; +a b c d +1 b1 111 dd1 +2 b2 222 dd2 +3 b3 333 dd3 +4 b4 444 dd4 +5 b5 555 dd5 +6 b6 666 dd6 +7 b7 777 dd7 +8 b8 888 dd8 +9 b9 999 dd9 +alter table t1 add x int; +select * from t1 order by a; +a b c d x +1 b1 111 dd1 NULL +2 b2 222 dd2 NULL +3 b3 333 dd3 NULL +4 b4 444 dd4 NULL +5 b5 555 dd5 NULL +6 b6 666 dd6 NULL +7 b7 777 dd7 NULL +8 b8 888 dd8 NULL +9 b9 999 dd9 NULL +alter table t1 drop x; +select * from t1 order by a; +a b c d +1 b1 111 dd1 +2 b2 222 dd2 +3 b3 333 dd3 +4 b4 444 dd4 +5 b5 555 dd5 +6 b6 666 dd6 +7 b7 777 dd7 +8 b8 888 dd8 +9 b9 999 dd9 +drop table t1; +drop database test2; +set autocommit=0; +create table t1 ( +a int not null primary key, +b tinytext +) engine=ndbcluster; +insert into t1 values(1, 'x'); +update t1 set b = 'y'; +select * from t1; +a b +1 y +delete from t1; +select * from t1; +a b +commit; +drop table t1; +set autocommit=0; +create table t1 ( +a int not null primary key, +b text not null +) engine=ndbcluster; +insert into t1 values(1, ''); +select * from t1; +a b +1 +commit; drop table t1; -drop database mysqltest; set autocommit=1; use test; CREATE TABLE t1 ( @@ -397,6 +460,7 @@ select * from t1 order by a; a b 1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 2 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +set autocommit=1; alter table t1 engine=myisam; select * from t1 order by a; a b diff --git a/mysql-test/r/ndb_insert.result b/mysql-test/r/ndb_insert.result index cdc445558b9..16c76f39680 100644 --- a/mysql-test/r/ndb_insert.result +++ b/mysql-test/r/ndb_insert.result @@ -557,3 +557,32 @@ select * from t1 where pk1=1; pk1 b c 1 2 3 DROP TABLE t1; +CREATE TABLE t1(a INT) ENGINE=ndb; +INSERT IGNORE INTO t1 VALUES (1); +INSERT IGNORE INTO t1 VALUES (1); +INSERT IGNORE INTO t1 SELECT a FROM t1; +INSERT IGNORE INTO t1 SELECT a FROM t1; +INSERT IGNORE INTO t1 SELECT a FROM t1; +INSERT IGNORE INTO t1 VALUES (1); +INSERT IGNORE INTO t1 VALUES (1); +SELECT * FROM t1; +a +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +DROP TABLE t1; diff --git a/mysql-test/r/ps_10nestset.result b/mysql-test/r/ps_10nestset.result index 68f58a03674..ff63485a5f9 100644 --- a/mysql-test/r/ps_10nestset.result +++ b/mysql-test/r/ps_10nestset.result @@ -62,4 +62,15 @@ id emp salary l r 4 Donna 1064.80 5 6 5 Eddie 931.70 7 8 6 Fred 798.60 9 10 +prepare st_round from 'update t1 set salary = salary + ? - ( salary MOD ? )'; +set @arg_round= 50; +execute st_round using @arg_round, @arg_round; +select * from t1; +id emp salary l r +1 Jerry 1350.00 1 12 +2 Bert 1200.00 2 3 +3 Chuck 1250.00 4 11 +4 Donna 1100.00 5 6 +5 Eddie 950.00 7 8 +6 Fred 800.00 9 10 drop table t1; diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 1a096a58252..e4333cc91fc 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -1580,7 +1580,9 @@ a b 1200 x1000_1updatedupdated delete from t1 where a >= 1000 ; prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' '; -ERROR HY000: This command is not supported in the prepared statement protocol yet +execute stmt1; +execute stmt1; +execute stmt1; test_sequence ------ multi table tests ------ delete from t1 ; diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 5c22beeb56b..30a5fd25ebd 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -1563,7 +1563,9 @@ a b 1200 x1000_1updatedupdated delete from t1 where a >= 1000 ; prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' '; -ERROR HY000: This command is not supported in the prepared statement protocol yet +execute stmt1; +execute stmt1; +execute stmt1; test_sequence ------ multi table tests ------ delete from t1 ; diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 9cbe87b004a..779f1e79cef 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -1564,7 +1564,9 @@ a b 1200 x1000_1updatedupdated delete from t1 where a >= 1000 ; prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' '; -ERROR HY000: This command is not supported in the prepared statement protocol yet +execute stmt1; +execute stmt1; +execute stmt1; test_sequence ------ multi table tests ------ delete from t1 ; diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 4ed0295a92e..5e31bd9d4e1 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -1606,7 +1606,9 @@ a b 1200 x1000_1updatedupdated delete from t1 where a >= 1000 ; prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' '; -ERROR HY000: This command is not supported in the prepared statement protocol yet +execute stmt1; +execute stmt1; +execute stmt1; test_sequence ------ multi table tests ------ delete from t1 ; @@ -4613,7 +4615,9 @@ a b 1200 x1000_1updatedupdated delete from t1 where a >= 1000 ; prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' '; -ERROR HY000: This command is not supported in the prepared statement protocol yet +execute stmt1; +execute stmt1; +execute stmt1; test_sequence ------ multi table tests ------ delete from t1 ; diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index 7ec7e303b42..202c6980430 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -1563,7 +1563,9 @@ a b 1200 x1000_1updatedupdated delete from t1 where a >= 1000 ; prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' '; -ERROR HY000: This command is not supported in the prepared statement protocol yet +execute stmt1; +execute stmt1; +execute stmt1; test_sequence ------ multi table tests ------ delete from t1 ; diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index cf567750b85..85e51df776f 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -1543,7 +1543,6 @@ a b 1000 x1000_1 delete from t1 where a >= 1000 ; prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' '; -ERROR HY000: This command is not supported in the prepared statement protocol yet test_sequence ------ multi table tests ------ delete from t1 ; diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index e7375b428c2..1374a8fd0ed 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -547,3 +547,20 @@ select count(*) from t2 where x = 18446744073709551601; count(*) 0 drop table t1,t2; +set names latin1; +create table t1 (a char(10), b text, key (a)) character set latin1; +INSERT INTO t1 (a) VALUES +('111'),('222'),('222'),('222'),('222'),('444'),('aaa'),('AAA'),('bbb'); +explain select * from t1 where a='aaa'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 11 const 2 Using where +explain select * from t1 where a=binary 'aaa'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 11 NULL 2 Using where +explain select * from t1 where a='aaa' collate latin1_bin; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 11 NULL 2 Using where +explain select * from t1 where a='aaa' collate latin1_german1_ci; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 9 Using where +drop table t1; diff --git a/mysql-test/r/rpl_failed_optimize.result b/mysql-test/r/rpl_failed_optimize.result new file mode 100644 index 00000000000..1576ec60500 --- /dev/null +++ b/mysql-test/r/rpl_failed_optimize.result @@ -0,0 +1,15 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t1 ( a int ) ENGINE=InnoDB; +BEGIN; +INSERT INTO t1 VALUES (1); +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status Operation failed +OPTIMIZE TABLE non_existing; +Table Op Msg_type Msg_text +test.non_existing optimize error Table 'test.non_existing' doesn't exist diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index a892967ac79..67446829eca 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -85,6 +85,36 @@ t1 CREATE TABLE "t1" ( UNIQUE KEY "email" ("email") ) drop table t1; +CREATE TABLE t1 ( +a char(10), +b char(10) collate latin1_bin, +c binary(10) +) character set latin1; +set @@sql_mode=""; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) default NULL, + `b` char(10) character set latin1 collate latin1_bin default NULL, + `c` binary(10) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +set @@sql_mode="mysql323"; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) default NULL, + `b` char(10) binary default NULL, + `c` binary(10) default NULL +) TYPE=MyISAM +set @@sql_mode="mysql40"; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) default NULL, + `b` char(10) binary default NULL, + `c` binary(10) default NULL +) TYPE=MyISAM +drop table t1; set session sql_mode = ''; create table t1 ( min_num dec(6,6) default .000001); show create table t1; diff --git a/mysql-test/t/client_test.test b/mysql-test/t/client_test.test index b56e8038d9b..830c5f1b8a2 100644 --- a/mysql-test/t/client_test.test +++ b/mysql-test/t/client_test.test @@ -1,2 +1,2 @@ --disable_result_log ---exec $TESTS_BINDIR/client_test --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT +--exec $TESTS_BINDIR/client_test --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent diff --git a/mysql-test/t/comments.test b/mysql-test/t/comments.test index 2fc6237907c..087df60f3f5 100644 --- a/mysql-test/t/comments.test +++ b/mysql-test/t/comments.test @@ -5,7 +5,8 @@ select 1+2/*hello*/+3; select 1 /* long multi line comment */; -!$1065 ; +--error 1065 + ; select 1 /*!32301 +1 */; select 1 /*!52301 +1 */; select 1--1; diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test index 5f417352d95..0e5e954c720 100644 --- a/mysql-test/t/ctype_recoding.test +++ b/mysql-test/t/ctype_recoding.test @@ -131,3 +131,51 @@ create table t1 (a char(10) character set koi8r, b text character set koi8r); insert into t1 values ('test','test'); insert into t1 values ('ÊÃÕË','ÊÃÕË'); drop table t1; + +# +# Try to apply an automatic conversion in some cases: +# E.g. when mixing a column to a string, the string +# is converted into the column character set. +# If conversion loses data, then error. Otherwise, +# the string is replaced by its converted representation +# +set names koi8r; +create table t1 (a char(10) character set cp1251); +insert into t1 values (_koi8r'×ÁÓÑ'); +# this is possible: +select * from t1 where a=_koi8r'×ÁÓÑ'; +# this is not possible, because we have a function, not just a constant: +--error 1267 +select * from t1 where a=concat(_koi8r'×ÁÓÑ'); +# this is not posible, cannot convert _latin1'×ÁÓÑ' into cp1251: +--error 1267 +select * from t1 where a=_latin1'×ÁÓÑ'; +drop table t1; +set names latin1; + +# +# Check more automatic conversion +# +set names koi8r; +create table t1 (c1 char(10) character set cp1251); +insert into t1 values ('ß'); +select c1 from t1 where c1 between 'ß' and 'ß'; +select ifnull(c1,'ß'), ifnull(null,c1) from t1; +select if(1,c1,'ö'), if(0,c1,'ö') from t1; +select coalesce('ö',c1), coalesce(null,c1) from t1; +select least(c1,'ö'), greatest(c1,'ö') from t1; +select locate(c1,'ß'), locate('ß',c1) from t1; +select field(c1,'ß'),field('ß',c1) from t1; +select concat(c1,'ö'), concat('ö',c1) from t1; +select concat_ws(c1,'ö','ß'), concat_ws('ö',c1,'ß') from t1; +select replace(c1,'ß','ö'), replace('ß',c1,'ö') from t1; +select substring_index(c1,'öößß',2) from t1; +select elt(1,c1,'ö'),elt(1,'ö',c1) from t1; +select make_set(3,c1,'ö'), make_set(3,'ö',c1) from t1; +select insert(c1,1,2,'ö'),insert('ö',1,2,c1) from t1; +select trim(c1 from 'ß'),trim('ß' from c1) from t1; +select lpad(c1,3,'ö'), lpad('ö',3,c1) from t1; +select rpad(c1,3,'ö'), rpad('ö',3,c1) from t1; +# TODO +#select case c1 when 'ß' then 'ß' when 'ö' then 'ö' else 'c' end from t1; +#select export_set(5,c1,'ö'), export_set(5,'ö',c1) from t1; diff --git a/mysql-test/t/ctype_sjis.test b/mysql-test/t/ctype_sjis.test index c910812ef8a..a3a44789975 100644 --- a/mysql-test/t/ctype_sjis.test +++ b/mysql-test/t/ctype_sjis.test @@ -51,3 +51,14 @@ insert into t1 values (0x9353); insert into t1 values (0x9373); select hex(c) from t1; drop table t1; + +# +# Bug #6223 Japanese half-width kana characters get truncated +# +SET NAMES sjis; +CREATE TABLE t1 ( + c char(16) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=sjis; +insert into t1 values(0xb1),(0xb2),(0xb3); +select hex(c) from t1; +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 0c8bdd6a94d..c75b1dee63c 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -645,6 +645,7 @@ insert into t1 values(1,'foo'),(2,'foobar'); select * from t1 where b like 'foob%'; --disable_warnings alter table t1 engine=bdb; +--enable_warnings select * from t1 where b like 'foob%'; drop table t1; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 66df5b1cb92..5af2575ddc4 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -253,10 +253,17 @@ select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against(' # bug with many short (< ft_min_word_len) words in boolean search # select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode); - drop table t1,t2; # +# bug with repair-by-sort and incorrect records estimation +# + +create table t1 (a text, fulltext key (a)); +insert into t1 select "xxxx yyyy zzzz"; +drop table t1; + +# # UTF8 # SET NAMES latin1; diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 739fced1f29..86c34eacbc5 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -284,3 +284,78 @@ drop table t1; create table t1 select POINT(1,3); show create table t1; drop table t1; + +CREATE TABLE `t1` (`object_id` bigint(20) unsigned NOT NULL default '0', `geo` +geometry NOT NULL default '') ENGINE=MyISAM ; + +insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363 +36.305435,-114.992394 36.305202,-114.991219 36.305975,-114.991163 +36.306845,-114.989432 36.309452,-114.978275 36.312642,-114.977363 +36.311978,-114.975327 36.312344,-114.96502 36.31597,-114.963364 +36.313629,-114.961723 36.313721,-114.956398 36.316057,-114.951882 +36.320979,-114.947073 36.323475,-114.945207 36.326451,-114.945207 +36.326451,-114.944132 36.326061,-114.94003 36.326588,-114.924017 +36.334484,-114.923281 36.334146,-114.92564 36.331504,-114.94072 +36.319282,-114.945348 36.314812,-114.948091 36.314762,-114.951755 +36.316211,-114.952446 36.313883,-114.952644 36.309488,-114.944725 +36.313083,-114.93706 36.32043,-114.932478 36.323497,-114.924556 +36.327708,-114.922608 36.329715,-114.92009 36.328695,-114.912105 +36.323566,-114.901647 36.317952,-114.897436 36.313968,-114.895344 +36.309573,-114.891699 36.304398,-114.890569 36.303551,-114.886356 +36.302702,-114.885141 36.301351,-114.885709 36.297391,-114.892499 +36.290893,-114.902142 36.288974,-114.904941 36.288838,-114.905308 +36.289845,-114.906325 36.290395,-114.909916 36.289549,-114.914527 +36.287535,-114.918797 36.284423,-114.922982 36.279731,-114.924113 +36.277282,-114.924057 36.275817,-114.927733 36.27053,-114.929354 +36.269029,-114.929354 36.269029,-114.950856 36.268715,-114.950768 +36.264324,-114.960206 36.264293,-114.960301 36.268943,-115.006662 +36.268929,-115.008583 36.265619,-115.00665 36.264247,-115.006659 +36.246873,-115.006659 36.246873,-115.006838 36.247697,-115.010764 +36.247774,-115.015609 36.25113,-115.015765 36.254505,-115.029517 +36.254619,-115.038573 36.249317,-115.038573 36.249317,-115.023403 +36.25841,-115.023873 36.258994,-115.031845 36.259829,-115.03183 +36.261053,-115.025561 36.261095,-115.036417 36.274632,-115.033729 +36.276041,-115.032217 36.274851,-115.029845 36.273959,-115.029934 +36.274966,-115.025763 36.274896,-115.025406 36.281044,-115.028731 +36.284471,-115.036497 36.290377,-115.042071 36.291039,-115.026759 +36.298478,-115.008995 36.301966,-115.006363 36.305435),(-115.079835 +36.244369,-115.079735 36.260186,-115.076435 36.262369,-115.069758 +36.265,-115.070235 36.268757,-115.064542 36.268655,-115.061843 +36.269857,-115.062676 36.270693,-115.06305 36.272344,-115.059051 +36.281023,-115.05918 36.283008,-115.060591 36.285246,-115.061913 +36.290022,-115.062499 36.306353,-115.062499 36.306353,-115.060918 +36.30642,-115.06112 36.289779,-115.05713 36.2825,-115.057314 +36.279446,-115.060779 36.274659,-115.061366 36.27209,-115.057858 +36.26557,-115.055805 36.262883,-115.054688 36.262874,-115.047335 +36.25037,-115.044234 36.24637,-115.052434 36.24047,-115.061734 +36.23507,-115.061934 36.22677,-115.061934 36.22677,-115.061491 +36.225267,-115.062024 36.218194,-115.060134 36.218278,-115.060133 +36.210771,-115.057833 36.210771,-115.057433 36.196271,-115.062233 +36.196271,-115.062233 36.190371,-115.062233 36.190371,-115.065533 +36.190371,-115.071333 36.188571,-115.098331 36.188275,-115.098331 +36.188275,-115.098435 36.237569,-115.097535 36.240369,-115.097535 +36.240369,-115.093235 36.240369,-115.089135 36.240469,-115.083135 +36.240569,-115.083135 36.240569,-115.079835 +36.244369)))')),('85998',GeomFromText('MULTIPOLYGON(((-115.333107 +36.264587,-115.333168 36.280638,-115.333168 36.280638,-115.32226 +36.280643,-115.322538 36.274311,-115.327222 36.274258,-115.32733 +36.263026,-115.330675 36.262984,-115.332132 36.264673,-115.333107 +36.264587),(-115.247239 36.247066,-115.247438 36.218267,-115.247438 +36.218267,-115.278525 36.219263,-115.278525 36.219263,-115.301545 +36.219559,-115.332748 36.219197,-115.332757 36.220041,-115.332757 +36.220041,-115.332895 36.233514,-115.349023 36.233479,-115.351489 +36.234475,-115.353681 36.237021,-115.357106 36.239789,-115.36519 +36.243331,-115.368156 36.243487,-115.367389 36.244902,-115.364553 +36.246014,-115.359219 36.24616,-115.356186 36.248025,-115.353347 +36.248004,-115.350813 36.249507,-115.339673 36.25387,-115.333069 +36.255018,-115.333069 36.255018,-115.333042 36.247767,-115.279039 +36.248666,-115.263639 36.247466,-115.263839 36.252766,-115.261439 +36.252666,-115.261439 36.247366,-115.247239 36.247066)))')); + +select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from +t1 where object_id=85998; + +select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from +t1 where object_id=85984; + +drop table t1; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 9b5fdb924e6..fc06aa4f544 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -34,11 +34,14 @@ explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1; select t1.*,t2.*,t3.a from t1 left join t2 on (t1.a=t2.a) left join t1 as t3 on (t2.a=t3.a); # The next query should rearange the left joins to get this to work -!$1120 explain select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a); -!$1120 select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a); +--error 1120 +explain select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a); +--error 1120 +select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a); # The next query should give an error in MySQL -!$1120 select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t2.a=t3.a); +--error 1120 +select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t2.a=t3.a); # Test of inner join select t1.*,t2.* from t1 inner join t2 using (a); @@ -94,7 +97,8 @@ WHERE t1.uniq_id = 4 ORDER BY t2.c_amount; INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes'); -!$1062 INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes'); +--error 1062 +INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes'); INSERT INTO t2 VALUES (7,3,1000,2000,0,0,746294,937484,'yes'); #3rd select should show that one record is returned with null entries for the @@ -288,7 +292,8 @@ insert into t3 values (1); insert into t4 values (1,1); insert into t5 values (1,1); -!$1120 explain select * from t3 left join t4 on t4.seq_1_id = t2.t2_id left join t1 on t1.t1_id = t4.seq_0_id left join t5 on t5.seq_0_id = t1.t1_id left join t2 on t2.t2_id = t5.seq_1_id where t3.t3_id = 23; +--error 1120 +explain select * from t3 left join t4 on t4.seq_1_id = t2.t2_id left join t1 on t1.t1_id = t4.seq_0_id left join t5 on t5.seq_0_id = t1.t1_id left join t2 on t2.t2_id = t5.seq_1_id where t3.t3_id = 23; drop table t1,t2,t3,t4,t5; diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index 4a3631d3918..8885f69e60c 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -150,7 +150,8 @@ create table t1 ); INSERT INTO t1 VALUES (1, 1, 1, 1, 'a'); INSERT INTO t1 VALUES (1, 1, 1, 1, 'b'); -!$1062 INSERT INTO t1 VALUES (1, 1, 1, 1, 'a'); +--error 1062 +INSERT INTO t1 VALUES (1, 1, 1, 1, 'a'); drop table t1; # diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index c18dfe1e25c..0802c18ed6c 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -6,17 +6,24 @@ # ============================================================================ # ---------------------------------------------------------------------------- +# $mysql_errno contains the return code of the last command +# send to the server. +# ---------------------------------------------------------------------------- +# get $mysql_errno before the first statement +# $mysql_errno should be -1 +eval select $mysql_errno as "before_use_test" ; + + +# ---------------------------------------------------------------------------- # Positive case(statement) # ---------------------------------------------------------------------------- select otto from (select 1 as otto) as t1; # expectation = response -!$0 select otto from (select 1 as otto) as t1; --error 0 select otto from (select 1 as otto) as t1; # expectation <> response --- // !$1054 select otto from (select 1 as otto) as t1; -- // --error 1054 -- // select otto from (select 1 as otto) as t1; @@ -29,12 +36,10 @@ select otto from (select 1 as otto) as t1; # ---------------------------------------------------------------------------- # expectation <> response -#!$0 select friedrich from (select 1 as otto) as t1; #--error 0 #select friedrich from (select 1 as otto) as t1; # expectation = response -!$1054 select friedrich from (select 1 as otto) as t1; --error 1054 select friedrich from (select 1 as otto) as t1; @@ -76,3 +81,208 @@ select friedrich from (select 1 as otto) as t1; #--error S00000 #select friedrich from (select 1 as otto) as t1; + +# ---------------------------------------------------------------------------- +# test cases for $mysql_errno +# +# $mysql_errno is a builtin variable of mysqltest and contains the return code +# of the last command send to the server. +# +# The following test cases often initialize $mysql_errno to 1064 by +# a command with wrong syntax. +# Example: --error 1064 To prevent the abort after the error. +# garbage ; +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# check mysql_errno = 0 after successful statement +# ---------------------------------------------------------------------------- +select otto from (select 1 as otto) as t1; +eval select $mysql_errno as "after_successful_stmt_errno" ; + +#---------------------------------------------------------------------------- +# check mysql_errno = 1064 after statement with wrong syntax +# ---------------------------------------------------------------------------- +--error 1064 +garbage ; +eval select $mysql_errno as "after_wrong_syntax_errno" ; + +# ---------------------------------------------------------------------------- +# check if let $my_var= 'abc' ; affects $mysql_errno +# ---------------------------------------------------------------------------- +--error 1064 +garbage ; +let $my_var= 'abc' ; +eval select $mysql_errno as "after_let_var_equal_value" ; + +# ---------------------------------------------------------------------------- +# check if set @my_var= 'abc' ; affects $mysql_errno +# ---------------------------------------------------------------------------- +--error 1064 +garbage ; +set @my_var= 'abc' ; +eval select $mysql_errno as "after_set_var_equal_value" ; + +# ---------------------------------------------------------------------------- +# check if the setting of --disable-warnings itself affects $mysql_errno +# (May be --<whatever> modifies $mysql_errno.) +# ---------------------------------------------------------------------------- +--error 1064 +garbage ; +--disable_warnings +eval select $mysql_errno as "after_disable_warnings_command" ; + +# ---------------------------------------------------------------------------- +# check if --disable-warnings + command with warning affects the errno +# stored within $mysql_errno +# (May be disabled warnings affect $mysql_errno.) +# ---------------------------------------------------------------------------- +drop table if exists t1 ; +--error 1064 +garbage ; +drop table if exists t1 ; +eval select $mysql_errno as "after_disable_warnings" ; +--enable_warnings + +# ---------------------------------------------------------------------------- +# check if masked errors affect $mysql_errno +# ---------------------------------------------------------------------------- +--error 1064 +garbage ; +--error 1146 +select 3 from t1 ; +eval select $mysql_errno as "after_minus_masked" ; +--error 1064 +garbage ; +--error 1146 +select 3 from t1 ; +eval select $mysql_errno as "after_!_masked" ; + +# ---------------------------------------------------------------------------- +# Will manipulations of $mysql_errno be possible and visible ? +# ---------------------------------------------------------------------------- +--error 1064 +garbage ; +let $mysql_errno= -1; +eval select $mysql_errno as "after_let_errno_equal_value" ; + +# ---------------------------------------------------------------------------- +# How affect actions on prepared statements $mysql_errno ? +# ---------------------------------------------------------------------------- +# failing prepare +--error 1064 +garbage ; +--error 1146 +prepare stmt from "select 3 from t1" ; +eval select $mysql_errno as "after_failing_prepare" ; +create table t1 ( f1 char(10)); + +# successful prepare +--error 1064 +garbage ; +prepare stmt from "select 3 from t1" ; +eval select $mysql_errno as "after_successful_prepare" ; + +# successful execute +--error 1064 +garbage ; +execute stmt; +eval select $mysql_errno as "after_successful_execute" ; + +# failing execute (table dropped) +drop table t1; +--error 1064 +garbage ; +--error 1146 +execute stmt; +eval select $mysql_errno as "after_failing_execute" ; + +# failing execute (unknown statement) +--error 1064 +garbage ; +--error 1243 +execute __stmt_; +eval select $mysql_errno as "after_failing_execute" ; + +# successful deallocate +--error 1064 +garbage ; +deallocate prepare stmt; +eval select $mysql_errno as "after_successful_deallocate" ; + +# failing deallocate ( statement handle does not exist ) +--error 1064 +garbage ; +--error 1243 +deallocate prepare __stmt_; +eval select $mysql_errno as "after_failing_deallocate" ; + + +# ---------------------------------------------------------------------------- +# test cases for "--disable_abort_on_error" +# +# "--disable_abort_on_error" switches the abort of mysqltest +# after "unmasked" failing statements off. +# +# The default is "--enable_abort_on_error". +# +# "Maskings" are +# --error <error number> and --error <error number> +# in the line before the failing statement. +# +# There are some additional test case for $mysql_errno +# because "--disable_abort_on_error" enables a new situation. +# Example: "unmasked" statement fails + analysis of $mysql_errno +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Switch the abort on error off and check the effect on $mysql_errno +# ---------------------------------------------------------------------------- +--error 1064 +garbage ; +--disable_abort_on_error +eval select $mysql_errno as "after_--disable_abort_on_error" ; + +# ---------------------------------------------------------------------------- +# "unmasked" failing statement should not cause an abort +# ---------------------------------------------------------------------------- +select 3 from t1 ; + +# ---------------------------------------------------------------------------- +# masked failing statements +# ---------------------------------------------------------------------------- +# expected error = response +--error 1146 +select 3 from t1 ; +--error 1146 +select 3 from t1 ; +eval select $mysql_errno as "after_!errno_masked_error" ; +# expected error <> response +# --error 1000 +# select 3 from t1 ; +# --error 1000 +# select 3 from t1 ; + +# ---------------------------------------------------------------------------- +# Switch the abort on error on and check the effect on $mysql_errno +# ---------------------------------------------------------------------------- +--error 1064 +garbage ; +--enable_abort_on_error +eval select $mysql_errno as "after_--enable_abort_on_error" ; + +# ---------------------------------------------------------------------------- +# masked failing statements +# ---------------------------------------------------------------------------- +# expected error = response +--error 1146 +select 3 from t1 ; + +# ---------------------------------------------------------------------------- +# check that the old default behaviour is not changed +# Please remove the '#' to get the abort on error +# ---------------------------------------------------------------------------- +#--error 1064 +#select 3 from t1 ; +# +#select 3 from t1 ; diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test index e79815bbeb1..f5bed3dcdff 100644 --- a/mysql-test/t/ndb_basic.test +++ b/mysql-test/t/ndb_basic.test @@ -371,3 +371,154 @@ select * from t1 order by b; select * from t1 where b IS NULL; select * from t1 where b IS NOT NULL; drop table t1; + +# +# test the limit of no of attributes in one table +# + +create table t1 ( +c1 int, +c2 int, +c3 int, +c4 int, +c5 int, +c6 int, +c7 int, +c8 int, +c9 int, +c10 int, +c11 int, +c12 int, +c13 int, +c14 int, +c15 int, +c16 int, +c17 int, +c18 int, +c19 int, +c20 int, +c21 int, +c22 int, +c23 int, +c24 int, +c25 int, +c26 int, +c27 int, +c28 int, +c29 int, +c30 int, +c31 int, +c32 int, +c33 int, +c34 int, +c35 int, +c36 int, +c37 int, +c38 int, +c39 int, +c40 int, +c41 int, +c42 int, +c43 int, +c44 int, +c45 int, +c46 int, +c47 int, +c48 int, +c49 int, +c50 int, +c51 int, +c52 int, +c53 int, +c54 int, +c55 int, +c56 int, +c57 int, +c58 int, +c59 int, +c60 int, +c61 int, +c62 int, +c63 int, +c64 int, +c65 int, +c66 int, +c67 int, +c68 int, +c69 int, +c70 int, +c71 int, +c72 int, +c73 int, +c74 int, +c75 int, +c76 int, +c77 int, +c78 int, +c79 int, +c80 int, +c81 int, +c82 int, +c83 int, +c84 int, +c85 int, +c86 int, +c87 int, +c88 int, +c89 int, +c90 int, +c91 int, +c92 int, +c93 int, +c94 int, +c95 int, +c96 int, +c97 int, +c98 int, +c99 int, +c100 int, +c101 int, +c102 int, +c103 int, +c104 int, +c105 int, +c106 int, +c107 int, +c108 int, +c109 int, +c110 int, +c111 int, +c112 int, +c113 int, +c114 int, +c115 int, +c116 int, +c117 int, +c118 int, +c119 int, +c120 int, +c121 int, +c122 int, +c123 int, +c124 int, +c125 int, +c126 int, +c127 int, +c128 int, +primary key(c1)) engine=ndb; +drop table t1; + +# +# test max size of attribute name and truncation +# + +create table t1 ( +a1234567890123456789012345678901234567890 int primary key, +a12345678901234567890123456789a1234567890 int, +index(a12345678901234567890123456789a1234567890) +) engine=ndb; +show tables; +insert into t1 values (1,1),(2,1),(3,1),(4,1),(5,2),(6,1),(7,1); +explain select * from t1 where a12345678901234567890123456789a1234567890=2; +select * from t1 where a12345678901234567890123456789a1234567890=2; +drop table t1; diff --git a/mysql-test/t/ndb_blob.test b/mysql-test/t/ndb_blob.test index 5454dd91d26..06ecbc66d97 100644 --- a/mysql-test/t/ndb_blob.test +++ b/mysql-test/t/ndb_blob.test @@ -2,7 +2,7 @@ --disable_warnings drop table if exists t1; -drop database if exists mysqltest; +drop database if exists test2; --enable_warnings # @@ -12,31 +12,7 @@ drop database if exists mysqltest; # A prerequisite for this handler test is that "testBlobs" succeeds. # -# -- bug-5252 tinytext crashes -- - -create table t1 ( - a int not null primary key, - b tinytext -) engine=ndbcluster; - -insert into t1 values(1, 'x'); -update t1 set b = 'y'; -select * from t1; -delete from t1; -drop table t1; - -# -- bug-5013 insert empty string to text -- - -create table t1 ( - a int not null primary key, - b text not null -) engine=ndbcluster; - -insert into t1 values(1, ''); -select * from t1; -drop table t1; - --- general test starts -- +# -- general test starts -- # make test harder with autocommit off set autocommit=0; @@ -117,7 +93,6 @@ from t1 where a=2; # pk update to null update t1 set d=null where a=1; commit; -# FIXME now fails at random due to weird mixup between the 2 rows select a from t1 where d is null; # pk delete @@ -126,6 +101,49 @@ delete from t1 where a=2; commit; select count(*) from t1; +# -- replace ( bug-6018 ) -- + +# insert +replace t1 set a=1,b=@b1,c=111,d=@d1; +replace t1 set a=2,b=@b2,c=222,d=@d2; +commit; +explain select * from t1 where a = 1; + +# pk read +select a,length(b),substr(b,1+2*900,2),length(d),substr(d,1+3*900,3) +from t1 where a=1; +select a,length(b),substr(b,1+2*9000,2),length(d),substr(d,1+3*9000,3) +from t1 where a=2; + +# update +replace t1 set a=1,b=@b2,c=111,d=@d2; +replace t1 set a=2,b=@b1,c=222,d=@d1; +commit; +select a,length(b),substr(b,1+2*9000,2),length(d),substr(d,1+3*9000,3) +from t1 where a=1; +select a,length(b),substr(b,1+2*900,2),length(d),substr(d,1+3*900,3) +from t1 where a=2; + +# update +replace t1 set a=1,b=concat(@b2,@b2),c=111,d=concat(@d2,@d2); +replace t1 set a=2,b=concat(@b1,@b1),c=222,d=concat(@d1,@d1); +commit; +select a,length(b),substr(b,1+4*9000,2),length(d),substr(d,1+6*9000,3) +from t1 where a=1; +select a,length(b),substr(b,1+4*900,2),length(d),substr(d,1+6*900,3) +from t1 where a=2; + +# update to null +replace t1 set a=1,b='xyz',c=111,d=null; +commit; +select a,b from t1 where d is null; + +# pk delete +delete from t1 where a=1; +delete from t1 where a=2; +commit; +select count(*) from t1; + # -- hash index ops -- insert into t1 values(1,@b1,111,@d1); @@ -231,39 +249,6 @@ where c >= 100; commit; select * from t1 where c >= 100 order by a; -# alter table - -select * from t1 order by a; -alter table t1 add x int; -select * from t1 order by a; -alter table t1 drop x; -select * from t1 order by a; - -# multi db - -create database mysqltest; -use mysqltest; - -CREATE TABLE t2 ( - a bigint unsigned NOT NULL PRIMARY KEY, - b int unsigned not null, - c int unsigned -) engine=ndbcluster; - -insert into t2 values (1,1,1),(2,2,2); -select * from test.t1,t2 where test.t1.a = t2.a order by test.t1.a; - -drop table t2; -use test; - -# alter table - -select * from t1 order by a; -alter table t1 add x int; -select * from t1 order by a; -alter table t1 drop x; -select * from t1 order by a; - # range scan delete delete from t1 where c >= 100; commit; @@ -306,10 +291,82 @@ select a,length(b),substr(b,1+2*900,2),length(d),substr(d,1+3*900,3) from t1 order by a; rollback; select count(*) from t1; + +# -- alter table and multi db -- + +insert into t1 values(1,'b1',111,'dd1'); +insert into t1 values(2,'b2',222,'dd2'); +insert into t1 values(3,'b3',333,'dd3'); +insert into t1 values(4,'b4',444,'dd4'); +insert into t1 values(5,'b5',555,'dd5'); +insert into t1 values(6,'b6',666,'dd6'); +insert into t1 values(7,'b7',777,'dd7'); +insert into t1 values(8,'b8',888,'dd8'); +insert into t1 values(9,'b9',999,'dd9'); +commit; + +select * from t1 order by a; +alter table t1 add x int; +select * from t1 order by a; +alter table t1 drop x; +select * from t1 order by a; + +create database test2; +use test2; + +CREATE TABLE t2 ( + a bigint unsigned NOT NULL PRIMARY KEY, + b int unsigned not null, + c int unsigned +) engine=ndbcluster; + +insert into t2 values (1,1,1),(2,2,2); +select * from test.t1,t2 where test.t1.a = t2.a order by test.t1.a; + +drop table t2; +use test; + +select * from t1 order by a; +alter table t1 add x int; +select * from t1 order by a; +alter table t1 drop x; +select * from t1 order by a; + +# -- end general test -- + drop table t1; -drop database mysqltest; +drop database test2; -# bug #5349 +# -- bug-5252 tinytext crashes plus no-commit result -- + +set autocommit=0; +create table t1 ( + a int not null primary key, + b tinytext +) engine=ndbcluster; + +insert into t1 values(1, 'x'); +update t1 set b = 'y'; +select * from t1; +delete from t1; +select * from t1; +commit; +drop table t1; + +# -- bug-5013 insert empty string to text -- + +set autocommit=0; +create table t1 ( + a int not null primary key, + b text not null +) engine=ndbcluster; + +insert into t1 values(1, ''); +select * from t1; +commit; +drop table t1; + +# -- bug #5349 -- set autocommit=1; use test; CREATE TABLE t1 ( @@ -327,7 +384,8 @@ select * from t1 order by a; alter table t1 engine=ndb; select * from t1 order by a; -# bug #5872 +# -- bug #5872 -- +set autocommit=1; alter table t1 engine=myisam; select * from t1 order by a; drop table t1; diff --git a/mysql-test/t/ndb_insert.test b/mysql-test/t/ndb_insert.test index 310c16de3d8..c3da4641014 100644 --- a/mysql-test/t/ndb_insert.test +++ b/mysql-test/t/ndb_insert.test @@ -583,3 +583,18 @@ INSERT INTO t1 VALUES(1,1,1) ON DUPLICATE KEY UPDATE b=79; select * from t1 where pk1=1; DROP TABLE t1; + +# +# Bug #6331: problem with 'insert ignore' +# + +CREATE TABLE t1(a INT) ENGINE=ndb; +INSERT IGNORE INTO t1 VALUES (1); +INSERT IGNORE INTO t1 VALUES (1); +INSERT IGNORE INTO t1 SELECT a FROM t1; +INSERT IGNORE INTO t1 SELECT a FROM t1; +INSERT IGNORE INTO t1 SELECT a FROM t1; +INSERT IGNORE INTO t1 VALUES (1); +INSERT IGNORE INTO t1 VALUES (1); +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/t/ps_10nestset.test b/mysql-test/t/ps_10nestset.test index d2adaca689e..53e84f7a47d 100644 --- a/mysql-test/t/ps_10nestset.test +++ b/mysql-test/t/ps_10nestset.test @@ -61,12 +61,11 @@ while ($1) select * from t1; -# Waiting for the resolution of bug#6138 -# # Now, increase salary to a multiple of 50 -# prepare st_round from 'update t1 set salary = salary + ? - ( salary MOD ? )'; -# set @arg_round= 50; -# execute st_round using @arg_round, @arg_round; -# -# select * from t1; +# Now, increase salary to a multiple of 50 (checks for bug#6138) +prepare st_round from 'update t1 set salary = salary + ? - ( salary MOD ? )'; +set @arg_round= 50; +execute st_round using @arg_round, @arg_round; + +select * from t1; drop table t1; diff --git a/mysql-test/t/ps_7ndb.test b/mysql-test/t/ps_7ndb.test index af669a26400..22370a7f3ac 100644 --- a/mysql-test/t/ps_7ndb.test +++ b/mysql-test/t/ps_7ndb.test @@ -339,8 +339,8 @@ select a,b from t1 where a >= 1000 order by a ; delete from t1 where a >= 1000 ; ## replace ---error 1295 prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' '; +--error 1031 ## multi table statements --disable_query_log diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index d8794b2f394..e0d2e07bef2 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -418,3 +418,17 @@ select count(*) from t2 where x > -16; select count(*) from t2 where x = 18446744073709551601; drop table t1,t2; +# +# Bug #6045: Binary Comparison regression in MySQL 4.1 +# Binary searches didn't use a case insensitive index. +# +set names latin1; +create table t1 (a char(10), b text, key (a)) character set latin1; +INSERT INTO t1 (a) VALUES +('111'),('222'),('222'),('222'),('222'),('444'),('aaa'),('AAA'),('bbb'); +# all these three can be optimized +explain select * from t1 where a='aaa'; +explain select * from t1 where a=binary 'aaa'; +explain select * from t1 where a='aaa' collate latin1_bin; +# this one cannot: +explain select * from t1 where a='aaa' collate latin1_german1_ci; diff --git a/mysql-test/t/rpl_failed_optimize-master.opt b/mysql-test/t/rpl_failed_optimize-master.opt new file mode 100644 index 00000000000..a6ef074a120 --- /dev/null +++ b/mysql-test/t/rpl_failed_optimize-master.opt @@ -0,0 +1 @@ +--innodb-lock-wait-timeout=1 diff --git a/mysql-test/t/rpl_failed_optimize.test b/mysql-test/t/rpl_failed_optimize.test new file mode 100644 index 00000000000..d245d1bacbb --- /dev/null +++ b/mysql-test/t/rpl_failed_optimize.test @@ -0,0 +1,18 @@ +source include/have_innodb.inc; +source include/master-slave.inc; + +# +# BUG#5551 "Failed OPTIMIZE TABLE is logged to binary log" +# Replication should work when OPTIMIZE TABLE timeouts, and +# when OPTIMIZE TABLE is executed on a non-existing table +# + +CREATE TABLE t1 ( a int ) ENGINE=InnoDB; +BEGIN; +INSERT INTO t1 VALUES (1); + +connection master1; +OPTIMIZE TABLE t1; + +OPTIMIZE TABLE non_existing; +sync_slave_with_master; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 9e18f1cd88c..b09d7240721 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -21,7 +21,8 @@ check table t1 changed; check table t1 medium; check table t1 extended; show index from t1; -!$1062 insert into t1 values (5,5,5); +--error 1062 +insert into t1 values (5,5,5); optimize table t1; optimize table t1; drop table t1; diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test index 26a5d07d951..fa5c6cb8a5b 100644 --- a/mysql-test/t/sql_mode.test +++ b/mysql-test/t/sql_mode.test @@ -30,6 +30,37 @@ show create table t1; drop table t1; # +# Check that a binary collation adds 'binary' +# suffix into a char() column definition in +# mysql40 and mysql2323 modes. This allows +# not to lose the column's case sensitivity +# when loading the dump in pre-4.1 servers. +# +# Thus, in 4.0 and 3.23 modes we dump: +# +# 'char(10) collate xxx_bin' as 'char(10) binary' +# 'binary(10)' as 'binary(10)' +# +# In mysql-4.1 these types are different, and they will +# be recreated differently. +# +# In mysqld-4.0 the the above two types were the same, +# so it will create a 'char(10) binary' column for both definitions. +# +CREATE TABLE t1 ( + a char(10), + b char(10) collate latin1_bin, + c binary(10) +) character set latin1; +set @@sql_mode=""; +show create table t1; +set @@sql_mode="mysql323"; +show create table t1; +set @@sql_mode="mysql40"; +show create table t1; +drop table t1; + +# # BUG#5318 - failure: 'IGNORE_SPACE' affects numeric values after DEFAULT # # Force the usage of the default diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test index 2181d3eb74c..74276c7668c 100644 --- a/mysql-test/t/temp_table.test +++ b/mysql-test/t/temp_table.test @@ -20,8 +20,10 @@ create TEMPORARY TABLE t2 engine=heap select * from t1; create TEMPORARY TABLE IF NOT EXISTS t2 (a int) engine=heap; # This should give errors -!$1050 CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null); -!$1050 ALTER TABLE t1 RENAME t2; +--error 1050 +CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null); +--error 1050 +ALTER TABLE t1 RENAME t2; select * from t2; alter table t2 add primary key (a,b); diff --git a/mysql-test/t/type_ranges.test b/mysql-test/t/type_ranges.test index 09b5867e7a8..572dc0af313 100644 --- a/mysql-test/t/type_ranges.test +++ b/mysql-test/t/type_ranges.test @@ -135,7 +135,8 @@ drop table t1,t2; create table t1 (c int); insert into t1 values(1),(2); create table t2 select * from t1; -!$1060 create table t3 select * from t1, t2; # Should give an error +--error 1060 +create table t3 select * from t1, t2; # Should give an error create table t3 select t1.c AS c1, t2.c AS c2,1 as "const" from t1, t2; show full columns from t3; drop table t1,t2,t3; diff --git a/ndb/include/kernel/ndb_limits.h b/ndb/include/kernel/ndb_limits.h index 88fcff22da7..48a56c019bb 100644 --- a/ndb/include/kernel/ndb_limits.h +++ b/ndb/include/kernel/ndb_limits.h @@ -117,4 +117,9 @@ */ #define NDB_BLOB_HEAD_SIZE 2 /* sizeof(NdbBlob::Head) >> 2 */ +/* + * Long signals + */ +#define NDB_SECTION_SEGMENT_SZ 60 + #endif diff --git a/ndb/include/kernel/signaldata/DictTabInfo.hpp b/ndb/include/kernel/signaldata/DictTabInfo.hpp index 6b4a3f34553..ae78c023c2a 100644 --- a/ndb/include/kernel/signaldata/DictTabInfo.hpp +++ b/ndb/include/kernel/signaldata/DictTabInfo.hpp @@ -51,7 +51,6 @@ class DictTabInfo { friend class Trix; friend class DbUtil; // API - friend class Table; friend class NdbSchemaOp; /** diff --git a/ndb/include/ndb_global.h b/ndb/include/ndb_global.h index 09559f6ddff..bdd4e503cc5 100644 --- a/ndb/include/ndb_global.h +++ b/ndb/include/ndb_global.h @@ -82,19 +82,12 @@ extern "C" { /* call in main() - does not return on error */ extern int ndb_init(void); extern void ndb_end(int); +#define NDB_INIT(prog_name) {my_progname=(prog_name); ndb_init();} #ifndef HAVE_STRDUP extern char * strdup(const char *s); #endif -#ifndef HAVE_STRLCPY -extern size_t strlcpy (char *dst, const char *src, size_t dst_sz); -#endif - -#ifndef HAVE_STRLCAT -extern size_t strlcat (char *dst, const char *src, size_t dst_sz); -#endif - #ifndef HAVE_STRCASECMP extern int strcasecmp(const char *s1, const char *s2); extern int strncasecmp(const char *s1, const char *s2, size_t n); diff --git a/ndb/include/ndbapi/NdbBlob.hpp b/ndb/include/ndbapi/NdbBlob.hpp index 5df61a0806c..0fb63015da2 100644 --- a/ndb/include/ndbapi/NdbBlob.hpp +++ b/ndb/include/ndbapi/NdbBlob.hpp @@ -36,7 +36,7 @@ class NdbColumnImpl; * Blob data is stored in 2 places: * * - "header" and "inline bytes" stored in the blob attribute - * - "blob parts" stored in a separate table NDB$BLOB_<t>_<v>_<c> + * - "blob parts" stored in a separate table NDB$BLOB_<tid>_<cid> * * Inline and part sizes can be set via NdbDictionary::Column methods * when the table is created. @@ -74,23 +74,21 @@ class NdbColumnImpl; * NdbBlob methods return -1 on error and 0 on success, and use output * parameters when necessary. * - * Notes: - * - table and its blob part tables are not created atomically - * - scan must use the "new" interface NdbScanOperation - * - to update a blob in a read op requires exclusive tuple lock - * - update op in scan must do its own getBlobHandle - * - delete creates implicit, not-accessible blob handles - * - NdbOperation::writeTuple does not support blobs - * - there is no support for an asynchronous interface + * Operation types: + * - insertTuple must use setValue if blob column is non-nullable + * - readTuple with exclusive lock can also update existing value + * - updateTuple can overwrite with setValue or update existing value + * - writeTuple always overwrites and must use setValue if non-nullable + * - deleteTuple creates implicit non-accessible blob handles + * - scan with exclusive lock can also update existing value + * - scan "lock takeover" update op must do its own getBlobHandle * * Bugs / limitations: - * - scan must use exclusive locking for now - * - * Todo: - * - add scan method hold-read-lock + return-keyinfo - * - check keyinfo length when setting keys - * - check allowed blob ops vs locking mode - * - overload control (too many pending ops) + * - lock mode upgrade should be handled automatically + * - lock mode vs allowed operation is not checked + * - too many pending blob ops can blow up i/o buffers + * - table and its blob part tables are not created atomically + * - there is no support for an asynchronous interface */ class NdbBlob { public: @@ -173,19 +171,11 @@ public: */ int readData(void* data, Uint32& bytes); /** - * Read at given position. Does not use or update current position. - */ - int readData(Uint64 pos, void* data, Uint32& bytes); - /** * Write at current position and set new position to first byte after * the data written. A write past blob end extends the blob value. */ int writeData(const void* data, Uint32 bytes); /** - * Write at given position. Does not use or update current position. - */ - int writeData(Uint64 pos, const void* data, Uint32 bytes); - /** * Return the blob column. */ const NdbDictionary::Column* getColumn(); @@ -266,14 +256,17 @@ private: Buf(); ~Buf(); void alloc(unsigned n); + void copyfrom(const Buf& src); }; Buf theKeyBuf; Buf theAccessKeyBuf; Buf theHeadInlineBuf; + Buf theHeadInlineCopyBuf; // for writeTuple Buf thePartBuf; Head* theHead; char* theInlineData; NdbRecAttr* theHeadInlineRecAttr; + NdbOperation* theHeadInlineReadOp; bool theHeadInlineUpdateFlag; // length and read/write position int theNullFlag; @@ -294,6 +287,7 @@ private: bool isReadOp(); bool isInsertOp(); bool isUpdateOp(); + bool isWriteOp(); bool isDeleteOp(); bool isScanOp(); // computations @@ -309,12 +303,13 @@ private: void getHeadFromRecAttr(); int setHeadInlineValue(NdbOperation* anOp); // data operations - int readDataPrivate(Uint64 pos, char* buf, Uint32& bytes); - int writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes); + int readDataPrivate(char* buf, Uint32& bytes); + int writeDataPrivate(const char* buf, Uint32 bytes); int readParts(char* buf, Uint32 part, Uint32 count); int insertParts(const char* buf, Uint32 part, Uint32 count); int updateParts(const char* buf, Uint32 part, Uint32 count); int deleteParts(Uint32 part, Uint32 count); + int deletePartsUnknown(Uint32 part); // pending ops int executePendingBlobReads(); int executePendingBlobWrites(); diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp index 92b940e96f7..7af5d27b922 100644 --- a/ndb/include/ndbapi/NdbConnection.hpp +++ b/ndb/include/ndbapi/NdbConnection.hpp @@ -526,7 +526,7 @@ private: int sendCOMMIT(); // Send a TC_COMMITREQ signal; void setGCI(int GCI); // Set the global checkpoint identity - int OpCompleteFailure(Uint8 abortoption); + int OpCompleteFailure(Uint8 abortoption, bool setFailure = true); int OpCompleteSuccess(); void CompletedOperations(); // Move active ops to list of completed @@ -552,7 +552,7 @@ private: void setOperationErrorCode(int anErrorCode); // Indicate something went wrong in the definition phase - void setOperationErrorCodeAbort(int anErrorCode); + void setOperationErrorCodeAbort(int anErrorCode, int abortOption = -1); int checkMagicNumber(); // Verify correct object NdbOperation* getNdbOperation(const class NdbTableImpl* aTable, diff --git a/ndb/include/ndbapi/NdbIndexOperation.hpp b/ndb/include/ndbapi/NdbIndexOperation.hpp index 7612fe54d1b..1472f1b249e 100644 --- a/ndb/include/ndbapi/NdbIndexOperation.hpp +++ b/ndb/include/ndbapi/NdbIndexOperation.hpp @@ -49,6 +49,9 @@ public: * @{ */ + /** insert is not allowed */ + int insertTuple(); + /** * Define the NdbIndexOperation to be a standard operation of type readTuple. * When calling NdbConnection::execute, this operation @@ -193,6 +196,7 @@ private: // Private attributes const NdbIndexImpl* m_theIndex; + const NdbTableImpl* m_thePrimaryTable; Uint32 m_theIndexDefined[NDB_MAX_ATTRIBUTES_IN_INDEX][3]; Uint32 m_theIndexLen; // Length of the index in words Uint32 m_theNoOfIndexDefined; // The number of index attributes diff --git a/ndb/include/ndbapi/NdbOperation.hpp b/ndb/include/ndbapi/NdbOperation.hpp index 8e0294e41e6..46d4ddab0f5 100644 --- a/ndb/include/ndbapi/NdbOperation.hpp +++ b/ndb/include/ndbapi/NdbOperation.hpp @@ -918,6 +918,13 @@ protected: // Blobs in this operation NdbBlob* theBlobList; + /* + * Abort option per operation, used by blobs. Default -1. If set, + * overrides abort option on connection level. If set to IgnoreError, + * does not cause execute() to return failure. This is different from + * IgnoreError on connection level. + */ + Int8 m_abortOption; }; #ifdef NDB_NO_DROPPED_SIGNAL @@ -1160,5 +1167,3 @@ NdbOperation::setValue(Uint32 anAttrId, double aPar) } #endif - - diff --git a/ndb/include/ndbapi/ndbapi_limits.h b/ndb/include/ndbapi/ndbapi_limits.h index 1cf2d9b342d..d1cb135b39d 100644 --- a/ndb/include/ndbapi/ndbapi_limits.h +++ b/ndb/include/ndbapi/ndbapi_limits.h @@ -22,12 +22,13 @@ #define NDB_MAX_DATABASE_NAME_SIZE 128 #define NDB_MAX_SCHEMA_NAME_SIZE 128 #define NDB_MAX_TAB_NAME_SIZE 128 -#define NDB_MAX_ATTRIBUTES_IN_TABLE 91 +#define NDB_MAX_ATTR_NAME_SIZE 32 +#define NDB_MAX_ATTRIBUTES_IN_TABLE 128 -#define NDB_MAX_TUPLE_SIZE_IN_WORDS 1023 +#define NDB_MAX_TUPLE_SIZE_IN_WORDS 2013 #define NDB_MAX_KEYSIZE_IN_WORDS 1023 -#define NDB_MAX_KEY_SIZE NDB_MAX_KEYSIZE_IN_WORDS*sizeof(Uint32) -#define NDB_MAX_TUPLE_SIZE NDB_MAX_TUPLE_SIZE_IN_WORDS*sizeof(uint32) +#define NDB_MAX_KEY_SIZE (NDB_MAX_KEYSIZE_IN_WORDS*4) +#define NDB_MAX_TUPLE_SIZE (NDB_MAX_TUPLE_SIZE_IN_WORDS*4) #define NDB_MAX_ACTIVE_EVENTS 100 #endif diff --git a/ndb/include/util/ndb_opts.h b/ndb/include/util/ndb_opts.h new file mode 100644 index 00000000000..6cba9c04449 --- /dev/null +++ b/ndb/include/util/ndb_opts.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _NDB_OPTS_H +#define _NDB_OPTS_H + +#include <my_sys.h> +#include <my_getopt.h> +#include <mysql_version.h> +#include <ndb_version.h> + +#ifndef DBUG_OFF +#define NDB_STD_OPTS(prog_name) \ + { "debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", \ + 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }, \ + { "usage", '?', "Display this help and exit.", \ + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \ + { "help", '?', "Display this help and exit.", \ + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \ + { "version", 'V', "Output version information and exit.", 0, 0, 0, \ + GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \ + { "connect-string", 'c', \ + "Set connect string for connecting to ndb_mgmd. " \ + "<constr>=\"host=<hostname:port>[;nodeid=<id>]\". " \ + "Overides specifying entries in NDB_CONNECTSTRING and config file", \ + (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0, \ + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 } +#else +#define NDB_STD_OPTS(prog_name) \ + { "usage", '?', "Display this help and exit.", \ + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \ + { "help", '?', "Display this help and exit.", \ + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \ + { "version", 'V', "Output version information and exit.", 0, 0, 0, \ + GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \ + { "connect-string", 'c', \ + "Set connect string for connecting to ndb_mgmd. " \ + "<constr>=\"host=<hostname:port>[;nodeid=<id>]\". " \ + "Overides specifying entries in NDB_CONNECTSTRING and config file", \ + (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0, \ + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 } +#endif + +#endif /*_NDB_OPTS_H */ diff --git a/ndb/src/common/editline/sysunix.c b/ndb/src/common/editline/sysunix.c index 000bca78dfc..d7437f6a9c7 100644 --- a/ndb/src/common/editline/sysunix.c +++ b/ndb/src/common/editline/sysunix.c @@ -138,6 +138,11 @@ rl_add_slash(char *path, char *p, size_t p_len) { struct stat Sb; - if (stat(path, &Sb) >= 0) - (void)strlcat(p, S_ISDIR(Sb.st_mode) ? "/" : " ", p_len); + if (stat(path, &Sb) >= 0) { + size_t len= strlen(p); + if (len+1 < p_len) { + p[len]= S_ISDIR(Sb.st_mode) ? '/' : ' '; + p[len+1]= 0; + } + } } diff --git a/ndb/src/common/util/Makefile.am b/ndb/src/common/util/Makefile.am index 0235adae7c9..61fd7992002 100644 --- a/ndb/src/common/util/Makefile.am +++ b/ndb/src/common/util/Makefile.am @@ -7,8 +7,8 @@ libgeneral_la_SOURCES = \ SocketServer.cpp SocketClient.cpp SocketAuthenticator.cpp\ OutputStream.cpp NdbOut.cpp BaseString.cpp Base64.cpp \ NdbSqlUtil.cpp new.cpp \ - uucode.c random.c getarg.c version.c \ - strdup.c strlcat.c strlcpy.c \ + uucode.c random.c version.c \ + strdup.c \ ConfigValues.cpp ndb_init.c basestring_vsnprintf.c include $(top_srcdir)/ndb/config/common.mk.am diff --git a/ndb/src/common/util/basestring_vsnprintf.c b/ndb/src/common/util/basestring_vsnprintf.c index 10932226d18..7307279f345 100644 --- a/ndb/src/common/util/basestring_vsnprintf.c +++ b/ndb/src/common/util/basestring_vsnprintf.c @@ -18,6 +18,7 @@ #define _XOPEN_SOURCE 500 #include <stdio.h> #include <basestring_vsnprintf.h> +#include <my_config.h> int basestring_snprintf(char *str, size_t size, const char *format, ...) @@ -30,8 +31,30 @@ basestring_snprintf(char *str, size_t size, const char *format, ...) return(ret); } +#ifdef HAVE_SNPRINTF + #define BASESTRING_VSNPRINTF_FUNC(a,b,c,d) vsnprintf(a,b,c,d) +#else + #define SNPRINTF_RETURN_TRUNC + /* #define BASESTRING_VSNPRINTF_FUNC(a,b,c,d) my_vsnprintf(a,b,c,d) + * we would like to use my_vsnprintf but it does not have enough features + * Let's hope vsnprintf works anyways + */ + #define BASESTRING_VSNPRINTF_FUNC(a,b,c,d) vsnprintf(a,b,c,d) + extern int my_vsnprintf(char *str, size_t size, const char *format, va_list ap); +#endif +#ifdef SNPRINTF_RETURN_TRUNC +static char basestring_vsnprintf_buf[16*1024]; +#endif int basestring_vsnprintf(char *str, size_t size, const char *format, va_list ap) { - return(vsnprintf(str, size, format, ap)); + int ret= BASESTRING_VSNPRINTF_FUNC(str, size, format, ap); +#ifdef SNPRINTF_RETURN_TRUNC + if (ret == size-1 || ret == -1) { + ret= BASESTRING_VSNPRINTF_FUNC(basestring_vsnprintf_buf, + sizeof(basestring_vsnprintf_buf), + format, ap); + } +#endif + return ret; } diff --git a/ndb/src/common/util/socket_io.cpp b/ndb/src/common/util/socket_io.cpp index 6f4c7e63684..83a546de773 100644 --- a/ndb/src/common/util/socket_io.cpp +++ b/ndb/src/common/util/socket_io.cpp @@ -172,22 +172,21 @@ vprint_socket(NDB_SOCKET_TYPE socket, int timeout_millis, const char * fmt, va_list ap){ char buf[1000]; char *buf2 = buf; - size_t size = sizeof(buf); + size_t size; - if (fmt != 0) { + if (fmt != 0 && fmt[0] != 0) { size = BaseString::vsnprintf(buf, sizeof(buf), fmt, ap); /* Check if the output was truncated */ - if(size >= sizeof(buf)) { - buf2 = (char *)malloc(size+1); + if(size > sizeof(buf)) { + buf2 = (char *)malloc(size); if(buf2 == NULL) return -1; BaseString::vsnprintf(buf2, size, fmt, ap); - } else - size = sizeof(buf); + } } else - buf[0] = 0; + return 0; - int ret = write_socket(socket, timeout_millis, buf2, strlen(buf2)); + int ret = write_socket(socket, timeout_millis, buf2, size); if(buf2 != buf) free(buf2); return ret; @@ -199,23 +198,23 @@ vprintln_socket(NDB_SOCKET_TYPE socket, int timeout_millis, const char * fmt, va_list ap){ char buf[1000]; char *buf2 = buf; - size_t size = sizeof(buf); + size_t size; - if (fmt != 0) { - size = BaseString::vsnprintf(buf, sizeof(buf), fmt, ap); + if (fmt != 0 && fmt[0] != 0) { + size = BaseString::vsnprintf(buf, sizeof(buf), fmt, ap)+1;// extra byte for '/n' /* Check if the output was truncated */ - if(size >= sizeof(buf)-1) { - buf2 = (char *)malloc(size+2); + if(size > sizeof(buf)) { + buf2 = (char *)malloc(size); if(buf2 == NULL) return -1; - BaseString::vsnprintf(buf2, size+1, fmt, ap); - } else - size = sizeof(buf); - } else - buf[0] = 0; - strlcat(buf2, "\n", size+2); + BaseString::vsnprintf(buf2, size, fmt, ap); + } + } else { + size = 1; + } + buf2[size-1]='\n'; - int ret = write_socket(socket, timeout_millis, buf2, strlen(buf2)); + int ret = write_socket(socket, timeout_millis, buf2, size); if(buf2 != buf) free(buf2); return ret; diff --git a/ndb/src/common/util/strlcat.c b/ndb/src/common/util/strlcat.c deleted file mode 100644 index aa282abe48d..00000000000 --- a/ndb/src/common/util/strlcat.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 1995 - 1999 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <ndb_global.h> - -/* RCSID("$KTH: strlcat.c,v 1.1 2000/08/16 01:23:47 lha Exp $"); */ - - -#ifndef HAVE_STRLCAT - -size_t -strlcat (char *dst, const char *src, size_t dst_sz) -{ - size_t len = strlen(dst); - - return len + strlcpy (dst + len, src, dst_sz - len); -} -#endif diff --git a/ndb/src/common/util/strlcpy.c b/ndb/src/common/util/strlcpy.c deleted file mode 100644 index 97cff177d48..00000000000 --- a/ndb/src/common/util/strlcpy.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 1995 - 1999 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <ndb_global.h> - -/* RCSID("$KTH: strlcpy.c,v 1.1 2000/08/16 01:23:48 lha Exp $"); */ - -#ifndef HAVE_STRLCPY - -size_t -strlcpy (char *dst, const char *src, size_t dst_sz) -{ - size_t n; - char *p; - - for (p = dst, n = 0; - n + 1 < dst_sz && *src != '\0'; - ++p, ++src, ++n) - *p = *src; - *p = '\0'; - if (*src == '\0') - return n; - else - return n + strlen (src); -} - -#endif diff --git a/ndb/src/cw/cpcd/common.cpp b/ndb/src/cw/cpcd/common.cpp index cb1c0c37183..53c0e4d5a64 100644 --- a/ndb/src/cw/cpcd/common.cpp +++ b/ndb/src/cw/cpcd/common.cpp @@ -96,66 +96,3 @@ insert_file(const char * filename, class Properties& p){ if(f) fclose(f); return res; } - -int -parse_config_file(struct getargs args[], int num_arg, const Properties& p){ - Properties::Iterator it(&p); - for(const char * name = it.first(); name != 0; name = it.next()){ - bool found = false; - for(int i = 0; i<num_arg; i++){ - if(strcmp(name, args[i].long_name) != 0) - continue; - - found = true; - - const char * tmp; - p.get(name, &tmp); - - int t = 1; - - switch(args[i].type){ - case arg_integer:{ - int val = atoi(tmp); - if(args[i].value){ - *((int*)args[i].value) = val; - } - } - break; - case arg_string: - if(args[i].value){ - *((const char**)args[i].value) = tmp; - } - break; - case arg_negative_flag: - t = 0; - case arg_flag: - if(args[i].value){ - if(!strcasecmp(tmp, "y") || - !strcasecmp(tmp, "on") || - !strcasecmp(tmp, "true") || - !strcasecmp(tmp, "1")){ - *((int*)args[i].value) = t; - } - if(!strcasecmp(tmp, "n") || - !strcasecmp(tmp, "off") || - !strcasecmp(tmp, "false") || - !strcasecmp(tmp, "0")){ - *((int*)args[i].value) = t; - } - } - t = 1; - break; - case arg_strings: - case arg_double: - case arg_collect: - case arg_counter: - break; - } - } - if(!found) { - printf("Unknown parameter: %s\n", name); - return 1; - } - } - return 0; -} diff --git a/ndb/src/cw/cpcd/common.hpp b/ndb/src/cw/cpcd/common.hpp index c3d87b8b9f5..4f5f702762f 100644 --- a/ndb/src/cw/cpcd/common.hpp +++ b/ndb/src/cw/cpcd/common.hpp @@ -19,7 +19,9 @@ #include <ndb_global.h> #include <logger/Logger.hpp> +#if 0 #include <getarg.h> +#endif extern int debug; @@ -30,6 +32,5 @@ int insert(const char * pair, class Properties & p); int insert_file(const char * filename, class Properties&); int insert_file(FILE *, class Properties&, bool break_on_empty = false); -int parse_config_file(struct getargs args[], int num_arg, const Properties& p); #endif /* ! __CPCD_COMMON_HPP_INCLUDED__ */ diff --git a/ndb/src/cw/cpcd/main.cpp b/ndb/src/cw/cpcd/main.cpp index 207b81bfa89..300b51d7b5a 100644 --- a/ndb/src/cw/cpcd/main.cpp +++ b/ndb/src/cw/cpcd/main.cpp @@ -15,13 +15,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <ndb_global.h> /* Needed for mkdir(2) */ +#include <ndb_opts.h> #include "CPCD.hpp" #include "APIService.hpp" #include <NdbMain.h> #include <NdbSleep.h> #include <BaseString.hpp> -#include <getarg.h> #include <logger/Logger.hpp> #include <logger/FileLogHandler.hpp> #include <logger/SysLogHandler.hpp> @@ -29,28 +29,44 @@ #include "common.hpp" static const char *work_dir = CPCD_DEFAULT_WORK_DIR; -static int port = CPCD_DEFAULT_TCP_PORT; -static int use_syslog = 0; +static int port; +static int use_syslog; static const char *logfile = NULL; static const char *config_file = CPCD_DEFAULT_CONFIG_FILE; static const char *user = 0; -static struct getargs args[] = { - { "work-dir", 'w', arg_string, &work_dir, - "Work directory", "directory" }, - { "port", 'p', arg_integer, &port, - "TCP port to listen on", "port" }, - { "syslog", 'S', arg_flag, &use_syslog, - "Log events to syslog", NULL}, - { "logfile", 'L', arg_string, &logfile, - "File to log events to", "file"}, - { "debug", 'D', arg_flag, &debug, - "Enable debug mode", NULL}, - { "config", 'c', arg_string, &config_file, "Config file", NULL }, - { "user", 'u', arg_string, &user, "Run as user", NULL } +static struct my_option my_long_options[] = +{ + { "work-dir", 'w', "Work directory", + (gptr*) &work_dir, (gptr*) &work_dir, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "port", 'p', "TCP port to listen on", + (gptr*) &port, (gptr*) &port, 0, + GET_INT, REQUIRED_ARG, CPCD_DEFAULT_TCP_PORT, 0, 0, 0, 0, 0 }, + { "syslog", 'S', "Log events to syslog", + (gptr*) &use_syslog, (gptr*) &use_syslog, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "logfile", 'L', "File to log events to", + (gptr*) &logfile, (gptr*) &logfile, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "debug", 'D', "Enable debug mode", + (gptr*) &debug, (gptr*) &debug, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "config", 'c', "Config file", + (gptr*) &config_file, (gptr*) &config_file, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "user", 'u', "Run as user", + (gptr*) &user, (gptr*) &user, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; -static const int num_args = sizeof(args) / sizeof(args[0]); +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + return 0; +} static CPCD * g_cpcd = 0; #if 0 @@ -59,23 +75,16 @@ extern "C" static void sig_child(int signo, siginfo_t*, void*); const char *progname = "ndb_cpcd"; -NDB_MAIN(ndb_cpcd){ - int optind = 0; - - if(getarg(args, num_args, argc, argv, &optind)) { - arg_printusage(args, num_args, progname, ""); - exit(1); - } - - Properties p; - insert_file(config_file, p); - if(parse_config_file(args, num_args, p)){ - ndbout_c("Invalid config file: %s", config_file); - exit(1); - } +int main(int argc, char** argv){ + int save_argc= argc; + char** save_argv= argv; + const char *load_default_groups[]= { "ndb_cpcd",0 }; + MY_INIT(argv[0]); - if(getarg(args, num_args, argc, argv, &optind)) { - arg_printusage(args, num_args, progname, ""); + load_defaults("ndb_cpcd",load_default_groups,&argc,&argv); + if (handle_options(&argc, &argv, my_long_options, get_one_option)) { + my_print_help(my_long_options); + my_print_variables(my_long_options); exit(1); } diff --git a/ndb/src/kernel/blocks/backup/restore/main.cpp b/ndb/src/kernel/blocks/backup/restore/main.cpp index f7b1479cc93..482212911cb 100644 --- a/ndb/src/kernel/blocks/backup/restore/main.cpp +++ b/ndb/src/kernel/blocks/backup/restore/main.cpp @@ -14,7 +14,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <getarg.h> +#include <ndb_global.h> +#include <ndb_opts.h> #include <Vector.hpp> #include <ndb_limits.h> #include <NdbTCP.h> @@ -35,80 +36,107 @@ static Vector<class BackupConsumer *> g_consumers; static const char* ga_backupPath = "." DIR_SEPARATOR; -static const char* ga_connect_NDB = NULL; +static const char* opt_connect_str= NULL; /** * print and restore flags */ static bool ga_restore = false; static bool ga_print = false; +static int _print = 0; +static int _print_meta = 0; +static int _print_data = 0; +static int _print_log = 0; +static int _restore_data = 0; +static int _restore_meta = 0; + +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS("ndb_restore"), + { "connect", 'c', "same as --connect-string", + (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "nodeid", 'n', "Backup files from node with id", + (gptr*) &ga_nodeId, (gptr*) &ga_nodeId, 0, + GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "backupid", 'b', "Backup id", + (gptr*) &ga_backupId, (gptr*) &ga_backupId, 0, + GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "restore_data", 'r', + "Restore table data/logs into NDB Cluster using NDBAPI", + (gptr*) &_restore_data, (gptr*) &_restore_data, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "restore_meta", 'm', + "Restore meta data into NDB Cluster using NDBAPI", + (gptr*) &_restore_meta, (gptr*) &_restore_meta, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "parallelism", 'p', + "No of parallel transactions during restore of data." + "(parallelism can be 1 to 1024)", + (gptr*) &ga_nParallelism, (gptr*) &ga_nParallelism, 0, + GET_INT, REQUIRED_ARG, 128, 0, 0, 0, 0, 0 }, + { "print", 256, "Print data and log to stdout", + (gptr*) &_print, (gptr*) &_print, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "print_data", 257, "Print data to stdout", + (gptr*) &_print_data, (gptr*) &_print_data, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "print_meta", 258, "Print meta data to stdout", + (gptr*) &_print_meta, (gptr*) &_print_meta, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "print_log", 259, "Print log to stdout", + (gptr*) &_print_log, (gptr*) &_print_log, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "dont_ignore_systab_0", 'f', + "Experimental. Do not ignore system table during restore.", + (gptr*) &ga_dont_ignore_systab_0, (gptr*) &ga_dont_ignore_systab_0, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; + +static void short_usage_sub(void) +{ + printf("Usage: %s [OPTIONS] [<path to backup files>]\n", my_progname); +} +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ + short_usage_sub(); + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_restore.trace"); + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); + } + return 0; +} bool -readArguments(const int argc, const char** argv) +readArguments(int *pargc, char*** pargv) { - - int _print = 0; - int _print_meta = 0; - int _print_data = 0; - int _print_log = 0; - int _restore_data = 0; - int _restore_meta = 0; - - - struct getargs args[] = - { - { "connect", 'c', arg_string, &ga_connect_NDB, - "NDB Cluster connection", "\"nodeid=<api id>;host=<hostname:port>\""}, - { "nodeid", 'n', arg_integer, &ga_nodeId, - "Backup files from node", "db node id"}, - { "backupid", 'b',arg_integer, &ga_backupId, "Backup id", "backup id"}, - { "print", '\0', arg_flag, &_print, - "Print data and log to stdout", "print data and log"}, - { "print_data", '\0', arg_flag, &_print_data, - "Print data to stdout", "print data"}, - { "print_meta", '\0', arg_flag, &_print_meta, - "Print meta data to stdout", "print meta data"}, - { "print_log", '\0', arg_flag, &_print_log, - "Print log to stdout", "print log"}, - { "restore_data", 'r', arg_flag, &_restore_data, - "Restore table data/logs into NDB Cluster using NDBAPI", - "Restore table data/log"}, - { "restore_meta", 'm', arg_flag, &_restore_meta, - "Restore meta data into NDB Cluster using NDBAPI", "Restore meta data"}, - { "parallelism", 'p', arg_integer, &ga_nParallelism, - "No of parallel transactions during restore of data." - "(parallelism can be 1 to 1024)", - "Parallelism"}, -#ifdef USE_MYSQL - { "use_mysql", '\0', arg_flag, &use_mysql, - "Restore meta data via mysql. Systab will be ignored. Data is restored " - "using NDBAPI.", "use mysql"}, - { "user", '\0', arg_string, &ga_user, "MySQL user", "Default: root"}, - { "password", '\0', arg_string, &ga_password, "MySQL user's password", - "Default: \"\" "}, - { "host", '\0', arg_string, &ga_host, "Hostname of MySQL server", - "Default: localhost"}, - { "socket", '\0', arg_string, &ga_socket, "Path to MySQL server socket file", - "Default: /tmp/mysql.sock"}, - { "port", '\0', arg_integer, &ga_port, "Port number of MySQL server", - "Default: 3306"}, -#endif - { "dont_ignore_systab_0", 'f', arg_flag, &ga_dont_ignore_systab_0, - "Experimental. Do not ignore system table during restore.", - "dont_ignore_systab_0"} - - }; - - int num_args = sizeof(args) / sizeof(args[0]); - int optind = 0; - - if (getarg(args, num_args, argc, argv, &optind) || + const char *load_default_groups[]= { "ndb_tools","ndb_restore",0 }; + load_defaults("my",load_default_groups,pargc,pargv); + if (handle_options(pargc, pargv, my_long_options, get_one_option) || ga_nodeId == 0 || ga_backupId == 0 || ga_nParallelism < 1 || - ga_nParallelism >1024) - { - arg_printusage(args, num_args, argv[0], "<path to backup files>\n"); - return false; + ga_nParallelism >1024) { + exit(1); } BackupPrinter* printer = new BackupPrinter(); @@ -122,10 +150,6 @@ readArguments(const int argc, const char** argv) return false; } - /** - * Got segmentation fault when using the printer's attributes directly - * in getargs... Do not have the time to found out why... this is faster... - */ if (_print) { ga_print = true; @@ -169,15 +193,14 @@ readArguments(const int argc, const char** argv) g_consumers.push_back(c); } // Set backup file path - if (argv[optind] != NULL) + if (*pargv[0] != NULL) { - ga_backupPath = argv[optind]; + ga_backupPath = *pargv[0]; } return true; } - void clearConsumers() { @@ -204,19 +227,16 @@ free_data_callback() } int -main(int argc, const char** argv) +main(int argc, char** argv) { - ndb_init(); - if (!readArguments(argc, argv)) + NDB_INIT(argv[0]); + + if (!readArguments(&argc, &argv)) { return -1; } - if (ga_connect_NDB != NULL) - { - // Use connection string - Ndb::setConnectString(ga_connect_NDB); - } + Ndb::setConnectString(opt_connect_str); /** * we must always load meta data, even if we will only print it to stdout diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index d1a8128ea7f..882557daae1 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -3661,9 +3661,8 @@ Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){ req->tableId = tabPtr.i; req->tableVersion = tabEntry->m_tableVersion + 1; - sendSignal(rg, GSN_CREATE_TAB_REQ, signal, - CreateTabReq::SignalLength, JBB); - + sendFragmentedSignal(rg, GSN_CREATE_TAB_REQ, signal, + CreateTabReq::SignalLength, JBB); return; } diff --git a/ndb/src/kernel/error/ErrorReporter.cpp b/ndb/src/kernel/error/ErrorReporter.cpp index 35c99b30994..35cd3f099d9 100644 --- a/ndb/src/kernel/error/ErrorReporter.cpp +++ b/ndb/src/kernel/error/ErrorReporter.cpp @@ -137,7 +137,7 @@ ErrorReporter::formatMessage(ErrorCategory type, faultID, (problemData == NULL) ? "" : problemData, objRef, - programName, + my_progname, processId, theNameOfTheTraceFile ? theNameOfTheTraceFile : "<no tracefile>"); diff --git a/ndb/src/kernel/main.cpp b/ndb/src/kernel/main.cpp index fa44704807d..926647838c9 100644 --- a/ndb/src/kernel/main.cpp +++ b/ndb/src/kernel/main.cpp @@ -53,11 +53,9 @@ extern "C" void handler_error(int signum); // for process signal handling void systemInfo(const Configuration & conf, const LogLevel & ll); -const char programName[] = "NDB Kernel"; - -NDB_MAIN(ndb_kernel){ - - ndb_init(); +int main(int argc, char** argv) +{ + NDB_INIT(argv[0]); // Print to stdout/console g_eventLogger.createConsoleHandler(); g_eventLogger.setCategory("NDB"); diff --git a/ndb/src/kernel/vm/Configuration.cpp b/ndb/src/kernel/vm/Configuration.cpp index 706f60fd9cf..b3a436275f7 100644 --- a/ndb/src/kernel/vm/Configuration.cpp +++ b/ndb/src/kernel/vm/Configuration.cpp @@ -15,6 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <ndb_global.h> +#include <ndb_opts.h> #include <LocalConfig.hpp> #include "Configuration.hpp" @@ -28,8 +29,6 @@ #include <NdbOut.hpp> #include <WatchDog.hpp> -#include <getarg.h> - #include <mgmapi_configuration.hpp> #include <mgmapi_config_parameters_debug.h> #include <kernel_config_parameters.h> @@ -47,81 +46,86 @@ extern "C" { #include <EventLogger.hpp> extern EventLogger g_eventLogger; +static const char* opt_connect_str= 0; +static int _daemon, _no_daemon, _initial, _no_start; +/** + * Arguments to NDB process + */ +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS("ndbd"), + { "initial", 256, + "Perform initial start of ndbd, including cleaning the file system. " + "Consult documentation before using this", + (gptr*) &_initial, (gptr*) &_initial, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "nostart", 'n', + "Don't start ndbd immediately. Ndbd will await command from ndb_mgmd", + (gptr*) &_no_start, (gptr*) &_no_start, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "daemon", 'd', "Start ndbd as daemon (default)", + (gptr*) &_daemon, (gptr*) &_daemon, 0, + GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, + { "nodaemon", 257, + "Do not start ndbd as daemon, provided for testing purposes", + (gptr*) &_no_daemon, (gptr*) &_no_daemon, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; +static void short_usage_sub(void) +{ + printf("Usage: %s [OPTIONS]\n", my_progname); +} +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ + short_usage_sub(); + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndbd.trace"); + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); + } + return 0; +} + bool -Configuration::init(int argc, const char** argv){ +Configuration::init(int argc, char** argv) +{ + const char *load_default_groups[]= { "ndbd",0 }; + load_defaults("my",load_default_groups,&argc,&argv); - /** - * Default values for arguments - */ - int _no_start = 0; - int _initial = 0; - const char* _connect_str = NULL; - int _daemon = 1; - int _no_daemon = 0; - int _help = 0; - int _print_version = 0; -#ifndef DBUG_OFF - const char *debug_option= 0; -#endif - - /** - * Arguments to NDB process - */ - - struct getargs args[] = { - { "version", 'v', arg_flag, &_print_version, "Print ndbd version", "" }, - { "nostart", 'n', arg_flag, &_no_start, - "Don't start ndbd immediately. Ndbd will await command from ndb_mgmd", "" }, - { "daemon", 'd', arg_flag, &_daemon, "Start ndbd as daemon (default)", "" }, - { "nodaemon", 0, arg_flag, &_no_daemon, "Do not start ndbd as daemon, provided for testing purposes", "" }, -#ifndef DBUG_OFF - { "debug", 0, arg_string, &debug_option, - "Specify debug options e.g. d:t:i:o,out.trace", "options" }, -#endif - { "initial", 0, arg_flag, &_initial, - "Perform initial start of ndbd, including cleaning the file system. Consult documentation before using this", "" }, + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + exit(ho_error); - { "connect-string", 'c', arg_string, &_connect_str, - "Set connect string for connecting to ndb_mgmd. <constr>=\"host=<hostname:port>[;nodeid=<id>]\". Overides specifying entries in NDB_CONNECTSTRING and config file", - "<constr>" }, - { "usage", '?', arg_flag, &_help, "Print help", "" } - }; - int num_args = sizeof(args) / sizeof(args[0]); - int optind = 0; - char desc[] = - "The MySQL Cluster kernel"; - - if(getarg(args, num_args, argc, argv, &optind) || _help) { - arg_printusage(args, num_args, argv[0], desc); - for (int i = 0; i < argc; i++) { - if (strcmp("-i",argv[i]) == 0) { - printf("flag depricated %s, use %s\n", "-i", "--initial"); - } - } - return false; - } if (_no_daemon) { _daemon= 0; } - // check for depricated flag '-i' - -#ifndef DBUG_OFF - if (debug_option) - DBUG_PUSH(debug_option); -#endif DBUG_PRINT("info", ("no_start=%d", _no_start)); DBUG_PRINT("info", ("initial=%d", _initial)); DBUG_PRINT("info", ("daemon=%d", _daemon)); - DBUG_PRINT("info", ("connect_str=%s", _connect_str)); + DBUG_PRINT("info", ("connect_str=%s", opt_connect_str)); ndbSetOwnVersion(); - if (_print_version) { - ndbPrintVersion(); - return false; - } - // Check the start flag if (_no_start) globalData.theRestartFlag = initial_state; @@ -133,8 +137,8 @@ Configuration::init(int argc, const char** argv){ _initialStart = true; // Check connectstring - if (_connect_str) - _connectString = strdup(_connect_str); + if (opt_connect_str) + _connectString = strdup(opt_connect_str); // Check daemon flag if (_daemon) diff --git a/ndb/src/kernel/vm/Configuration.hpp b/ndb/src/kernel/vm/Configuration.hpp index 2ea32ffea37..e4cd64f5ca8 100644 --- a/ndb/src/kernel/vm/Configuration.hpp +++ b/ndb/src/kernel/vm/Configuration.hpp @@ -31,7 +31,7 @@ public: /** * Returns false if arguments are invalid */ - bool init(int argc, const char** argv); + bool init(int argc, char** argv); void fetch_configuration(LocalConfig &local_config); void setupConfiguration(); diff --git a/ndb/src/kernel/vm/Emulator.hpp b/ndb/src/kernel/vm/Emulator.hpp index bd240f8679b..b3c64830802 100644 --- a/ndb/src/kernel/vm/Emulator.hpp +++ b/ndb/src/kernel/vm/Emulator.hpp @@ -25,6 +25,7 @@ // //=========================================================================== #include <kernel_types.h> +#include <TransporterRegistry.hpp> extern class JobTable globalJobTable; extern class TimeQueue globalTimeQueue; diff --git a/ndb/src/kernel/vm/LongSignal.hpp b/ndb/src/kernel/vm/LongSignal.hpp index f9ed443d995..9818358011f 100644 --- a/ndb/src/kernel/vm/LongSignal.hpp +++ b/ndb/src/kernel/vm/LongSignal.hpp @@ -25,7 +25,7 @@ */ struct SectionSegment { - STATIC_CONST( DataLength = 60 ); + STATIC_CONST( DataLength = NDB_SECTION_SEGMENT_SZ ); Uint32 m_ownerRef; Uint32 m_sz; diff --git a/ndb/src/mgmclient/main.cpp b/ndb/src/mgmclient/main.cpp index cc6d4bf600e..a37214d366b 100644 --- a/ndb/src/mgmclient/main.cpp +++ b/ndb/src/mgmclient/main.cpp @@ -15,11 +15,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <ndb_global.h> +#include <ndb_opts.h> #include <NdbMain.h> #include <NdbHost.h> -#include <util/getarg.h> #include <mgmapi.h> +#include <ndb_version.h> #include <LocalConfig.hpp> #include "CommandInterpreter.hpp" @@ -43,28 +44,62 @@ handler(int sig){ } } -int main(int argc, const char** argv){ - ndb_init(); - int optind = 0; + +static unsigned _try_reconnect; +static char *opt_connect_str= 0; + +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS("ndb_mgm"), + { "try-reconnect", 't', + "Specify number of retries for connecting to ndb_mgmd, default infinite", + (gptr*) &_try_reconnect, (gptr*) &_try_reconnect, 0, + GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; +static void short_usage_sub(void) +{ + printf("Usage: %s [OPTIONS] [hostname [port]]\n", my_progname); +} +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ + short_usage_sub(); + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_mgm.trace"); + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); + } + return 0; +} + +int main(int argc, char** argv){ + NDB_INIT(argv[0]); const char *_host = 0; int _port = 0; - int _help = 0; - int _try_reconnect = 0; - - struct getargs args[] = { - { "try-reconnect", 't', arg_integer, &_try_reconnect, "Specify number of retries for connecting to ndb_mgmd, default infinite", "#" }, - { "usage", '?', arg_flag, &_help, "Print help", "" }, - }; - int num_args = sizeof(args) / sizeof(args[0]); /* Number of arguments */ - - - if(getarg(args, num_args, argc, argv, &optind) || _help) { - arg_printusage(args, num_args, progname, "[host [port]]"); - exit(1); - } + const char *load_default_groups[]= { "ndb_mgm",0 }; - argv += optind; - argc -= optind; + load_defaults("my",load_default_groups,&argc,&argv); + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + exit(ho_error); LocalConfig cfg; @@ -74,7 +109,7 @@ int main(int argc, const char** argv){ _port = atoi(argv[1]); } } else { - if(cfg.init(0, 0) && cfg.ids.size() > 0 && cfg.ids[0].type == MgmId_TCP){ + if(cfg.init(opt_connect_str, 0) && cfg.ids.size() > 0 && cfg.ids[0].type == MgmId_TCP){ _host = cfg.ids[0].name.c_str(); _port = cfg.ids[0].port; } else { diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index 29df10630f3..2e30d73290b 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -407,7 +407,6 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId, // signals to other management servers. _ownReference(0), m_local_config(local_config), - m_allocated_resources(*this), theSignalIdleList(NULL), theWaitState(WAIT_SUBSCRIBE_CONF), m_statisticsListner(this) @@ -480,6 +479,13 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId, _ownNodeId= 0; NodeId tmp= nodeId; BaseString error_string; + + if ((m_node_id_mutex = NdbMutex_Create()) == 0) + { + ndbout << "mutex creation failed line = " << __LINE__ << endl; + exit(-1); + } + #if 0 char my_hostname[256]; struct sockaddr_in tmp_addr; @@ -512,7 +518,6 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId, #endif _ownNodeId = tmp; - { DBUG_PRINT("info", ("verifyConfig")); ConfigRetriever cr(m_local_config, NDB_VERSION, NDB_MGM_NODE_TYPE_MGM); @@ -534,12 +539,6 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId, m_statisticsListner.m_logLevel = se.m_logLevel; } - if ((m_node_id_mutex = NdbMutex_Create()) == 0) - { - ndbout << "mutex creation failed line = " << __LINE__ << endl; - exit(-1); - } - DBUG_VOID_RETURN; } diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp index a5f21b6bc4a..c796e1e9219 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -534,7 +534,6 @@ private: Uint32 m_nextConfigGenerationNumber; NodeBitmask m_reserved_nodes; - Allocated_resources m_allocated_resources; struct in_addr m_connect_address[MAX_NODES]; //************************************************************************** diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index 5b552836955..2672d8c9d4b 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -773,8 +773,10 @@ MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &, /* XXX should use constants for this value */ if(level > 15) { - errorString.assign("Invalied loglevel"); - goto error; + m_output->println("set cluster loglevel reply"); + m_output->println("result: Invalid loglevel"); + m_output->println(""); + return; } EventSubscribeReq req; @@ -786,11 +788,6 @@ MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &, m_output->println("set cluster loglevel reply"); m_output->println("result: Ok"); m_output->println(""); - return; -error: - m_output->println("set cluster loglevel reply"); - m_output->println("result: %s", errorString.c_str()); - m_output->println(""); } void @@ -807,8 +804,10 @@ MgmApiSession::setLogLevel(Parser<MgmApiSession>::Context &, /* XXX should use constants for this value */ if(level > 15) { - errorString.assign("Invalied loglevel"); - goto error; + m_output->println("set loglevel reply"); + m_output->println("result: Invalid loglevel", errorString.c_str()); + m_output->println(""); + return; } EventSubscribeReq req; @@ -820,11 +819,6 @@ MgmApiSession::setLogLevel(Parser<MgmApiSession>::Context &, m_output->println("set loglevel reply"); m_output->println("result: Ok"); m_output->println(""); - return; - error: - m_output->println("set loglevel reply"); - m_output->println("result: %s", errorString.c_str()); - m_output->println(""); } void diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index 5ee48e4cfcc..15767e4766d 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -15,6 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <ndb_global.h> +#include <ndb_opts.h> #include "MgmtSrvr.hpp" #include "EventLogger.hpp" @@ -33,7 +34,6 @@ #include <ndb_version.h> #include <ConfigRetriever.hpp> #include <mgmapi_config_parameters.h> -#include <getarg.h> #include <NdbAutoPtr.hpp> @@ -97,41 +97,93 @@ bool g_StopServer; extern EventLogger g_EventLogger; extern int global_mgmt_server_check; -int _print_version = 0; -#ifndef DBUG_OFF -const char *debug_option= 0; -#endif +static char *opt_connect_str= 0; -struct getargs args[] = { - { "version", 'v', arg_flag, &_print_version, - "Print ndb_mgmd version",""}, - { "config-file", 'c', arg_string, &glob.config_filename, - "Specify cluster configuration file (default config.ini if available)", - "filename"}, +static struct my_option my_long_options[] = +{ #ifndef DBUG_OFF - { "debug", 0, arg_string, &debug_option, - "Specify debug options e.g. d:t:i:o,out.trace", "options"}, + { "debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", + 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }, #endif - { "daemon", 'd', arg_flag, &glob.daemon, - "Run ndb_mgmd in daemon mode (default)",""}, - { NULL, 'l', arg_string, &glob.local_config_filename, - "Specify configuration file connect string (default Ndb.cfg if available)", - "filename"}, - { "interactive", 0, arg_flag, &glob.interactive, - "Run interactive. Not supported but provided for testing purposes", ""}, - { "no-nodeid-checks", 0, arg_flag, &g_no_nodeid_checks, - "Do not provide any node id checks", ""}, - { "nodaemon", 0, arg_flag, &glob.non_interactive, - "Don't run as daemon, but don't read from stdin", "non-interactive"} + { "usage", '?', "Display this help and exit.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "help", '?', "Display this help and exit.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "version", 'V', "Output version information and exit.", 0, 0, 0, + GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "connect-string", 1023, + "Set connect string for connecting to ndb_mgmd. " + "<constr>=\"host=<hostname:port>[;nodeid=<id>]\". " + "Overides specifying entries in NDB_CONNECTSTRING and config file", + (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "config-file", 'f', "Specify cluster configuration file", + (gptr*) &glob.config_filename, (gptr*) &glob.config_filename, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "daemon", 'd', "Run ndb_mgmd in daemon mode (default)", + (gptr*) &glob.daemon, (gptr*) &glob.daemon, 0, + GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, + { "l", 'l', "Specify configuration file connect string (default Ndb.cfg if available)", + (gptr*) &glob.local_config_filename, (gptr*) &glob.local_config_filename, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "interactive", 256, "Run interactive. Not supported but provided for testing purposes", + (gptr*) &glob.interactive, (gptr*) &glob.interactive, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "no-nodeid-checks", 257, "Do not provide any node id checks", + (gptr*) &g_no_nodeid_checks, (gptr*) &g_no_nodeid_checks, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "nodaemon", 258, "Don't run as daemon, but don't read from stdin", + (gptr*) &glob.non_interactive, (gptr*) &glob.non_interactive, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "config-file", 'c', + "-c provided for backwards compatability, will be removed in 5.0." + " Use -f instead", + (gptr*) &glob.config_filename, (gptr*) &glob.config_filename, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; - -int num_args = sizeof(args) / sizeof(args[0]); +static void short_usage_sub(void) +{ + printf("Usage: %s [OPTIONS]\n", my_progname); +} +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ + short_usage_sub(); + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_mgmd.trace"); + break; + case 'V': + print_version(); + exit(0); + case 'c': + printf("Warning: -c will be removed in 5.0, use -f instead\n"); + break; + case '?': + usage(); + exit(0); + } + return 0; +} /* * MAIN */ -NDB_MAIN(mgmsrv){ - ndb_init(); +int main(int argc, char** argv) +{ + NDB_INIT(argv[0]); /** * OSE specific. Enable shared ownership of file system resources. @@ -143,31 +195,20 @@ NDB_MAIN(mgmsrv){ #endif global_mgmt_server_check = 1; + glob.config_filename= "config.ini"; - int optind = 0; - if(getarg(args, num_args, argc, argv, &optind)) { - arg_printusage(args, num_args, progname, ""); - exit(1); - } + const char *load_default_groups[]= { "ndb_mgmd",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + exit(ho_error); if (glob.interactive || glob.non_interactive) { glob.daemon= 0; } -#ifndef DBUG_OFF - if (debug_option) - DBUG_PUSH(debug_option); -#endif - - if (_print_version) { - ndbPrintVersion(); - exit(0); - } - - if(glob.config_filename == NULL) { - glob.config_filename= "config.ini"; - } glob.socketServer = new SocketServer(); MgmApiService * mapi = new MgmApiService(); diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index d7b8a695fe2..75ae539fc8b 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -1386,6 +1386,7 @@ Ndb::printState(const char* fmt, ...) va_end(ap); NdbMutex_Lock(ndb_print_state_mutex); bool dups = false; + unsigned i; ndbout << buf << " ndb=" << hex << this << dec; #ifndef NDB_WIN32 ndbout << " thread=" << (int)pthread_self(); @@ -1406,21 +1407,21 @@ Ndb::printState(const char* fmt, ...) ndbout << "!! DUPS !!" << endl; dups = true; } - for (unsigned i = 0; i < theNoOfPreparedTransactions; i++) + for (i = 0; i < theNoOfPreparedTransactions; i++) thePreparedTransactionsArray[i]->printState(); ndbout << "sent: " << theNoOfSentTransactions<< endl; if (checkdups(theSentTransactionsArray, theNoOfSentTransactions)) { ndbout << "!! DUPS !!" << endl; dups = true; } - for (unsigned i = 0; i < theNoOfSentTransactions; i++) + for (i = 0; i < theNoOfSentTransactions; i++) theSentTransactionsArray[i]->printState(); ndbout << "completed: " << theNoOfCompletedTransactions<< endl; if (checkdups(theCompletedTransactionsArray, theNoOfCompletedTransactions)) { ndbout << "!! DUPS !!" << endl; dups = true; } - for (unsigned i = 0; i < theNoOfCompletedTransactions; i++) + for (i = 0; i < theNoOfCompletedTransactions; i++) theCompletedTransactionsArray[i]->printState(); NdbMutex_Unlock(ndb_print_state_mutex); } diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp index feab95d8ca5..53c0a0e07f9 100644 --- a/ndb/src/ndbapi/NdbBlob.cpp +++ b/ndb/src/ndbapi/NdbBlob.cpp @@ -33,21 +33,24 @@ ndbout << prefix << " " << hex << (void*)this << " " << cname; \ ndbout << " " << dec << __LINE__ << " " << x << " " << *this << endl; \ } while (0) -#else -#define DBG(x) -#endif static char* ndb_blob_debug(const Uint32* data, unsigned size) { - static char buf[128 + 1]; // MT irrelevant + static char buf[200]; // MT irrelevant buf[0] = 0; - for (unsigned i = 0; i < size && i < 128 / 4; i++) { - sprintf(buf + strlen(buf), "%*s%08x", i != 0, "", data[i]); + for (unsigned i = 0; i < size; i++) { + unsigned n = strlen(buf); + if (n + 10 < sizeof(buf)) + sprintf(buf + n, "%*s%08x", i != 0, "", data[i]); } return buf; } +#else +#define DBG(x) +#endif + /* * Reading index table directly (as a table) is faster but there are * bugs or limitations. Keep the code and make possible to choose. @@ -94,22 +97,24 @@ NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnIm bt.setName(btname); bt.setLogging(t->getLogging()); bt.setFragmentType(t->getFragmentType()); - { NdbDictionary::Column bc("DIST"); + { NdbDictionary::Column bc("PK"); bc.setType(NdbDictionary::Column::Unsigned); + assert(t->m_sizeOfKeysInWords != 0); + bc.setLength(t->m_sizeOfKeysInWords); bc.setPrimaryKey(true); bc.setDistributionKey(true); bt.addColumn(bc); } - { NdbDictionary::Column bc("PART"); + { NdbDictionary::Column bc("DIST"); bc.setType(NdbDictionary::Column::Unsigned); bc.setPrimaryKey(true); + bc.setDistributionKey(true); bt.addColumn(bc); } - { NdbDictionary::Column bc("PK"); + { NdbDictionary::Column bc("PART"); bc.setType(NdbDictionary::Column::Unsigned); - assert(t->m_sizeOfKeysInWords != 0); - bc.setLength(t->m_sizeOfKeysInWords); bc.setPrimaryKey(true); + bc.setDistributionKey(false); bt.addColumn(bc); } { NdbDictionary::Column bc("DATA"); @@ -162,6 +167,7 @@ NdbBlob::init() theHead = NULL; theInlineData = NULL; theHeadInlineRecAttr = NULL; + theHeadInlineReadOp = NULL; theHeadInlineUpdateFlag = false; theNullFlag = -1; theLength = 0; @@ -206,6 +212,13 @@ NdbBlob::Buf::alloc(unsigned n) #endif } +void +NdbBlob::Buf::copyfrom(const NdbBlob::Buf& src) +{ + assert(size == src.size); + memcpy(data, src.data, size); +} + // classify operations (inline) inline bool @@ -226,6 +239,7 @@ NdbBlob::isKeyOp() return theNdbOp->theOperationType == NdbOperation::InsertRequest || theNdbOp->theOperationType == NdbOperation::UpdateRequest || + theNdbOp->theOperationType == NdbOperation::WriteRequest || theNdbOp->theOperationType == NdbOperation::ReadRequest || theNdbOp->theOperationType == NdbOperation::ReadExclusive || theNdbOp->theOperationType == NdbOperation::DeleteRequest; @@ -254,6 +268,13 @@ NdbBlob::isUpdateOp() } inline bool +NdbBlob::isWriteOp() +{ + return + theNdbOp->theOperationType == NdbOperation::WriteRequest; +} + +inline bool NdbBlob::isDeleteOp() { return @@ -373,9 +394,10 @@ NdbBlob::setPartKeyValue(NdbOperation* anOp, Uint32 part) Uint32* data = (Uint32*)theKeyBuf.data; unsigned size = theTable->m_sizeOfKeysInWords; DBG("setPartKeyValue dist=" << getDistKey(part) << " part=" << part << " key=" << ndb_blob_debug(data, size)); - if (anOp->equal((Uint32)0, getDistKey(part)) == -1 || - anOp->equal((Uint32)1, part) == -1 || - anOp->equal((Uint32)2, theKeyBuf.data) == -1) { + // TODO use attr ids after compatibility with 4.1.7 not needed + if (anOp->equal("PK", theKeyBuf.data) == -1 || + anOp->equal("DIST", getDistKey(part)) == -1 || + anOp->equal("PART", part) == -1) { setErrorCode(anOp); return -1; } @@ -401,7 +423,7 @@ NdbBlob::getHeadFromRecAttr() theNullFlag = theHeadInlineRecAttr->isNULL(); assert(theNullFlag != -1); theLength = ! theNullFlag ? theHead->length : 0; - DBG("getHeadFromRecAttr out"); + DBG("getHeadFromRecAttr [out]"); } int @@ -453,7 +475,7 @@ NdbBlob::setValue(const void* data, Uint32 bytes) setErrorCode(ErrState); return -1; } - if (! isInsertOp() && ! isUpdateOp()) { + if (! isInsertOp() && ! isUpdateOp() && ! isWriteOp()) { setErrorCode(ErrUsage); return -1; } @@ -466,11 +488,12 @@ NdbBlob::setValue(const void* data, Uint32 bytes) theGetSetBytes = bytes; if (isInsertOp()) { // write inline part now - if (theSetBuf != 0) { - unsigned n = theGetSetBytes; + if (theSetBuf != NULL) { + Uint32 n = theGetSetBytes; if (n > theInlineSize) n = theInlineSize; - if (writeDataPrivate(0, theSetBuf, n) == -1) + assert(thePos == 0); + if (writeDataPrivate(theSetBuf, n) == -1) return -1; } else { theNullFlag = true; @@ -555,7 +578,7 @@ NdbBlob::getLength(Uint64& len) int NdbBlob::truncate(Uint64 length) { - DBG("truncate length=" << length); + DBG("truncate [in] length=" << length); if (theNullFlag == -1) { setErrorCode(ErrState); return -1; @@ -573,7 +596,10 @@ NdbBlob::truncate(Uint64 length) } theLength = length; theHeadInlineUpdateFlag = true; + if (thePos > length) + thePos = length; } + DBG("truncate [out]"); return 0; } @@ -610,32 +636,20 @@ NdbBlob::setPos(Uint64 pos) int NdbBlob::readData(void* data, Uint32& bytes) { - if (readData(thePos, data, bytes) == -1) - return -1; - thePos += bytes; - assert(thePos <= theLength); - return 0; -} - -int -NdbBlob::readData(Uint64 pos, void* data, Uint32& bytes) -{ if (theState != Active) { setErrorCode(ErrState); return -1; } char* buf = static_cast<char*>(data); - return readDataPrivate(pos, buf, bytes); + return readDataPrivate(buf, bytes); } int -NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes) +NdbBlob::readDataPrivate(char* buf, Uint32& bytes) { - DBG("readData pos=" << pos << " bytes=" << bytes); - if (pos > theLength) { - setErrorCode(ErrSeek); - return -1; - } + DBG("readData [in] bytes=" << bytes); + assert(thePos <= theLength); + Uint64 pos = thePos; if (bytes > theLength - pos) bytes = theLength - pos; Uint32 len = bytes; @@ -665,7 +679,6 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes) if (readParts(thePartBuf.data, part, 1) == -1) return -1; // need result now - DBG("execute pending part reads"); if (executePendingBlobReads() == -1) return -1; Uint32 n = thePartSize - off; @@ -699,7 +712,6 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes) if (readParts(thePartBuf.data, part, 1) == -1) return -1; // need result now - DBG("execute pending part reads"); if (executePendingBlobReads() == -1) return -1; memcpy(buf, thePartBuf.data, len); @@ -709,38 +721,29 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes) len -= n; } assert(len == 0); - return 0; -} - -int -NdbBlob::writeData(const void* data, Uint32 bytes) -{ - if (writeData(thePos, data, bytes) == -1) - return -1; - thePos += bytes; + thePos = pos; assert(thePos <= theLength); + DBG("readData [out]"); return 0; } int -NdbBlob::writeData(Uint64 pos, const void* data, Uint32 bytes) +NdbBlob::writeData(const void* data, Uint32 bytes) { if (theState != Active) { setErrorCode(ErrState); return -1; } const char* buf = static_cast<const char*>(data); - return writeDataPrivate(pos, buf, bytes); + return writeDataPrivate(buf, bytes); } int -NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes) +NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes) { - DBG("writeData pos=" << pos << " bytes=" << bytes); - if (pos > theLength) { - setErrorCode(ErrSeek); - return -1; - } + DBG("writeData [in] bytes=" << bytes); + assert(thePos <= theLength); + Uint64 pos = thePos; Uint32 len = bytes; // any write makes blob not NULL if (theNullFlag) { @@ -771,14 +774,12 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes) if (off != 0) { DBG("partial first block pos=" << pos << " len=" << len); // flush writes to guarantee correct read - DBG("execute pending part writes"); if (executePendingBlobWrites() == -1) return -1; Uint32 part = (pos - theInlineSize) / thePartSize; if (readParts(thePartBuf.data, part, 1) == -1) return -1; // need result now - DBG("execute pending part reafs"); if (executePendingBlobReads() == -1) return -1; Uint32 n = thePartSize - off; @@ -822,13 +823,11 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes) Uint32 part = (pos - theInlineSize) / thePartSize; if (theLength > pos + len) { // flush writes to guarantee correct read - DBG("execute pending part writes"); if (executePendingBlobWrites() == -1) return -1; if (readParts(thePartBuf.data, part, 1) == -1) return -1; // need result now - DBG("execute pending part reads"); if (executePendingBlobReads() == -1) return -1; memcpy(thePartBuf.data, buf, len); @@ -855,14 +854,16 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes) theLength = pos; theHeadInlineUpdateFlag = true; } - DBG("writeData out"); + thePos = pos; + assert(thePos <= theLength); + DBG("writeData [out]"); return 0; } int NdbBlob::readParts(char* buf, Uint32 part, Uint32 count) { - DBG("readParts part=" << part << " count=" << count); + DBG("readParts [in] part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); @@ -873,6 +874,7 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count) setErrorCode(tOp); return -1; } + tOp->m_abortOption = AbortOnError; buf += thePartSize; n++; thePendingBlobOps |= (1 << NdbOperation::ReadRequest); @@ -884,7 +886,7 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count) int NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count) { - DBG("insertParts part=" << part << " count=" << count); + DBG("insertParts [in] part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); @@ -895,6 +897,7 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count) setErrorCode(tOp); return -1; } + tOp->m_abortOption = AbortOnError; buf += thePartSize; n++; thePendingBlobOps |= (1 << NdbOperation::InsertRequest); @@ -906,7 +909,7 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count) int NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count) { - DBG("updateParts part=" << part << " count=" << count); + DBG("updateParts [in] part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); @@ -917,6 +920,7 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count) setErrorCode(tOp); return -1; } + tOp->m_abortOption = AbortOnError; buf += thePartSize; n++; thePendingBlobOps |= (1 << NdbOperation::UpdateRequest); @@ -928,7 +932,7 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count) int NdbBlob::deleteParts(Uint32 part, Uint32 count) { - DBG("deleteParts part=" << part << " count=" << count); + DBG("deleteParts [in] part=" << part << " count=" << count); Uint32 n = 0; while (n < count) { NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable); @@ -938,6 +942,7 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count) setErrorCode(tOp); return -1; } + tOp->m_abortOption = AbortOnError; n++; thePendingBlobOps |= (1 << NdbOperation::DeleteRequest); theNdbCon->thePendingBlobOps |= (1 << NdbOperation::DeleteRequest); @@ -945,6 +950,59 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count) return 0; } +/* + * Number of blob parts not known. Used to check for race condition + * when writeTuple is used for insert. Deletes all parts found. + */ +int +NdbBlob::deletePartsUnknown(Uint32 part) +{ + DBG("deletePartsUnknown [in] part=" << part << " count=all"); + static const unsigned maxbat = 256; + static const unsigned minbat = 1; + unsigned bat = minbat; + NdbOperation* tOpList[maxbat]; + Uint32 count = 0; + while (true) { + Uint32 n; + n = 0; + while (n < bat) { + NdbOperation*& tOp = tOpList[n]; // ref + tOp = theNdbCon->getNdbOperation(theBlobTable); + if (tOp == NULL || + tOp->deleteTuple() == -1 || + setPartKeyValue(tOp, part + count + n) == -1) { + setErrorCode(tOp); + return -1; + } + tOp->m_abortOption = IgnoreError; + n++; + } + DBG("deletePartsUnknown: executeNoBlobs [in] bat=" << bat); + if (theNdbCon->executeNoBlobs(NoCommit) == -1) + return -1; + DBG("deletePartsUnknown: executeNoBlobs [out]"); + n = 0; + while (n < bat) { + NdbOperation* tOp = tOpList[n]; + if (tOp->theError.code != 0) { + if (tOp->theError.code != 626) { + setErrorCode(tOp); + return -1; + } + // first non-existent part + DBG("deletePartsUnknown [out] count=" << count); + return 0; + } + n++; + count++; + } + bat *= 4; + if (bat > maxbat) + bat = maxbat; + } +} + // pending ops int @@ -952,8 +1010,10 @@ NdbBlob::executePendingBlobReads() { Uint8 flags = (1 << NdbOperation::ReadRequest); if (thePendingBlobOps & flags) { + DBG("executePendingBlobReads: executeNoBlobs [in]"); if (theNdbCon->executeNoBlobs(NoCommit) == -1) return -1; + DBG("executePendingBlobReads: executeNoBlobs [out]"); thePendingBlobOps = 0; theNdbCon->thePendingBlobOps = 0; } @@ -965,8 +1025,10 @@ NdbBlob::executePendingBlobWrites() { Uint8 flags = 0xFF & ~(1 << NdbOperation::ReadRequest); if (thePendingBlobOps & flags) { + DBG("executePendingBlobWrites: executeNoBlobs [in]"); if (theNdbCon->executeNoBlobs(NoCommit) == -1) return -1; + DBG("executePendingBlobWrites: executeNoBlobs [out]"); thePendingBlobOps = 0; theNdbCon->thePendingBlobOps = 0; } @@ -978,10 +1040,10 @@ NdbBlob::executePendingBlobWrites() int NdbBlob::invokeActiveHook() { - DBG("invokeActiveHook"); + DBG("invokeActiveHook [in]"); assert(theState == Active && theActiveHook != NULL); int ret = (*theActiveHook)(this, theActiveHookArg); - DBG("invokeActiveHook ret=" << ret); + DBG("invokeActiveHook [out] ret=" << ret); if (ret != 0) { // no error is set on blob level return -1; @@ -1007,7 +1069,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* theTable = anOp->m_currentTable; theAccessTable = anOp->m_accessTable; theColumn = aColumn; - DBG("atPrepare"); + DBG("atPrepare [in]"); NdbDictionary::Column::Type partType = NdbDictionary::Column::Undefined; switch (theColumn->getType()) { case NdbDictionary::Column::Blob: @@ -1046,6 +1108,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* theKeyBuf.alloc(theTable->m_sizeOfKeysInWords << 2); theAccessKeyBuf.alloc(theAccessTable->m_sizeOfKeysInWords << 2); theHeadInlineBuf.alloc(sizeof(Head) + theInlineSize); + theHeadInlineCopyBuf.alloc(sizeof(Head) + theInlineSize); thePartBuf.alloc(thePartSize); theHead = (Head*)theHeadInlineBuf.data; theInlineData = theHeadInlineBuf.data + sizeof(Head); @@ -1080,6 +1143,12 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* theNullFlag = true; theLength = 0; } + if (isWriteOp()) { + // becomes NULL unless set before execute + theNullFlag = true; + theLength = 0; + theHeadInlineUpdateFlag = true; + } supportedOp = true; } if (isScanOp()) { @@ -1093,19 +1162,21 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* return -1; } setState(Prepared); - DBG("atPrepare out"); + DBG("atPrepare [out]"); return 0; } /* * Before execute of prepared operation. May add new operations before * this one. May ask that this operation and all before it (a "batch") - * is executed immediately in no-commit mode. + * is executed immediately in no-commit mode. In this case remaining + * prepared operations are saved in a separate list. They are added + * back after postExecute. */ int NdbBlob::preExecute(ExecType anExecType, bool& batch) { - DBG("preExecute"); + DBG("preExecute [in]"); if (theState == Invalid) return -1; assert(theState == Prepared); @@ -1120,11 +1191,11 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch) if (isInsertOp()) { if (theSetFlag && theGetSetBytes > theInlineSize) { // add ops to write rest of a setValue - assert(theSetBuf != 0); - Uint64 pos = theInlineSize; + assert(theSetBuf != NULL); const char* buf = theSetBuf + theInlineSize; Uint32 bytes = theGetSetBytes - theInlineSize; - if (writeDataPrivate(pos, buf, bytes) == -1) + assert(thePos == theInlineSize); + if (writeDataPrivate(buf, bytes) == -1) return -1; if (theHeadInlineUpdateFlag) { // add an operation to update head+inline @@ -1136,11 +1207,12 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch) setErrorCode(ErrAbort); return -1; } + DBG("add op to update head+inline"); } } } if (isTableOp()) { - if (isUpdateOp() || isDeleteOp()) { + if (isUpdateOp() || isWriteOp() || isDeleteOp()) { // add operation before this one to read head+inline NdbOperation* tOp = theNdbCon->getNdbOperation(theTable, theNdbOp); if (tOp == NULL || @@ -1150,8 +1222,13 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch) setErrorCode(tOp); return -1; } + if (isWriteOp()) { + tOp->m_abortOption = IgnoreError; + } + theHeadInlineReadOp = tOp; // execute immediately batch = true; + DBG("add op before to read head+inline"); } } if (isIndexOp()) { @@ -1170,7 +1247,7 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch) return -1; } } else { - NdbOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp); + NdbIndexOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp); if (tOp == NULL || tOp->readTuple() == -1 || setAccessKeyValue(tOp) == -1 || @@ -1180,6 +1257,7 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch) } } } + DBG("added op before to read table key"); if (isUpdateOp() || isDeleteOp()) { // add op before this one to read head+inline via index NdbIndexOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp); @@ -1190,15 +1268,43 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch) setErrorCode(tOp); return -1; } + if (isWriteOp()) { + tOp->m_abortOption = IgnoreError; + } + theHeadInlineReadOp = tOp; // execute immediately batch = true; + DBG("added index op before to read head+inline"); + } + if (isWriteOp()) { + // XXX until IgnoreError fixed for index op + batch = true; + } + } + if (isWriteOp()) { + if (theSetFlag) { + // write head+inline now + theNullFlag = true; + theLength = 0; + if (theSetBuf != NULL) { + Uint32 n = theGetSetBytes; + if (n > theInlineSize) + n = theInlineSize; + assert(thePos == 0); + if (writeDataPrivate(theSetBuf, n) == -1) + return -1; + } + if (setHeadInlineValue(theNdbOp) == -1) + return -1; + // the read op before us may overwrite + theHeadInlineCopyBuf.copyfrom(theHeadInlineBuf); } } if (theActiveHook != NULL) { // need blob head for callback batch = true; } - DBG("preExecute out batch=" << batch); + DBG("preExecute [out] batch=" << batch); return 0; } @@ -1211,15 +1317,16 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch) int NdbBlob::postExecute(ExecType anExecType) { - DBG("postExecute type=" << anExecType); + DBG("postExecute [in] type=" << anExecType); if (theState == Invalid) return -1; if (theState == Active) { setState(anExecType == NoCommit ? Active : Closed); - DBG("postExecute skip"); + DBG("postExecute [skip]"); return 0; } assert(theState == Prepared); + setState(anExecType == NoCommit ? Active : Closed); assert(isKeyOp()); if (isIndexOp()) { NdbBlob* tFirstBlob = theNdbOp->theBlobList; @@ -1231,22 +1338,13 @@ NdbBlob::postExecute(ExecType anExecType) } if (isReadOp()) { getHeadFromRecAttr(); - if (theGetFlag && theGetSetBytes > 0) { - // copy inline bytes to user buffer - assert(theGetBuf != NULL); - unsigned n = theGetSetBytes; - if (n > theInlineSize) - n = theInlineSize; - memcpy(theGetBuf, theInlineData, n); - } - if (theGetFlag && theGetSetBytes > theInlineSize) { - // add ops to read rest of a getValue - assert(anExecType == NoCommit); - assert(theGetBuf != 0); - Uint64 pos = theInlineSize; - char* buf = theGetBuf + theInlineSize; - Uint32 bytes = theGetSetBytes - theInlineSize; - if (readDataPrivate(pos, buf, bytes) == -1) + if (setPos(0) == -1) + return -1; + if (theGetFlag) { + assert(theGetSetBytes == 0 || theGetBuf != 0); + assert(theGetSetBytes <= theInlineSize || anExecType == NoCommit); + Uint32 bytes = theGetSetBytes; + if (readDataPrivate(theGetBuf, bytes) == -1) return -1; } } @@ -1255,10 +1353,11 @@ NdbBlob::postExecute(ExecType anExecType) getHeadFromRecAttr(); if (theSetFlag) { // setValue overwrites everything - if (theSetBuf != 0) { + if (theSetBuf != NULL) { if (truncate(0) == -1) return -1; - if (writeDataPrivate(0, theSetBuf, theGetSetBytes) == -1) + assert(thePos == 0); + if (writeDataPrivate(theSetBuf, theGetSetBytes) == -1) return -1; } else { if (setNull() == -1) @@ -1266,6 +1365,57 @@ NdbBlob::postExecute(ExecType anExecType) } } } + if (isWriteOp() && isTableOp()) { + assert(anExecType == NoCommit); + if (theHeadInlineReadOp->theError.code == 0) { + int tNullFlag = theNullFlag; + Uint64 tLength = theLength; + Uint64 tPos = thePos; + getHeadFromRecAttr(); + DBG("tuple found"); + if (truncate(0) == -1) + return -1; + // restore previous head+inline + theHeadInlineBuf.copyfrom(theHeadInlineCopyBuf); + theNullFlag = tNullFlag; + theLength = tLength; + thePos = tPos; + } else { + if (theHeadInlineReadOp->theError.code != 626) { + setErrorCode(theHeadInlineReadOp); + return -1; + } + DBG("tuple not found"); + /* + * Read found no tuple but it is possible that a tuple was + * created after the read by another transaction. Delete all + * blob parts which may exist. + */ + if (deletePartsUnknown(0) == -1) + return -1; + } + if (theSetFlag && theGetSetBytes > theInlineSize) { + assert(theSetBuf != NULL); + const char* buf = theSetBuf + theInlineSize; + Uint32 bytes = theGetSetBytes - theInlineSize; + assert(thePos == theInlineSize); + if (writeDataPrivate(buf, bytes) == -1) + return -1; + } + } + if (isWriteOp() && isIndexOp()) { + // XXX until IgnoreError fixed for index op + if (deletePartsUnknown(0) == -1) + return -1; + if (theSetFlag && theGetSetBytes > theInlineSize) { + assert(theSetBuf != NULL); + const char* buf = theSetBuf + theInlineSize; + Uint32 bytes = theGetSetBytes - theInlineSize; + assert(thePos == theInlineSize); + if (writeDataPrivate(buf, bytes) == -1) + return -1; + } + } if (isDeleteOp()) { assert(anExecType == NoCommit); getHeadFromRecAttr(); @@ -1278,7 +1428,19 @@ NdbBlob::postExecute(ExecType anExecType) if (invokeActiveHook() == -1) return -1; } - DBG("postExecute out"); + if (anExecType == NoCommit && theHeadInlineUpdateFlag) { + NdbOperation* tOp = theNdbCon->getNdbOperation(theTable); + if (tOp == NULL || + tOp->updateTuple() == -1 || + setTableKeyValue(tOp) == -1 || + setHeadInlineValue(tOp) == -1) { + setErrorCode(ErrAbort); + return -1; + } + tOp->m_abortOption = AbortOnError; + DBG("added op to update head+inline"); + } + DBG("postExecute [out]"); return 0; } @@ -1289,12 +1451,12 @@ NdbBlob::postExecute(ExecType anExecType) int NdbBlob::preCommit() { - DBG("preCommit"); + DBG("preCommit [in]"); if (theState == Invalid) return -1; assert(theState == Active); assert(isKeyOp()); - if (isInsertOp() || isUpdateOp()) { + if (isInsertOp() || isUpdateOp() || isWriteOp()) { if (theHeadInlineUpdateFlag) { // add an operation to update head+inline NdbOperation* tOp = theNdbCon->getNdbOperation(theTable); @@ -1305,9 +1467,11 @@ NdbBlob::preCommit() setErrorCode(ErrAbort); return -1; } + tOp->m_abortOption = AbortOnError; + DBG("added op to update head+inline"); } } - DBG("preCommit out"); + DBG("preCommit [out]"); return 0; } @@ -1317,13 +1481,10 @@ NdbBlob::preCommit() int NdbBlob::atNextResult() { - DBG("atNextResult"); + DBG("atNextResult [in]"); if (theState == Invalid) return -1; assert(isScanOp()); - getHeadFromRecAttr(); - // reset position - thePos = 0; // get primary key { Uint32* data = (Uint32*)theKeyBuf.data; unsigned size = theTable->m_sizeOfKeysInWords; @@ -1332,26 +1493,14 @@ NdbBlob::atNextResult() return -1; } } - if (! theNullFlag) { - if (theGetFlag && theGetSetBytes > 0) { - // copy inline bytes to user buffer - assert(theGetBuf != NULL); - unsigned n = theGetSetBytes; - if (n > theLength) - n = theLength; - if (n > theInlineSize) - n = theInlineSize; - memcpy(theGetBuf, theInlineData, n); - } - if (theGetFlag && theGetSetBytes > theInlineSize && theLength > theInlineSize) { - // add ops to read rest of a getValue - assert(theGetBuf != 0); - Uint64 pos = theInlineSize; - char* buf = theGetBuf + theInlineSize; - Uint32 bytes = theGetSetBytes - theInlineSize; - if (readDataPrivate(pos, buf, bytes) == -1) - return -1; - } + getHeadFromRecAttr(); + if (setPos(0) == -1) + return -1; + if (theGetFlag) { + assert(theGetSetBytes == 0 || theGetBuf != 0); + Uint32 bytes = theGetSetBytes; + if (readDataPrivate(theGetBuf, bytes) == -1) + return -1; } setState(Active); // activation callback @@ -1359,7 +1508,7 @@ NdbBlob::atNextResult() if (invokeActiveHook() == -1) return -1; } - DBG("atNextResult out"); + DBG("atNextResult [out]"); return 0; } @@ -1444,7 +1593,8 @@ operator<<(NdbOut& out, const NdbBlob& blob) ndbout << dec << " n=" << blob.theNullFlag;; ndbout << dec << " l=" << blob.theLength; ndbout << dec << " p=" << blob.thePos; - ndbout << dec << " u=" << (Uint32) blob.theHeadInlineUpdateFlag; + ndbout << dec << " u=" << (Uint32)blob.theHeadInlineUpdateFlag; + ndbout << dec << " g=" << (Uint32)blob.theGetSetBytes; return out; } #endif diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp index 1457792cf28..4f6468eb4ae 100644 --- a/ndb/src/ndbapi/NdbConnection.cpp +++ b/ndb/src/ndbapi/NdbConnection.cpp @@ -170,12 +170,14 @@ Remark: Sets an error code on the connection object from an operation object. *****************************************************************************/ void -NdbConnection::setOperationErrorCodeAbort(int error) +NdbConnection::setOperationErrorCodeAbort(int error, int abortOption) { DBUG_ENTER("NdbConnection::setOperationErrorCodeAbort"); + if (abortOption == -1) + abortOption = m_abortOption; if (theTransactionIsStarted == false) { theCommitStatus = Aborted; - } else if ((m_abortOption == AbortOnError) && + } else if ((abortOption == AbortOnError) && (theCommitStatus != Committed) && (theCommitStatus != Aborted)) { theCommitStatus = NeedAbort; @@ -335,8 +337,16 @@ NdbConnection::execute(ExecType aTypeOfExec, tOp = tOp->next(); } } + if (executeNoBlobs(tExecType, abortOption, forceSend) == -1) ret = -1; +#ifndef VM_TRACE + // can happen in complex abort cases + theFirstOpInList = theLastOpInList = NULL; +#else + assert(theFirstOpInList == NULL && theLastOpInList == NULL); +#endif + { NdbOperation* tOp = theCompletedFirstOp; while (tOp != NULL) { @@ -360,6 +370,7 @@ NdbConnection::execute(ExecType aTypeOfExec, theLastOpInList->next(tRestOp); theLastOpInList = tLastOp; } + assert(theFirstOpInList == NULL || tExecType == NoCommit); } while (theFirstOpInList != NULL || tExecType != aTypeOfExec); DBUG_RETURN(ret); @@ -1806,11 +1817,12 @@ Parameters: aErrorCode: The error code. Remark: An operation was completed with failure. *******************************************************************************/ int -NdbConnection::OpCompleteFailure(Uint8 abortOption) +NdbConnection::OpCompleteFailure(Uint8 abortOption, bool setFailure) { Uint32 tNoComp = theNoOfOpCompleted; Uint32 tNoSent = theNoOfOpSent; - theCompletionStatus = NdbConnection::CompletedFailure; + if (setFailure) + theCompletionStatus = NdbConnection::CompletedFailure; tNoComp++; theNoOfOpCompleted = tNoComp; if (tNoComp == tNoSent) { diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index cf51a30fe0b..304d1b904d4 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -47,13 +47,13 @@ * Column */ NdbColumnImpl::NdbColumnImpl() - : NdbDictionary::Column(* this), m_facade(this) + : NdbDictionary::Column(* this), m_attrId(-1), m_facade(this) { init(); } NdbColumnImpl::NdbColumnImpl(NdbDictionary::Column & f) - : NdbDictionary::Column(* this), m_facade(&f) + : NdbDictionary::Column(* this), m_attrId(-1), m_facade(&f) { init(); } @@ -93,8 +93,7 @@ NdbColumnImpl::init(Type t) { // do not use default_charset_info as it may not be initialized yet // use binary collation until NDB tests can handle charsets - CHARSET_INFO* default_cs = &my_charset_latin1_bin; - m_attrId = -1; + CHARSET_INFO* default_cs = &my_charset_bin; m_type = t; switch (m_type) { case Tinyint: diff --git a/ndb/src/ndbapi/NdbIndexOperation.cpp b/ndb/src/ndbapi/NdbIndexOperation.cpp index 9abde639914..3f174a61b64 100644 --- a/ndb/src/ndbapi/NdbIndexOperation.cpp +++ b/ndb/src/ndbapi/NdbIndexOperation.cpp @@ -71,6 +71,7 @@ NdbIndexOperation::indxInit(const NdbIndexImpl * anIndex, return -1; } m_theIndex = anIndex; + m_thePrimaryTable = aTable; m_accessTable = anIndex->m_table; m_theIndexLen = 0; m_theNoOfIndexDefined = 0; @@ -102,6 +103,12 @@ int NdbIndexOperation::readTuple(NdbOperation::LockMode lm) }; } +int NdbIndexOperation::insertTuple() +{ + setErrorCode(4200); + return -1; +} + int NdbIndexOperation::readTuple() { // First check that index is unique @@ -341,12 +348,11 @@ int NdbIndexOperation::equal_impl(const NdbColumnImpl* tAttrInfo, theDistrGroupIndicator = 1; }//if /************************************************************************** - * If the operation is an insert request and the attribute is stored then + * If the operation is a write request and the attribute is stored then * we also set the value in the stored part through putting the * information in the INDXATTRINFO signals. *************************************************************************/ - if ((tOpType == InsertRequest) || - (tOpType == WriteRequest)) { + if ((tOpType == WriteRequest)) { if (!tAttrInfo->m_indexOnly){ // invalid data can crash kernel if (cs != NULL && @@ -357,7 +363,13 @@ int NdbIndexOperation::equal_impl(const NdbColumnImpl* tAttrInfo, goto equal_error4; Uint32 ahValue; Uint32 sz = totalSizeInWords; - AttributeHeader::init(&ahValue, tAttrId, sz); + /* + * XXX should be linked in metadata but cannot now because + * things can be defined in arbitrary order + */ + const NdbColumnImpl* primaryCol = m_thePrimaryTable->getColumn(tAttrInfo->m_name.c_str()); + assert(primaryCol != NULL); + AttributeHeader::init(&ahValue, primaryCol->m_attrId, sz); insertATTRINFO( ahValue ); insertATTRINFOloop((Uint32*)aValueToWrite, sizeInWords); if (bitsInLastWord != 0) { @@ -369,7 +381,6 @@ int NdbIndexOperation::equal_impl(const NdbColumnImpl* tAttrInfo, }//if }//if }//if - /************************************************************************** * Store the Key information in the TCINDXREQ and INDXKEYINFO signals. *************************************************************************/ @@ -734,13 +745,10 @@ NdbIndexOperation::receiveTCINDXREF( NdbApiSignal* aSignal) }//if theStatus = Finished; - + theNdbCon->theReturnStatus = NdbConnection::ReturnFailure; Uint32 errorCode = tcIndxRef->errorCode; theError.code = errorCode; theNdbCon->setOperationErrorCodeAbort(errorCode); return theNdbCon->OpCompleteFailure(theNdbCon->m_abortOption); }//NdbIndexOperation::receiveTCINDXREF() - - - diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp index b0b95d0ff43..88d8a000d50 100644 --- a/ndb/src/ndbapi/NdbOperation.cpp +++ b/ndb/src/ndbapi/NdbOperation.cpp @@ -78,7 +78,8 @@ NdbOperation::NdbOperation(Ndb* aNdb) : m_tcReqGSN(GSN_TCKEYREQ), m_keyInfoGSN(GSN_KEYINFO), m_attrInfoGSN(GSN_ATTRINFO), - theBlobList(NULL) + theBlobList(NULL), + m_abortOption(-1) { theReceiver.init(NdbReceiver::NDB_OPERATION, this); theError.code = 0; @@ -167,6 +168,7 @@ NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){ theTotalNrOfKeyWordInSignal = 8; theMagicNumber = 0xABCDEF01; theBlobList = NULL; + m_abortOption = -1; tSignal = theNdb->getSignal(); if (tSignal == NULL) diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp index f1338ae01e4..13664794dcd 100644 --- a/ndb/src/ndbapi/NdbOperationExec.cpp +++ b/ndb/src/ndbapi/NdbOperationExec.cpp @@ -191,7 +191,8 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId) Uint8 tDirtyIndicator = theDirtyIndicator; OperationType tOperationType = theOperationType; Uint32 tTupKeyLen = theTupKeyLen; - Uint8 abortOption = theNdbCon->m_abortOption; + Uint8 abortOption = + m_abortOption != (Int8)-1 ? m_abortOption : theNdbCon->m_abortOption; tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator); tcKeyReq->setOperationType(tReqInfo, tOperationType); @@ -541,17 +542,20 @@ NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal) return -1; }//if - AbortOption ao = (AbortOption)theNdbCon->m_abortOption; + AbortOption ao = (AbortOption) + (m_abortOption != (Int8)-1 ? m_abortOption : theNdbCon->m_abortOption); theReceiver.m_received_result_length = ~0; theStatus = Finished; - theNdbCon->theReturnStatus = NdbConnection::ReturnFailure; + // blobs want this + if (m_abortOption != IgnoreError) + theNdbCon->theReturnStatus = NdbConnection::ReturnFailure; theError.code = aSignal->readData(4); - theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4)); + theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4), m_abortOption); if(theOperationType != ReadRequest || !theSimpleIndicator) // not simple read - return theNdbCon->OpCompleteFailure(ao); + return theNdbCon->OpCompleteFailure(ao, m_abortOption != IgnoreError); /** * If TCKEYCONF has arrived diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index fd63ce96f25..86bac7deb16 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -612,7 +612,7 @@ NdbScanOperation::send_next_scan(Uint32 cnt, bool stopScanFlag){ LinearSectionPtr ptr[3]; ptr[0].p = prep_array; ptr[0].sz = cnt; - ret = tp->sendFragmentedSignal(&tSignal, nodeId, ptr, 1); + ret = tp->sendSignal(&tSignal, nodeId, ptr, 1); } else { tSignal.setLength(4+cnt); ret = tp->sendSignal(&tSignal, nodeId); @@ -803,7 +803,7 @@ NdbScanOperation::doSendScan(int aProcessorId) LinearSectionPtr ptr[3]; ptr[0].p = m_prepared_receivers; ptr[0].sz = theParallelism; - if (tp->sendFragmentedSignal(tSignal, aProcessorId, ptr, 1) == -1) { + if (tp->sendSignal(tSignal, aProcessorId, ptr, 1) == -1) { setErrorCode(4002); return -1; } diff --git a/ndb/src/ndbapi/TransporterFacade.cpp b/ndb/src/ndbapi/TransporterFacade.cpp index bc24110ea14..dfb090c8416 100644 --- a/ndb/src/ndbapi/TransporterFacade.cpp +++ b/ndb/src/ndbapi/TransporterFacade.cpp @@ -34,6 +34,7 @@ #include <NdbConfig.h> #include <ndb_version.h> #include <SignalLoggerManager.hpp> +#include <kernel/ndb_limits.h> //#define REPORT_TRANSPORTER //#define API_TRACE; @@ -475,7 +476,8 @@ TransporterFacade::TransporterFacade() : theTransporterRegistry(0), theStopReceive(0), theSendThread(NULL), - theReceiveThread(NULL) + theReceiveThread(NULL), + m_fragmented_signal_id(0) { theOwnId = 0; @@ -833,9 +835,129 @@ TransporterFacade::sendSignalUnCond(NdbApiSignal * aSignal, NodeId aNode){ return (ss == SEND_OK ? 0 : -1); } +#define CHUNK_SZ NDB_SECTION_SEGMENT_SZ*64 // related to MAX_MESSAGE_SIZE int TransporterFacade::sendFragmentedSignal(NdbApiSignal* aSignal, NodeId aNode, - LinearSectionPtr ptr[3], Uint32 secs){ + LinearSectionPtr ptr[3], Uint32 secs) +{ + if(getIsNodeSendable(aNode) != true) + return -1; + +#ifdef API_TRACE + if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){ + Uint32 tmp = aSignal->theSendersBlockRef; + aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId); + signalLogger.sendSignal(* aSignal, + 1, + aSignal->getDataPtrSend(), + aNode, + ptr, secs); + aSignal->theSendersBlockRef = tmp; + } +#endif + + NdbApiSignal tmp_signal(*(SignalHeader*)aSignal); + LinearSectionPtr tmp_ptr[3]; + Uint32 unique_id= m_fragmented_signal_id++; // next unique id + unsigned i; + for (i= 0; i < secs; i++) + tmp_ptr[i]= ptr[i]; + + unsigned start_i= 0; + unsigned chunk_sz= 0; + unsigned fragment_info= 0; + Uint32 *tmp_data= tmp_signal.getDataPtrSend(); + for (i= 0; i < secs;) { + unsigned save_sz= tmp_ptr[i].sz; + tmp_data[i-start_i]= i; + if (chunk_sz + save_sz > CHUNK_SZ) { + // truncate + unsigned send_sz= CHUNK_SZ - chunk_sz; + if (i != start_i) // first piece of a new section has to be a multiple of NDB_SECTION_SEGMENT_SZ + { + send_sz= + NDB_SECTION_SEGMENT_SZ + *(send_sz+NDB_SECTION_SEGMENT_SZ-1) + /NDB_SECTION_SEGMENT_SZ; + if (send_sz > save_sz) + send_sz= save_sz; + } + tmp_ptr[i].sz= send_sz; + + if (fragment_info < 2) // 1 = first fragment, 2 = middle fragments + fragment_info++; + + // send tmp_signal + tmp_data[i-start_i+1]= unique_id; + tmp_signal.setLength(i-start_i+2); + tmp_signal.m_fragmentInfo= fragment_info; + tmp_signal.m_noOfSections= i-start_i+1; + // do prepare send + { + SendStatus ss = theTransporterRegistry->prepareSend + (&tmp_signal, + 1, /*JBB*/ + tmp_data, + aNode, + &tmp_ptr[start_i]); + assert(ss != SEND_MESSAGE_TOO_BIG); + if (ss != SEND_OK) return -1; + } + // setup variables for next signal + start_i= i; + chunk_sz= 0; + tmp_ptr[i].sz= save_sz-send_sz; + tmp_ptr[i].p+= send_sz; + if (tmp_ptr[i].sz == 0) + i++; + } + else + { + chunk_sz+=save_sz; + i++; + } + } + + unsigned a_sz= aSignal->getLength(); + + if (fragment_info > 0) { + // update the original signal to include section info + Uint32 *a_data= aSignal->getDataPtrSend(); + unsigned tmp_sz= i-start_i; + memcpy(a_data+a_sz, + tmp_data, + tmp_sz*sizeof(Uint32)); + a_data[a_sz+tmp_sz]= unique_id; + aSignal->setLength(a_sz+tmp_sz+1); + + // send last fragment + aSignal->m_fragmentInfo= 3; // 3 = last fragment + aSignal->m_noOfSections= i-start_i; + } else { + aSignal->m_noOfSections= secs; + } + + // send aSignal + int ret; + { + SendStatus ss = theTransporterRegistry->prepareSend + (aSignal, + 1/*JBB*/, + aSignal->getDataPtrSend(), + aNode, + &tmp_ptr[start_i]); + assert(ss != SEND_MESSAGE_TOO_BIG); + ret = (ss == SEND_OK ? 0 : -1); + } + aSignal->m_noOfSections = 0; + aSignal->m_fragmentInfo = 0; + aSignal->setLength(a_sz); + return ret; +} + +int +TransporterFacade::sendSignal(NdbApiSignal* aSignal, NodeId aNode, + LinearSectionPtr ptr[3], Uint32 secs){ aSignal->m_noOfSections = secs; if(getIsNodeSendable(aNode) == true){ #ifdef API_TRACE @@ -865,39 +987,6 @@ TransporterFacade::sendFragmentedSignal(NdbApiSignal* aSignal, NodeId aNode, return -1; } - - -int -TransporterFacade::sendFragmentedSignalUnCond(NdbApiSignal* aSignal, - NodeId aNode, - LinearSectionPtr ptr[3], - Uint32 secs){ - aSignal->m_noOfSections = secs; - -#ifdef API_TRACE - if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){ - Uint32 tmp = aSignal->theSendersBlockRef; - aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId); - signalLogger.sendSignal(* aSignal, - 1, - aSignal->getDataPtrSend(), - aNode, - ptr, secs); - aSignal->theSendersBlockRef = tmp; - } -#endif - SendStatus ss = theTransporterRegistry->prepareSend(aSignal, - 1, // JBB - aSignal->getDataPtrSend(), - aNode, - ptr); - assert(ss != SEND_MESSAGE_TOO_BIG); - aSignal->m_noOfSections = 0; - return (ss == SEND_OK ? 0 : -1); -} - - - /****************************************************************************** * CONNECTION METHODS Etc ******************************************************************************/ diff --git a/ndb/src/ndbapi/TransporterFacade.hpp b/ndb/src/ndbapi/TransporterFacade.hpp index 5f473975585..5680e3a6f03 100644 --- a/ndb/src/ndbapi/TransporterFacade.hpp +++ b/ndb/src/ndbapi/TransporterFacade.hpp @@ -69,14 +69,11 @@ public: // Only sends to nodes which are alive int sendSignal(NdbApiSignal * signal, NodeId nodeId); + int sendSignal(NdbApiSignal*, NodeId, + LinearSectionPtr ptr[3], Uint32 secs); int sendFragmentedSignal(NdbApiSignal*, NodeId, LinearSectionPtr ptr[3], Uint32 secs); - //Dirrrrty - int sendFragmentedSignalUnCond(NdbApiSignal*, NodeId, - LinearSectionPtr ptr[3], Uint32 secs); - - // Is node available for running transactions bool get_node_alive(NodeId nodeId) const; bool get_node_stopping(NodeId nodeId) const; @@ -224,7 +221,8 @@ private: } m_threads; Uint32 m_max_trans_id; - + Uint32 m_fragmented_signal_id; + /** * execute function */ diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index 20661b89517..17a80082023 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -150,7 +150,7 @@ ErrorBundle ErrorCodes[] = { { 623, IS, "623" }, { 624, IS, "624" }, { 625, IS, "Out of memory in Ndb Kernel, index part" }, - { 826, IS, "826" }, + { 826, IS, "Too many tables and attributes (increase MaxNoOfAttributes)" }, { 827, IS, "Out of memory in Ndb Kernel, data part" }, { 832, IS, "832" }, diff --git a/ndb/include/util/getarg.h b/ndb/test/include/getarg.h index 03ed25f6828..03ed25f6828 100644 --- a/ndb/include/util/getarg.h +++ b/ndb/test/include/getarg.h diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp index 41bb82f3e06..efa0811aa39 100644 --- a/ndb/test/ndbapi/testBlobs.cpp +++ b/ndb/test/ndbapi/testBlobs.cpp @@ -42,13 +42,14 @@ struct Opt { bool m_core; bool m_dbg; bool m_dbgall; + const char* m_dbug; bool m_full; unsigned m_loop; unsigned m_parts; unsigned m_rows; unsigned m_seed; const char* m_skip; - const char* m_style; + const char* m_test; // metadata const char* m_tname; const char* m_x1name; // hash index @@ -66,13 +67,14 @@ struct Opt { m_core(false), m_dbg(false), m_dbgall(false), + m_dbug(0), m_full(false), m_loop(1), m_parts(10), m_rows(100), m_seed(0), - m_skip(""), - m_style("012"), + m_skip(0), + m_test(0), // metadata m_tname("TBLOB1"), m_x1name("TBLOB1X1"), @@ -100,46 +102,46 @@ printusage() << " -core dump core on error" << endl << " -dbg print debug" << endl << " -dbgall print also NDB API debug (if compiled in)" << endl + << " -dbug opt dbug options" << endl << " -full read/write only full blob values" << endl - << " -inline read/write only blobs which fit inline" << endl << " -loop N loop N times 0=forever [" << d.m_loop << "]" << endl << " -parts N max parts in blob value [" << d.m_parts << "]" << endl << " -rows N number of rows [" << d.m_rows << "]" << endl << " -seed N random seed 0=loop number [" << d.m_seed << "]" << endl - << " -skip xxx skip these tests (see list) [" << d.m_skip << endl - << " -style xxx access styles to test (see list) [" << d.m_style << "]" << endl + << " -skip xxx skip given tests (see list) [no tests]" << endl + << " -test xxx only given tests (see list) [all tests]" << endl << "metadata" << endl << " -pk2len N length of PK2 [" << d.m_pk2len << "/" << g_max_pk2len <<"]" << endl << " -oneblob only 1 blob attribute [default 2]" << endl - << "testcases for -skip" << endl + << "testcases for test/skip" << endl << " k primary key ops" << endl << " i hash index ops" << endl << " s table scans" << endl << " r ordered index scans" << endl - << " u update blob value" << endl - << "access styles for -style" << endl + << "additional flags for test/skip" << endl + << " u update existing blob value" << endl + << " n normal insert and update" << endl + << " w insert and update using writeTuple" << endl << " 0 getValue / setValue" << endl << " 1 setActiveHook" << endl << " 2 readData / writeData" << endl << "bug tests (no blob test)" << endl << " -bug 4088 ndb api hang with mixed ops on index table" << endl - << " -bug 2222 delete + write gives 626" << endl - << " -bug 3333 acc crash on delete and long key" << endl + << " -bug nnnn delete + write gives 626" << endl + << " -bug nnnn acc crash on delete and long key" << endl ; } static Opt g_opt; static bool -skipcase(int x) +testcase(char x) { - return strchr(g_opt.m_skip, x) != 0; -} - -static bool -skipstyle(int x) -{ - return strchr(g_opt.m_style, '0' + x) == 0; + if (x < 10) + x += '0'; + return + (g_opt.m_test == 0 || strchr(g_opt.m_test, x) != 0) && + (g_opt.m_skip == 0 || strchr(g_opt.m_skip, x) == 0); } static Ndb* g_ndb = 0; @@ -435,7 +437,9 @@ getBlobLength(NdbBlob* h, unsigned& len) CHK(h->getLength(len2) == 0); len = (unsigned)len2; assert(len == len2); - DBG("getBlobLength " << h->getColumn()->getName() << " len=" << len); + bool isNull; + CHK(h->getNull(isNull) == 0); + DBG("getBlobLength " << h->getColumn()->getName() << " len=" << len << " null=" << isNull); return 0; } @@ -912,6 +916,41 @@ updatePk(int style) } static int +writePk(int style) +{ + DBG("--- writePk " << stylename[style] << " ---"); + for (unsigned k = 0; k < g_opt.m_rows; k++) { + Tup& tup = g_tups[k]; + DBG("writePk pk1=" << hex << tup.m_pk1); + CHK((g_con = g_ndb->startTransaction()) != 0); + CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0); + CHK(g_opr->writeTuple() == 0); + CHK(g_opr->equal("PK1", tup.m_pk1) == 0); + if (g_opt.m_pk2len != 0) + CHK(g_opr->equal("PK2", tup.m_pk2) == 0); + CHK(getBlobHandles(g_opr) == 0); + if (style == 0) { + CHK(setBlobValue(tup) == 0); + } else if (style == 1) { + // non-nullable must be set + CHK(g_bh1->setValue("", 0) == 0); + CHK(setBlobWriteHook(tup) == 0); + } else { + // non-nullable must be set + CHK(g_bh1->setValue("", 0) == 0); + CHK(g_con->execute(NoCommit) == 0); + CHK(writeBlobData(tup) == 0); + } + CHK(g_con->execute(Commit) == 0); + g_ndb->closeTransaction(g_con); + g_opr = 0; + g_con = 0; + tup.m_exists = true; + } + return 0; +} + +static int deletePk() { DBG("--- deletePk ---"); @@ -996,6 +1035,39 @@ updateIdx(int style) } static int +writeIdx(int style) +{ + DBG("--- writeIdx " << stylename[style] << " ---"); + for (unsigned k = 0; k < g_opt.m_rows; k++) { + Tup& tup = g_tups[k]; + DBG("writeIdx pk1=" << hex << tup.m_pk1); + CHK((g_con = g_ndb->startTransaction()) != 0); + CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0); + CHK(g_opx->writeTuple() == 0); + CHK(g_opx->equal("PK2", tup.m_pk2) == 0); + CHK(getBlobHandles(g_opx) == 0); + if (style == 0) { + CHK(setBlobValue(tup) == 0); + } else if (style == 1) { + // non-nullable must be set + CHK(g_bh1->setValue("", 0) == 0); + CHK(setBlobWriteHook(tup) == 0); + } else { + // non-nullable must be set + CHK(g_bh1->setValue("", 0) == 0); + CHK(g_con->execute(NoCommit) == 0); + CHK(writeBlobData(tup) == 0); + } + CHK(g_con->execute(Commit) == 0); + g_ndb->closeTransaction(g_con); + g_opx = 0; + g_con = 0; + tup.m_exists = true; + } + return 0; +} + +static int deleteIdx() { DBG("--- deleteIdx ---"); @@ -1167,10 +1239,16 @@ deleteScan(bool idx) // main +// from here on print always +#undef DBG +#define DBG(x) \ + do { \ + ndbout << "line " << __LINE__ << " " << x << endl; \ + } while (0) + static int testmain() { - int style; g_ndb = new Ndb("TEST_DB"); CHK(g_ndb->init() == 0); CHK(g_ndb->waitUntilReady() == 0); @@ -1194,55 +1272,88 @@ testmain() if (g_opt.m_seed != 0) srandom(g_opt.m_seed); for (g_loop = 0; g_opt.m_loop == 0 || g_loop < g_opt.m_loop; g_loop++) { + int style; DBG("=== loop " << g_loop << " ==="); if (g_opt.m_seed == 0) srandom(g_loop); // pk for (style = 0; style <= 2; style++) { - if (skipcase('k') || skipstyle(style)) + if (! testcase('k') || ! testcase(style)) continue; DBG("--- pk ops " << stylename[style] << " ---"); - calcTups(false); - CHK(insertPk(style) == 0); - CHK(verifyBlob() == 0); - CHK(readPk(style) == 0); - if (! skipcase('u')) { - calcTups(style); - CHK(updatePk(style) == 0); + if (testcase('n')) { + calcTups(false); + CHK(insertPk(style) == 0); + CHK(verifyBlob() == 0); + CHK(readPk(style) == 0); + if (testcase('u')) { + calcTups(style); + CHK(updatePk(style) == 0); + CHK(verifyBlob() == 0); + CHK(readPk(style) == 0); + } + CHK(deletePk() == 0); + CHK(verifyBlob() == 0); + } + if (testcase('w')) { + calcTups(false); + CHK(writePk(style) == 0); + CHK(verifyBlob() == 0); + CHK(readPk(style) == 0); + if (testcase('u')) { + calcTups(style); + CHK(writePk(style) == 0); + CHK(verifyBlob() == 0); + CHK(readPk(style) == 0); + } + CHK(deletePk() == 0); CHK(verifyBlob() == 0); } - CHK(readPk(style) == 0); - CHK(deletePk() == 0); - CHK(verifyBlob() == 0); } // hash index for (style = 0; style <= 2; style++) { - if (skipcase('i') || skipstyle(style)) + if (! testcase('i') || ! testcase(style)) continue; DBG("--- idx ops " << stylename[style] << " ---"); - calcTups(false); - CHK(insertPk(style) == 0); - CHK(verifyBlob() == 0); - CHK(readIdx(style) == 0); - calcTups(style); - if (! skipcase('u')) { - CHK(updateIdx(style) == 0); + if (testcase('n')) { + calcTups(false); + CHK(insertPk(style) == 0); + CHK(verifyBlob() == 0); + CHK(readIdx(style) == 0); + if (testcase('u')) { + calcTups(style); + CHK(updateIdx(style) == 0); + CHK(verifyBlob() == 0); + CHK(readIdx(style) == 0); + } + CHK(deleteIdx() == 0); + CHK(verifyBlob() == 0); + } + if (testcase('w')) { + calcTups(false); + CHK(writePk(style) == 0); CHK(verifyBlob() == 0); CHK(readIdx(style) == 0); + if (testcase('u')) { + calcTups(style); + CHK(writeIdx(style) == 0); + CHK(verifyBlob() == 0); + CHK(readIdx(style) == 0); + } + CHK(deleteIdx() == 0); + CHK(verifyBlob() == 0); } - CHK(deleteIdx() == 0); - CHK(verifyBlob() == 0); } // scan table for (style = 0; style <= 2; style++) { - if (skipcase('s') || skipstyle(style)) + if (! testcase('s') || ! testcase(style)) continue; DBG("--- table scan " << stylename[style] << " ---"); calcTups(false); CHK(insertPk(style) == 0); CHK(verifyBlob() == 0); CHK(readScan(style, false) == 0); - if (! skipcase('u')) { + if (testcase('u')) { CHK(updateScan(style, false) == 0); CHK(verifyBlob() == 0); } @@ -1251,14 +1362,14 @@ testmain() } // scan index for (style = 0; style <= 2; style++) { - if (skipcase('r') || skipstyle(style)) + if (! testcase('r') || ! testcase(style)) continue; DBG("--- index scan " << stylename[style] << " ---"); calcTups(false); CHK(insertPk(style) == 0); CHK(verifyBlob() == 0); CHK(readScan(style, true) == 0); - if (! skipcase('u')) { + if (testcase('u')) { CHK(updateScan(style, true) == 0); CHK(verifyBlob() == 0); } @@ -1331,9 +1442,7 @@ static struct { int m_bug; int (*m_test)(); } g_bugtest[] = { - { 4088, bugtest_4088 }, - { 2222, bugtest_2222 }, - { 3333, bugtest_3333 } + { 4088, bugtest_4088 } }; NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535) @@ -1361,6 +1470,12 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535) putenv(strdup("NDB_BLOB_DEBUG=1")); continue; } + if (strcmp(arg, "-dbug") == 0) { + if (++argv, --argc > 0) { + g_opt.m_dbug = strdup(argv[0]); + continue; + } + } if (strcmp(arg, "-full") == 0) { g_opt.m_full = true; continue; @@ -1395,9 +1510,9 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535) continue; } } - if (strcmp(arg, "-style") == 0) { + if (strcmp(arg, "-test") == 0) { if (++argv, --argc > 0) { - g_opt.m_style = strdup(argv[0]); + g_opt.m_test = strdup(argv[0]); continue; } } @@ -1431,9 +1546,14 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535) printusage(); return NDBT_ProgramExit(NDBT_WRONGARGS); } + if (g_opt.m_dbug != 0) { + DBUG_PUSH(g_opt.m_dbug); + } if (g_opt.m_pk2len == 0) { char b[100]; - strcpy(b, g_opt.m_skip); + b[0] = 0; + if (g_opt.m_skip != 0) + strcpy(b, g_opt.m_skip); strcat(b, "i"); strcat(b, "r"); g_opt.m_skip = strdup(b); diff --git a/ndb/test/run-test/Makefile.am b/ndb/test/run-test/Makefile.am index 3bf2edde47a..1eac96e7ac7 100644 --- a/ndb/test/run-test/Makefile.am +++ b/ndb/test/run-test/Makefile.am @@ -11,8 +11,9 @@ test_SCRIPTS=atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \ atrt-clear-result.sh make-config.sh make-index.sh make-html-reports.sh atrt_SOURCES = main.cpp -INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmclient +INCLUDES_LOC = -I$(top_srcdir)/ndb/test/include -I$(top_srcdir)/ndb/src/mgmclient LDADD_LOC = $(top_builddir)/ndb/src/mgmclient/CpcClient.o \ + $(top_builddir)/ndb/test/src/libNDBT.a \ $(top_builddir)/ndb/src/libndbclient.la \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ diff --git a/ndb/test/src/Makefile.am b/ndb/test/src/Makefile.am index a513086dc33..a8f34a0ea22 100644 --- a/ndb/test/src/Makefile.am +++ b/ndb/test/src/Makefile.am @@ -9,7 +9,7 @@ libNDBT_a_SOURCES = \ HugoAsynchTransactions.cpp UtilTransactions.cpp \ NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \ NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp \ - NdbSchemaCon.cpp NdbSchemaOp.cpp + NdbSchemaCon.cpp NdbSchemaOp.cpp getarg.c INCLUDES_LOC = -I$(top_srcdir)/ndb/src/common/mgmcommon -I$(top_srcdir)/ndb/include/mgmcommon -I$(top_srcdir)/ndb/include/kernel -I$(top_srcdir)/ndb/src/mgmapi diff --git a/ndb/src/common/util/getarg.c b/ndb/test/src/getarg.c index 99b2840a5a6..9f03af69824 100644 --- a/ndb/src/common/util/getarg.c +++ b/ndb/test/src/getarg.c @@ -36,15 +36,33 @@ #include "getarg.h" -#define ISFLAG(X) ((X).type == arg_flag || (X).type == arg_negative_flag) - #ifndef HAVE_STRLCPY -extern size_t strlcpy (char *dst, const char *src, size_t dst_sz); -#endif /* !HAVE_STRLCPY */ - +static size_t +strlcpy (char *dst, const char *src, size_t dst_sz) +{ + size_t n; + char *p; + for (p = dst, n = 0; + n + 1 < dst_sz && *src != '\0'; + ++p, ++src, ++n) + *p = *src; + *p = '\0'; + if (*src == '\0') + return n; + else + return n + strlen (src); +} +#endif #ifndef HAVE_STRLCAT -extern size_t strlcat (char *dst, const char *src, size_t dst_sz); -#endif /* !HAVE_STRLCAT */ +static size_t +strlcat (char *dst, const char *src, size_t dst_sz) +{ + size_t len = strlen(dst); + return len + strlcpy (dst + len, src, dst_sz - len); +} +#endif + +#define ISFLAG(X) ((X).type == arg_flag || (X).type == arg_negative_flag) #ifndef max #define max(a, b) (a) > (b) ? (a) : (b) diff --git a/ndb/tools/delete_all.cpp b/ndb/tools/delete_all.cpp index aa5798376ae..a4fd73a5128 100644 --- a/ndb/tools/delete_all.cpp +++ b/ndb/tools/delete_all.cpp @@ -15,41 +15,65 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <ndb_global.h> +#include <ndb_opts.h> #include <NdbOut.hpp> #include <NdbApi.hpp> #include <NdbSleep.h> #include <NDBT.hpp> -#include <getarg.h> - static int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism=240); -int main(int argc, const char** argv){ - ndb_init(); - - const char* _tabname = NULL; - const char* _dbname = "TEST_DB"; - int _help = 0; - - struct getargs args[] = { - { "usage", '?', arg_flag, &_help, "Print help", "" }, - { "database", 'd', arg_string, &_dbname, "dbname", - "Name of database table is in"} - }; - int num_args = sizeof(args) / sizeof(args[0]); - int optind = 0; +static const char* opt_connect_str= 0; +static const char* _dbname = "TEST_DB"; +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS("ndb_desc"), + { "database", 'd', "Name of database table is in", + (gptr*) &_dbname, (gptr*) &_dbname, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ char desc[] = "tabname\n"\ "This program will delete all records in the specified table using scan delete.\n"; - - if(getarg(args, num_args, argc, argv, &optind) || - argv[optind] == NULL || _help) { - arg_printusage(args, num_args, argv[0], desc); - return NDBT_ProgramExit(NDBT_WRONGARGS); + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_delete_all.trace"); + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); } - _tabname = argv[optind]; + return 0; +} +int main(int argc, char** argv){ + NDB_INIT(argv[0]); + const char *load_default_groups[]= { "ndb_tools",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + return NDBT_ProgramExit(NDBT_WRONGARGS); + + Ndb::setConnectString(opt_connect_str); // Connect to Ndb Ndb MyNdb(_dbname); @@ -64,13 +88,12 @@ int main(int argc, const char** argv){ // Check if table exists in db int res = NDBT_OK; - for(int i = optind; i<argc; i++){ + for(int i = 0; i<argc; i++){ const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, argv[i]); if(pTab == NULL){ - ndbout << " Table " << _tabname << " does not exist!" << endl; + ndbout << " Table " << argv[i] << " does not exist!" << endl; return NDBT_ProgramExit(NDBT_WRONGARGS); } - ndbout << "Deleting all from " << argv[i] << "..."; if(clear_table(&MyNdb, pTab) == NDBT_FAILED){ res = NDBT_FAILED; diff --git a/ndb/tools/desc.cpp b/ndb/tools/desc.cpp index 9eed1485a6d..8f7a2031ef0 100644 --- a/ndb/tools/desc.cpp +++ b/ndb/tools/desc.cpp @@ -14,40 +14,66 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <getarg.h> +#include <ndb_global.h> +#include <ndb_opts.h> #include <NDBT.hpp> #include <NdbApi.hpp> - - - -int main(int argc, const char** argv){ - ndb_init(); - const char* _tabname = NULL; - const char* _dbname = "TEST_DB"; - int _unqualified = 0; - int _help = 0; - - struct getargs args[] = { - { "unqualified", 'u', arg_flag, &_unqualified, "unqualified", - "Use unqualified table names"}, - { "database", 'd', arg_string, &_dbname, "dbname", - "Name of database table is in"}, - { "usage", '?', arg_flag, &_help, "Print help", "" } - }; - int num_args = sizeof(args) / sizeof(args[0]); - int optind = 0; +static const char* opt_connect_str= 0; +static const char* _dbname = "TEST_DB"; +static int _unqualified = 0; +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS("ndb_desc"), + { "database", 'd', "Name of database table is in", + (gptr*) &_dbname, (gptr*) &_dbname, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "unqualified", 'u', "Use unqualified table names", + (gptr*) &_unqualified, (gptr*) &_unqualified, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ char desc[] = "tabname\n"\ "This program list all properties of table(s) in NDB Cluster.\n"\ - " ex: desc T1 T2 T4\n"; - - if(getarg(args, num_args, argc, argv, &optind) || - argv[optind] == NULL ||_help) { - arg_printusage(args, num_args, argv[0], desc); - return NDBT_ProgramExit(NDBT_WRONGARGS); + " ex: desc T1 T2 T4\n"; + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_desc.trace"); + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); } - _tabname = argv[optind]; + return 0; +} + +int main(int argc, char** argv){ + NDB_INIT(argv[0]); + const char *load_default_groups[]= { "ndb_tools",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + return NDBT_ProgramExit(NDBT_WRONGARGS); + + Ndb::setConnectString(opt_connect_str); Ndb* pMyNdb; pMyNdb = new Ndb(_dbname); @@ -60,7 +86,7 @@ int main(int argc, const char** argv){ ndbout << endl; NdbDictionary::Dictionary * dict = pMyNdb->getDictionary(); - for (int i = optind; i < argc; i++) { + for (int i = 0; i < argc; i++) { NDBT_Table* pTab = (NDBT_Table*)dict->getTable(argv[i]); if (pTab != 0){ ndbout << (* pTab) << endl; diff --git a/ndb/tools/drop_index.cpp b/ndb/tools/drop_index.cpp index 70c29461c23..1d4b454682f 100644 --- a/ndb/tools/drop_index.cpp +++ b/ndb/tools/drop_index.cpp @@ -15,38 +15,66 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <ndb_global.h> +#include <ndb_opts.h> #include <NdbOut.hpp> #include <NdbApi.hpp> #include <NDBT.hpp> -#include <getarg.h> - -int main(int argc, const char** argv){ - ndb_init(); - - const char* _tabname = NULL; - const char* _dbname = "TEST_DB"; - int _help = 0; - - struct getargs args[] = { - { "database", 'd', arg_string, &_dbname, "dbname", - "Name of database table is in"}, - { "usage", '?', arg_flag, &_help, "Print help", "" } - }; - int num_args = sizeof(args) / sizeof(args[0]); - int optind = 0; +static const char* opt_connect_str= 0; +static const char* _dbname = "TEST_DB"; +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS("ndb_desc"), + { "database", 'd', "Name of database table is in", + (gptr*) &_dbname, (gptr*) &_dbname, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ char desc[] = "<indexname>+\n"\ "This program will drop index(es) in Ndb\n"; + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_drop_index.trace"); + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); + } + return 0; +} - if(getarg(args, num_args, argc, argv, &optind) || - argv[optind] == NULL || _help){ - arg_printusage(args, num_args, argv[0], desc); +int main(int argc, char** argv){ + NDB_INIT(argv[0]); + const char *load_default_groups[]= { "ndb_tools",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + return NDBT_ProgramExit(NDBT_WRONGARGS); + if (argc < 1) { + usage(); return NDBT_ProgramExit(NDBT_WRONGARGS); } - _tabname = argv[optind]; + Ndb::setConnectString(opt_connect_str); // Connect to Ndb Ndb MyNdb(_dbname); if(MyNdb.init() != 0){ @@ -58,7 +86,7 @@ int main(int argc, const char** argv){ ndbout << "Waiting for ndb to become ready..." << endl; int res = 0; - for(int i = optind; i<argc; i++){ + for(int i = 0; i<argc; i++){ ndbout << "Dropping index " << argv[i] << "..."; int tmp; if((tmp = MyNdb.getDictionary()->dropIndex(argv[i], 0)) != 0){ diff --git a/ndb/tools/drop_tab.cpp b/ndb/tools/drop_tab.cpp index 15c229cb0fb..3362c7de47b 100644 --- a/ndb/tools/drop_tab.cpp +++ b/ndb/tools/drop_tab.cpp @@ -15,43 +15,66 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <ndb_global.h> +#include <ndb_opts.h> #include <NdbOut.hpp> #include <NdbApi.hpp> #include <NDBT.hpp> -#include <getarg.h> - -int main(int argc, const char** argv){ - ndb_init(); - - const char* _tabname = NULL; - const char* _dbname = "TEST_DB"; - const char* _connectstr = NULL; - int _help = 0; - - struct getargs args[] = { - { "database", 'd', arg_string, &_dbname, "dbname", - "Name of database table is in"}, - { "connstr", 'c', arg_string, &_connectstr, "connect string", - "How to connect to NDB"}, - { "usage", '?', arg_flag, &_help, "Print help", "" } - }; - int num_args = sizeof(args) / sizeof(args[0]); - int optind = 0; +static const char* opt_connect_str= 0; +static const char* _dbname = "TEST_DB"; +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS("ndb_desc"), + { "database", 'd', "Name of database table is in", + (gptr*) &_dbname, (gptr*) &_dbname, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ char desc[] = "tabname\n"\ "This program will drop one table in Ndb\n"; + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_drop_table.trace"); + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); + } + return 0; +} - if(getarg(args, num_args, argc, argv, &optind) || - argv[optind] == NULL || _help){ - arg_printusage(args, num_args, argv[0], desc); +int main(int argc, char** argv){ + NDB_INIT(argv[0]); + const char *load_default_groups[]= { "ndb_tools",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + return NDBT_ProgramExit(NDBT_WRONGARGS); + if (argc < 1) { + usage(); return NDBT_ProgramExit(NDBT_WRONGARGS); } - _tabname = argv[optind]; - - if (_connectstr) - Ndb::setConnectString(_connectstr); + + Ndb::setConnectString(opt_connect_str); Ndb MyNdb(_dbname); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); @@ -62,7 +85,7 @@ int main(int argc, const char** argv){ ndbout << "Waiting for ndb to become ready..." << endl; int res = 0; - for(int i = optind; i<argc; i++){ + for(int i = 0; i<argc; i++){ ndbout << "Dropping table " << argv[i] << "..."; int tmp; if((tmp = MyNdb.getDictionary()->dropTable(argv[i])) != 0){ diff --git a/ndb/tools/listTables.cpp b/ndb/tools/listTables.cpp index 4fc5bcd7f21..05e864a35c4 100644 --- a/ndb/tools/listTables.cpp +++ b/ndb/tools/listTables.cpp @@ -22,7 +22,7 @@ */ #include <ndb_global.h> -#include <getarg.h> +#include <ndb_opts.h> #include <NdbApi.hpp> #include <NDBT.hpp> @@ -161,39 +161,33 @@ list(const char * tabname, } } -#ifndef DBUG_OFF -const char *debug_option= 0; -#endif - -int main(int argc, const char** argv){ - ndb_init(); - int _loops = 1; - const char* _tabname = NULL; - const char* _dbname = "TEST_DB"; - int _type = 0; - int _help = 0; - const char* _connect_str = NULL; - - struct getargs args[] = { - { "loops", 'l', arg_integer, &_loops, "loops", - "Number of times to run(default = 1)" }, - { "unqualified", 'u', arg_flag, &_unqualified, "unqualified", - "Use unqualified table names"}, - { "database", 'd', arg_string, &_dbname, "dbname", - "Name of database table is in"}, - { "type", 't', arg_integer, &_type, "type", - "Type of objects to show, see NdbDictionary.hpp for numbers(default = 0)" }, - { "connect-string", 'c', arg_string, &_connect_str, - "Set connect string for connecting to ndb_mgmd. <constr>=\"host=<hostname:port>[;nodeid=<id>]\". Overides specifying entries in NDB_CONNECTSTRING and config file", - "<constr>" }, -#ifndef DBUG_OFF - { "debug", 0, arg_string, &debug_option, - "Specify debug options e.g. d:t:i:o,out.trace", "options" }, -#endif - { "usage", '?', arg_flag, &_help, "Print help", "" } - }; - int num_args = sizeof(args) / sizeof(args[0]); - int optind = 0; +static const char* opt_connect_str= 0; +static const char* _dbname = "TEST_DB"; +static int _loops; +static int _type; +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS("ndb_desc"), + { "database", 'd', "Name of database table is in", + (gptr*) &_dbname, (gptr*) &_dbname, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "loops", 'l', "loops", + (gptr*) &_loops, (gptr*) &_loops, 0, + GET_INT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0 }, + { "type", 't', "type", + (gptr*) &_type, (gptr*) &_type, 0, + GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "unqualified", 'u', "Use unqualified table names", + (gptr*) &_unqualified, (gptr*) &_unqualified, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ char desc[] = "tabname\n"\ "This program list all system objects in NDB Cluster.\n"\ @@ -201,19 +195,39 @@ int main(int argc, const char** argv){ " ex: list_tables -t 2 would show all UserTables\n"\ "To show all indexes for a table write table name as final argument\n"\ " ex: list_tables T1\n"; - - if(getarg(args, num_args, argc, argv, &optind) || _help) { - arg_printusage(args, num_args, argv[0], desc); - return NDBT_ProgramExit(NDBT_WRONGARGS); + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_show_tables.trace"); + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); } - _tabname = argv[optind]; - -#ifndef DBUG_OFF - if (debug_option) - DBUG_PUSH(debug_option); -#endif + return 0; +} + +int main(int argc, char** argv){ + NDB_INIT(argv[0]); + const char* _tabname; + const char *load_default_groups[]= { "ndb_tools",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + return NDBT_ProgramExit(NDBT_WRONGARGS); + _tabname = argv[0]; - ndb_cluster_connection = new Ndb_cluster_connection(_connect_str); + ndb_cluster_connection = new Ndb_cluster_connection(opt_connect_str); ndb = new Ndb(ndb_cluster_connection, _dbname); if (ndb->init() != 0) fatal("init"); diff --git a/ndb/tools/select_all.cpp b/ndb/tools/select_all.cpp index 9f8108d9f32..758c1e48c88 100644 --- a/ndb/tools/select_all.cpp +++ b/ndb/tools/select_all.cpp @@ -16,6 +16,7 @@ #include <ndb_global.h> +#include <ndb_opts.h> #include <NdbOut.hpp> @@ -23,13 +24,8 @@ #include <NdbMain.h> #include <NDBT.hpp> #include <NdbSleep.h> -#include <getarg.h> #include <NdbScanFilter.hpp> -#ifndef DBUG_OFF -const char *debug_option= 0; -#endif - int scanReadRecords(Ndb*, const NdbDictionary::Table*, const NdbDictionary::Index*, @@ -40,39 +36,44 @@ int scanReadRecords(Ndb*, char delim, bool orderby); -int main(int argc, const char** argv){ - ndb_init(); - int _parallelism = 240; - const char* _delimiter = "\t"; - int _header = true; - int _useHexFormat = false; - const char* _tabname = NULL; - const char* _dbname = "TEST_DB"; - int _help = 0; - int _lock = 0; - int _order = 0; - - struct getargs args[] = { - { "database", 'd', arg_string, &_dbname, "dbname", - "Name of database table is in"}, - { "parallelism", 'p', arg_integer, &_parallelism, "parallelism", - "parallelism" }, - { "header", 'h', arg_flag, &_header, "Print header", "header" }, - { "useHexFormat", 'x', arg_flag, &_useHexFormat, - "Output numbers in hexadecimal format", "useHexFormat" }, - { "delimiter", 'd', arg_string, &_delimiter, "Column delimiter", - "delimiter" }, -#ifndef DBUG_OFF - { "debug", 0, arg_string, &debug_option, - "Specify debug options e.g. d:t:i:o,out.trace", "options" }, -#endif - { "usage", '?', arg_flag, &_help, "Print help", "" }, - { "lock", 'l', arg_integer, &_lock, - "Read(0), Read-hold(1), Exclusive(2)", "lock"}, - { "order", 'o', arg_flag, &_order, "Sort resultset according to index", ""} - }; - int num_args = sizeof(args) / sizeof(args[0]); - int optind = 0; +static const char* opt_connect_str= 0; +static const char* _dbname = "TEST_DB"; +static const char* _delimiter = "\t"; +static int _unqualified, _header, _parallelism, _useHexFormat, _lock, + _order; + +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS("ndb_desc"), + { "database", 'd', "Name of database table is in", + (gptr*) &_dbname, (gptr*) &_dbname, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "parallelism", 'p', "parallelism", + (gptr*) &_parallelism, (gptr*) &_parallelism, 0, + GET_INT, REQUIRED_ARG, 240, 0, 0, 0, 0, 0 }, + { "lock", 'l', "Read(0), Read-hold(1), Exclusive(2)", + (gptr*) &_lock, (gptr*) &_lock, 0, + GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "order", 'o', "Sort resultset according to index", + (gptr*) &_order, (gptr*) &_order, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "header", 'h', "Print header", + (gptr*) &_header, (gptr*) &_header, 0, + GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, + { "useHexFormat", 'x', "Output numbers in hexadecimal format", + (gptr*) &_useHexFormat, (gptr*) &_useHexFormat, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "delimiter", 'D', "Column delimiter", + (gptr*) &_delimiter, (gptr*) &_delimiter, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ char desc[] = "tabname\n"\ "This program reads all records from one table in NDB Cluster\n"\ @@ -80,19 +81,42 @@ int main(int argc, const char** argv){ "(It only print error messages if it encounters a permanent error.)\n"\ "It can also be used to dump the content of a table to file \n"\ " ex: select_all --no-header --delimiter=';' T4 > T4.data\n"; - - if(getarg(args, num_args, argc, argv, &optind) || - argv[optind] == NULL || _help) { - arg_printusage(args, num_args, argv[0], desc); - return NDBT_ProgramExit(NDBT_WRONGARGS); + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_select_all.trace"); + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); } - _tabname = argv[optind]; + return 0; +} -#ifndef DBUG_OFF - if (debug_option) - DBUG_PUSH(debug_option); -#endif +int main(int argc, char** argv){ + NDB_INIT(argv[0]); + const char *load_default_groups[]= { "ndb_tools",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + const char* _tabname; + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + return NDBT_ProgramExit(NDBT_WRONGARGS); + if ((_tabname = argv[0]) == 0) { + usage(); + return NDBT_ProgramExit(NDBT_WRONGARGS); + } + Ndb::setConnectString(opt_connect_str); // Connect to Ndb Ndb MyNdb(_dbname); @@ -108,8 +132,8 @@ int main(int argc, const char** argv){ // Check if table exists in db const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(&MyNdb, _tabname); const NdbDictionary::Index * pIdx = 0; - if(optind+1 < argc){ - pIdx = MyNdb.getDictionary()->getIndex(argv[optind+1], _tabname); + if(argc > 1){ + pIdx = MyNdb.getDictionary()->getIndex(argv[0], _tabname); } if(pTab == NULL){ diff --git a/ndb/tools/select_count.cpp b/ndb/tools/select_count.cpp index 6650421e637..6ee49ddbff0 100644 --- a/ndb/tools/select_count.cpp +++ b/ndb/tools/select_count.cpp @@ -16,6 +16,7 @@ #include <ndb_global.h> +#include <ndb_opts.h> #include <NdbOut.hpp> @@ -23,7 +24,6 @@ #include <NdbMain.h> #include <NDBT.hpp> #include <NdbSleep.h> -#include <getarg.h> #include <UtilTransactions.hpp> static int @@ -32,34 +32,68 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab, int* count_rows, UtilTransactions::ScanLock lock); -int main(int argc, const char** argv){ - ndb_init(); - const char* _dbname = "TEST_DB"; - int _parallelism = 240; - int _help = 0; - int _lock = 0; - - struct getargs args[] = { - { "database", 'd', arg_string, &_dbname, "dbname", - "Name of database table is in"}, - { "parallelism", 's', arg_integer, &_parallelism, "parallelism", "parallelism" }, - { "usage", '?', arg_flag, &_help, "Print help", "" }, - { "lock", 'l', arg_integer, &_lock, - "Read(0), Read-hold(1), Exclusive(2)", "lock"} - - }; - int num_args = sizeof(args) / sizeof(args[0]); - int optind = 0; +static const char* opt_connect_str= 0; +static const char* _dbname = "TEST_DB"; +static int _parallelism = 240; +static int _lock = 0; +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS("ndb_desc"), + { "database", 'd', "Name of database table is in", + (gptr*) &_dbname, (gptr*) &_dbname, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "parallelism", 'p', "parallelism", + (gptr*) &_parallelism, (gptr*) &_parallelism, 0, + GET_INT, REQUIRED_ARG, 240, 0, 0, 0, 0, 0 }, + { "lock", 'l', "Read(0), Read-hold(1), Exclusive(2)", + (gptr*) &_lock, (gptr*) &_lock, 0, + GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ char desc[] = "tabname1 ... tabnameN\n"\ "This program will count the number of records in tables\n"; - - if(getarg(args, num_args, argc, argv, &optind) || - argv[optind] == NULL || _help) { - arg_printusage(args, num_args, argv[0], desc); + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_select_count.trace"); + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); + } + return 0; +} + +int main(int argc, char** argv){ + NDB_INIT(argv[0]); + const char *load_default_groups[]= { "ndb_tools",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + return NDBT_ProgramExit(NDBT_WRONGARGS); + if (argc < 1) { + usage(); return NDBT_ProgramExit(NDBT_WRONGARGS); } + Ndb::setConnectString(opt_connect_str); // Connect to Ndb Ndb MyNdb(_dbname); @@ -72,7 +106,7 @@ int main(int argc, const char** argv){ while(MyNdb.waitUntilReady() != 0) ndbout << "Waiting for ndb to become ready..." << endl; - for(int i = optind; i<argc; i++){ + for(int i = 0; i<argc; i++){ // Check if table exists in db const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, argv[i]); if(pTab == NULL){ diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp index c01a3f9192e..c9e76bb8ed3 100644 --- a/ndb/tools/waiter.cpp +++ b/ndb/tools/waiter.cpp @@ -16,11 +16,12 @@ #include <ndb_global.h> +#include <ndb_opts.h> + #include <mgmapi.h> #include <NdbMain.h> #include <NdbOut.hpp> #include <NdbSleep.h> -#include <getarg.h> #include <kernel/ndb_limits.h> #include "../include/mgmcommon/LocalConfig.hpp" @@ -29,34 +30,59 @@ int waitClusterStatus(const char* _addr, ndb_mgm_node_status _status, unsigned int _timeout); -int main(int argc, const char** argv){ - ndb_init(); +static const char* opt_connect_str= 0; +static int _no_contact = 0; +static int _timeout = 120; +static struct my_option my_long_options[] = +{ + NDB_STD_OPTS("ndb_desc"), + { "no-contact", 'n', "Wait for cluster no contact", + (gptr*) &_no_contact, (gptr*) &_no_contact, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "timeout", 't', "Timeout to wait", + (gptr*) &_timeout, (gptr*) &_timeout, 0, + GET_INT, REQUIRED_ARG, 120, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; +static void print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} +static void usage() +{ + print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +get_one_option(int optid, const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case '#': + DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_drop_table.trace"); + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); + } + return 0; +} +int main(int argc, char** argv){ + NDB_INIT(argv[0]); + const char *load_default_groups[]= { "ndb_tools",0 }; + load_defaults("my",load_default_groups,&argc,&argv); const char* _hostName = NULL; - int _no_contact = 0; - int _help = 0; - int _timeout = 120; - - struct getargs args[] = { - { "timeout", 0, arg_integer, &_timeout, "Timeout to wait", "#" }, - { "no-contact", 0, arg_flag, &_no_contact, "Wait for cluster no contact", "" }, - { "usage", '?', arg_flag, &_help, "Print help", "" } - }; - - int num_args = sizeof(args) / sizeof(args[0]); - int optind = 0; - char desc[] = - "hostname:port\n"\ - "This program will connect to the mgmsrv of a NDB cluster.\n"\ - "It will then wait for all nodes to be started\n"; - - if(getarg(args, num_args, argc, argv, &optind) || _help) { - arg_printusage(args, num_args, argv[0], desc); + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) return NDBT_ProgramExit(NDBT_WRONGARGS); - } char buf[255]; - _hostName = argv[optind]; + _hostName = argv[0]; if (_hostName == NULL){ LocalConfig lcfg; diff --git a/sql/field.cc b/sql/field.cc index 7a8f59c25fe..1275e1bbb8e 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -547,7 +547,8 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) /* Convert character set if the old one is multi byte */ if (cs->mbmaxlen > 1) { - tmp.copy(from, len, cs, &my_charset_bin); + uint dummy_errors; + tmp.copy(from, len, cs, &my_charset_bin, &dummy_errors); from= tmp.ptr(); len= tmp.length(); } @@ -4444,6 +4445,7 @@ void Field_string::sort_string(char *to,uint length) void Field_string::sql_type(String &res) const { + THD *thd= table->in_use; CHARSET_INFO *cs=res.charset(); ulong length= cs->cset->snprintf(cs,(char*) res.ptr(), res.alloced_length(), "%s(%d)", @@ -4454,6 +4456,9 @@ void Field_string::sql_type(String &res) const (has_charset() ? "char" : "binary")), (int) field_length / charset()->mbmaxlen); res.length(length); + if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) && + has_charset() && (charset()->state & MY_CS_BINSORT)) + res.append(" binary"); } char *Field_string::pack(char *to, const char *from, uint max_length) @@ -5530,7 +5535,8 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) /* Convert character set if nesessary */ if (String::needs_conversion(length, cs, field_charset, ¬_used)) { - tmpstr.copy(from, length, cs, field_charset); + uint dummy_errors; + tmpstr.copy(from, length, cs, field_charset, &dummy_errors); from= tmpstr.ptr(); length= tmpstr.length(); } @@ -5678,10 +5684,11 @@ void Field_enum::sql_type(String &res) const bool flag=0; for (const char **pos= typelib->type_names; *pos; pos++) { + uint dummy_errors; if (flag) res.append(','); /* convert to res.charset() == utf8, then quote */ - enum_item.copy(*pos, strlen(*pos), charset(), res.charset()); + enum_item.copy(*pos, strlen(*pos), charset(), res.charset(), &dummy_errors); append_unescaped(&res, enum_item.ptr(), enum_item.length()); flag= 1; } @@ -5712,7 +5719,8 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) /* Convert character set if nesessary */ if (String::needs_conversion(length, cs, field_charset, ¬_used_offset)) { - tmpstr.copy(from, length, cs, field_charset); + uint dummy_errors; + tmpstr.copy(from, length, cs, field_charset, &dummy_errors); from= tmpstr.ptr(); length= tmpstr.length(); } @@ -5788,10 +5796,11 @@ void Field_set::sql_type(String &res) const bool flag=0; for (const char **pos= typelib->type_names; *pos; pos++) { + uint dummy_errors; if (flag) res.append(','); /* convert to res.charset() == utf8, then quote */ - set_item.copy(*pos, strlen(*pos), charset(), res.charset()); + set_item.copy(*pos, strlen(*pos), charset(), res.charset(), &dummy_errors); append_unescaped(&res, set_item.ptr(), set_item.length()); flag= 1; } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 7878684718c..ebbbaf8acc8 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1393,8 +1393,13 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, // Set bound if not cancelled via type -1 if (p.bound_type != -1) - if (op->setBound(field->field_name, p.bound_type, p.bound_ptr)) + { + char truncated_field_name[NDB_MAX_ATTR_NAME_SIZE]; + strnmov(truncated_field_name,field->field_name,sizeof(truncated_field_name)); + truncated_field_name[sizeof(truncated_field_name)-1]= '\0'; + if (op->setBound(truncated_field_name, p.bound_type, p.bound_ptr)) ERR_RETURN(op->getNdbError()); + } } } @@ -2653,7 +2658,8 @@ int ha_ndbcluster::extra(enum ha_extra_function operation) m_use_write= TRUE; } else { - m_ignore_dup_key_not_supported= TRUE; + if (table->keys) + m_ignore_dup_key_not_supported= TRUE; } break; case HA_EXTRA_NO_IGNORE_DUP_KEY: @@ -3112,7 +3118,12 @@ static int create_ndb_column(NDBCOL &col, HA_CREATE_INFO *info) { // Set name - col.setName(field->field_name); + { + char truncated_field_name[NDB_MAX_ATTR_NAME_SIZE]; + strnmov(truncated_field_name,field->field_name,sizeof(truncated_field_name)); + truncated_field_name[sizeof(truncated_field_name)-1]= '\0'; + col.setName(truncated_field_name); + } // Get char set CHARSET_INFO *cs= field->charset(); // Set type and sizes @@ -3440,7 +3451,12 @@ int ha_ndbcluster::create_index(const char *name, { Field *field= key_part->field; DBUG_PRINT("info", ("attr: %s", field->field_name)); - ndb_index.addColumnName(field->field_name); + { + char truncated_field_name[NDB_MAX_ATTR_NAME_SIZE]; + strnmov(truncated_field_name,field->field_name,sizeof(truncated_field_name)); + truncated_field_name[sizeof(truncated_field_name)-1]= '\0'; + ndb_index.addColumnName(truncated_field_name); + } } if (dict->createIndex(ndb_index)) diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 245d906c5ae..fc1e4390adb 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -26,7 +26,6 @@ #endif #include <ndbapi_limits.h> -#include <ndb_types.h> class Ndb; // Forward declaration class NdbOperation; // Forward declaration diff --git a/sql/item.cc b/sql/item.cc index 6730b0dd4a2..1f90b1842ac 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -261,6 +261,41 @@ bool Item::eq(const Item *item, bool binary_cmp) const } +Item *Item::safe_charset_converter(CHARSET_INFO *tocs) +{ + /* + Don't allow automatic conversion to non-Unicode charsets, + as it potentially loses data. + */ + if (!(tocs->state & MY_CS_UNICODE)) + return NULL; // safe conversion is not possible + return new Item_func_conv_charset(this, tocs); +} + + +Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs) +{ + Item_string *conv; + uint conv_errors; + String tmp, cstr, *ostr= val_str(&tmp); + cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors); + if (conv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(), + cstr.charset(), + collation.derivation))) + { + /* + Safe conversion is not possible (or EOM). + We could not convert a string into the requested character set + without data loss. The target charset does not cover all the + characters from the string. Operation cannot be done correctly. + */ + return NULL; + } + conv->str_value.copy(); + return conv; +} + + bool Item_string::eq(const Item *item, bool binary_cmp) const { if (type() == item->type()) @@ -355,7 +390,43 @@ Item_splocal::type() const } -bool DTCollation::aggregate(DTCollation &dt, bool superset_conversion) + +/* + Aggregate two collations together taking + into account their coercibility (aka derivation): + + 0 == DERIVATION_EXPLICIT - an explicitely written COLLATE clause + 1 == DERIVATION_NONE - a mix of two different collations + 2 == DERIVATION_IMPLICIT - a column + 3 == DERIVATION_COERCIBLE - a string constant + + The most important rules are: + + 1. If collations are the same: + chose this collation, and the strongest derivation. + + 2. If collations are different: + - Character sets may differ, but only if conversion without + data loss is possible. The caller provides flags whether + character set conversion attempts should be done. If no + flags are substituted, then the character sets must be the same. + Currently processed flags are: + MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset + MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value + - two EXPLICIT collations produce an error, e.g. this is wrong: + CONCAT(expr1 collate latin1_swedish_ci, expr2 collate latin1_german_ci) + - the side with smaller derivation value wins, + i.e. a column is stronger than a string constant, + an explicit COLLATE clause is stronger than a column. + - if derivations are the same, we have DERIVATION_NONE, + we'll wait for an explicit COLLATE clause which possibly can + come from another argument later: for example, this is valid, + but we don't know yet when collecting the first two arguments: + CONCAT(latin1_swedish_ci_column, + latin1_german1_ci_column, + expr COLLATE latin1_german2_ci) +*/ +bool DTCollation::aggregate(DTCollation &dt, uint flags) { nagg++; if (!my_charset_same(collation, dt.collation)) @@ -386,28 +457,37 @@ bool DTCollation::aggregate(DTCollation &dt, bool superset_conversion) else ; // Do nothing } - else if (superset_conversion) + else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) && + derivation < dt.derivation && + collation->state & MY_CS_UNICODE) { - if (derivation < dt.derivation && - collation->state & MY_CS_UNICODE) - ; // Do nothing - else if (dt.derivation < derivation && - dt.collation->state & MY_CS_UNICODE) - { - set(dt); - strong= nagg; - } - else - { - // Cannot convert to superset - set(0, DERIVATION_NONE); - return 1; - } + // Do nothing + } + else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) && + dt.derivation < derivation && + dt.collation->state & MY_CS_UNICODE) + { + set(dt); + strong= nagg; + } + else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) && + derivation < dt.derivation && + dt.derivation == DERIVATION_COERCIBLE) + { + // Do nothing; + } + else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) && + dt.derivation < derivation && + derivation == DERIVATION_COERCIBLE) + { + set(dt); + strong= nagg; } else { + // Cannot apply conversion set(0, DERIVATION_NONE); - return 1; + return 1; } } else if (derivation < dt.derivation) @@ -830,6 +910,12 @@ String *Item_null::val_str(String *str) } +Item *Item_null::safe_charset_converter(CHARSET_INFO *tocs) +{ + collation.set(tocs); + return this; +} + /*********************** Item_param related ******************************/ /* @@ -925,7 +1011,9 @@ bool Item_param::set_str(const char *str, ulong length) Assign string with no conversion: data is converted only after it's been written to the binary log. */ - if (str_value.copy(str, length, &my_charset_bin, &my_charset_bin)) + uint dummy_errors; + if (str_value.copy(str, length, &my_charset_bin, &my_charset_bin, + &dummy_errors)) DBUG_RETURN(TRUE); state= STRING_VALUE; maybe_null= 0; diff --git a/sql/item.h b/sql/item.h index d3e53af1523..11aeb22b6e5 100644 --- a/sql/item.h +++ b/sql/item.h @@ -38,6 +38,25 @@ enum Derivation DERIVATION_EXPLICIT= 0 }; +/* + Flags for collation aggregation modes: + MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset + MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value + (i.e. constant). + MY_COLL_ALLOW_CONV - allow any kind of conversion + (combintion of the above two) + MY_COLL_DISALLOW_NONE - don't allow return DERIVATION_NONE + (e.g. when aggregating for comparison) + MY_COLL_CMP_CONV - combination of MY_COLL_ALLOW_CONV + and MY_COLL_DISALLOW_NONE +*/ + +#define MY_COLL_ALLOW_SUPERSET_CONV 1 +#define MY_COLL_ALLOW_COERCIBLE_CONV 2 +#define MY_COLL_ALLOW_CONV 3 +#define MY_COLL_DISALLOW_NONE 4 +#define MY_COLL_CMP_CONV 7 + class DTCollation { public: CHARSET_INFO *collation; @@ -73,9 +92,9 @@ public: { collation= collation_arg; } void set(Derivation derivation_arg) { derivation= derivation_arg; } - bool aggregate(DTCollation &dt, bool superset_conversion= FALSE); - bool set(DTCollation &dt1, DTCollation &dt2, bool superset_conversion= FALSE) - { set(dt1); return aggregate(dt2, superset_conversion); } + bool aggregate(DTCollation &dt, uint flags= 0); + bool set(DTCollation &dt1, DTCollation &dt2, uint flags= 0) + { set(dt1); return aggregate(dt2, flags); } const char *derivation_name() const { switch(derivation) @@ -305,6 +324,7 @@ public: virtual Item_field *filed_for_view_update() { return 0; } virtual Item *neg_transformer(THD *thd) { return NULL; } + virtual Item *safe_charset_converter(CHARSET_INFO *tocs); void delete_self() { cleanup(); @@ -572,6 +592,7 @@ public: Item *new_item() { return new Item_null(name); } bool is_null() { return 1; } void print(String *str) { str->append("NULL", 4); } + Item *safe_charset_converter(CHARSET_INFO *tocs); }; @@ -861,6 +882,7 @@ public: return new Item_string(name, str_value.ptr(), str_value.length(), &my_charset_bin); } + Item *safe_charset_converter(CHARSET_INFO *tocs); String *const_string() { return &str_value; } inline void append(char *str, uint length) { str_value.append(str, length); } void print(String *str); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 467cd8313a4..b08a6fcd2e6 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -185,55 +185,14 @@ void Item_bool_func2::fix_length_and_dec() to the collation of A. */ - if (args[0] && args[1]) - { - uint strong= 0; - uint weak= 0; - uint32 dummy_offset; - DTCollation coll; - - if (args[0]->result_type() == STRING_RESULT && - args[1]->result_type() == STRING_RESULT && - String::needs_conversion(0, args[0]->collation.collation, - args[1]->collation.collation, - &dummy_offset) && - !coll.set(args[0]->collation, args[1]->collation, TRUE)) - { - Item* conv= 0; - Item_arena *arena= thd->current_arena, backup; - strong= coll.strong; - weak= strong ? 0 : 1; - /* - In case we're in statement prepare, create conversion item - in its memory: it will be reused on each execute. - */ - if (arena->is_stmt_prepare()) - thd->set_n_backup_item_arena(arena, &backup); - if (args[weak]->type() == STRING_ITEM) - { - String tmp, cstr; - String *ostr= args[weak]->val_str(&tmp); - cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), - args[strong]->collation.collation); - conv= new Item_string(cstr.ptr(),cstr.length(),cstr.charset(), - args[weak]->collation.derivation); - ((Item_string*)conv)->str_value.copy(); - } - else - { - conv= new Item_func_conv_charset(args[weak], - args[strong]->collation.collation); - conv->collation.set(args[weak]->collation.derivation); - conv->fix_fields(thd, 0, &conv); - } - if (arena->is_stmt_prepare()) - thd->restore_backup_item_arena(arena, &backup); - if (args[weak]->type() == FIELD_ITEM) - ((Item_field *)args[weak])->no_const_subst= 1; - args[weak]= conv ? conv : args[weak]; - } - } + DTCollation coll; + if (args[0]->result_type() == STRING_RESULT && + args[1]->result_type() == STRING_RESULT && + agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV)) + return; + + // Make a special case of compare with fields to get nicer DATE comparisons if (functype() == LIKE_FUNC) // Disable conversion in case of LIKE function. @@ -859,7 +818,7 @@ void Item_func_between::fix_length_and_dec() return; agg_cmp_type(&cmp_type, args, 3); if (cmp_type == STRING_RESULT && - agg_arg_collations_for_comparison(cmp_collation, args, 3)) + agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV)) return; /* @@ -975,7 +934,7 @@ Item_func_ifnull::fix_length_and_dec() decimals=max(args[0]->decimals,args[1]->decimals); agg_result_type(&cached_result_type, args, 2); if (cached_result_type == STRING_RESULT) - agg_arg_collations(collation, args, arg_count); + agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV); else if (cached_result_type != REAL_RESULT) decimals= 0; @@ -1071,8 +1030,8 @@ Item_func_if::fix_length_and_dec() agg_result_type(&cached_result_type, args+1, 2); if (cached_result_type == STRING_RESULT) { - if (agg_arg_collations(collation, args+1, 2)) - return; + if (agg_arg_charsets(collation, args+1, 2, MY_COLL_ALLOW_CONV)) + return; } else { @@ -1331,8 +1290,10 @@ void Item_func_case::fix_length_and_dec() if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1)))) return; - // Aggregate all THEN and ELSE expression types - // and collations when string result + /* + Aggregate all THEN and ELSE expression types + and collations when string result + */ for (nagg= 0 ; nagg < ncases/2 ; nagg++) agg[nagg]= args[nagg*2+1]; @@ -1342,7 +1303,7 @@ void Item_func_case::fix_length_and_dec() agg_result_type(&cached_result_type, agg, nagg); if ((cached_result_type == STRING_RESULT) && - agg_arg_collations(collation, agg, nagg)) + agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV)) return; @@ -1358,7 +1319,7 @@ void Item_func_case::fix_length_and_dec() nagg++; agg_cmp_type(&cmp_type, agg, nagg); if ((cmp_type == STRING_RESULT) && - agg_arg_collations_for_comparison(cmp_collation, agg, nagg)) + agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV)) return; } @@ -1465,7 +1426,7 @@ void Item_func_coalesce::fix_length_and_dec() set_if_bigger(decimals,args[i]->decimals); } if (cached_result_type == STRING_RESULT) - agg_arg_collations(collation, args, arg_count); + agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV); else if (cached_result_type != REAL_RESULT) decimals= 0; } @@ -1795,14 +1756,13 @@ void Item_func_in::fix_length_and_dec() via creating Item_func_conv_charset(). */ - if (agg_arg_collations_for_comparison(cmp_collation, - args, arg_count, TRUE)) + if (agg_arg_collations_for_comparison(cmp_collation, args, arg_count, + MY_COLL_ALLOW_SUPERSET_CONV)) return; if ((!my_charset_same(args[0]->collation.collation, cmp_collation.collation) || !const_itm)) { - if (agg_arg_collations_for_comparison(cmp_collation, - args, arg_count, FALSE)) + if (agg_arg_collations_for_comparison(cmp_collation, args, arg_count)) return; } else @@ -1821,8 +1781,9 @@ void Item_func_in::fix_length_and_dec() { Item_string *conv; String tmp, cstr, *ostr= arg[0]->val_str(&tmp); + uint dummy_errors; cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), - cmp_collation.collation); + cmp_collation.collation, &dummy_errors); conv= new Item_string(cstr.ptr(),cstr.length(), cstr.charset(), arg[0]->collation.derivation); conv->str_value.copy(); @@ -2449,7 +2410,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) max_length= 1; decimals= 0; - if (agg_arg_collations(cmp_collation, args, 2)) + if (agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV)) return 1; used_tables_cache=args[0]->used_tables() | args[1]->used_tables(); diff --git a/sql/item_create.cc b/sql/item_create.cc index e21364045ba..cec6de3eede 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -370,7 +370,10 @@ Item *create_func_space(Item *a) { sp= new Item_string("",0,cs); if (sp) - sp->str_value.copy(" ",1,&my_charset_latin1,cs); + { + uint dummy_errors; + sp->str_value.copy(" ", 1, &my_charset_latin1, cs, &dummy_errors); + } } else { diff --git a/sql/item_func.cc b/sql/item_func.cc index 3cc0fd077a4..173b1b3fd82 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -79,7 +79,7 @@ static void my_coll_agg_error(Item** args, uint count, const char *fname) bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count, - bool allow_superset_conversion) + uint flags) { uint i; c.nagg= 0; @@ -87,29 +87,27 @@ bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count, c.set(av[0]->collation); for (i= 1; i < count; i++) { - if (c.aggregate(av[i]->collation, allow_superset_conversion)) + if (c.aggregate(av[i]->collation, flags)) { my_coll_agg_error(av, count, func_name()); return TRUE; } } + if ((flags & MY_COLL_DISALLOW_NONE) && + c.derivation == DERIVATION_NONE) + { + my_coll_agg_error(av, count, func_name()); + return TRUE; + } return FALSE; } bool Item_func::agg_arg_collations_for_comparison(DTCollation &c, Item **av, uint count, - bool allow_superset_conv) + uint flags) { - if (agg_arg_collations(c, av, count, allow_superset_conv)) - return TRUE; - - if (c.derivation == DERIVATION_NONE) - { - my_coll_agg_error(av, count, func_name()); - return TRUE; - } - return FALSE; + return (agg_arg_collations(c, av, count, flags | MY_COLL_DISALLOW_NONE)); } @@ -122,6 +120,89 @@ eval_const_cond(COND *cond) } + +/* + Collect arguments' character sets together. + We allow to apply automatic character set conversion in some cases. + The conditions when conversion is possible are: + - arguments A and B have different charsets + - A wins according to coercibility rules + (i.e. a column is stronger than a string constant, + an explicit COLLATE clause is stronger than a column) + - character set of A is either superset for character set of B, + or B is a string constant which can be converted into the + character set of A without data loss. + + If all of the above is true, then it's possible to convert + B into the character set of A, and then compare according + to the collation of A. + + For functions with more than two arguments: + + collect(A,B,C) ::= collect(collect(A,B),C) +*/ + +bool Item_func::agg_arg_charsets(DTCollation &coll, + Item **args, uint nargs, uint flags) +{ + Item **arg, **last, *safe_args[2]; + if (agg_arg_collations(coll, args, nargs, flags)) + return TRUE; + + /* + For better error reporting: save the first and the second argument. + We need this only if the the number of args is 3 or 2: + - for a longer argument list, "Illegal mix of collations" + doesn't display each argument's characteristics. + - if nargs is 1, then this error cannot happen. + */ + if (nargs >=2 && nargs <= 3) + { + safe_args[0]= args[0]; + safe_args[1]= args[1]; + } + + THD *thd= current_thd; + Item_arena *arena= thd->current_arena, backup; + bool res= FALSE; + /* + In case we're in statement prepare, create conversion item + in its memory: it will be reused on each execute. + */ + if (arena->is_stmt_prepare()) + thd->set_n_backup_item_arena(arena, &backup); + + for (arg= args, last= args + nargs; arg < last; arg++) + { + Item* conv; + uint dummy_offset; + if (!String::needs_conversion(0, coll.collation, + (*arg)->collation.collation, + &dummy_offset)) + continue; + + if (!(conv= (*arg)->safe_charset_converter(coll.collation))) + { + if (nargs >=2 && nargs <= 3) + { + /* restore the original arguments for better error message */ + args[0]= safe_args[0]; + args[1]= safe_args[1]; + } + my_coll_agg_error(args, nargs, func_name()); + res= TRUE; + break; // we cannot return here, we need to restore "arena". + } + conv->fix_fields(thd, 0, &conv); + *arg= conv; + } + if (arena->is_stmt_prepare()) + thd->restore_backup_item_arena(arena, &backup); + return res; +} + + + void Item_func::set_arguments(List<Item> &list) { allowed_arg_cols= 1; @@ -1185,7 +1266,7 @@ void Item_func_min_max::fix_length_and_dec() cmp_type=item_cmp_type(cmp_type,args[i]->result_type()); } if (cmp_type == STRING_RESULT) - agg_arg_collations_for_comparison(collation, args, arg_count); + agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV); } @@ -1339,7 +1420,7 @@ longlong Item_func_coercibility::val_int() void Item_func_locate::fix_length_and_dec() { maybe_null=0; max_length=11; - agg_arg_collations_for_comparison(cmp_collation, args, 2); + agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV); } @@ -1438,7 +1519,7 @@ void Item_func_field::fix_length_and_dec() for (uint i=1; i < arg_count ; i++) cmp_type= item_cmp_type(cmp_type, args[i]->result_type()); if (cmp_type == STRING_RESULT) - agg_arg_collations_for_comparison(cmp_collation, args, arg_count); + agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV); } @@ -3003,8 +3084,9 @@ void Item_func_match::init_search(bool no_order) if (ft_tmp->charset() != cmp_collation.collation) { + uint dummy_errors; search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(), - cmp_collation.collation); + cmp_collation.collation, &dummy_errors); ft_tmp= &search_value; } diff --git a/sql/item_func.h b/sql/item_func.h index 3b941c4a40c..602b77ae956 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -146,11 +146,12 @@ public: Item *get_tmp_table_item(THD *thd); bool agg_arg_collations(DTCollation &c, Item **items, uint nitems, - bool allow_superset_conversion= FALSE); + uint flags= 0); bool agg_arg_collations_for_comparison(DTCollation &c, Item **items, uint nitems, - bool allow_superset_comversion= FALSE); - + uint flags= 0); + bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, + uint flags= 0); bool walk(Item_processor processor, byte *arg); Item *transform(Item_transformer transformer, byte *arg); }; diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 935925c1e83..7c3319bbfea 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -148,9 +148,9 @@ String *Item_func_geometry_type::val_str(String *str) swkb->length() - SRID_SIZE))))) return 0; /* String will not move */ - str->set(geom->get_class_info()->m_name.str, - geom->get_class_info()->m_name.length, - default_charset()); + str->copy(geom->get_class_info()->m_name.str, + geom->get_class_info()->m_name.length, + default_charset()); return str; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index d015ca36eac..889b00eb6a0 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -346,7 +346,7 @@ void Item_func_concat::fix_length_and_dec() { max_length=0; - if (agg_arg_collations(collation, args, arg_count)) + if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV)) return; for (uint i=0 ; i < arg_count ; i++) @@ -640,10 +640,15 @@ void Item_func_concat_ws::fix_length_and_dec() { max_length=0; - if (agg_arg_collations(collation, args, arg_count)) + if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV)) return; - max_length= arg_count > 1 ? args[0]->max_length * (arg_count - 2) : 0; + /* + arg_count cannot be less than 2, + it is done on parser level in sql_yacc.yy + so, (arg_count - 2) is safe here. + */ + max_length= args[0]->max_length * (arg_count - 2); for (uint i=1 ; i < arg_count ; i++) max_length+=args[i]->max_length; @@ -843,7 +848,7 @@ void Item_func_replace::fix_length_and_dec() maybe_null=1; } - if (agg_arg_collations_for_comparison(collation, args, 3)) + if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV)) return; } @@ -888,11 +893,13 @@ null: void Item_func_insert::fix_length_and_dec() { - if (collation.set(args[0]->collation, args[3]->collation)) - { - my_coll_agg_error(args[0]->collation, args[3]->collation, func_name()); - return; - } + Item *cargs[2]; + cargs[0]= args[0]; + cargs[1]= args[3]; + if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV)) + return; + args[0]= cargs[0]; + args[3]= cargs[1]; max_length=args[0]->max_length+args[3]->max_length; if (max_length > MAX_BLOB_WIDTH) { @@ -1058,7 +1065,7 @@ void Item_func_substr_index::fix_length_and_dec() { max_length= args[0]->max_length; - if (agg_arg_collations_for_comparison(collation, args, 2)) + if (agg_arg_charsets(collation, args, 2, MY_COLL_CMP_CONV)) return; } @@ -1350,10 +1357,14 @@ void Item_func_trim::fix_length_and_dec() remove.set_ascii(" ",1); } else - if (collation.set(args[1]->collation, args[0]->collation) || - collation.derivation == DERIVATION_NONE) { - my_coll_agg_error(args[1]->collation, args[0]->collation, func_name()); + Item *cargs[2]; + cargs[0]= args[1]; + cargs[1]= args[0]; + if (agg_arg_charsets(collation, cargs, 2, MY_COLL_CMP_CONV)) + return; + args[0]= cargs[1]; + args[1]= cargs[0]; } } @@ -1674,7 +1685,7 @@ void Item_func_elt::fix_length_and_dec() max_length=0; decimals=0; - if (agg_arg_collations(collation, args+1, arg_count-1)) + if (agg_arg_charsets(collation, args+1, arg_count-1, MY_COLL_ALLOW_CONV)) return; for (uint i= 1 ; i < arg_count ; i++) @@ -1750,7 +1761,7 @@ void Item_func_make_set::fix_length_and_dec() { max_length=arg_count-1; - if (agg_arg_collations(collation, args, arg_count)) + if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV)) return; for (uint i=0 ; i < arg_count ; i++) @@ -1958,12 +1969,13 @@ err: void Item_func_rpad::fix_length_and_dec() { - if (collation.set(args[0]->collation, args[2]->collation)) - { - my_coll_agg_error(args[0]->collation, args[2]->collation, func_name()); + Item *cargs[2]; + cargs[0]= args[0]; + cargs[1]= args[2]; + if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV)) return; - } - + args[0]= cargs[0]; + args[2]= cargs[1]; if (args[1]->const_item()) { uint32 length= (uint32) args[1]->val_int() * collation.collation->mbmaxlen; @@ -2042,11 +2054,13 @@ String *Item_func_rpad::val_str(String *str) void Item_func_lpad::fix_length_and_dec() { - if (collation.set(args[0]->collation, args[2]->collation)) - { - my_coll_agg_error(args[0]->collation, args[2]->collation, func_name()); + Item *cargs[2]; + cargs[0]= args[0]; + cargs[1]= args[2]; + if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV)) return; - } + args[0]= cargs[0]; + args[2]= cargs[1]; if (args[1]->const_item()) { @@ -2155,13 +2169,14 @@ String *Item_func_conv_charset::val_str(String *str) { DBUG_ASSERT(fixed == 1); String *arg= args[0]->val_str(str); + uint dummy_errors; if (!arg) { null_value=1; return 0; } null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(), - conv_charset); + conv_charset, &dummy_errors); return null_value ? 0 : &str_value; } @@ -2256,11 +2271,12 @@ String *Item_func_charset::val_str(String *str) { DBUG_ASSERT(fixed == 1); String *res = args[0]->val_str(str); + uint dummy_errors; if ((null_value=(args[0]->null_value || !res->charset()))) return 0; str->copy(res->charset()->csname,strlen(res->charset()->csname), - &my_charset_latin1, collation.collation); + &my_charset_latin1, collation.collation, &dummy_errors); return str; } @@ -2268,11 +2284,12 @@ String *Item_func_collation::val_str(String *str) { DBUG_ASSERT(fixed == 1); String *res = args[0]->val_str(str); + uint dummy_errors; if ((null_value=(args[0]->null_value || !res->charset()))) return 0; str->copy(res->charset()->name,strlen(res->charset()->name), - &my_charset_latin1, collation.collation); + &my_charset_latin1, collation.collation, &dummy_errors); return str; } @@ -2499,7 +2516,8 @@ void Item_func_export_set::fix_length_and_dec() uint sep_length=(arg_count > 3 ? args[3]->max_length : 1); max_length=length*64+sep_length*63; - if (agg_arg_collations(collation, args+1, min(4,arg_count)-1)) + if (agg_arg_charsets(collation, args+1, min(4,arg_count)-1), + MY_COLL_ALLOW_CONV) return; } diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 3a25921d84b..fd7a2ea2cb4 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2140,8 +2140,10 @@ String *Item_char_typecast::val_str(String *str) else { // Convert character set if differ + uint dummy_errors; if (!(res1= args[0]->val_str(&tmp_value)) || - str->copy(res1->ptr(), res1->length(),res1->charset(), cast_cs)) + str->copy(res1->ptr(), res1->length(), res1->charset(), + cast_cs, &dummy_errors)) { null_value= 1; return 0; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3d7ab14f13d..6214481e273 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2972,11 +2972,10 @@ we force server id to 2, but this MySQL server will not act as a slave."); exit(1); #ifdef __WIN__ -#define MYSQL_ERR_FILE "mysql.err" if (!opt_console) { - freopen(MYSQL_ERR_FILE,"a+",stdout); - freopen(MYSQL_ERR_FILE,"a+",stderr); + freopen(log_error_file,"a+",stdout); + freopen(log_error_file,"a+",stderr); FreeConsole(); // Remove window } #endif @@ -5132,12 +5131,12 @@ The minimum value for this variable is 4096.", "Persistent buffer for query parsing and execution", (gptr*) &global_system_variables.query_prealloc_size, (gptr*) &max_system_variables.query_prealloc_size, 0, GET_ULONG, - REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0}, + REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, 16384, ~0L, 0, 1024, 0}, {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE, "Allocation block size for storing ranges during optimization", (gptr*) &global_system_variables.range_alloc_block_size, (gptr*) &max_system_variables.range_alloc_block_size, 0, GET_ULONG, - REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0}, + REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 4096, ~0L, 0, 1024, 0}, {"read_buffer_size", OPT_RECORD_BUFFER, "Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.", (gptr*) &global_system_variables.read_buff_size, diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 27311cb5613..bcb1f8634c0 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -53,19 +53,9 @@ #include <errno.h> #ifdef EMBEDDED_LIBRARY - #undef MYSQL_SERVER - -#ifndef MYSQL_CLIENT +#undef MYSQL_CLIENT #define MYSQL_CLIENT -#endif - -#undef net_flush - -extern "C" { -my_bool net_flush(NET *net); -} - #endif /*EMBEDDED_LIBRARY */ diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 286d0d01842..b832b33049d 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3566,13 +3566,22 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, } /* - We can't use an index when comparing strings of - different collations + 1. Usually we can't use an index if the column collation + differ from the operation collation. + + 2. However, we can reuse a case insensitive index for + the binary searches: + + WHERE latin1_swedish_ci_column = 'a' COLLATE lati1_bin; + + WHERE latin1_swedish_ci_colimn = BINARY 'a ' + */ if (field->result_type() == STRING_RESULT && value->result_type() == STRING_RESULT && key_part->image_type == Field::itRAW && - ((Field_str*)field)->charset() != conf_func->compare_collation()) + ((Field_str*)field)->charset() != conf_func->compare_collation() && + !(conf_func->compare_collation()->state & MY_CS_BINSORT)) DBUG_RETURN(0); optimize_range= field->optimize_range(param->real_keynr[key_part->key], diff --git a/sql/protocol.cc b/sql/protocol.cc index 051eaaf7bda..2b0ae60f944 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -486,6 +486,15 @@ void Protocol::init(THD *thd_arg) } +bool Protocol::flush() +{ +#ifndef EMBEDDED_LIBRARY + return net_flush(&thd->net); +#else + return 0; +#endif +} + /* Send name and type of result to client. @@ -731,7 +740,8 @@ bool Protocol::store_string_aux(const char *from, uint length, fromcs != &my_charset_bin && tocs != &my_charset_bin) { - return convert->copy(from, length, fromcs, tocs) || + uint dummy_errors; + return convert->copy(from, length, fromcs, tocs, &dummy_errors) || net_store_data(convert->ptr(), convert->length()); } return net_store_data(from, length); diff --git a/sql/protocol.h b/sql/protocol.h index 7d390242417..d342af3ee9f 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -74,6 +74,7 @@ public: field_count=item_list->elements; return 0; } + virtual bool flush(); virtual void prepare_for_resend()=0; virtual bool store_null()=0; diff --git a/sql/spatial.cc b/sql/spatial.cc index 0668dd2faab..bcfefd9dde8 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -828,9 +828,7 @@ int Gis_polygon::centroid_xy(double *x, double *y) const if (!first_loop) { - double d_area= res_area - cur_area; - if (d_area <= 0) - return 1; + double d_area= fabs(res_area - cur_area); res_cx= (res_area * res_cx - cur_area * cur_cx) / d_area; res_cy= (res_area * res_cy - cur_area * cur_cy) / d_area; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f5283020b30..5ed5468af2f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -567,13 +567,14 @@ bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs, { DBUG_ENTER("convert_string"); size_s new_length= to_cs->mbmaxlen * from_length; + uint dummy_errors; if (!(to->str= alloc(new_length+1))) { to->length= 0; // Safety fix DBUG_RETURN(1); // EOM } to->length= copy_and_convert((char*) to->str, new_length, to_cs, - from, from_length, from_cs); + from, from_length, from_cs, &dummy_errors); to->str[to->length]=0; // Safety DBUG_RETURN(0); } @@ -596,7 +597,8 @@ bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs, bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) { - if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs)) + uint dummy_errors; + if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors)) return TRUE; /* If convert_buffer >> s copying is more efficient long term */ if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 || diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 60f69b578e9..35bad134127 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -899,18 +899,20 @@ static int check_connection(THD *thd) /* Since 4.1 all database names are stored in utf8 */ if (db) { + uint dummy_errors; db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info, db, strlen(db), - thd->charset())]= 0; + thd->charset(), &dummy_errors)]= 0; db= db_buff; } if (user) { + uint dummy_errors; user_buff[copy_and_convert(user_buff, sizeof(user_buff)-1, system_charset_info, user, strlen(user), - thd->charset())]= '\0'; + thd->charset(), &dummy_errors)]= '\0'; user= user_buff; } @@ -1412,9 +1414,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } #endif /* Convert database name to utf8 */ + uint dummy_errors; db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info, db, strlen(db), - thd->charset())]= 0; + thd->charset(), &dummy_errors)]= 0; db= db_buff; /* Save user and privileges */ @@ -2148,8 +2151,12 @@ mysql_execute_command(THD *thd) } if (need_conversion) - query_len= copy_and_convert(query_str, query_len, to_cs, pstr->ptr(), - pstr->length(), pstr->charset()); + { + uint dummy_errors; + query_len= copy_and_convert(query_str, query_len, to_cs, + pstr->ptr(), pstr->length(), + pstr->charset(), &dummy_errors); + } else memcpy(query_str, pstr->ptr(), pstr->length()); query_str[query_len]= 0; @@ -2716,6 +2723,7 @@ unsent_create_error: { if (mysql_bin_log.is_open()) { + thd->clear_error(); // No binlog error generated Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -2745,6 +2753,7 @@ unsent_create_error: { if (mysql_bin_log.is_open()) { + thd->clear_error(); // No binlog error generated Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -2767,6 +2776,7 @@ unsent_create_error: { if (mysql_bin_log.is_open()) { + thd->clear_error(); // No binlog error generated Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index bb2362dd562..d908e63210a 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -170,8 +170,7 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns) (stmt->param_count && stmt->thd->protocol_simple.send_fields((List<Item> *) &stmt->lex->param_list, - Protocol::SEND_EOF)) || - net_flush(net)); + Protocol::SEND_EOF))); } #else static bool send_prep_stmt(Prepared_statement *stmt, @@ -1097,7 +1096,7 @@ static int mysql_test_select(Prepared_statement *stmt, { if (lex->describe) { - if (send_prep_stmt(stmt, 0)) + if (send_prep_stmt(stmt, 0) || thd->protocol->flush()) goto err_prep; } else @@ -1115,11 +1114,8 @@ static int mysql_test_select(Prepared_statement *stmt, prepared in unit->prepare call above. */ if (send_prep_stmt(stmt, lex->result->field_count(fields)) || - lex->result->send_fields(fields, Protocol::SEND_EOF) -#ifndef EMBEDDED_LIBRARY - || net_flush(&thd->net) -#endif - ) + lex->result->send_fields(fields, Protocol::SEND_EOF) || + thd->protocol->flush()) goto err_prep; } } @@ -1402,7 +1398,6 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol) enum enum_sql_command sql_command= lex->sql_command; int res= 0; DBUG_ENTER("send_prepare_results"); - DBUG_PRINT("enter",("command: %d, param_count: %ld", sql_command, stmt->param_count)); @@ -1453,6 +1448,7 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol) break; case SQLCOM_INSERT_SELECT: + case SQLCOM_REPLACE_SELECT: res= mysql_test_insert_select(stmt, tables); break; @@ -1491,7 +1487,8 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol) goto error; } if (res == 0) - DBUG_RETURN(text_protocol? 0 : send_prep_stmt(stmt, 0)); + DBUG_RETURN(text_protocol? 0 : (send_prep_stmt(stmt, 0) || + thd->protocol->flush())); error: if (res < 0) send_error(thd,thd->killed_errno()); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 28e9baa1c36..557ec1bd5d2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -804,8 +804,9 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, String def(tmp1,sizeof(tmp1), system_charset_info); type.set(tmp, sizeof(tmp), field->charset()); field->val_str(&type); + uint dummy_errors; def.copy(type.ptr(), type.length(), type.charset(), - system_charset_info); + system_charset_info, &dummy_errors); protocol->store(def.ptr(), def.length(), def.charset()); } else if (field->unireg_check == Field::NEXT_NUMBER || @@ -1177,7 +1178,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS | Protocol::SEND_EOF)) DBUG_VOID_RETURN; - net_flush(&thd->net); + thd->protocol->flush(); DBUG_VOID_RETURN; } @@ -1194,13 +1195,11 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) if (store_create_info(thd, table, packet)) DBUG_RETURN(-1); - //if (protocol->convert) - // protocol->convert->convert((char*) packet->ptr(), packet->length()); if (fd < 0) { if (protocol->write()) DBUG_RETURN(-1); - net_flush(&thd->net); + protocol->flush(); } else { @@ -1436,9 +1435,10 @@ store_create_info(THD *thd, TABLE *table, String *packet) if (type.length()) { String def_val; + uint dummy_errors; /* convert to system_charset_info == utf8 */ def_val.copy(type.ptr(), type.length(), field->charset(), - system_charset_info); + system_charset_info, &dummy_errors); append_unescaped(packet, def_val.ptr(), def_val.length()); } else diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 7d0dd3ca566..69b530911f4 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -121,12 +121,13 @@ bool String::set(ulonglong num, CHARSET_INFO *cs) bool String::set(double num,uint decimals, CHARSET_INFO *cs) { char buff[331]; + uint dummy_errors; str_charset=cs; if (decimals >= NOT_FIXED_DEC) { uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME - return copy(buff, len, &my_charset_latin1, cs); + return copy(buff, len, &my_charset_latin1, cs, &dummy_errors); } #ifdef HAVE_FCONVERT int decpt,sign; @@ -141,7 +142,8 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs) buff[0]='-'; pos=buff; } - return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs); + uint dummy_errors; + return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs, &dummy_errors); } if (alloc((uint32) ((uint32) decpt+3+decimals))) return TRUE; @@ -191,7 +193,8 @@ end: #else sprintf(buff,"%.*f",(int) decimals,num); #endif - return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs); + return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs, + &dummy_errors); #endif } @@ -336,14 +339,12 @@ bool String::copy(const char *str, uint32 arg_length, uint32 offset; if (!needs_conversion(arg_length, from_cs, to_cs, &offset)) { - if (errors) - *errors= 0; + *errors= 0; return copy(str, arg_length, to_cs); } if ((from_cs == &my_charset_bin) && offset) { - if (errors) - *errors= 0; + *errors= 0; return copy_aligned(str, arg_length, offset, to_cs); } uint32 new_length= to_cs->mbmaxlen*arg_length; @@ -382,7 +383,8 @@ bool String::set_ascii(const char *str, uint32 arg_length) set(str, arg_length, str_charset); return 0; } - return copy(str, arg_length, &my_charset_latin1, str_charset); + uint dummy_errors; + return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors); } @@ -436,10 +438,12 @@ bool String::append(const char *s,uint32 arg_length) if (str_charset->mbminlen > 1) { uint32 add_length=arg_length * str_charset->mbmaxlen; + uint dummy_errors; if (realloc(str_length+ add_length)) return TRUE; str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset, - s, arg_length, &my_charset_latin1); + s, arg_length, &my_charset_latin1, + &dummy_errors); return FALSE; } @@ -476,10 +480,11 @@ bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs) if (needs_conversion(arg_length, cs, str_charset, &dummy_offset)) { uint32 add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen; + uint dummy_errors; if (realloc(str_length + add_length)) return TRUE; str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset, - s, arg_length, cs); + s, arg_length, cs, &dummy_errors); } else { @@ -829,8 +834,7 @@ outp: else break; } - if (errors) - *errors= error_count; + *errors= error_count; return (uint32) (to - to_start); } diff --git a/sql/sql_string.h b/sql/sql_string.h index d6807fa83ad..cb5b1fb25fd 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -29,7 +29,7 @@ int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, const char *from, uint32 from_length, - CHARSET_INFO *from_cs, uint *errors= 0); + CHARSET_INFO *from_cs, uint *errors); class String { @@ -199,7 +199,7 @@ public: CHARSET_INFO *cs); bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, - CHARSET_INFO *csto, uint *errors= 0); + CHARSET_INFO *csto, uint *errors); bool append(const String &s); bool append(const char *s); bool append(const char *s,uint32 arg_length); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 26c483a61a8..f4f9841ead3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1740,6 +1740,12 @@ end: } +/* + RETURN VALUES + 0 Message sent to net (admin operation went ok) + -1 Message should be sent by caller + (admin operation or network communication failed) +*/ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt, const char *operator_name, @@ -1787,9 +1793,13 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, if (prepare_func) { switch ((*prepare_func)(thd, table, check_opt)) { - case 1: continue; // error, message written to net - case -1: goto err; // error, message could be written to net - default: ; // should be 0 otherwise + case 1: // error, message written to net + close_thread_tables(thd); + continue; + case -1: // error, message could be written to net + goto err; + default: // should be 0 otherwise + ; } } diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc index fa678ec7de2..0df60858bcb 100644 --- a/sql/thr_malloc.cc +++ b/sql/thr_malloc.cc @@ -108,8 +108,11 @@ char *sql_strmake_with_convert(const char *str, uint32 arg_length, memcpy(pos, str, new_length); } else + { + uint dummy_errors; new_length= copy_and_convert((char*) pos, new_length, to_cs, str, - arg_length, from_cs); + arg_length, from_cs, &dummy_errors); + } pos[new_length]= 0; *result_length= new_length; return pos; diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 4176ff2e538..a8b5394f8c5 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4581,14 +4581,19 @@ uint my_well_formed_len_sjis(CHARSET_INFO *cs __attribute__((unused)), */ if (((int8)b[0]) >= 0) { - /* Single byte character */ - b+= 1; + /* Single byte ascii character */ + b++; } else if (issjishead((uchar)*b) && (e-b)>1 && issjistail((uchar)b[1])) { /* Double byte character */ b+= 2; } + else if (((uchar)*b) >= 0xA1 && ((uchar)*b) <= 0xDF) + { + /* Half width kana */ + b++; + } else { /* Wrong byte sequence */ diff --git a/tests/client_test.c b/tests/client_test.c index 0ef8bd1ea66..ae80478c3c5 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 MySQL AB +/* Copyright (C) 2003-2004 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,6 +27,7 @@ #include <my_getopt.h> #include <m_string.h> +#define VER "2.0" #define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */ #define MAX_KEY 64 @@ -38,7 +39,7 @@ static char *opt_password= 0; static char *opt_host= 0; static char *opt_unix_socket= 0; static unsigned int opt_port; -static my_bool tty_password= 0; +static my_bool tty_password= 0, opt_silent= 0; static MYSQL *mysql= 0; static char query[MAX_TEST_QUERY_LENGTH]; @@ -53,6 +54,7 @@ static double total_time; const char *default_dbug_option= "d:t:o,/tmp/client_test.trace"; #define myheader(str) \ +if (opt_silent < 2) \ { \ fprintf(stdout, "\n\n#####################################\n"); \ fprintf(stdout, "%d of (%d/%d): %s", test_count++, iter_count, \ @@ -60,6 +62,7 @@ const char *default_dbug_option= "d:t:o,/tmp/client_test.trace"; fprintf(stdout, " \n#####################################\n"); \ } #define myheader_r(str) \ +if (!opt_silent) \ { \ fprintf(stdout, "\n\n#####################################\n"); \ fprintf(stdout, "%s", str); \ @@ -145,32 +148,39 @@ DIE_UNLESS(stmt == 0);\ static void print_error(const char *msg) { - if (mysql && mysql_errno(mysql)) + if (!opt_silent) { - if (mysql->server_version) - fprintf(stdout, "\n [MySQL-%s]", mysql->server_version); - else - fprintf(stdout, "\n [MySQL]"); - fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql)); + if (mysql && mysql_errno(mysql)) + { + if (mysql->server_version) + fprintf(stdout, "\n [MySQL-%s]", mysql->server_version); + else + fprintf(stdout, "\n [MySQL]"); + fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql)); + } + else if (msg) + fprintf(stderr, " [MySQL] %s\n", msg); } - else if (msg) fprintf(stderr, " [MySQL] %s\n", msg); } static void print_st_error(MYSQL_STMT *stmt, const char *msg) { - if (stmt && mysql_stmt_errno(stmt)) + if (!opt_silent) { - if (stmt->mysql && stmt->mysql->server_version) - fprintf(stdout, "\n [MySQL-%s]", stmt->mysql->server_version); - else - fprintf(stdout, "\n [MySQL]"); + if (stmt && mysql_stmt_errno(stmt)) + { + if (stmt->mysql && stmt->mysql->server_version) + fprintf(stdout, "\n [MySQL-%s]", stmt->mysql->server_version); + else + fprintf(stdout, "\n [MySQL]"); - fprintf(stdout, "[%d] %s\n", mysql_stmt_errno(stmt), - mysql_stmt_error(stmt)); + fprintf(stdout, "[%d] %s\n", mysql_stmt_errno(stmt), + mysql_stmt_error(stmt)); + } + else if (msg) + fprintf(stderr, " [MySQL] %s\n", msg); } - else if (msg) - fprintf(stderr, " [MySQL] %s\n", msg); } @@ -199,8 +209,9 @@ static void client_connect() int rc; myheader_r("client_connect"); - fprintf(stdout, "\n Establishing a connection to '%s' ...", - opt_host ? opt_host : ""); + if (!opt_silent) + fprintf(stdout, "\n Establishing a connection to '%s' ...", + opt_host ? opt_host : ""); if (!(mysql= mysql_init(NULL))) { @@ -218,12 +229,14 @@ static void client_connect() exit(1); } - fprintf(stdout, " OK"); + if (!opt_silent) + fprintf(stdout, " OK"); /* set AUTOCOMMIT to ON*/ mysql_autocommit(mysql, TRUE); - fprintf(stdout, "\n Creating a test database '%s' ...", current_db); + if (!opt_silent) + fprintf(stdout, "\n Creating a test database '%s' ...", current_db); strxmov(query, "CREATE DATABASE IF NOT EXISTS ", current_db, NullS); rc= mysql_query(mysql, query); @@ -233,7 +246,8 @@ static void client_connect() rc= mysql_query(mysql, query); myquery(rc); - fprintf(stdout, " OK"); + if (!opt_silent) + fprintf(stdout, " OK"); } @@ -245,13 +259,16 @@ static void client_disconnect() if (mysql) { - fprintf(stdout, "\n dropping the test database '%s' ...", current_db); + if (!opt_silent) + fprintf(stdout, "\n dropping the test database '%s' ...", current_db); strxmov(query, "DROP DATABASE IF EXISTS ", current_db, NullS); mysql_query(mysql, query); - fprintf(stdout, " OK"); + if (!opt_silent) + fprintf(stdout, " OK"); - fprintf(stdout, "\n closing the connection ..."); + if (!opt_silent) + fprintf(stdout, "\n closing the connection ..."); mysql_close(mysql); fprintf(stdout, " OK\n"); } @@ -332,8 +349,11 @@ static void my_print_result_metadata(MYSQL_RES *result) unsigned int field_count; mysql_field_seek(result, 0); - fputc('\n', stdout); - fputc('\n', stdout); + if (!opt_silent) + { + fputc('\n', stdout); + fputc('\n', stdout); + } field_count= mysql_num_fields(result); for(i= 0; i< field_count; i++) @@ -346,18 +366,25 @@ static void my_print_result_metadata(MYSQL_RES *result) j= 4; field->max_length= j; } - my_print_dashes(result); - fputc('\t', stdout); - fputc('|', stdout); + if (!opt_silent) + { + my_print_dashes(result); + fputc('\t', stdout); + fputc('|', stdout); + } mysql_field_seek(result, 0); for(i= 0; i< field_count; i++) { field= mysql_fetch_field(result); - fprintf(stdout, " %-*s |", (int) field->max_length, field->name); + if (!opt_silent) + fprintf(stdout, " %-*s |", (int) field->max_length, field->name); + } + if (!opt_silent) + { + fputc('\n', stdout); + my_print_dashes(result); } - fputc('\n', stdout); - my_print_dashes(result); } @@ -378,31 +405,43 @@ int my_process_result_set(MYSQL_RES *result) while ((row= mysql_fetch_row(result)) != NULL) { mysql_field_seek(result, 0); - fputc('\t', stdout); - fputc('|', stdout); + if (!opt_silent) + { + fputc('\t', stdout); + fputc('|', stdout); + } for(i= 0; i< mysql_num_fields(result); i++) { field= mysql_fetch_field(result); - if (row[i] == NULL) - fprintf(stdout, " %-*s |", (int) field->max_length, "NULL"); - else if (IS_NUM(field->type)) - fprintf(stdout, " %*s |", (int) field->max_length, row[i]); - else - fprintf(stdout, " %-*s |", (int) field->max_length, row[i]); + if (!opt_silent) + { + if (row[i] == NULL) + fprintf(stdout, " %-*s |", (int) field->max_length, "NULL"); + else if (IS_NUM(field->type)) + fprintf(stdout, " %*s |", (int) field->max_length, row[i]); + else + fprintf(stdout, " %-*s |", (int) field->max_length, row[i]); + } + } + if (!opt_silent) + { + fputc('\t', stdout); + fputc('\n', stdout); } - fputc('\t', stdout); - fputc('\n', stdout); row_count++; } - if (row_count) - my_print_dashes(result); + if (!opt_silent) + { + if (row_count) + my_print_dashes(result); - if (mysql_errno(mysql) != 0) - fprintf(stderr, "\n\tmysql_fetch_row() failed\n"); - else - fprintf(stdout, "\n\t%d %s returned\n", row_count, - row_count == 1 ? "row" : "rows"); + if (mysql_errno(mysql) != 0) + fprintf(stderr, "\n\tmysql_fetch_row() failed\n"); + else + fprintf(stdout, "\n\t%d %s returned\n", row_count, + row_count == 1 ? "row" : "rows"); + } return row_count; } @@ -471,34 +510,44 @@ int my_process_stmt_result(MYSQL_STMT *stmt) mysql_field_seek(result, 0); while (mysql_stmt_fetch(stmt) == 0) { - fputc('\t', stdout); - fputc('|', stdout); - + if (!opt_silent) + { + fputc('\t', stdout); + fputc('|', stdout); + } mysql_field_seek(result, 0); for (i= 0; i < field_count; i++) { field= mysql_fetch_field(result); - if (is_null[i]) - fprintf(stdout, " %-*s |", (int) field->max_length, "NULL"); - else if (length[i] == 0) + if (!opt_silent) { - data[i][0]= '\0'; /* unmodified buffer */ - fprintf(stdout, " %*s |", (int) field->max_length, data[i]); + if (is_null[i]) + fprintf(stdout, " %-*s |", (int) field->max_length, "NULL"); + else if (length[i] == 0) + { + data[i][0]= '\0'; /* unmodified buffer */ + fprintf(stdout, " %*s |", (int) field->max_length, data[i]); + } + else if (IS_NUM(field->type)) + fprintf(stdout, " %*s |", (int) field->max_length, data[i]); + else + fprintf(stdout, " %-*s |", (int) field->max_length, data[i]); } - else if (IS_NUM(field->type)) - fprintf(stdout, " %*s |", (int) field->max_length, data[i]); - else - fprintf(stdout, " %-*s |", (int) field->max_length, data[i]); } - fputc('\t', stdout); - fputc('\n', stdout); + if (!opt_silent) + { + fputc('\t', stdout); + fputc('\n', stdout); + } row_count++; } - if (row_count) - my_print_dashes(result); - - fprintf(stdout, "\n\t%d %s returned\n", row_count, - row_count == 1 ? "row" : "rows"); + if (!opt_silent) + { + if (row_count) + my_print_dashes(result); + fprintf(stdout, "\n\t%d %s returned\n", row_count, + row_count == 1 ? "row" : "rows"); + } mysql_free_result(result); return row_count; } @@ -512,7 +561,8 @@ int my_stmt_result(const char *buff) int row_count; int rc; - fprintf(stdout, "\n\n %s", buff); + if (!opt_silent) + fprintf(stdout, "\n\n %s", buff); stmt= mysql_simple_prepare(mysql, buff); check_stmt(stmt); @@ -538,7 +588,8 @@ static void verify_col_data(const char *table, const char *col, if (table && col) { strxmov(query, "SELECT ", col, " FROM ", table, " LIMIT 1", NullS); - fprintf(stdout, "\n %s", query); + if (!opt_silent) + fprintf(stdout, "\n %s", query); rc= mysql_query(mysql, query); myquery(rc); @@ -566,10 +617,12 @@ static void verify_col_data(const char *table, const char *col, /* Utility function to verify the field members */ static void verify_prepare_field(MYSQL_RES *result, - unsigned int no, const char *name, const char *org_name, - enum enum_field_types type, const char *table, - const char *org_table, const char *db, - unsigned long length, const char *def) + unsigned int no, const char *name, + const char *org_name, + enum enum_field_types type, + const char *table, + const char *org_table, const char *db, + unsigned long length, const char *def) { MYSQL_FIELD *field; @@ -578,23 +631,26 @@ static void verify_prepare_field(MYSQL_RES *result, fprintf(stdout, "\n *** ERROR: FAILED TO GET THE RESULT ***"); exit(1); } - fprintf(stdout, "\n field[%d]:", no); - fprintf(stdout, "\n name :`%s`\t(expected: `%s`)", field->name, name); - fprintf(stdout, "\n org_name :`%s`\t(expected: `%s`)", - field->org_name, org_name); - fprintf(stdout, "\n type :`%d`\t(expected: `%d`)", field->type, type); - fprintf(stdout, "\n table :`%s`\t(expected: `%s`)", - field->table, table); - fprintf(stdout, "\n org_table:`%s`\t(expected: `%s`)", - field->org_table, org_table); - fprintf(stdout, "\n database :`%s`\t(expected: `%s`)", field->db, db); - fprintf(stdout, "\n length :`%ld`\t(expected: `%ld`)", - field->length, length); - fprintf(stdout, "\n maxlength:`%ld`", field->max_length); - fprintf(stdout, "\n charsetnr:`%d`", field->charsetnr); - fprintf(stdout, "\n default :`%s`\t(expected: `%s`)", - field->def ? field->def : "(null)", def ? def: "(null)"); - fprintf(stdout, "\n"); + if (!opt_silent) + { + fprintf(stdout, "\n field[%d]:", no); + fprintf(stdout, "\n name :`%s`\t(expected: `%s`)", field->name, name); + fprintf(stdout, "\n org_name :`%s`\t(expected: `%s`)", + field->org_name, org_name); + fprintf(stdout, "\n type :`%d`\t(expected: `%d`)", field->type, type); + fprintf(stdout, "\n table :`%s`\t(expected: `%s`)", + field->table, table); + fprintf(stdout, "\n org_table:`%s`\t(expected: `%s`)", + field->org_table, org_table); + fprintf(stdout, "\n database :`%s`\t(expected: `%s`)", field->db, db); + fprintf(stdout, "\n length :`%ld`\t(expected: `%ld`)", + field->length, length); + fprintf(stdout, "\n maxlength:`%ld`", field->max_length); + fprintf(stdout, "\n charsetnr:`%d`", field->charsetnr); + fprintf(stdout, "\n default :`%s`\t(expected: `%s`)", + field->def ? field->def : "(null)", def ? def: "(null)"); + fprintf(stdout, "\n"); + } DIE_UNLESS(strcmp(field->name, name) == 0); DIE_UNLESS(strcmp(field->org_name, org_name) == 0); DIE_UNLESS(field->type == type); @@ -612,8 +668,9 @@ static void verify_prepare_field(MYSQL_RES *result, static void verify_param_count(MYSQL_STMT *stmt, long exp_count) { long param_count= mysql_stmt_param_count(stmt); - fprintf(stdout, "\n total parameters in stmt: `%ld` (expected: `%ld`)", - param_count, exp_count); + if (!opt_silent) + fprintf(stdout, "\n total parameters in stmt: `%ld` (expected: `%ld`)", + param_count, exp_count); DIE_UNLESS(param_count == exp_count); } @@ -623,8 +680,9 @@ static void verify_param_count(MYSQL_STMT *stmt, long exp_count) static void verify_st_affected_rows(MYSQL_STMT *stmt, ulonglong exp_count) { ulonglong affected_rows= mysql_stmt_affected_rows(stmt); - fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)", - affected_rows, exp_count); + if (!opt_silent) + fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)", + affected_rows, exp_count); DIE_UNLESS(affected_rows == exp_count); } @@ -634,7 +692,8 @@ static void verify_st_affected_rows(MYSQL_STMT *stmt, ulonglong exp_count) static void verify_affected_rows(ulonglong exp_count) { ulonglong affected_rows= mysql_affected_rows(mysql); - fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)", + if (!opt_silent) + fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)", affected_rows, exp_count); DIE_UNLESS(affected_rows == exp_count); } @@ -645,8 +704,9 @@ static void verify_affected_rows(ulonglong exp_count) static void verify_field_count(MYSQL_RES *result, uint exp_count) { uint field_count= mysql_num_fields(result); - fprintf(stdout, "\n total fields in the result set: `%d` (expected: `%d`)", - field_count, exp_count); + if (!opt_silent) + fprintf(stdout, "\n total fields in the result set: `%d` (expected: `%d`)", + field_count, exp_count); DIE_UNLESS(field_count == exp_count); } @@ -666,8 +726,9 @@ static void execute_prepare_query(const char *query, ulonglong exp_count) myquery(rc); affected_rows= mysql_stmt_affected_rows(stmt); - fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)", - affected_rows, exp_count); + if (!opt_silent) + fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)", + affected_rows, exp_count); DIE_UNLESS(affected_rows == exp_count); mysql_stmt_close(stmt); @@ -722,6 +783,7 @@ static void client_use_result() void fill_tables(const char **query_list, unsigned query_count) { + DBUG_ENTER("fill_tables"); int rc; const char **query; for (query= query_list; query < query_list + query_count; @@ -730,6 +792,7 @@ void fill_tables(const char **query_list, unsigned query_count) rc= mysql_query(mysql, *query); myquery(rc); } + DBUG_VOID_RETURN; } /* @@ -766,6 +829,7 @@ void stmt_fetch_init(Stmt_fetch *fetch, unsigned stmt_no_arg, int rc; unsigned i; MYSQL_RES *metadata; + DBUG_ENTER("stmt_fetch_init"); /* Save query and statement number for error messages */ fetch->stmt_no= stmt_no_arg; @@ -817,6 +881,7 @@ void stmt_fetch_init(Stmt_fetch *fetch, unsigned stmt_no_arg, fetch->is_open= TRUE; /* Ready for reading rows */ + DBUG_VOID_RETURN; } @@ -826,26 +891,30 @@ int stmt_fetch_fetch_row(Stmt_fetch *fetch) { int rc; unsigned i; + DBUG_ENTER("stmt_fetch_fetch_row"); if ((rc= mysql_stmt_fetch(fetch->handle)) == 0) { ++fetch->row_count; - printf("Stmt %d fetched row %d:\n", fetch->stmt_no, fetch->row_count); + if (!opt_silent) + printf("Stmt %d fetched row %d:\n", fetch->stmt_no, fetch->row_count); for (i= 0; i < fetch->column_count; ++i) { fetch->out_data[i][fetch->out_data_length[i]]= '\0'; - printf("column %d: %s\n", i+1, fetch->out_data[i]); + if (!opt_silent) + printf("column %d: %s\n", i+1, fetch->out_data[i]); } } else fetch->is_open= FALSE; - return rc; + DBUG_RETURN(rc); } void stmt_fetch_close(Stmt_fetch *fetch) { unsigned i; + DBUG_ENTER("stmt_fetch_close"); for (i= 0; i < fetch->column_count; ++i) free(fetch->out_data[i]); @@ -853,6 +922,7 @@ void stmt_fetch_close(Stmt_fetch *fetch) free(fetch->out_data_length); free(fetch->bind_array); mysql_stmt_close(fetch->handle); + DBUG_VOID_RETURN; } /* @@ -862,13 +932,14 @@ void stmt_fetch_close(Stmt_fetch *fetch) reading from the rest. */ -bool fetch_n(const char **query_list, unsigned query_count) +my_bool fetch_n(const char **query_list, unsigned query_count) { unsigned open_statements= query_count; int rc, error_count= 0; Stmt_fetch *fetch_array= (Stmt_fetch*) calloc(1, sizeof(Stmt_fetch) * query_count); Stmt_fetch *fetch; + DBUG_ENTER("fetch_n"); for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch) { @@ -883,7 +954,7 @@ bool fetch_n(const char **query_list, unsigned query_count) { if (fetch->is_open && (rc= stmt_fetch_fetch_row(fetch))) { - --open_statements; + open_statements--; /* We try to fetch from the rest of the statements in case of error @@ -895,7 +966,7 @@ bool fetch_n(const char **query_list, unsigned query_count) "query is: %s,\n" "error message: %s", fetch - fetch_array, fetch->query, mysql_stmt_error(fetch->handle)); - ++error_count; + error_count++; } } } @@ -907,12 +978,13 @@ bool fetch_n(const char **query_list, unsigned query_count) unsigned total_row_count= 0; for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch) total_row_count+= fetch->row_count; - printf("Success, total rows fetched: %d\n", total_row_count); + if (!opt_silent) + printf("Success, total rows fetched: %d\n", total_row_count); } for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch) stmt_fetch_close(fetch); free(fetch_array); - return error_count != 0; + DBUG_RETURN(error_count != 0); } /* Separate thread query to test some cases */ @@ -923,7 +995,8 @@ static my_bool thread_query(char *query) my_bool error; error= 0; - fprintf(stdout, "\n in thread_query(%s)", query); + if (!opt_silent) + fprintf(stdout, "\n in thread_query(%s)", query); if (!(l_mysql= mysql_init(NULL))) { myerror("mysql_init() failed"); @@ -1234,7 +1307,8 @@ static void test_prepare_field_result() my_print_result_metadata(result); - fprintf(stdout, "\n\n field attributes:\n"); + if (!opt_silent) + fprintf(stdout, "\n\n field attributes:\n"); verify_prepare_field(result, 0, "int_c", "int_c", MYSQL_TYPE_LONG, "t1", "test_prepare_field_result", current_db, 11, 0); verify_prepare_field(result, 1, "var_c", "var_c", MYSQL_TYPE_VAR_STRING, @@ -1408,17 +1482,19 @@ static void test_prepare() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n"); - - fprintf(stdout, "\n\t tiny : %d (%lu)", tiny_data, length[0]); - fprintf(stdout, "\n\t short : %d (%lu)", small_data, length[3]); - fprintf(stdout, "\n\t int : %d (%lu)", int_data, length[2]); - fprintf(stdout, "\n\t big : %lld (%lu)", big_data, length[4]); + if (!opt_silent) + { + fprintf(stdout, "\n"); + fprintf(stdout, "\n\t tiny : %d (%lu)", tiny_data, length[0]); + fprintf(stdout, "\n\t short : %d (%lu)", small_data, length[3]); + fprintf(stdout, "\n\t int : %d (%lu)", int_data, length[2]); + fprintf(stdout, "\n\t big : %lld (%lu)", big_data, length[4]); - fprintf(stdout, "\n\t float : %f (%lu)", real_data, length[5]); - fprintf(stdout, "\n\t double : %f (%lu)", double_data, length[6]); + fprintf(stdout, "\n\t float : %f (%lu)", real_data, length[5]); + fprintf(stdout, "\n\t double : %f (%lu)", double_data, length[6]); - fprintf(stdout, "\n\t str : %s (%lu)", str_data, length[1]); + fprintf(stdout, "\n\t str : %s (%lu)", str_data, length[1]); + } DIE_UNLESS(tiny_data == o_tiny_data); DIE_UNLESS(is_null[0] == 0); @@ -1779,11 +1855,13 @@ static void test_fetch_null() rc++; for (i= 0; i < 10; i++) { - fprintf(stdout, "\n data[%d] : %s", i, - is_null[i] ? "NULL" : "NOT NULL"); + if (!opt_silent) + fprintf(stdout, "\n data[%d] : %s", i, + is_null[i] ? "NULL" : "NOT NULL"); DIE_UNLESS(is_null[i]); } - fprintf(stdout, "\n data[%d]: %d", i, nData); + if (!opt_silent) + fprintf(stdout, "\n data[%d]: %d", i, nData); DIE_UNLESS(nData == 1000 || nData == 88 || nData == 389789); DIE_UNLESS(is_null[i] == 0); DIE_UNLESS(length[i] == 4); @@ -2568,7 +2646,8 @@ static void test_long_data() /* execute */ rc= mysql_stmt_execute(stmt); - fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc); + if (!opt_silent) + fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc); check_execute(stmt, rc); rc= mysql_commit(mysql); @@ -2651,7 +2730,8 @@ static void test_long_data_str() } /* execute */ rc= mysql_stmt_execute(stmt); - fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc); + if (!opt_silent) + fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc); check_execute(stmt, rc); mysql_stmt_close(stmt); @@ -2742,7 +2822,8 @@ static void test_long_data_str1() /* execute */ rc= mysql_stmt_execute(stmt); - fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc); + if (!opt_silent) + fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc); check_execute(stmt, rc); mysql_stmt_close(stmt); @@ -2893,7 +2974,8 @@ static void test_long_data_bin() } /* execute */ rc= mysql_stmt_execute(stmt); - fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc); + if (!opt_silent) + fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc); check_execute(stmt, rc); mysql_stmt_close(stmt); @@ -3200,7 +3282,8 @@ static void test_bind_result() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 1: %d, %s(%lu)", nData, szData, length1); + if (!opt_silent) + fprintf(stdout, "\n row 1: %d, %s(%lu)", nData, szData, length1); DIE_UNLESS(nData == 10); DIE_UNLESS(strcmp(szData, "venu") == 0); DIE_UNLESS(length1 == 4); @@ -3208,7 +3291,8 @@ static void test_bind_result() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 2: %d, %s(%lu)", nData, szData, length1); + if (!opt_silent) + fprintf(stdout, "\n row 2: %d, %s(%lu)", nData, szData, length1); DIE_UNLESS(nData == 20); DIE_UNLESS(strcmp(szData, "MySQL") == 0); DIE_UNLESS(length1 == 5); @@ -3217,7 +3301,7 @@ static void test_bind_result() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - if (is_null[0]) + if (!opt_silent && is_null[0]) fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1); DIE_UNLESS(is_null[0]); DIE_UNLESS(strcmp(szData, "monty") == 0); @@ -3315,19 +3399,21 @@ static void test_bind_result_ext() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n data (tiny) : %d", t_data); - fprintf(stdout, "\n data (short) : %d", s_data); - fprintf(stdout, "\n data (int) : %d", i_data); - fprintf(stdout, "\n data (big) : %lld", b_data); - - fprintf(stdout, "\n data (float) : %f", f_data); - fprintf(stdout, "\n data (double) : %f", d_data); + if (!opt_silent) + { + fprintf(stdout, "\n data (tiny) : %d", t_data); + fprintf(stdout, "\n data (short) : %d", s_data); + fprintf(stdout, "\n data (int) : %d", i_data); + fprintf(stdout, "\n data (big) : %lld", b_data); - fprintf(stdout, "\n data (str) : %s(%lu)", szData, szLength); + fprintf(stdout, "\n data (float) : %f", f_data); + fprintf(stdout, "\n data (double) : %f", d_data); - bData[bLength]= '\0'; /* bData is binary */ - fprintf(stdout, "\n data (bin) : %s(%lu)", bData, bLength); + fprintf(stdout, "\n data (str) : %s(%lu)", szData, szLength); + bData[bLength]= '\0'; /* bData is binary */ + fprintf(stdout, "\n data (bin) : %s(%lu)", bData, bLength); + } DIE_UNLESS(t_data == 19); DIE_UNLESS(s_data == 2999); @@ -3435,16 +3521,19 @@ static void test_bind_result_ext1() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n data (tiny) : %s(%lu)", t_data, length[0]); - fprintf(stdout, "\n data (short) : %f(%lu)", s_data, length[1]); - fprintf(stdout, "\n data (int) : %d(%lu)", i_data, length[2]); - fprintf(stdout, "\n data (big) : %d(%lu)", b_data, length[3]); + if (!opt_silent) + { + fprintf(stdout, "\n data (tiny) : %s(%lu)", t_data, length[0]); + fprintf(stdout, "\n data (short) : %f(%lu)", s_data, length[1]); + fprintf(stdout, "\n data (int) : %d(%lu)", i_data, length[2]); + fprintf(stdout, "\n data (big) : %d(%lu)", b_data, length[3]); - fprintf(stdout, "\n data (float) : %d(%lu)", f_data, length[4]); - fprintf(stdout, "\n data (double) : %s(%lu)", d_data, length[5]); + fprintf(stdout, "\n data (float) : %d(%lu)", f_data, length[4]); + fprintf(stdout, "\n data (double) : %s(%lu)", d_data, length[5]); - fprintf(stdout, "\n data (bin) : %ld(%lu)", bData, length[6]); - fprintf(stdout, "\n data (str) : %g(%lu)", szData, length[7]); + fprintf(stdout, "\n data (bin) : %ld(%lu)", bData, length[6]); + fprintf(stdout, "\n data (str) : %g(%lu)", szData, length[7]); + } DIE_UNLESS(strcmp(t_data, "120") == 0); DIE_UNLESS(i_data == 3999); @@ -3569,15 +3658,17 @@ static void bind_fetch(int row_count) rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n"); - fprintf(stdout, "\n tiny : %ld(%lu)", (ulong) i8_data, length[0]); - fprintf(stdout, "\n short : %ld(%lu)", (ulong) i16_data, length[1]); - fprintf(stdout, "\n int : %ld(%lu)", (ulong) i32_data, length[2]); - fprintf(stdout, "\n longlong : %ld(%lu)", (ulong) i64_data, length[3]); - fprintf(stdout, "\n float : %f(%lu)", f_data, length[4]); - fprintf(stdout, "\n double : %g(%lu)", d_data, length[5]); - fprintf(stdout, "\n char : %s(%lu)", s_data, length[6]); - + if (!opt_silent) + { + fprintf(stdout, "\n"); + fprintf(stdout, "\n tiny : %ld(%lu)", (ulong) i8_data, length[0]); + fprintf(stdout, "\n short : %ld(%lu)", (ulong) i16_data, length[1]); + fprintf(stdout, "\n int : %ld(%lu)", (ulong) i32_data, length[2]); + fprintf(stdout, "\n longlong : %ld(%lu)", (ulong) i64_data, length[3]); + fprintf(stdout, "\n float : %f(%lu)", f_data, length[4]); + fprintf(stdout, "\n double : %g(%lu)", d_data, length[5]); + fprintf(stdout, "\n char : %s(%lu)", s_data, length[6]); + } rc= 10+row_count; /* TINY */ @@ -3719,13 +3810,16 @@ static void test_fetch_date() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n date : %s(%lu)", date, d_length); - fprintf(stdout, "\n time : %s(%lu)", time, t_length); - fprintf(stdout, "\n ts : %s(%lu)", ts, ts_length); - fprintf(stdout, "\n year : %d(%lu)", year, y_length); - fprintf(stdout, "\n dt : %s(%lu)", dt, dt_length); - fprintf(stdout, "\n ts(4) : %s(%lu)", ts_4, ts4_length); - fprintf(stdout, "\n ts(6) : %s(%lu)", ts_6, ts6_length); + if (!opt_silent) + { + fprintf(stdout, "\n date : %s(%lu)", date, d_length); + fprintf(stdout, "\n time : %s(%lu)", time, t_length); + fprintf(stdout, "\n ts : %s(%lu)", ts, ts_length); + fprintf(stdout, "\n year : %d(%lu)", year, y_length); + fprintf(stdout, "\n dt : %s(%lu)", dt, dt_length); + fprintf(stdout, "\n ts(4) : %s(%lu)", ts_4, ts4_length); + fprintf(stdout, "\n ts(6) : %s(%lu)", ts_6, ts6_length); + } DIE_UNLESS(strcmp(date, "2002-01-02") == 0); DIE_UNLESS(d_length == 10); @@ -4052,7 +4146,8 @@ static void test_field_names() myheader("test_field_names"); - fprintf(stdout, "\n %d, %d, %d", MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NEWDATE, MYSQL_TYPE_ENUM); + if (!opt_silent) + fprintf(stdout, "\n %d, %d, %d", MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NEWDATE, MYSQL_TYPE_ENUM); rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_names1"); myquery(rc); @@ -4103,7 +4198,8 @@ static void test_warnings() rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists"); myquery(rc); - fprintf(stdout, "\n total warnings: %d", mysql_warning_count(mysql)); + if (!opt_silent) + fprintf(stdout, "\n total warnings: %d", mysql_warning_count(mysql)); rc= mysql_query(mysql, "SHOW WARNINGS"); myquery(rc); @@ -4285,23 +4381,27 @@ static void test_field_flags() mytest(result); mysql_field_seek(result, 0); - fputc('\n', stdout); + if (!opt_silent) + fputc('\n', stdout); for(i= 0; i< mysql_num_fields(result); i++) { field= mysql_fetch_field(result); - fprintf(stdout, "\n field:%d", i); - if (field->flags & NOT_NULL_FLAG) - fprintf(stdout, "\n NOT_NULL_FLAG"); - if (field->flags & PRI_KEY_FLAG) - fprintf(stdout, "\n PRI_KEY_FLAG"); - if (field->flags & UNIQUE_KEY_FLAG) - fprintf(stdout, "\n UNIQUE_KEY_FLAG"); - if (field->flags & MULTIPLE_KEY_FLAG) - fprintf(stdout, "\n MULTIPLE_KEY_FLAG"); - if (field->flags & AUTO_INCREMENT_FLAG) - fprintf(stdout, "\n AUTO_INCREMENT_FLAG"); + if (!opt_silent) + { + fprintf(stdout, "\n field:%d", i); + if (field->flags & NOT_NULL_FLAG) + fprintf(stdout, "\n NOT_NULL_FLAG"); + if (field->flags & PRI_KEY_FLAG) + fprintf(stdout, "\n PRI_KEY_FLAG"); + if (field->flags & UNIQUE_KEY_FLAG) + fprintf(stdout, "\n UNIQUE_KEY_FLAG"); + if (field->flags & MULTIPLE_KEY_FLAG) + fprintf(stdout, "\n MULTIPLE_KEY_FLAG"); + if (field->flags & AUTO_INCREMENT_FLAG) + fprintf(stdout, "\n AUTO_INCREMENT_FLAG"); + } } mysql_free_result(result); } @@ -4320,7 +4420,8 @@ static void test_stmt_close() myheader("test_stmt_close"); - fprintf(stdout, "\n Establishing a test connection ..."); + if (!opt_silent) + fprintf(stdout, "\n Establishing a test connection ..."); if (!(lmysql= mysql_init(NULL))) { myerror("mysql_init() failed"); @@ -4333,7 +4434,8 @@ static void test_stmt_close() myerror("connection failed"); exit(1); } - fprintf(stdout, " OK"); + if (!opt_silent) + fprintf(stdout, " OK"); /* set AUTOCOMMIT to ON*/ @@ -4370,7 +4472,8 @@ static void test_stmt_close() verify_param_count(stmt2, 1); rc= mysql_stmt_close(stmt1); - fprintf(stdout, "\n mysql_close_stmt(1) returned: %d", rc); + if (!opt_silent) + fprintf(stdout, "\n mysql_close_stmt(1) returned: %d", rc); DIE_UNLESS(rc == 0); /* @@ -4404,7 +4507,8 @@ static void test_stmt_close() verify_st_affected_rows(stmt_x, 1); rc= mysql_stmt_close(stmt_x); - fprintf(stdout, "\n mysql_close_stmt(x) returned: %d", rc); + if (!opt_silent) + fprintf(stdout, "\n mysql_close_stmt(x) returned: %d", rc); DIE_UNLESS( rc == 0); rc= mysql_query(mysql, "SELECT id FROM test_stmt_close"); @@ -4463,7 +4567,8 @@ static void test_set_variable() rc= mysql_stmt_fetch(stmt1); check_execute(stmt1, rc); - fprintf(stdout, "\n max_error_count(default): %d", get_count); + if (!opt_silent) + fprintf(stdout, "\n max_error_count(default): %d", get_count); def_count= get_count; DIE_UNLESS(strcmp(var, "max_error_count") == 0); @@ -4493,7 +4598,8 @@ static void test_set_variable() rc= mysql_stmt_fetch(stmt1); check_execute(stmt1, rc); - fprintf(stdout, "\n max_error_count : %d", get_count); + if (!opt_silent) + fprintf(stdout, "\n max_error_count : %d", get_count); DIE_UNLESS(get_count == set_count); rc= mysql_stmt_fetch(stmt1); @@ -4510,7 +4616,8 @@ static void test_set_variable() rc= mysql_stmt_fetch(stmt1); check_execute(stmt1, rc); - fprintf(stdout, "\n max_error_count(default): %d", get_count); + if (!opt_silent) + fprintf(stdout, "\n max_error_count(default): %d", get_count); DIE_UNLESS(get_count == set_count); rc= mysql_stmt_fetch(stmt1); @@ -4568,12 +4675,14 @@ static void test_insert_meta() mysql_field_seek(result, 0); field= mysql_fetch_field(result); mytest(field); - fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col1"); + if (!opt_silent) + fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col1"); DIE_UNLESS(strcmp(field->name, "col1") == 0); field= mysql_fetch_field(result); mytest(field); - fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col3"); + if (!opt_silent) + fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col3"); DIE_UNLESS(strcmp(field->name, "col3") == 0); field= mysql_fetch_field(result); @@ -4630,15 +4739,21 @@ static void test_update_meta() mysql_field_seek(result, 0); field= mysql_fetch_field(result); mytest(field); - fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1"); - fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update"); + if (!opt_silent) + { + fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1"); + fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update"); + } DIE_UNLESS(strcmp(field->name, "col1") == 0); DIE_UNLESS(strcmp(field->table, "test_prep_update") == 0); field= mysql_fetch_field(result); mytest(field); - fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col3"); - fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update"); + if (!opt_silent) + { + fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col3"); + fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update"); + } DIE_UNLESS(strcmp(field->name, "col3") == 0); DIE_UNLESS(strcmp(field->table, "test_prep_update") == 0); @@ -4694,15 +4809,21 @@ static void test_select_meta() mysql_field_seek(result, 0); field= mysql_fetch_field(result); mytest(field); - fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1"); - fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select"); + if (!opt_silent) + { + fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1"); + fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select"); + } DIE_UNLESS(strcmp(field->name, "col1") == 0); DIE_UNLESS(strcmp(field->table, "test_prep_select") == 0); field= mysql_fetch_field(result); mytest(field); - fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col2"); - fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select"); + if (!opt_silent) + { + fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col2"); + fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select"); + } DIE_UNLESS(strcmp(field->name, "col2") == 0); DIE_UNLESS(strcmp(field->table, "test_prep_select") == 0); @@ -4746,8 +4867,9 @@ static void test_func_fields() field= mysql_fetch_field(result); mytest(field); - fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table, - "test_dateformat"); + if (!opt_silent) + fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table, + "test_dateformat"); DIE_UNLESS(strcmp(field->table, "test_dateformat") == 0); field= mysql_fetch_field(result); @@ -4764,7 +4886,8 @@ static void test_func_fields() field= mysql_fetch_field(result); mytest(field); - fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table, ""); + if (!opt_silent) + fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table, ""); DIE_UNLESS(field->table[0] == '\0'); field= mysql_fetch_field(result); @@ -4781,8 +4904,11 @@ static void test_func_fields() field= mysql_fetch_field(result); mytest(field); - fprintf(stdout, "\n field name: `%s` (expected: `%s`)", field->name, "YEAR"); - fprintf(stdout, "\n field org name: `%s` (expected: `%s`)", field->org_name, ""); + if (!opt_silent) + { + printf("\n field name: `%s` (expected: `%s`)", field->name, "YEAR"); + printf("\n field org name: `%s` (expected: `%s`)", field->org_name, ""); + } DIE_UNLESS(strcmp(field->name, "YEAR") == 0); DIE_UNLESS(field->org_name[0] == '\0'); @@ -4859,8 +4985,11 @@ static void test_multi_stmt() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n int_data: %lu(%lu)", (ulong) id, length[0]); - fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]); + if (!opt_silent) + { + fprintf(stdout, "\n int_data: %lu(%lu)", (ulong) id, length[0]); + fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]); + } DIE_UNLESS(id == 10); DIE_UNLESS(strcmp(name, "mysql") == 0); @@ -4888,8 +5017,11 @@ static void test_multi_stmt() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n int_data: %lu(%lu)", (ulong) id, length[0]); - fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]); + if (!opt_silent) + { + fprintf(stdout, "\n int_data: %lu(%lu)", (ulong) id, length[0]); + fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]); + } DIE_UNLESS(id == 10); DIE_UNLESS(strcmp(name, "updated") == 0); @@ -4963,12 +5095,14 @@ static void test_manual_sample() fprintf(stderr, "\n %s", mysql_error(mysql)); exit(1); } - fprintf(stdout, "\n prepare, insert successful"); + if (!opt_silent) + fprintf(stdout, "\n prepare, insert successful"); /* Get the parameter count from the statement */ param_count= mysql_stmt_param_count(stmt); - fprintf(stdout, "\n total parameters in insert: %d", param_count); + if (!opt_silent) + fprintf(stdout, "\n total parameters in insert: %d", param_count); if (param_count != 3) /* validate parameter count */ { fprintf(stderr, "\n invalid parameter count returned by MySQL"); @@ -5024,7 +5158,8 @@ static void test_manual_sample() /* Get the total rows affected */ affected_rows= mysql_stmt_affected_rows(stmt); - fprintf(stdout, "\n total affected rows: %lld", affected_rows); + if (!opt_silent) + fprintf(stdout, "\n total affected rows: %lld", affected_rows); if (affected_rows != 1) /* validate affected rows */ { fprintf(stderr, "\n invalid affected rows by MySQL"); @@ -5048,7 +5183,8 @@ static void test_manual_sample() /* Get the total rows affected */ affected_rows= mysql_stmt_affected_rows(stmt); - fprintf(stdout, "\n total affected rows: %lld", affected_rows); + if (!opt_silent) + fprintf(stdout, "\n total affected rows: %lld", affected_rows); if (affected_rows != 1) /* validate affected rows */ { fprintf(stderr, "\n invalid affected rows by MySQL"); @@ -5072,7 +5208,8 @@ static void test_manual_sample() fprintf(stderr, "\n %s", mysql_error(mysql)); exit(1); } - fprintf(stdout, "Success !!!"); + if (!opt_silent) + fprintf(stdout, "Success !!!"); } @@ -5194,13 +5331,14 @@ DROP TABLE IF EXISTS test_multi_tab"; for (count= 0 ; count < array_elements(rows) ; count++) { - fprintf(stdout, "\n Query %d: ", count); + if (!opt_silent) + fprintf(stdout, "\n Query %d: ", count); if ((result= mysql_store_result(mysql_local))) { (void) my_process_result_set(result); mysql_free_result(result); } - else + else if (!opt_silent) fprintf(stdout, "OK, %lld row(s) affected, %d warning(s)\n", mysql_affected_rows(mysql_local), mysql_warning_count(mysql_local)); @@ -5208,7 +5346,7 @@ DROP TABLE IF EXISTS test_multi_tab"; exp_value= (uint) mysql_affected_rows(mysql_local); if (rows[count] != exp_value) { - fprintf(stdout, "row %d had affected rows: %d, should be %d\n", + fprintf(stderr, "row %d had affected rows: %d, should be %d\n", count, exp_value, rows[count]); exit(1); } @@ -5284,7 +5422,7 @@ static void test_prepare_multi_statements() if (!(mysql_local= mysql_init(NULL))) { - fprintf(stdout, "\n mysql_init() failed"); + fprintf(stderr, "\n mysql_init() failed"); exit(1); } @@ -5292,7 +5430,7 @@ static void test_prepare_multi_statements() opt_password, current_db, opt_port, opt_unix_socket, CLIENT_MULTI_STATEMENTS))) { - fprintf(stdout, "\n connection failed(%s)", mysql_error(mysql_local)); + fprintf(stderr, "\n connection failed(%s)", mysql_error(mysql_local)); exit(1); } strmov(query, "select 1; select 'another value'"); @@ -5360,7 +5498,8 @@ static void test_store_result() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 1: %ld, %s(%lu)", (long) nData, szData, length1); + if (!opt_silent) + fprintf(stdout, "\n row 1: %ld, %s(%lu)", (long) nData, szData, length1); DIE_UNLESS(nData == 10); DIE_UNLESS(strcmp(szData, "venu") == 0); DIE_UNLESS(length1 == 4); @@ -5368,7 +5507,8 @@ static void test_store_result() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 2: %ld, %s(%lu)", (long) nData, szData, length1); + if (!opt_silent) + fprintf(stdout, "\n row 2: %ld, %s(%lu)", (long) nData, szData, length1); DIE_UNLESS(nData == 20); DIE_UNLESS(strcmp(szData, "mysql") == 0); DIE_UNLESS(length1 == 5); @@ -5377,7 +5517,7 @@ static void test_store_result() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - if (is_null[0]) + if (!opt_silent && is_null[0]) fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1); DIE_UNLESS(is_null[0]); DIE_UNLESS(strcmp(szData, "monty") == 0); @@ -5395,7 +5535,8 @@ static void test_store_result() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 1: %ld, %s(%lu)", (long) nData, szData, length1); + if (!opt_silent) + fprintf(stdout, "\n row 1: %ld, %s(%lu)", (long) nData, szData, length1); DIE_UNLESS(nData == 10); DIE_UNLESS(strcmp(szData, "venu") == 0); DIE_UNLESS(length1 == 4); @@ -5403,7 +5544,8 @@ static void test_store_result() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 2: %ld, %s(%lu)", (long) nData, szData, length1); + if (!opt_silent) + fprintf(stdout, "\n row 2: %ld, %s(%lu)", (long) nData, szData, length1); DIE_UNLESS(nData == 20); DIE_UNLESS(strcmp(szData, "mysql") == 0); DIE_UNLESS(length1 == 5); @@ -5412,7 +5554,7 @@ static void test_store_result() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - if (is_null[0]) + if (!opt_silent && is_null[0]) fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1); DIE_UNLESS(is_null[0]); DIE_UNLESS(strcmp(szData, "monty") == 0); @@ -5461,7 +5603,8 @@ static void test_store_result1() rc= 0; while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) rc++; - fprintf(stdout, "\n total rows: %d", rc); + if (!opt_silent) + fprintf(stdout, "\n total rows: %d", rc); DIE_UNLESS(rc == 3); rc= mysql_stmt_execute(stmt); @@ -5473,7 +5616,8 @@ static void test_store_result1() rc= 0; while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) rc++; - fprintf(stdout, "\n total rows: %d", rc); + if (!opt_silent) + fprintf(stdout, "\n total rows: %d", rc); DIE_UNLESS(rc == 3); mysql_stmt_close(stmt); @@ -5539,7 +5683,8 @@ static void test_store_result2() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 1: %d", nData); + if (!opt_silent) + fprintf(stdout, "\n row 1: %d", nData); DIE_UNLESS(nData == 10); rc= mysql_stmt_fetch(stmt); @@ -5556,7 +5701,8 @@ static void test_store_result2() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 1: %d", nData); + if (!opt_silent) + fprintf(stdout, "\n row 1: %d", nData); DIE_UNLESS(nData == 20); rc= mysql_stmt_fetch(stmt); @@ -5660,7 +5806,8 @@ static void test_subselect() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 1: %d", id); + if (!opt_silent) + fprintf(stdout, "\n row 1: %d", id); DIE_UNLESS(id == 1); rc= mysql_stmt_fetch(stmt); @@ -5673,7 +5820,8 @@ static void test_subselect() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 1: %d", id); + if (!opt_silent) + fprintf(stdout, "\n row 1: %d", id); DIE_UNLESS(id == 0); rc= mysql_stmt_fetch(stmt); @@ -5790,21 +5938,21 @@ static void test_bind_date_conv(uint row_count) rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n"); + if (!opt_silent) + fprintf(stdout, "\n"); for (i= 0; i < array_elements(bind); i++) { - fprintf(stdout, "\n"); - fprintf(stdout, " time[%d]: %02d-%02d-%02d %02d:%02d:%02d.%02lu", - i, tm[i].year, tm[i].month, tm[i].day, - tm[i].hour, tm[i].minute, tm[i].second, - tm[i].second_part); - + if (!opt_silent) + fprintf(stdout, "\ntime[%d]: %02d-%02d-%02d %02d:%02d:%02d.%02lu", + i, tm[i].year, tm[i].month, tm[i].day, + tm[i].hour, tm[i].minute, tm[i].second, + tm[i].second_part); DIE_UNLESS(tm[i].year == 0 || tm[i].year == year+count); DIE_UNLESS(tm[i].month == 0 || tm[i].month == month+count); DIE_UNLESS(tm[i].day == 0 || tm[i].day == day+count); DIE_UNLESS(tm[i].hour == 0 || tm[i].hour == hour+count); -#if 0 +#ifdef NOT_USED /* minute causes problems from date<->time, don't assert, instead validate separatly in another routine @@ -6059,7 +6207,8 @@ static void test_buffers() buffer[1]= 'X'; rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n data: %s (%lu)", buffer, length); + if (!opt_silent) + fprintf(stdout, "\n data: %s (%lu)", buffer, length); DIE_UNLESS(buffer[0] == 'M'); DIE_UNLESS(buffer[1] == 'X'); DIE_UNLESS(length == 5); @@ -6070,7 +6219,8 @@ static void test_buffers() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n data: %s (%lu)", buffer, length); + if (!opt_silent) + fprintf(stdout, "\n data: %s (%lu)", buffer, length); DIE_UNLESS(strncmp(buffer, "Database", 8) == 0); DIE_UNLESS(length == 8); @@ -6080,7 +6230,8 @@ static void test_buffers() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n data: %s (%lu)", buffer, length); + if (!opt_silent) + fprintf(stdout, "\n data: %s (%lu)", buffer, length); DIE_UNLESS(strcmp(buffer, "Open-Source") == 0); DIE_UNLESS(length == 11); @@ -6090,7 +6241,8 @@ static void test_buffers() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n data: %s (%lu)", buffer, length); + if (!opt_silent) + fprintf(stdout, "\n data: %s (%lu)", buffer, length); DIE_UNLESS(strncmp(buffer, "Popula", 6) == 0); DIE_UNLESS(length == 7); @@ -6221,7 +6373,8 @@ static void test_fetch_nobuffs() while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) rc++; - fprintf(stdout, "\n total rows : %d", rc); + if (!opt_silent) + fprintf(stdout, "\n total rows : %d", rc); DIE_UNLESS(rc == 1); bind[0].buffer_type= MYSQL_TYPE_STRING; @@ -6244,12 +6397,16 @@ static void test_fetch_nobuffs() while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) { rc++; - fprintf(stdout, "\n CURRENT_DATABASE(): %s", str[0]); - fprintf(stdout, "\n CURRENT_USER() : %s", str[1]); - fprintf(stdout, "\n CURRENT_DATE() : %s", str[2]); - fprintf(stdout, "\n CURRENT_TIME() : %s", str[3]); + if (!opt_silent) + { + fprintf(stdout, "\n CURRENT_DATABASE(): %s", str[0]); + fprintf(stdout, "\n CURRENT_USER() : %s", str[1]); + fprintf(stdout, "\n CURRENT_DATE() : %s", str[2]); + fprintf(stdout, "\n CURRENT_TIME() : %s", str[3]); + } } - fprintf(stdout, "\n total rows : %d", rc); + if (!opt_silent) + fprintf(stdout, "\n total rows : %d", rc); DIE_UNLESS(rc == 1); mysql_stmt_close(stmt); @@ -6316,10 +6473,13 @@ static void test_ushort_bug() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n ushort : %d (%ld)", short_value, s_length); - fprintf(stdout, "\n ulong : %lu (%ld)", (ulong) long_value, l_length); - fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length); - fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length); + if (!opt_silent) + { + fprintf(stdout, "\n ushort : %d (%ld)", short_value, s_length); + fprintf(stdout, "\n ulong : %lu (%ld)", (ulong) long_value, l_length); + fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length); + fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length); + } DIE_UNLESS(short_value == 35999); DIE_UNLESS(s_length == 2); @@ -6400,10 +6560,13 @@ static void test_sshort_bug() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length); - fprintf(stdout, "\n slong : %ld (%ld)", (long) long_value, l_length); - fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length); - fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length); + if (!opt_silent) + { + fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length); + fprintf(stdout, "\n slong : %ld (%ld)", (long) long_value, l_length); + fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length); + fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length); + } DIE_UNLESS(short_value == -5999); DIE_UNLESS(s_length == 2); @@ -6484,10 +6647,13 @@ static void test_stiny_bug() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length); - fprintf(stdout, "\n slong : %ld (%ld)", (long) long_value, l_length); - fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length); - fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length); + if (!opt_silent) + { + fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length); + fprintf(stdout, "\n slong : %ld (%ld)", (long) long_value, l_length); + fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length); + fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length); + } DIE_UNLESS(short_value == -128); DIE_UNLESS(s_length == 2); @@ -6576,7 +6742,8 @@ static void test_field_misc() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n default table type: %s(%ld)", table_type, type_length); + if (!opt_silent) + fprintf(stdout, "\n default table type: %s(%ld)", table_type, type_length); rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == MYSQL_NO_DATA); @@ -6696,7 +6863,8 @@ static void test_set_option() rc= mysql_query(mysql, "INSERT INTO test_limit VALUES(10), (20), (30), (40)"); myquery(rc); - fprintf(stdout, "\n with SQL_SELECT_LIMIT= 2 (direct)"); + if (!opt_silent) + fprintf(stdout, "\n with SQL_SELECT_LIMIT= 2 (direct)"); rc= mysql_query(mysql, "SELECT * FROM test_limit"); myquery(rc); @@ -6708,7 +6876,8 @@ static void test_set_option() mysql_free_result(result); - fprintf(stdout, "\n with SQL_SELECT_LIMIT=2 (prepare)"); + if (!opt_silent) + fprintf(stdout, "\n with SQL_SELECT_LIMIT=2 (prepare)"); stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_limit"); check_stmt(stmt); @@ -6721,7 +6890,8 @@ static void test_set_option() mysql_stmt_close(stmt); /* RESET the LIMIT the rows count to 0 */ - fprintf(stdout, "\n with SQL_SELECT_LIMIT=DEFAULT (prepare)"); + if (!opt_silent) + fprintf(stdout, "\n with SQL_SELECT_LIMIT=DEFAULT (prepare)"); rc= mysql_query(mysql, "SET OPTION SQL_SELECT_LIMIT=DEFAULT"); myquery(rc); @@ -6779,7 +6949,8 @@ static void test_prepare_grant() MYSQL *org_mysql= mysql, *lmysql; MYSQL_STMT *stmt; - fprintf(stdout, "\n Establishing a test connection ..."); + if (!opt_silent) + fprintf(stdout, "\n Establishing a test connection ..."); if (!(lmysql= mysql_init(NULL))) { myerror("mysql_init() failed"); @@ -6793,7 +6964,8 @@ static void test_prepare_grant() mysql_close(lmysql); exit(1); } - fprintf(stdout, " OK"); + if (!opt_silent) + fprintf(stdout, " OK"); mysql= lmysql; rc= mysql_query(mysql, "INSERT INTO test_grant VALUES(NULL)"); @@ -6880,14 +7052,16 @@ static void test_frm_bug() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n data directory: %s", data_dir); + if (!opt_silent) + fprintf(stdout, "\n data directory: %s", data_dir); rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == MYSQL_NO_DATA); strxmov(test_frm, data_dir, "/", current_db, "/", "test_frm_bug.frm", NullS); - fprintf(stdout, "\n test_frm: %s", test_frm); + if (!opt_silent) + fprintf(stdout, "\n test_frm: %s", test_frm); if (!(test_file= my_fopen(test_frm, (int) (O_RDWR | O_CREAT), MYF(MY_WME)))) { @@ -6895,7 +7069,8 @@ static void test_frm_bug() fprintf(stdout, "\n test cancelled"); exit(1); } - fprintf(test_file, "this is a junk file for test"); + if (!opt_silent) + fprintf(test_file, "this is a junk file for test"); rc= mysql_query(mysql, "SHOW TABLE STATUS like 'test_frm_bug'"); myquery(rc); @@ -6911,7 +7086,8 @@ static void test_frm_bug() row= mysql_fetch_row(result); mytest(row); - fprintf(stdout, "\n Comment: %s", row[17]); + if (!opt_silent) + fprintf(stdout, "\n Comment: %s", row[17]); DIE_UNLESS(row[17] != 0); mysql_free_result(result); @@ -6974,7 +7150,8 @@ static void test_decimal_bug() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n data: %s", data); + if (!opt_silent) + fprintf(stdout, "\n data: %s", data); DIE_UNLESS(strcmp(data, "8.00") == 0); rc= mysql_stmt_fetch(stmt); @@ -6991,7 +7168,8 @@ static void test_decimal_bug() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n data: %s", data); + if (!opt_silent) + fprintf(stdout, "\n data: %s", data); DIE_UNLESS(strcmp(data, "5.61") == 0); rc= mysql_stmt_fetch(stmt); @@ -7015,7 +7193,8 @@ static void test_decimal_bug() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n data: %s", data); + if (!opt_silent) + fprintf(stdout, "\n data: %s", data); DIE_UNLESS(strcmp(data, "10.22") == 0); rc= mysql_stmt_fetch(stmt); @@ -7055,8 +7234,9 @@ static void test_explain_bug() result= mysql_stmt_result_metadata(stmt); mytest(result); - fprintf(stdout, "\n total fields in the result: %d", - mysql_num_fields(result)); + if (!opt_silent) + fprintf(stdout, "\n total fields in the result: %d", + mysql_num_fields(result)); DIE_UNLESS(6 == mysql_num_fields(result)); verify_prepare_field(result, 0, "Field", "", MYSQL_TYPE_VAR_STRING, @@ -7092,8 +7272,9 @@ static void test_explain_bug() result= mysql_stmt_result_metadata(stmt); mytest(result); - fprintf(stdout, "\n total fields in the result: %d", - mysql_num_fields(result)); + if (!opt_silent) + fprintf(stdout, "\n total fields in the result: %d", + mysql_num_fields(result)); DIE_UNLESS(10 == mysql_num_fields(result)); verify_prepare_field(result, 0, "id", "", MYSQL_TYPE_LONGLONG, @@ -7114,8 +7295,12 @@ static void test_explain_bug() verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_LEN, 0); - verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING, - "", "", "", NAME_LEN*MAX_KEY, 0); + verify_prepare_field(result, 6, "key_len", "", + (mysql_get_server_version(mysql) <= 50000 ? + MYSQL_TYPE_LONGLONG : MYSQL_TYPE_VAR_STRING), + "", "", "", + (mysql_get_server_version(mysql) <= 50000 ? 3 : 4096), + 0); verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_LEN*16, 0); @@ -7141,11 +7326,14 @@ static void test_explain_bug() static void check_errcode(const unsigned int err) { - if (mysql->server_version) - fprintf(stdout, "\n [MySQL-%s]", mysql->server_version); - else - fprintf(stdout, "\n [MySQL]"); - fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql)); + if (!opt_silent || mysql_errno(mysql) != err) + { + if (mysql->server_version) + fprintf(stdout, "\n [MySQL-%s]", mysql->server_version); + else + fprintf(stdout, "\n [MySQL]"); + fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql)); + } DIE_UNLESS(mysql_errno(mysql) == err); } @@ -7191,7 +7379,8 @@ static void test_drop_temp() { MYSQL *org_mysql= mysql, *lmysql; - fprintf(stdout, "\n Establishing a test connection ..."); + if (!opt_silent) + fprintf(stdout, "\n Establishing a test connection ..."); if (!(lmysql= mysql_init(NULL))) { myerror("mysql_init() failed"); @@ -7210,7 +7399,8 @@ static void test_drop_temp() mysql_close(lmysql); exit(1); } - fprintf(stdout, " OK"); + if (!opt_silent) + fprintf(stdout, " OK"); mysql= lmysql; rc= mysql_query(mysql, "INSERT INTO t1 VALUES(10, 'C')"); @@ -7279,14 +7469,16 @@ static void test_cuted_rows() myquery(rc); count= mysql_warning_count(mysql); - fprintf(stdout, "\n total warnings: %d", count); + if (!opt_silent) + fprintf(stdout, "\n total warnings: %d", count); DIE_UNLESS(count == 0); rc= mysql_query(mysql, "INSERT INTO t2 SELECT * FROM t1"); myquery(rc); count= mysql_warning_count(mysql); - fprintf(stdout, "\n total warnings: %d", count); + if (!opt_silent) + fprintf(stdout, "\n total warnings: %d", count); DIE_UNLESS(count == 2); rc= mysql_query(mysql, "SHOW WARNINGS"); @@ -7303,7 +7495,8 @@ static void test_cuted_rows() myquery(rc); count= mysql_warning_count(mysql); - fprintf(stdout, "\n total warnings: %d", count); + if (!opt_silent) + fprintf(stdout, "\n total warnings: %d", count); DIE_UNLESS(count == 2); rc= mysql_query(mysql, "SHOW WARNINGS"); @@ -7416,8 +7609,11 @@ static void test_logs() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n id : %d", id); - fprintf(stdout, "\n name : %s(%ld)", data, length); + if (!opt_silent) + { + fprintf(stdout, "\n id : %d", id); + fprintf(stdout, "\n name : %s(%ld)", data, length); + } DIE_UNLESS(id == 9876); DIE_UNLESS(length == 19); /* Due to VARCHAR(20) */ @@ -7426,7 +7622,8 @@ static void test_logs() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n name : %s(%ld)", data, length); + if (!opt_silent) + fprintf(stdout, "\n name : %s(%ld)", data, length); DIE_UNLESS(length == 1); DIE_UNLESS(strcmp(data, "'") == 0); @@ -7434,7 +7631,8 @@ static void test_logs() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n name : %s(%ld)", data, length); + if (!opt_silent) + fprintf(stdout, "\n name : %s(%ld)", data, length); DIE_UNLESS(length == 1); DIE_UNLESS(strcmp(data, "\"") == 0); @@ -7442,7 +7640,8 @@ static void test_logs() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n name : %s(%ld)", data, length); + if (!opt_silent) + fprintf(stdout, "\n name : %s(%ld)", data, length); DIE_UNLESS(length == 7); DIE_UNLESS(strcmp(data, "my\'sql\'") == 0); @@ -7450,7 +7649,8 @@ static void test_logs() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n name : %s(%ld)", data, length); + if (!opt_silent) + fprintf(stdout, "\n name : %s(%ld)", data, length); DIE_UNLESS(length == 7); /*DIE_UNLESS(strcmp(data, "my\"sql\"") == 0); */ @@ -7496,7 +7696,8 @@ static void test_nstmts() for (i= 0; i < total_stmts; i++) { - fprintf(stdout, "\r stmt: %d", i); + if (!opt_silent) + fprintf(stdout, "\r stmt: %d", i); strmov(query, "insert into test_nstmts values(?)"); stmt= mysql_simple_prepare(mysql, query); @@ -7523,7 +7724,8 @@ static void test_nstmts() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n total rows: %d", i); + if (!opt_silent) + fprintf(stdout, "\n total rows: %d", i); DIE_UNLESS( i == total_stmts); rc= mysql_stmt_fetch(stmt); @@ -7589,7 +7791,8 @@ static void test_fetch_seek() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 0: %ld, %s, %s", (long) c1, c2, c3); + if (!opt_silent) + fprintf(stdout, "\n row 0: %ld, %s, %s", (long) c1, c2, c3); row= mysql_stmt_row_tell(stmt); @@ -7598,21 +7801,24 @@ static void test_fetch_seek() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 2: %ld, %s, %s", (long) c1, c2, c3); + if (!opt_silent) + fprintf(stdout, "\n row 2: %ld, %s, %s", (long) c1, c2, c3); row= mysql_stmt_row_seek(stmt, row); rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 2: %ld, %s, %s", (long) c1, c2, c3); + if (!opt_silent) + fprintf(stdout, "\n row 2: %ld, %s, %s", (long) c1, c2, c3); mysql_stmt_data_seek(stmt, 0); rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 0: %ld, %s, %s", (long) c1, c2, c3); + if (!opt_silent) + fprintf(stdout, "\n row 0: %ld, %s, %s", (long) c1, c2, c3); rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); @@ -7680,17 +7886,20 @@ static void test_fetch_offset() data[0]= '\0'; rc= mysql_stmt_fetch_column(stmt, bind, 0, 0); check_execute(stmt, rc); - fprintf(stdout, "\n col 1: %s (%ld)", data, length); + if (!opt_silent) + fprintf(stdout, "\n col 1: %s (%ld)", data, length); DIE_UNLESS(strncmp(data, "abcd", 4) == 0 && length == 10); rc= mysql_stmt_fetch_column(stmt, bind, 0, 5); check_execute(stmt, rc); - fprintf(stdout, "\n col 1: %s (%ld)", data, length); + if (!opt_silent) + fprintf(stdout, "\n col 1: %s (%ld)", data, length); DIE_UNLESS(strncmp(data, "fg", 2) == 0 && length == 10); rc= mysql_stmt_fetch_column(stmt, bind, 0, 9); check_execute(stmt, rc); - fprintf(stdout, "\n col 0: %s (%ld)", data, length); + if (!opt_silent) + fprintf(stdout, "\n col 0: %s (%ld)", data, length); DIE_UNLESS(strncmp(data, "j", 1) == 0 && length == 10); rc= mysql_stmt_fetch(stmt); @@ -7763,7 +7972,8 @@ static void test_fetch_column() rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 0: %d, %s", bc1, bc2); + if (!opt_silent) + fprintf(stdout, "\n row 0: %d, %s", bc1, bc2); c2[0]= '\0'; l2= 0; bind[0].buffer_type= MYSQL_TYPE_STRING; @@ -7774,13 +7984,15 @@ static void test_fetch_column() rc= mysql_stmt_fetch_column(stmt, bind, 1, 0); check_execute(stmt, rc); - fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); + if (!opt_silent) + fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); DIE_UNLESS(strncmp(c2, "venu", 4) == 0 && l2 == 4); c2[0]= '\0'; l2= 0; rc= mysql_stmt_fetch_column(stmt, bind, 1, 0); check_execute(stmt, rc); - fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); + if (!opt_silent) + fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); DIE_UNLESS(strcmp(c2, "venu") == 0 && l2 == 4); c1= 0; @@ -7792,13 +8004,15 @@ static void test_fetch_column() rc= mysql_stmt_fetch_column(stmt, bind, 0, 0); check_execute(stmt, rc); - fprintf(stdout, "\n col 0: %d(%ld)", c1, l1); + if (!opt_silent) + fprintf(stdout, "\n col 0: %d(%ld)", c1, l1); DIE_UNLESS(c1 == 1 && l1 == 4); rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - fprintf(stdout, "\n row 1: %d, %s", bc1, bc2); + if (!opt_silent) + fprintf(stdout, "\n row 1: %d, %s", bc1, bc2); c2[0]= '\0'; l2= 0; bind[0].buffer_type= MYSQL_TYPE_STRING; @@ -7809,13 +8023,15 @@ static void test_fetch_column() rc= mysql_stmt_fetch_column(stmt, bind, 1, 0); check_execute(stmt, rc); - fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); + if (!opt_silent) + fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); DIE_UNLESS(strncmp(c2, "mysq", 4) == 0 && l2 == 5); c2[0]= '\0'; l2= 0; rc= mysql_stmt_fetch_column(stmt, bind, 1, 0); check_execute(stmt, rc); - fprintf(stdout, "\n col 1: %si(%ld)", c2, l2); + if (!opt_silent) + fprintf(stdout, "\n col 1: %si(%ld)", c2, l2); DIE_UNLESS(strcmp(c2, "mysql") == 0 && l2 == 5); c1= 0; @@ -7827,7 +8043,8 @@ static void test_fetch_column() rc= mysql_stmt_fetch_column(stmt, bind, 0, 0); check_execute(stmt, rc); - fprintf(stdout, "\n col 0: %d(%ld)", c1, l1); + if (!opt_silent) + fprintf(stdout, "\n col 0: %d(%ld)", c1, l1); DIE_UNLESS(c1 == 2 && l1 == 4); rc= mysql_stmt_fetch(stmt); @@ -7881,7 +8098,6 @@ static void test_mem_overun() MYSQL_RES *field_res; int rc, i, length; - myheader("test_mem_overun"); /* @@ -7931,7 +8147,8 @@ static void test_mem_overun() field_res= mysql_stmt_result_metadata(stmt); mytest(field_res); - fprintf(stdout, "\n total fields : %d", mysql_num_fields(field_res)); + if (!opt_silent) + fprintf(stdout, "\n total fields : %d", mysql_num_fields(field_res)); DIE_UNLESS( 1000 == mysql_num_fields(field_res)); rc= mysql_stmt_store_result(stmt); @@ -7998,7 +8215,8 @@ static void test_free_result() rc= mysql_stmt_fetch_column(stmt, bind, 0, 0); check_execute(stmt, rc); - fprintf(stdout, "\n col 0: %s(%ld)", c2, l2); + if (!opt_silent) + fprintf(stdout, "\n col 0: %s(%ld)", c2, l2); DIE_UNLESS(strncmp(c2, "1", 1) == 0 && l2 == 1); rc= mysql_stmt_fetch(stmt); @@ -8013,7 +8231,8 @@ static void test_free_result() rc= mysql_stmt_fetch_column(stmt, bind, 0, 0); check_execute(stmt, rc); - fprintf(stdout, "\n col 0: %d(%ld)", c1, l2); + if (!opt_silent) + fprintf(stdout, "\n col 0: %d(%ld)", c1, l2); DIE_UNLESS(c1 == 2 && l2 == 4); rc= mysql_query(mysql, "drop table test_free_result"); @@ -8080,7 +8299,8 @@ static void test_free_store_result() rc= mysql_stmt_fetch_column(stmt, bind, 0, 0); check_execute(stmt, rc); - fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); + if (!opt_silent) + fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); DIE_UNLESS(strncmp(c2, "1", 1) == 0 && l2 == 1); rc= mysql_stmt_fetch(stmt); @@ -8095,7 +8315,8 @@ static void test_free_store_result() rc= mysql_stmt_fetch_column(stmt, bind, 0, 0); check_execute(stmt, rc); - fprintf(stdout, "\n col 0: %d(%ld)", c1, l2); + if (!opt_silent) + fprintf(stdout, "\n col 0: %d(%ld)", c1, l2); DIE_UNLESS(c1 == 2 && l2 == 4); rc= mysql_stmt_free_result(stmt); @@ -8127,16 +8348,19 @@ static void test_sqlmode() /* PIPES_AS_CONCAT */ strcpy(query, "SET SQL_MODE= \"PIPES_AS_CONCAT\""); - fprintf(stdout, "\n With %s", query); + if (!opt_silent) + fprintf(stdout, "\n With %s", query); rc= mysql_query(mysql, query); myquery(rc); strcpy(query, "INSERT INTO test_piping VALUES(?||?)"); - fprintf(stdout, "\n query: %s", query); + if (!opt_silent) + fprintf(stdout, "\n query: %s", query); stmt= mysql_simple_prepare(mysql, query); check_stmt(stmt); - fprintf(stdout, "\n total parameters: %ld", mysql_stmt_param_count(stmt)); + if (!opt_silent) + fprintf(stdout, "\n total parameters: %ld", mysql_stmt_param_count(stmt)); /* We need to bzero bind structure because mysql_stmt_bind_param checks all @@ -8166,21 +8390,25 @@ static void test_sqlmode() myquery(rc); strcpy(query, "SELECT connection_id ()"); - fprintf(stdout, "\n query: %s", query); + if (!opt_silent) + fprintf(stdout, "\n query: %s", query); stmt= mysql_simple_prepare(mysql, query); check_stmt_r(stmt); /* ANSI */ strcpy(query, "SET SQL_MODE= \"ANSI\""); - fprintf(stdout, "\n With %s", query); + if (!opt_silent) + fprintf(stdout, "\n With %s", query); rc= mysql_query(mysql, query); myquery(rc); strcpy(query, "INSERT INTO test_piping VALUES(?||?)"); - fprintf(stdout, "\n query: %s", query); + if (!opt_silent) + fprintf(stdout, "\n query: %s", query); stmt= mysql_simple_prepare(mysql, query); check_stmt(stmt); - fprintf(stdout, "\n total parameters: %ld", mysql_stmt_param_count(stmt)); + if (!opt_silent) + fprintf(stdout, "\n total parameters: %ld", mysql_stmt_param_count(stmt)); rc= mysql_stmt_bind_param(stmt, bind); check_execute(stmt, rc); @@ -8194,7 +8422,8 @@ static void test_sqlmode() /* ANSI mode spaces ... */ strcpy(query, "SELECT connection_id ()"); - fprintf(stdout, "\n query: %s", query); + if (!opt_silent) + fprintf(stdout, "\n query: %s", query); stmt= mysql_simple_prepare(mysql, query); check_stmt(stmt); @@ -8206,18 +8435,21 @@ static void test_sqlmode() rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == MYSQL_NO_DATA); - fprintf(stdout, "\n returned 1 row\n"); + if (!opt_silent) + fprintf(stdout, "\n returned 1 row\n"); mysql_stmt_close(stmt); /* IGNORE SPACE MODE */ strcpy(query, "SET SQL_MODE= \"IGNORE_SPACE\""); - fprintf(stdout, "\n With %s", query); + if (!opt_silent) + fprintf(stdout, "\n With %s", query); rc= mysql_query(mysql, query); myquery(rc); strcpy(query, "SELECT connection_id ()"); - fprintf(stdout, "\n query: %s", query); + if (!opt_silent) + fprintf(stdout, "\n query: %s", query); stmt= mysql_simple_prepare(mysql, query); check_stmt(stmt); @@ -8229,7 +8461,8 @@ static void test_sqlmode() rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == MYSQL_NO_DATA); - fprintf(stdout, "\n returned 1 row"); + if (!opt_silent) + fprintf(stdout, "\n returned 1 row"); mysql_stmt_close(stmt); } @@ -8321,7 +8554,8 @@ static void test_ts() sprintf(query, "SELECT a, b, c FROM test_ts WHERE %c=?", name); - fprintf(stdout, "\n %s", query); + if (!opt_silent) + fprintf(stdout, "\n %s", query); stmt= mysql_simple_prepare(mysql, query); check_stmt(stmt); @@ -8334,7 +8568,8 @@ static void test_ts() while (mysql_stmt_fetch(stmt) == 0) row_count++; - fprintf(stdout, "\n returned '%d' rows", row_count); + if (!opt_silent) + fprintf(stdout, "\n returned '%d' rows", row_count); DIE_UNLESS(row_count == 2); mysql_stmt_close(stmt); } @@ -8476,7 +8711,8 @@ static void test_bug1946() check_stmt(stmt); rc= mysql_real_query(mysql, query, strlen(query)); DIE_UNLESS(rc != 0); - fprintf(stdout, "Got error (as expected):\n"); + if (!opt_silent) + fprintf(stdout, "Got error (as expected):\n"); myerror(NULL); mysql_stmt_close(stmt); @@ -8494,19 +8730,23 @@ static void test_parse_error_and_bad_length() rc= mysql_query(mysql, "SHOW DATABAAAA"); DIE_UNLESS(rc); - fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql)); + if (!opt_silent) + fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql)); rc= mysql_real_query(mysql, "SHOW DATABASES", 100); DIE_UNLESS(rc); - fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql)); + if (!opt_silent) + fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql)); stmt= mysql_simple_prepare(mysql, "SHOW DATABAAAA"); DIE_UNLESS(!stmt); - fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql)); + if (!opt_silent) + fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql)); stmt= mysql_stmt_init(mysql); DIE_UNLESS(stmt); rc= mysql_stmt_prepare(stmt, "SHOW DATABASES", 100); DIE_UNLESS(rc != 0); - fprintf(stdout, "Got error (as expected): '%s'\n", mysql_stmt_error(stmt)); + if (!opt_silent) + fprintf(stdout, "Got error (as expected): '%s'\n", mysql_stmt_error(stmt)); mysql_stmt_close(stmt); } @@ -8527,7 +8767,8 @@ static void test_bug2247() myheader("test_bug2247"); - fprintf(stdout, "\nChecking if stmt_affected_rows is not affected by\n" + if (!opt_silent) + fprintf(stdout, "\nChecking if stmt_affected_rows is not affected by\n" "mysql_query ... "); /* create table and insert few rows */ rc= mysql_query(mysql, drop); @@ -8584,7 +8825,8 @@ static void test_bug2247() DIE_UNLESS(mysql_stmt_affected_rows(stmt) == exp_count); mysql_stmt_close(stmt); - fprintf(stdout, "OK"); + if (!opt_silent) + fprintf(stdout, "OK"); } @@ -8862,7 +9104,8 @@ static void test_bug3117() check_execute(stmt, rc); DIE_UNLESS(is_null == 0 && lii == 1); - fprintf(stdout, "\n\tLAST_INSERT_ID()= 1 ok\n"); + if (!opt_silent) + fprintf(stdout, "\n\tLAST_INSERT_ID()= 1 ok\n"); rc= mysql_query(mysql, "INSERT INTO t1 VALUES (NULL)"); myquery(rc); @@ -8874,7 +9117,8 @@ static void test_bug3117() check_execute(stmt, rc); DIE_UNLESS(is_null == 0 && lii == 2); - fprintf(stdout, "\tLAST_INSERT_ID()= 2 ok\n"); + if (!opt_silent) + fprintf(stdout, "\tLAST_INSERT_ID()= 2 ok\n"); mysql_stmt_close(stmt); @@ -9024,7 +9268,8 @@ static void test_create_drop() { rc= mysql_stmt_execute(stmt_create); check_execute(stmt_create, rc); - fprintf(stdout, "created %i\n", i); + if (!opt_silent) + fprintf(stdout, "created %i\n", i); rc= mysql_stmt_execute(stmt_select); check_execute(stmt_select, rc); @@ -9033,11 +9278,13 @@ static void test_create_drop() rc= mysql_stmt_execute(stmt_drop); check_execute(stmt_drop, rc); - fprintf(stdout, "droped %i\n", i); + if (!opt_silent) + fprintf(stdout, "droped %i\n", i); rc= mysql_stmt_execute(stmt_create_select); check_execute(stmt_create, rc); - fprintf(stdout, "created select %i\n", i); + if (!opt_silent) + fprintf(stdout, "created select %i\n", i); rc= mysql_stmt_execute(stmt_select); check_execute(stmt_select, rc); @@ -9046,7 +9293,8 @@ static void test_create_drop() rc= mysql_stmt_execute(stmt_drop); check_execute(stmt_drop, rc); - fprintf(stdout, "droped %i\n", i); + if (!opt_silent) + fprintf(stdout, "droped %i\n", i); } mysql_stmt_close(stmt_create); @@ -9077,25 +9325,29 @@ static void test_rename() rc= mysql_stmt_execute(stmt); check_execute_r(stmt, rc); - fprintf(stdout, "rename without t3\n"); + if (!opt_silent) + fprintf(stdout, "rename without t3\n"); rc= mysql_query(mysql, "create table t3 (a int)"); myquery(rc); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); - fprintf(stdout, "rename with t3\n"); + if (!opt_silent) + fprintf(stdout, "rename with t3\n"); rc= mysql_stmt_execute(stmt); check_execute_r(stmt, rc); - fprintf(stdout, "rename renamed\n"); + if (!opt_silent) + fprintf(stdout, "rename renamed\n"); rc= mysql_query(mysql, "rename table t2 to t1, t4 to t3"); myquery(rc); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); - fprintf(stdout, "rename reverted\n"); + if (!opt_silent) + fprintf(stdout, "rename reverted\n"); mysql_stmt_close(stmt); @@ -9129,10 +9381,12 @@ static void test_do_set() { rc= mysql_stmt_execute(stmt_do); check_execute(stmt_do, rc); - fprintf(stdout, "do %i\n", i); + if (!opt_silent) + fprintf(stdout, "do %i\n", i); rc= mysql_stmt_execute(stmt_set); check_execute(stmt_set, rc); - fprintf(stdout, "set %i\n", i); + if (!opt_silent) + fprintf(stdout, "set %i\n", i); } mysql_stmt_close(stmt_do); @@ -9198,11 +9452,13 @@ static void test_multi() rc= mysql_stmt_execute(stmt_update); check_execute(stmt_update, rc); - fprintf(stdout, "update %ld\n", (long) param); + if (!opt_silent) + fprintf(stdout, "update %ld\n", (long) param); rc= mysql_stmt_execute(stmt_delete); check_execute(stmt_delete, rc); - fprintf(stdout, "delete %ld\n", (long) param); + if (!opt_silent) + fprintf(stdout, "delete %ld\n", (long) param); rc= mysql_stmt_execute(stmt_select1); check_execute(stmt_select1, rc); @@ -9258,7 +9514,8 @@ static void test_insert_select() { rc= mysql_stmt_execute(stmt_insert); check_execute(stmt_insert, rc); - fprintf(stdout, "insert %u\n", i); + if (!opt_silent) + fprintf(stdout, "insert %u\n", i); rc= mysql_stmt_execute(stmt_select); check_execute(stmt_select, rc); @@ -10118,7 +10375,8 @@ static void test_bug3796() mysql_stmt_bind_result(stmt, bind); rc= mysql_stmt_fetch(stmt); - printf("Concat result: '%s'\n", out_buff); + if (!opt_silent) + printf("Concat result: '%s'\n", out_buff); check_execute(stmt, rc); strcpy(canonical_buff, concat_arg0); strcat(canonical_buff, "ONE"); @@ -10130,7 +10388,8 @@ static void test_bug3796() strcpy(canonical_buff + strlen(concat_arg0), "TWO"); DIE_UNLESS(strlen(canonical_buff) == out_length && strncmp(out_buff, canonical_buff, out_length) == 0); - printf("Concat result: '%s'\n", out_buff); + if (!opt_silent) + printf("Concat result: '%s'\n", out_buff); rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == MYSQL_NO_DATA); @@ -10204,12 +10463,15 @@ static void test_bug4026() rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == 0); - printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second, - time_out.second_part); - printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month, - datetime_out.day, datetime_out.hour, - datetime_out.minute, datetime_out.second, - datetime_out.second_part); + if (!opt_silent) + { + printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second, + time_out.second_part); + printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month, + datetime_out.day, datetime_out.hour, + datetime_out.minute, datetime_out.second, + datetime_out.second_part); + } DIE_UNLESS(memcmp(&time_in, &time_out, sizeof(time_in)) == 0); DIE_UNLESS(memcmp(&datetime_in, &datetime_out, sizeof(datetime_in)) == 0); mysql_stmt_close(stmt); @@ -10252,8 +10514,9 @@ static void test_bug4079() rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc != 0 && rc != MYSQL_NO_DATA); - printf("Got error from mysql_stmt_fetch (as expected):\n%s\n", - mysql_stmt_error(stmt)); + if (!opt_silent) + printf("Got error from mysql_stmt_fetch (as expected):\n%s\n", + mysql_stmt_error(stmt)); /* buggy version of libmysql hanged up here */ mysql_stmt_close(stmt); } @@ -10347,13 +10610,16 @@ static void test_bug4030() rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == 0); - printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second, - time_out.second_part); - printf("%d-%d-%d\n", date_out.year, date_out.month, date_out.day); - printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month, - datetime_out.day, datetime_out.hour, - datetime_out.minute, datetime_out.second, - datetime_out.second_part); + if (!opt_silent) + { + printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second, + time_out.second_part); + printf("%d-%d-%d\n", date_out.year, date_out.month, date_out.day); + printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month, + datetime_out.day, datetime_out.hour, + datetime_out.minute, datetime_out.second, + datetime_out.second_part); + } DIE_UNLESS(memcmp(&time_canonical, &time_out, sizeof(time_out)) == 0); DIE_UNLESS(memcmp(&date_canonical, &date_out, sizeof(date_out)) == 0); DIE_UNLESS(memcmp(&datetime_canonical, &datetime_out, sizeof(datetime_out)) == 0); @@ -10755,7 +11021,8 @@ static void test_bug5126() rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == 0); DIE_UNLESS(c1 == 8386608 && c2 == 1); - printf("%ld, %ld\n", (long) c1, (long) c2); + if (!opt_silent) + printf("%ld, %ld\n", (long) c1, (long) c2); mysql_stmt_close(stmt); } @@ -10861,7 +11128,8 @@ static void test_bug5399() check_execute(*stmt, rc); mysql_stmt_bind_result(*stmt, bind); } - printf("%d statements prepared.\n", NUM_OF_USED_STMT); + if (!opt_silent) + printf("%d statements prepared.\n", NUM_OF_USED_STMT); for (stmt= stmt_list; stmt != stmt_list + NUM_OF_USED_STMT; ++stmt) { @@ -11033,15 +11301,17 @@ static void test_bug5194() rc= mysql_stmt_prepare(stmt, query, query_ptr - query); if (rc && nrows * COLUMN_COUNT > uint16_max) { - printf("Failed to prepare a statement with %d placeholders " - "(as expected).\n", nrows * COLUMN_COUNT); + if (!opt_silent) + printf("Failed to prepare a statement with %d placeholders " + "(as expected).\n", nrows * COLUMN_COUNT); break; } else check_execute(stmt, rc); - printf("Insert: query length= %d, row count= %d, param count= %lu\n", - strlen(query), nrows, mysql_stmt_param_count(stmt)); + if (!opt_silent) + printf("Insert: query length= %d, row count= %d, param count= %lu\n", + strlen(query), nrows, mysql_stmt_param_count(stmt)); /* bind the parameter array and execute the query */ rc= mysql_stmt_bind_param(stmt, bind); @@ -11077,7 +11347,10 @@ static void test_bug5315() rc= mysql_stmt_execute(stmt); DIE_UNLESS(rc != 0); if (rc) - printf("Got error (as expected):\n%s", mysql_stmt_error(stmt)); + { + if (!opt_silent) + printf("Got error (as expected):\n%s", mysql_stmt_error(stmt)); + } /* check that connection is OK */ mysql_stmt_close(stmt); stmt= mysql_stmt_init(mysql); @@ -11125,8 +11398,11 @@ static void test_bug6049() rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == 0); - printf("Result from query: %s\n", row[0]); - printf("Result from prepared statement: %s\n", (char*) buffer); + if (!opt_silent) + { + printf("Result from query: %s\n", row[0]); + printf("Result from prepared statement: %s\n", (char*) buffer); + } DIE_UNLESS(strcmp(row[0], (char*) buffer) == 0); @@ -11171,8 +11447,11 @@ static void test_bug6058() rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == 0); - printf("Result from query: %s\n", row[0]); - printf("Result from prepared statement: %s\n", buffer); + if (!opt_silent) + { + printf("Result from query: %s\n", row[0]); + printf("Result from prepared statement: %s\n", buffer); + } DIE_UNLESS(strcmp(row[0], buffer) == 0); @@ -11211,17 +11490,17 @@ static void test_bug6046() stmt_text= "DROP TABLE IF EXISTS t1"; rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); myquery(rc); - stmt_text= "CREATE TABLE a1 (a int, b int)"; + stmt_text= "CREATE TABLE t1 (a int, b int)"; rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); myquery(rc); - stmt_text= "INSERT INTO a1 VALUES (1,1),(2,2),(3,1),(4,2)"; + stmt_text= "INSERT INTO t1 VALUES (1,1),(2,2),(3,1),(4,2)"; rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); myquery(rc); stmt= mysql_stmt_init(mysql); - stmt_text= "SELECT a1.a FROM a1 NATURAL JOIN a1 as X1 " - "WHERE a1.b > ? ORDER BY a1.a"; + stmt_text= "SELECT t1.a FROM t1 NATURAL JOIN t1 as X1 " + "WHERE t1.b > ? ORDER BY t1.a"; rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); check_execute(stmt, rc); @@ -11247,6 +11526,7 @@ static void test_bug6046() static void test_basic_cursors() { + DBUG_ENTER("test_basic_cursors"); const char *basic_tables[]= { "DROP TABLE IF EXISTS t1, t2", @@ -11284,6 +11564,7 @@ static void test_basic_cursors() fill_tables(basic_tables, sizeof(basic_tables)/sizeof(*basic_tables)); fetch_n(queries, sizeof(queries)/sizeof(*queries)); + DBUG_VOID_RETURN; } @@ -11381,22 +11662,25 @@ static void test_bug6096() /* Print out and check the metadata */ - printf(" ---------------------------------------------------------------\n"); - printf(" | Metadata \n"); - printf(" ---------------------------------------------------------------\n"); - printf(" | Query | Prepared statement \n"); - printf(" ---------------------------------------------------------------\n"); - printf(" field name | length | max_length | length | max_length \n"); - printf(" ---------------------------------------------------------------\n"); - - for (i= 0; i < query_field_count; ++i) + if (!opt_silent) { - MYSQL_FIELD *f1= &query_field_list[i], *f2= &stmt_field_list[i]; - printf(" %-11s | %9lu | %10lu | %9lu | %10lu \n", - f1->name, f1->length, f1->max_length, f2->length, f2->max_length); - DIE_UNLESS(f1->length == f2->length); + printf(" ------------------------------------------------------------\n"); + printf(" | Metadata \n"); + printf(" ------------------------------------------------------------\n"); + printf(" | Query | Prepared statement \n"); + printf(" ------------------------------------------------------------\n"); + printf(" field name | length | max_length | length | max_length\n"); + printf(" ------------------------------------------------------------\n"); + + for (i= 0; i < query_field_count; ++i) + { + MYSQL_FIELD *f1= &query_field_list[i], *f2= &stmt_field_list[i]; + printf(" %-11s | %9lu | %10lu | %9lu | %10lu \n", + f1->name, f1->length, f1->max_length, f2->length, f2->max_length); + DIE_UNLESS(f1->length == f2->length); + } + printf(" ---------------------------------------------------------------\n"); } - printf(" ---------------------------------------------------------------\n"); /* Bind and fetch the data */ @@ -11451,6 +11735,8 @@ static struct my_option client_test_long_options[] = #endif {"port", 'P', "Port number to use for connection", (char **) &opt_port, (char **) &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"silent", 's', "Be more silent", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, + 0}, {"socket", 'S', "Socket file to use for connection", (char **) &opt_unix_socket, (char **) &opt_unix_socket, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"testcase", 'c', "May disable some code when runs as mysql-test-run testcase.", @@ -11460,36 +11746,25 @@ static struct my_option client_test_long_options[] = { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; -static void client_test_print_version(void) -{ - fprintf(stdout, "%s Distrib %s, for %s (%s)\n\n", - my_progname, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); -} - static void usage(void) { - /* - * show the usage string when the user asks for this - */ + /* show the usage string when the user asks for this */ putc('\n', stdout); - puts("***********************************************************************\n"); - puts(" Test for client-server protocol 4.1"); - puts(" By Monty & Venu \n"); - puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software, "); - puts("and you are welcome to modify and redistribute it under the GPL license\n"); - puts(" Copyright (C) 1995-2003 MySQL AB "); - puts("-----------------------------------------------------------------------\n"); - client_test_print_version(); - fprintf(stdout, "Usage: %s [OPTIONS]\n\n", my_progname); - + printf("%s Ver %s Distrib %s, for %s (%s)\n", + my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); + puts("By Monty, Venu, Kent and others\n"); + printf("\ +Copyright (C) 2002-2004 MySQL AB\n\ +This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\ +and you are welcome to modify and redistribute it under the GPL license\n"); + printf("Usage: %s [OPTIONS]\n", my_progname); my_print_help(client_test_long_options); print_defaults("my", client_test_load_default_groups); my_print_variables(client_test_long_options); - - puts("***********************************************************************\n"); } + static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) @@ -11514,6 +11789,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), else tty_password= 1; break; + case 's': + if (argument == disabled_my_option) + opt_silent= 0; + else + opt_silent++; + break; case '?': case 'I': /* Info */ usage(); @@ -11542,14 +11823,17 @@ static void get_options(int argc, char **argv) static void print_test_output() { - fprintf(stdout, "\n\n"); - fprintf(stdout, "All '%d' tests were successful (in '%d' iterations)", - test_count-1, opt_count); - fprintf(stdout, "\n Total execution time: %g SECS", total_time); - if (opt_count > 1) - fprintf(stdout, " (Avg: %g SECS)", total_time/opt_count); - - fprintf(stdout, "\n\n!!! SUCCESS !!!\n"); + if (opt_silent < 3) + { + fprintf(stdout, "\n\n"); + fprintf(stdout, "All '%d' tests were successful (in '%d' iterations)", + test_count-1, opt_count); + fprintf(stdout, "\n Total execution time: %g SECS", total_time); + if (opt_count > 1) + fprintf(stdout, " (Avg: %g SECS)", total_time/opt_count); + + fprintf(stdout, "\n\n!!! SUCCESS !!!\n"); + } } |