summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BitKeeper/etc/logging_ok2
-rwxr-xr-xDocs/Support/texi2html98
-rw-r--r--client/mysqlcheck.c5
-rw-r--r--client/mysqltest.c78
-rw-r--r--configure.in30
-rw-r--r--include/my_list.h4
-rw-r--r--include/mysql.h17
-rw-r--r--include/mysql_com.h6
-rw-r--r--innobase/dict/dict0crea.c16
-rw-r--r--innobase/dict/dict0dict.c4
-rw-r--r--innobase/dict/dict0load.c35
-rw-r--r--innobase/eval/eval0eval.c18
-rw-r--r--innobase/ibuf/ibuf0ibuf.c6
-rw-r--r--innobase/pars/pars0pars.c8
-rw-r--r--innobase/row/row0mysql.c15
-rw-r--r--libmysql/libmysql.c16
-rw-r--r--myisam/mi_check.c2
-rw-r--r--myisam/myisamchk.c8
-rw-r--r--mysql-test/include/ps_modify.inc5
-rw-r--r--mysql-test/mysql-test-run.sh8
-rw-r--r--mysql-test/ndb/ndbcluster.sh6
-rw-r--r--mysql-test/r/ctype_recoding.result66
-rw-r--r--mysql-test/r/ctype_sjis.result11
-rw-r--r--mysql-test/r/fulltext.result3
-rw-r--r--mysql-test/r/gis.result74
-rw-r--r--mysql-test/r/mysqltest.result131
-rw-r--r--mysql-test/r/ndb_basic.result147
-rw-r--r--mysql-test/r/ndb_blob.result276
-rw-r--r--mysql-test/r/ndb_insert.result29
-rw-r--r--mysql-test/r/ps_10nestset.result11
-rw-r--r--mysql-test/r/ps_2myisam.result4
-rw-r--r--mysql-test/r/ps_3innodb.result4
-rw-r--r--mysql-test/r/ps_4heap.result4
-rw-r--r--mysql-test/r/ps_5merge.result8
-rw-r--r--mysql-test/r/ps_6bdb.result4
-rw-r--r--mysql-test/r/ps_7ndb.result1
-rw-r--r--mysql-test/r/range.result17
-rw-r--r--mysql-test/r/rpl_failed_optimize.result15
-rw-r--r--mysql-test/r/sql_mode.result30
-rw-r--r--mysql-test/t/client_test.test2
-rw-r--r--mysql-test/t/comments.test3
-rw-r--r--mysql-test/t/ctype_recoding.test48
-rw-r--r--mysql-test/t/ctype_sjis.test11
-rw-r--r--mysql-test/t/ctype_utf8.test1
-rw-r--r--mysql-test/t/fulltext.test9
-rw-r--r--mysql-test/t/gis.test75
-rw-r--r--mysql-test/t/join_outer.test15
-rw-r--r--mysql-test/t/key.test3
-rw-r--r--mysql-test/t/mysqltest.test218
-rw-r--r--mysql-test/t/ndb_basic.test151
-rw-r--r--mysql-test/t/ndb_blob.test184
-rw-r--r--mysql-test/t/ndb_insert.test15
-rw-r--r--mysql-test/t/ps_10nestset.test13
-rw-r--r--mysql-test/t/ps_7ndb.test2
-rw-r--r--mysql-test/t/range.test14
-rw-r--r--mysql-test/t/rpl_failed_optimize-master.opt1
-rw-r--r--mysql-test/t/rpl_failed_optimize.test18
-rw-r--r--mysql-test/t/show_check.test3
-rw-r--r--mysql-test/t/sql_mode.test31
-rw-r--r--mysql-test/t/temp_table.test6
-rw-r--r--mysql-test/t/type_ranges.test3
-rw-r--r--ndb/include/kernel/ndb_limits.h5
-rw-r--r--ndb/include/kernel/signaldata/DictTabInfo.hpp1
-rw-r--r--ndb/include/ndb_global.h9
-rw-r--r--ndb/include/ndbapi/NdbBlob.hpp47
-rw-r--r--ndb/include/ndbapi/NdbConnection.hpp4
-rw-r--r--ndb/include/ndbapi/NdbIndexOperation.hpp4
-rw-r--r--ndb/include/ndbapi/NdbOperation.hpp9
-rw-r--r--ndb/include/ndbapi/ndbapi_limits.h9
-rw-r--r--ndb/include/util/ndb_opts.h57
-rw-r--r--ndb/src/common/editline/sysunix.c9
-rw-r--r--ndb/src/common/util/Makefile.am4
-rw-r--r--ndb/src/common/util/basestring_vsnprintf.c25
-rw-r--r--ndb/src/common/util/socket_io.cpp39
-rw-r--r--ndb/src/common/util/strlcat.c48
-rw-r--r--ndb/src/common/util/strlcpy.c57
-rw-r--r--ndb/src/cw/cpcd/common.cpp63
-rw-r--r--ndb/src/cw/cpcd/common.hpp3
-rw-r--r--ndb/src/cw/cpcd/main.cpp75
-rw-r--r--ndb/src/kernel/blocks/backup/restore/main.cpp178
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.cpp5
-rw-r--r--ndb/src/kernel/error/ErrorReporter.cpp2
-rw-r--r--ndb/src/kernel/main.cpp8
-rw-r--r--ndb/src/kernel/vm/Configuration.cpp136
-rw-r--r--ndb/src/kernel/vm/Configuration.hpp2
-rw-r--r--ndb/src/kernel/vm/Emulator.hpp1
-rw-r--r--ndb/src/kernel/vm/LongSignal.hpp2
-rw-r--r--ndb/src/mgmclient/main.cpp77
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.cpp15
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.hpp1
-rw-r--r--ndb/src/mgmsrv/Services.cpp22
-rw-r--r--ndb/src/mgmsrv/main.cpp133
-rw-r--r--ndb/src/ndbapi/Ndb.cpp7
-rw-r--r--ndb/src/ndbapi/NdbBlob.cpp404
-rw-r--r--ndb/src/ndbapi/NdbConnection.cpp20
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp7
-rw-r--r--ndb/src/ndbapi/NdbIndexOperation.cpp26
-rw-r--r--ndb/src/ndbapi/NdbOperation.cpp4
-rw-r--r--ndb/src/ndbapi/NdbOperationExec.cpp14
-rw-r--r--ndb/src/ndbapi/NdbScanOperation.cpp4
-rw-r--r--ndb/src/ndbapi/TransporterFacade.cpp159
-rw-r--r--ndb/src/ndbapi/TransporterFacade.hpp10
-rw-r--r--ndb/src/ndbapi/ndberror.c2
-rw-r--r--ndb/test/include/getarg.h (renamed from ndb/include/util/getarg.h)0
-rw-r--r--ndb/test/ndbapi/testBlobs.cpp224
-rw-r--r--ndb/test/run-test/Makefile.am3
-rw-r--r--ndb/test/src/Makefile.am2
-rw-r--r--ndb/test/src/getarg.c (renamed from ndb/src/common/util/getarg.c)32
-rw-r--r--ndb/tools/delete_all.cpp73
-rw-r--r--ndb/tools/desc.cpp82
-rw-r--r--ndb/tools/drop_index.cpp70
-rw-r--r--ndb/tools/drop_tab.cpp77
-rw-r--r--ndb/tools/listTables.cpp104
-rw-r--r--ndb/tools/select_all.cpp124
-rw-r--r--ndb/tools/select_count.cpp82
-rw-r--r--ndb/tools/waiter.cpp74
-rw-r--r--sql/field.cc19
-rw-r--r--sql/ha_ndbcluster.cc24
-rw-r--r--sql/ha_ndbcluster.h1
-rw-r--r--sql/item.cc126
-rw-r--r--sql/item.h28
-rw-r--r--sql/item_cmpfunc.cc87
-rw-r--r--sql/item_create.cc5
-rw-r--r--sql/item_func.cc114
-rw-r--r--sql/item_func.h7
-rw-r--r--sql/item_geofunc.cc6
-rw-r--r--sql/item_strfunc.cc74
-rw-r--r--sql/item_timefunc.cc4
-rw-r--r--sql/mysqld.cc9
-rw-r--r--sql/net_serv.cc12
-rw-r--r--sql/opt_range.cc15
-rw-r--r--sql/protocol.cc12
-rw-r--r--sql/protocol.h1
-rw-r--r--sql/spatial.cc4
-rw-r--r--sql/sql_class.cc6
-rw-r--r--sql/sql_parse.cc20
-rw-r--r--sql/sql_prepare.cc17
-rw-r--r--sql/sql_show.cc12
-rw-r--r--sql/sql_string.cc28
-rw-r--r--sql/sql_string.h4
-rw-r--r--sql/sql_table.cc16
-rw-r--r--sql/thr_malloc.cc5
-rw-r--r--strings/ctype-sjis.c9
-rw-r--r--tests/client_test.c1136
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 &mdash;
+ "-", "",
);
#
@@ -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'} = "&bull;";
$things_map{'copyright'} = "&copy;";
+ $things_map{'registeredsymbol'} = "&reg;";
$things_map{'dots'} = "&hellip;";
$things_map{'equiv'} = "&equiv;";
$things_map{'expansion'} = "&rarr;";
$things_map{'point'} = "&lowast;";
$things_map{'result'} = "&rArr;";
+ $things_map{'ss'} = "&szlig;";
+ $things_map{'o'} = "&oslash;";
+ $things_map{'O'} = "&Oslash;";
}
#
@@ -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, &not_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, &not_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");
+ }
}