Commit 673e1557 authored by unknown's avatar unknown

Merge paul@bk-internal.mysql.com:/home/bk/mysql-4.1

into teton.kitebird.com:/home/paul/mysql-4.1

parents 608bda36 15fcc884
......@@ -1113,7 +1113,7 @@ AC_DEFUN([MYSQL_CHECK_BDB_VERSION], [
# mysql_bdb=a
# fi
dbl RAM:
dnl RAM:
want_bdb_version="4.1.24"
bdb_version_ok=yes
......
......@@ -17,7 +17,12 @@
C_MODE_START
enum get_opt_var_type { GET_NO_ARG, GET_BOOL, GET_INT, GET_UINT, GET_LONG,
GET_ULONG, GET_LL, GET_ULL, GET_STR, GET_STR_ALLOC };
GET_ULONG, GET_LL, GET_ULL, GET_STR, GET_STR_ALLOC
};
#define GET_ASK_ADDR 128
#define GET_TYPE_MASK 127
enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG };
struct my_option
......@@ -48,6 +53,8 @@ extern int handle_options (int *argc, char ***argv,
char *));
extern void my_print_help(const struct my_option *options);
extern void my_print_variables(const struct my_option *options);
extern void my_getopt_register_get_addr(gptr* (*func_addr)(char *, uint,
const struct my_option *));
ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp);
my_bool getopt_compare_strings(const char *s, const char *t, uint length);
......
......@@ -215,21 +215,21 @@ drop table t1;
create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
update t1 set word2=word;
select word, word=0xdf as t from t1 having t > 0;
select word, word=binary 0xdf as t from t1 having t > 0;
word t
1
select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0;
word t
ss 1
1
select * from t1 where word=0xDF;
select * from t1 where word=binary 0xDF;
word word2
select * from t1 where word=CAST(0xDF as CHAR);
word word2
ss ss
select * from t1 where word2=0xDF;
select * from t1 where word2=binary 0xDF;
word word2
select * from t1 where word2=CAST(0xDF as CHAR);
......@@ -244,7 +244,7 @@ select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR);
word word2
ae ae
select * from t1 where word between 0xDF and 0xDF;
select * from t1 where word between binary 0xDF and binary 0xDF;
word word2
select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR);
......@@ -257,7 +257,7 @@ ae ae
select * from t1 where word like 'AE';
word word2
ae ae
select * from t1 where word like 0xDF;
select * from t1 where word like binary 0xDF;
word word2
select * from t1 where word like CAST(0xDF as CHAR);
......
......@@ -276,6 +276,48 @@ select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2);
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'substr_index'
select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2);
ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'substr_index'
select _latin1'B' between _latin1'a' and _latin1'c';
_latin1'B' between _latin1'a' and _latin1'c'
1
select _latin1'B' collate latin1_bin between _latin1'a' and _latin1'c';
_latin1'B' collate latin1_bin between _latin1'a' and _latin1'c'
0
select _latin1'B' between _latin1'a' collate latin1_bin and _latin1'c';
_latin1'B' between _latin1'a' collate latin1_bin and _latin1'c'
0
select _latin1'B' between _latin1'a' and _latin1'c' collate latin1_bin;
_latin1'B' between _latin1'a' and _latin1'c' collate latin1_bin
0
select _latin2'B' between _latin1'a' and _latin1'b';
ERROR HY000: Illegal mix of collations (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation 'between'
select _latin1'B' between _latin2'a' and _latin1'b';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation 'between'
select _latin1'B' between _latin1'a' and _latin2'b';
ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE) for operation 'between'
select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b';
ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_bin,EXPLICIT), (latin1_swedish_ci,COERCIBLE) for operation 'between'
select _latin1'B' in (_latin1'a',_latin1'b');
_latin1'B' in (_latin1'a',_latin1'b')
1
select _latin1'B' collate latin1_bin in (_latin1'a',_latin1'b');
_latin1'B' collate latin1_bin in (_latin1'a',_latin1'b')
0
select _latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b');
_latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b')
0
select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin);
_latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin)
0
select _latin2'B' in (_latin1'a',_latin1'b');
ERROR HY000: Illegal mix of collations for operation ' IN '
select _latin1'B' in (_latin2'a',_latin1'b');
ERROR HY000: Illegal mix of collations for operation ' IN '
select _latin1'B' in (_latin1'a',_latin2'b');
ERROR HY000: Illegal mix of collations for operation ' IN '
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a' COLLATE latin1_bin,_latin1'b');
ERROR HY000: Illegal mix of collations for operation ' IN '
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE latin1_bin);
ERROR HY000: Illegal mix of collations for operation ' IN '
select collation(bin(130)), coercibility(bin(130));
collation(bin(130)) coercibility(bin(130))
latin1_swedish_ci 3
......
......@@ -52,21 +52,24 @@ drop table t1;
# Test bug report #152 (problem with index on latin1_de)
#
#
# The below checks both binary and character comparisons.
#
create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
update t1 set word2=word;
select word, word=0xdf as t from t1 having t > 0;
select word, word=binary 0xdf as t from t1 having t > 0;
select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0;
select * from t1 where word=0xDF;
select * from t1 where word=binary 0xDF;
select * from t1 where word=CAST(0xDF as CHAR);
select * from t1 where word2=0xDF;
select * from t1 where word2=binary 0xDF;
select * from t1 where word2=CAST(0xDF as CHAR);
select * from t1 where word='ae';
select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR);
select * from t1 where word between 0xDF and 0xDF;
select * from t1 where word between binary 0xDF and binary 0xDF;
select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR);
select * from t1 where word like 'ae';
select * from t1 where word like 'AE';
select * from t1 where word like 0xDF;
select * from t1 where word like binary 0xDF;
select * from t1 where word like CAST(0xDF as CHAR);
drop table t1;
......@@ -162,6 +162,33 @@ select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2);
--error 1265
select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2);
select _latin1'B' between _latin1'a' and _latin1'c';
select _latin1'B' collate latin1_bin between _latin1'a' and _latin1'c';
select _latin1'B' between _latin1'a' collate latin1_bin and _latin1'c';
select _latin1'B' between _latin1'a' and _latin1'c' collate latin1_bin;
--error 1268
select _latin2'B' between _latin1'a' and _latin1'b';
--error 1268
select _latin1'B' between _latin2'a' and _latin1'b';
--error 1268
select _latin1'B' between _latin1'a' and _latin2'b';
--error 1268
select _latin1'B' collate latin1_general_ci between _latin1'a' collate latin1_bin and _latin1'b';
select _latin1'B' in (_latin1'a',_latin1'b');
select _latin1'B' collate latin1_bin in (_latin1'a',_latin1'b');
select _latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b');
select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin);
--error 1269
select _latin2'B' in (_latin1'a',_latin1'b');
--error 1269
select _latin1'B' in (_latin2'a',_latin1'b');
--error 1269
select _latin1'B' in (_latin1'a',_latin2'b');
--error 1269
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a' COLLATE latin1_bin,_latin1'b');
--error 1269
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE latin1_bin);
select collation(bin(130)), coercibility(bin(130));
select collation(oct(130)), coercibility(oct(130));
......
......@@ -34,6 +34,7 @@ static ulonglong getopt_ull(char *arg, const struct my_option *optp,
static void init_variables(const struct my_option *options);
static int setval(const struct my_option *opts, char *argument,
my_bool set_maximum_value);
static char *check_struct_option(char *cur_arg, char *key_name);
/*
The following three variables belong to same group and the number and
......@@ -67,6 +68,14 @@ my_bool my_getopt_print_errors= 1;
one. Call function 'get_one_option()' once for each option.
*/
static gptr* (*getopt_get_addr)(char *, uint, const struct my_option *);
void my_getopt_register_get_addr(gptr* (*func_addr)(char *, uint,
const struct my_option *))
{
getopt_get_addr= func_addr;
}
int handle_options(int *argc, char ***argv,
const struct my_option *longopts,
my_bool (*get_one_option)(int,
......@@ -76,8 +85,10 @@ int handle_options(int *argc, char ***argv,
uint opt_found, argvpos= 0, length, i;
my_bool end_of_options= 0, must_be_var, set_maximum_value, special_used,
option_is_loose;
char *progname= *(*argv), **pos, **pos_end, *optend, *prev_found;
char **pos, **pos_end, *optend, *prev_found,
*opt_str, key_name[FN_REFLEN];
const struct my_option *optp;
gptr *value;
int error;
LINT_INIT(opt_found);
......@@ -110,7 +121,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: Option '-O' requires an argument\n",
progname);
my_progname);
return EXIT_ARGUMENT_REQUIRED;
}
cur_arg= *pos;
......@@ -128,7 +139,7 @@ int handle_options(int *argc, char ***argv,
if (my_getopt_print_errors)
fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n",
progname);
my_progname);
return EXIT_ARGUMENT_REQUIRED;
}
}
......@@ -142,7 +153,7 @@ int handle_options(int *argc, char ***argv,
if (my_getopt_print_errors)
fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n",
progname);
my_progname);
return EXIT_ARGUMENT_REQUIRED;
}
cur_arg= *pos;
......@@ -159,19 +170,20 @@ int handle_options(int *argc, char ***argv,
continue;
}
}
optend= strcend(cur_arg, '=');
length= optend - cur_arg;
opt_str= check_struct_option(cur_arg, key_name);
optend= strcend(opt_str, '=');
length= optend - opt_str;
if (*optend == '=')
optend++;
else
optend=0;
optend= 0;
/*
Find first the right option. Return error in case of an ambiguous,
or unknown option
*/
optp= longopts;
if (!(opt_found= findopt(cur_arg, length, &optp, &prev_found)))
if (!(opt_found= findopt(opt_str, length, &optp, &prev_found)))
{
/*
Didn't find any matching option. Let's see if someone called
......@@ -183,18 +195,18 @@ int handle_options(int *argc, char ***argv,
must_be_var= 1; /* option is followed by an argument */
for (i= 0; special_opt_prefix[i]; i++)
{
if (!getopt_compare_strings(special_opt_prefix[i], cur_arg,
if (!getopt_compare_strings(special_opt_prefix[i], opt_str,
special_opt_prefix_lengths[i]) &&
cur_arg[special_opt_prefix_lengths[i]] == '-')
opt_str[special_opt_prefix_lengths[i]] == '-')
{
/*
We were called with a special prefix, we can reuse opt_found
*/
special_used= 1;
cur_arg+= (special_opt_prefix_lengths[i] + 1);
opt_str+= (special_opt_prefix_lengths[i] + 1);
if (i == OPT_LOOSE)
option_is_loose= 1;
if ((opt_found= findopt(cur_arg, length -
if ((opt_found= findopt(opt_str, length -
(special_opt_prefix_lengths[i] + 1),
&optp, &prev_found)))
{
......@@ -203,7 +215,7 @@ int handle_options(int *argc, char ***argv,
if (my_getopt_print_errors)
fprintf(stderr,
"%s: ambiguous option '--%s-%s' (--%s-%s)\n",
progname, special_opt_prefix[i], cur_arg,
my_progname, special_opt_prefix[i], opt_str,
special_opt_prefix[i], prev_found);
return EXIT_AMBIGUOUS_OPTION;
}
......@@ -237,8 +249,8 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr,
"%s: %s: unknown variable '%s'\n", progname,
option_is_loose ? "WARNING" : "ERROR", cur_arg);
"%s: %s: unknown variable '%s'\n", my_progname,
option_is_loose ? "WARNING" : "ERROR", opt_str);
if (!option_is_loose)
return EXIT_UNKNOWN_VARIABLE;
}
......@@ -246,8 +258,8 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr,
"%s: %s: unknown option '--%s'\n", progname,
option_is_loose ? "WARNING" : "ERROR", cur_arg);
"%s: %s: unknown option '--%s'\n", my_progname,
option_is_loose ? "WARNING" : "ERROR", opt_str);
if (!option_is_loose)
return EXIT_UNKNOWN_OPTION;
}
......@@ -264,57 +276,61 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: variable prefix '%s' is not unique\n",
progname, cur_arg);
my_progname, opt_str);
return EXIT_VAR_PREFIX_NOT_UNIQUE;
}
else
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: ambiguous option '--%s' (%s, %s)\n",
progname, cur_arg, prev_found, optp->name);
my_progname, opt_str, prev_found, optp->name);
return EXIT_AMBIGUOUS_OPTION;
}
}
if (must_be_var && optp->var_type == GET_NO_ARG)
if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG)
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: option '%s' cannot take an argument\n",
progname, optp->name);
my_progname, optp->name);
return EXIT_NO_ARGUMENT_ALLOWED;
}
value= optp->var_type & GET_ASK_ADDR ?
(*getopt_get_addr)(key_name, strlen(key_name), optp) : optp->value;
if (optp->arg_type == NO_ARG)
{
if (optend && optp->var_type != GET_BOOL)
if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL)
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: option '--%s' cannot take an argument\n",
progname, optp->name);
my_progname, optp->name);
return EXIT_NO_ARGUMENT_ALLOWED;
}
if (optp->var_type == GET_BOOL)
if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL)
{
/*
Set bool to 1 if no argument or if the user has used
--enable-'option-name'.
*optend was set to '0' if one used --disable-option
*/
*((my_bool*) optp->value)= (my_bool) (!optend || *optend == '1');
*((my_bool*) value)= (my_bool) (!optend || *optend == '1');
(*argc)--;
get_one_option(optp->id, optp, argument);
continue;
}
argument= optend;
}
else if (optp->arg_type == OPT_ARG && optp->var_type == GET_BOOL)
else if (optp->arg_type == OPT_ARG &&
(optp->var_type & GET_TYPE_MASK) == GET_BOOL)
{
if (optend == disabled_my_option)
*((my_bool*) optp->value)= (my_bool) 0;
*((my_bool*) value)= (my_bool) 0;
else
{
if (!optend) /* No argument -> enable option */
*((my_bool*) optp->value)= (my_bool) 1;
*((my_bool*) value)= (my_bool) 1;
else /* If argument differs from 0, enable option, else disable */
*((my_bool*) optp->value)= (my_bool) atoi(optend) != 0;
*((my_bool*) value)= (my_bool) atoi(optend) != 0;
}
(*argc)--;
continue;
......@@ -326,7 +342,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr, "%s: option '--%s' requires an argument\n",
progname, optp->name);
my_progname, optp->name);
return EXIT_ARGUMENT_REQUIRED;
}
argument= *pos;
......@@ -346,7 +362,8 @@ int handle_options(int *argc, char ***argv,
{
/* Option recognized. Find next what to do with it */
opt_found= 1;
if (optp->var_type == GET_BOOL && optp->arg_type == NO_ARG)
if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL &&
optp->arg_type == NO_ARG)
{
*((my_bool*) optp->value)= (my_bool) 1;
get_one_option(optp->id, optp, argument);
......@@ -370,7 +387,7 @@ int handle_options(int *argc, char ***argv,
if (my_getopt_print_errors)
fprintf(stderr,
"%s: option '-%c' requires an argument\n",
progname, optp->id);
my_progname, optp->id);
return EXIT_ARGUMENT_REQUIRED;
}
argument= *pos;
......@@ -382,7 +399,7 @@ int handle_options(int *argc, char ***argv,
{
fprintf(stderr,
"%s: Error while setting value '%s' to '%s'\n",
progname, argument, optp->name);
my_progname, argument, optp->name);
return error;
}
get_one_option(optp->id, optp, argument);
......@@ -393,7 +410,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
fprintf(stderr,
"%s: unknown option '-%c'\n", progname, *optend);
"%s: unknown option '-%c'\n", my_progname, *optend);
return EXIT_UNKNOWN_OPTION;
}
}
......@@ -404,7 +421,7 @@ int handle_options(int *argc, char ***argv,
{
fprintf(stderr,
"%s: Error while setting value '%s' to '%s'\n",
progname, argument, optp->name);
my_progname, argument, optp->name);
return error;
}
get_one_option(optp->id, optp, argument);
......@@ -424,6 +441,47 @@ int handle_options(int *argc, char ***argv,
return 0;
}
/*
function: check_struct_option
Arguments: Current argument under processing from argv and a variable
where to store the possible key name.
Return value: In case option is a struct option, returns a pointer to
the current argument at the position where the struct option (key_name)
ends, the next character after the dot. In case argument is not a struct
option, returns a pointer to the argument.
key_name will hold the name of the key, or 0 if not found.
*/
static char *check_struct_option(char *cur_arg, char *key_name)
{
char *ptr, *ptr2;
ptr= strcend(cur_arg, '.');
ptr2= strcend(cur_arg, '=');
/*
Minimum length for a struct option is 3 (--a.b)
If the (first) dot is after an equal sign, then it is part
of a variable value and the option is not a struct option.
*/
if (strlen(ptr) >= 3 && ptr2 - ptr > 0)
{
uint len= ptr - cur_arg;
strnmov(key_name, cur_arg, len);
key_name[len]= '\0';
return ++ptr;
}
else
{
key_name= 0;
return cur_arg;
}
}
/*
function: setval
......@@ -444,7 +502,7 @@ static int setval(const struct my_option *opts, char *argument,
if (!result_pos)
return EXIT_NO_PTR_TO_VARIABLE;
switch (opts->var_type) {
switch ((opts->var_type & GET_TYPE_MASK)) {
case GET_INT:
case GET_UINT: /* fall through */
*((int*) result_pos)= (int) getopt_ll(argument, opts, &err);
......@@ -634,7 +692,7 @@ static void init_variables(const struct my_option *options)
{
if (options->value)
{
switch (options->var_type) {
switch ((options->var_type & GET_TYPE_MASK)) {
case GET_BOOL:
if (options->u_max_value)
*((my_bool*) options->u_max_value)= (my_bool) options->max_value;
......@@ -706,13 +764,15 @@ void my_print_help(const struct my_option *options)
{
printf("--%s", optp->name);
col+= 2 + strlen(optp->name);
if (optp->var_type == GET_STR || optp->var_type == GET_STR_ALLOC)
if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
(optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC)
{
printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "",
optp->arg_type == OPT_ARG ? "]" : "");
col+= (optp->arg_type == OPT_ARG) ? 8 : 6;
}
else if (optp->var_type == GET_NO_ARG || optp->var_type == GET_BOOL)
else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
(optp->var_type & GET_TYPE_MASK) == GET_BOOL)
{
putchar(' ');
col++;
......@@ -775,7 +835,7 @@ void my_print_variables(const struct my_option *options)
length= strlen(optp->name);
for (; length < name_space; length++)
putchar(' ');
switch (optp->var_type) {
switch ((optp->var_type & GET_TYPE_MASK)) {
case GET_STR:
case GET_STR_ALLOC: /* fall through */
printf("%s\n", *((char**) optp->value) ? *((char**) optp->value) :
......
......@@ -39,7 +39,7 @@ Item::Item():
{
marker= 0;
maybe_null=null_value=with_sum_func=unsigned_flag=0;
set_charset(&my_charset_bin, DERIVATION_COERCIBLE);
set_charset(default_charset(), DERIVATION_COERCIBLE);
name= 0;
decimals= 0; max_length= 0;
THD *thd= current_thd;
......@@ -185,27 +185,27 @@ CHARSET_INFO * Item::default_charset() const
bool DTCollation::aggregate(DTCollation &dt)
{
if (collation == &my_charset_bin || dt.collation == &my_charset_bin)
{
collation= &my_charset_bin;
derivation= derivation > dt.derivation ? derivation : dt.derivation;
return 0;
}
if (!my_charset_same(collation, dt.collation))
{
/*
We do allow to use binary strings (like BLOBS)
together with character strings.
Binaries have more precedance
Binaries have more precedance than a character
string of the same derivation.
*/
if ((derivation <= dt.derivation) && (collation == &my_charset_bin))
if (collation == &my_charset_bin)
{
// Do nothing
if (derivation <= dt.derivation)
; // Do nothing
else
set(dt);
}
else if ((dt.derivation <= derivation) && (dt.collation==&my_charset_bin))
else if (dt.collation == &my_charset_bin)
{
if (dt.derivation <= derivation)
set(dt);
else
; // Do nothing
}
else
{
......
......@@ -32,6 +32,18 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fnam
fname);
}
static void my_coll_agg3_error(DTCollation &c1,
DTCollation &c2,
DTCollation &c3,
const char *fname)
{
my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0),
c1.collation->name,c1.derivation_name(),
c2.collation->name,c2.derivation_name(),
c3.collation->name,c3.derivation_name(),
fname);
}
Item_bool_func2* Item_bool_func2::eq_creator(Item *a, Item *b)
{
return new Item_func_eq(a, b);
......@@ -575,11 +587,19 @@ void Item_func_between::fix_length_and_dec()
cmp_type=item_cmp_type(args[0]->result_type(),
item_cmp_type(args[1]->result_type(),
args[2]->result_type()));
/* QQ: COERCIBILITY */
if (args[0]->binary() | args[1]->binary() | args[2]->binary())
cmp_charset= &my_charset_bin;
else
cmp_charset= args[0]->charset();
if (cmp_type == STRING_RESULT)
{
cmp_collation.set(args[0]->collation);
if (!cmp_collation.aggregate(args[1]->collation))
cmp_collation.aggregate(args[2]->collation);
if (cmp_collation.derivation == DERIVATION_NONE)
{
my_coll_agg3_error(args[0]->collation, args[1]->collation,
args[2]->collation, func_name());
return;
}
}
/*
Make a special case of compare with date/time and longlong fields.
......@@ -611,17 +631,17 @@ longlong Item_func_between::val_int()
a=args[1]->val_str(&value1);
b=args[2]->val_str(&value2);
if (!args[1]->null_value && !args[2]->null_value)
return (sortcmp(value,a,cmp_charset) >= 0 &&
sortcmp(value,b,cmp_charset) <= 0) ? 1 : 0;
return (sortcmp(value,a,cmp_collation.collation) >= 0 &&
sortcmp(value,b,cmp_collation.collation) <= 0) ? 1 : 0;
if (args[1]->null_value && args[2]->null_value)
null_value=1;
else if (args[1]->null_value)
{
null_value= sortcmp(value,b,cmp_charset) <= 0; // not null if false range.
null_value= sortcmp(value,b,cmp_collation.collation) <= 0; // not null if false range.
}
else
{
null_value= sortcmp(value,a,cmp_charset) >= 0; // not null if false range.
null_value= sortcmp(value,a,cmp_collation.collation) >= 0; // not null if false range.
}
}
else if (cmp_type == INT_RESULT)
......@@ -1176,17 +1196,17 @@ void Item_func_coalesce::fix_length_and_dec()
Classes and function for the IN operator
****************************************************************************/
static int cmp_longlong(longlong *a,longlong *b)
static int cmp_longlong(void *cmp_arg, longlong *a,longlong *b)
{
return *a < *b ? -1 : *a == *b ? 0 : 1;
}
static int cmp_double(double *a,double *b)
static int cmp_double(void *cmp_arg, double *a,double *b)
{
return *a < *b ? -1 : *a == *b ? 0 : 1;
}
static int cmp_row(cmp_item_row* a, cmp_item_row* b)
static int cmp_row(void *cmp_arg, cmp_item_row* a, cmp_item_row* b)
{
return a->compare(b);
}
......@@ -1203,18 +1223,18 @@ int in_vector::find(Item *item)
{
uint mid=(start+end+1)/2;
int res;
if ((res=(*compare)(base+mid*size,result)) == 0)
if ((res=(*compare)(collation, base+mid*size, result)) == 0)
return 1;
if (res < 0)
start=mid;
else
end=mid-1;
}
return (int) ((*compare)(base+start*size,result) == 0);
return (int) ((*compare)(collation, base+start*size, result) == 0);
}
in_string::in_string(uint elements,qsort_cmp cmp_func)
:in_vector(elements, sizeof(String), cmp_func),
in_string::in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs)
:in_vector(elements, sizeof(String), cmp_func, cs),
tmp(buff, sizeof(buff), &my_charset_bin)
{}
......@@ -1253,7 +1273,7 @@ in_row::in_row(uint elements, Item * item)
{
base= (char*) new cmp_item_row[count= elements];
size= sizeof(cmp_item_row);
compare= (qsort_cmp) cmp_row;
compare= (qsort2_cmp) cmp_row;
tmp.store_value(item);
}
......@@ -1278,7 +1298,7 @@ void in_row::set(uint pos, Item *item)
}
in_longlong::in_longlong(uint elements)
:in_vector(elements,sizeof(longlong),(qsort_cmp) cmp_longlong)
:in_vector(elements,sizeof(longlong),(qsort2_cmp) cmp_longlong, 0)
{}
void in_longlong::set(uint pos,Item *item)
......@@ -1295,7 +1315,7 @@ byte *in_longlong::get_value(Item *item)
}
in_double::in_double(uint elements)
:in_vector(elements,sizeof(double),(qsort_cmp) cmp_double)
:in_vector(elements,sizeof(double),(qsort2_cmp) cmp_double, 0)
{}
void in_double::set(uint pos,Item *item)
......@@ -1442,17 +1462,8 @@ bool Item_func_in::nulls_in_row()
return 0;
}
static int srtcmp_in(const String *x,const String *y)
{
CHARSET_INFO *cs= x->charset();
return cs->coll->strnncollsp(cs,
(unsigned char *) x->ptr(),x->length(),
(unsigned char *) y->ptr(),y->length());
}
static int bincmp_in(const String *x,const String *y)
static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
{
CHARSET_INFO *cs= &my_charset_bin;
return cs->coll->strnncollsp(cs,
(unsigned char *) x->ptr(),x->length(),
(unsigned char *) y->ptr(),y->length());
......@@ -1468,10 +1479,18 @@ void Item_func_in::fix_length_and_dec()
{
switch (item->result_type()) {
case STRING_RESULT:
if (item->binary())
array=new in_string(arg_count,(qsort_cmp) srtcmp_in);
else
array=new in_string(arg_count,(qsort_cmp) bincmp_in);
uint i;
cmp_collation.set(item->collation);
for (i=0 ; i<arg_count; i++)
if (cmp_collation.aggregate(args[i]->collation))
break;
if (cmp_collation.derivation == DERIVATION_NONE)
{
my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),func_name());
return;
}
array=new in_string(arg_count,(qsort2_cmp) srtcmp_in,
cmp_collation.collation);
break;
case INT_RESULT:
array= new in_longlong(arg_count);
......
......@@ -245,7 +245,7 @@ class Item_func_ne :public Item_bool_rowready_func2
class Item_func_between :public Item_int_func
{
CHARSET_INFO *cmp_charset;
DTCollation cmp_collation;
public:
Item_result cmp_type;
String value0,value1,value2;
......@@ -382,21 +382,23 @@ class in_vector :public Sql_alloc
protected:
char *base;
uint size;
qsort_cmp compare;
qsort2_cmp compare;
CHARSET_INFO *collation;
uint count;
public:
uint used_count;
in_vector() {}
in_vector(uint elements,uint element_length,qsort_cmp cmp_func)
in_vector(uint elements,uint element_length,qsort2_cmp cmp_func,
CHARSET_INFO *cmp_coll)
:base((char*) sql_calloc(elements*element_length)),
size(element_length), compare(cmp_func), count(elements),
used_count(elements) {}
size(element_length), compare(cmp_func), collation(cmp_coll),
count(elements), used_count(elements) {}
virtual ~in_vector() {}
virtual void set(uint pos,Item *item)=0;
virtual byte *get_value(Item *item)=0;
void sort()
{
qsort(base,used_count,size,compare);
qsort2(base,used_count,size,compare,collation);
}
int find(Item *item);
};
......@@ -406,7 +408,7 @@ class in_string :public in_vector
char buff[80];
String tmp;
public:
in_string(uint elements,qsort_cmp cmp_func);
in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs);
~in_string();
void set(uint pos,Item *item);
byte *get_value(Item *item);
......@@ -605,6 +607,7 @@ class Item_func_in :public Item_int_func
in_vector *array;
cmp_item *in_item;
bool have_null;
DTCollation cmp_collation;
public:
Item_func_in(Item *a,List<Item> &list)
:Item_int_func(list), item(a), array(0), in_item(0), have_null(0)
......
......@@ -4092,7 +4092,8 @@ replicating a LOAD DATA INFILE command.",
IO_SIZE, 0},
{"key_buffer_size", OPT_KEY_BUFFER_SIZE,
"The size of the buffer used for index blocks. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.",
(gptr*) &keybuff_size, (gptr*) &keybuff_size, 0, GET_ULL,
(gptr*) &keybuff_size, (gptr*) &keybuff_size, 0,
(enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR),
REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD,
IO_SIZE, 0},
{"long_query_time", OPT_LONG_QUERY_TIME,
......@@ -5298,10 +5299,19 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
/* Initiates DEBUG - but no debugging here ! */
extern "C" gptr *
mysql_getopt_value(char *keyname, uint key_length,
const struct my_option *option)
{
return option->value;
}
static void get_options(int argc,char **argv)
{
int ho_error;
my_getopt_register_get_addr(mysql_getopt_value);
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(ho_error);
if (argc > 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment