Fixed a lot of wrong memory references as reported by valgrind

Portability fixes
Added new client function: mysql_get_server_version()
New server help code (From Victor Vagin)
Fixed wrong usage of binary()
Disabled RTREE usage for now.



BitKeeper/etc/ignore:
  added scripts/fill_help_tables.sql
client/mysql.cc:
  Some fixes when using 'help'
cmd-line-utils/libedit/compat.h:
  Portability fix
cmd-line-utils/libedit/fgetln.c:
  Portability fix
include/mysql.h:
  Added new client function: mysql_get_server_version()
libmysql/libmysql.c:
  Added new client function: mysql_get_server_version()
libmysqld/libmysqld.c:
  Fixed prototype
mysql-test/install_test_db.sh:
  Added creation of help tables
mysql-test/r/connect.result:
  Added help tables
mysql-test/r/myisam.result:
  Test of RTREE index
mysql-test/r/type_ranges.result:
  updated results
mysql-test/t/myisam.test:
  Test of RTREE index
mysql-test/t/type_ranges.test:
  Updated test
mysys/charset.c:
  Indentation change
mysys/my_symlink.c:
  Removed compiler warning
scripts/fill_help_tables.sh:
  Update for new help tables
sql/field.cc:
  Indentation changes
sql/filesort.cc:
  Optimized character set usage
sql/item_cmpfunc.cc:
  Fix wrong usage of binary()
sql/item_cmpfunc.h:
  Fix wrong usage of binary()
sql/item_func.cc:
  Fix wrong usage of binary()
sql/item_func.h:
  Fix wrong usage of binary()
sql/item_strfunc.cc:
  Fix wrong usage of binary()
sql/item_sum.cc:
  Fix wrong usage of binary()
sql/item_sum.h:
  Fix wrong usage of binary()
sql/key.cc:
  Indentation change
sql/lex.h:
  HELP -> HELP_SYM
sql/mysql_priv.h:
  Make get_field() more general
sql/password.c:
  Indentation change + variable initialisation moved
sql/sql_acl.cc:
  Make get_field() more general
sql/sql_base.cc:
  Added comments + assertion for double call to mysql_lock_tables
sql/sql_cache.cc:
  Indentation changes
sql/sql_class.h:
  Added need_strxnfrm to SORT_FIELD to be able to optimise character set handling in filesort
sql/sql_derived.cc:
  Renamed variables
sql/sql_help.cc:
  New help functions (from Victor Vagin)
sql/sql_lex.cc:
  Removed variables that doesn't have to be initialized for each query
sql/sql_lex.h:
  Removed not used variable (olap)
sql/sql_parse.cc:
  Fixed (not fatal) access of unitialized memory
  Indentation / code cleanup
sql/sql_prepare.cc:
  Indentaion cleanup
sql/sql_table.cc:
  Disabled RTREE until 5.0
sql/sql_udf.cc:
  Make get_field() more general
sql/sql_yacc.yy:
  Removed access to uninitialized memory
  Always set offset_limit and select_limit when using LIMIT (removed warnings)
  Allow usage of 'help week'
sql/table.cc:
  Make get_field() more general
  More comments
sql/table.h:
  Fixded type of TABLE_LIST->derived
sql/time.cc:
  Stricter date / datetime handling (to be able to handle timestamps with days and microseconds)
strings/ctype-bin.c:
  Added cha
This commit is contained in:
unknown 2003-02-12 21:55:37 +02:00
parent 363fd89b92
commit fcb61f5917
48 changed files with 1200 additions and 650 deletions

View file

@ -596,3 +596,4 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
scripts/fill_help_tables.sql

View file

@ -1398,8 +1398,8 @@ int mysql_real_query_for_lazy(const char *buf, int length)
if (!mysql_real_query(&mysql,buf,length))
return 0;
uint error=put_info(mysql_error(&mysql),INFO_ERROR, mysql_errno(&mysql));
if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1
|| status.batch)
if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 ||
status.batch)
return error;
if (reconnect())
return error;
@ -1417,8 +1417,9 @@ int mysql_store_result_for_lazy(MYSQL_RES **result)
return 0;
}
static int com_server_help(String *buffer __attribute__((unused)),
char *line __attribute__((unused)), char *help_arg)
char *line __attribute__((unused)), char *help_arg)
{
MYSQL_ROW cur;
const char *server_cmd= buffer->ptr();
@ -1460,22 +1461,23 @@ static int com_server_help(String *buffer __attribute__((unused)),
init_pager();
if (cur[1][0] == 'Y')
{
tee_fprintf(PAGER, "\nHelp topic \'%s\'\n", cur[0]);
tee_fprintf(PAGER, "Help topic \'%s\'\n", cur[0]);
tee_fprintf(PAGER, "%s\n", cur[2]);
tee_fprintf(PAGER, "For help on specific function please type 'help <function>' where function is one of next :\n%s\n", cur[3]);
tee_fprintf(PAGER, "For help on specific function please type 'help <function>'\nwhere function is one of next:\n%s\n", cur[3]);
}
else
{
tee_fprintf(PAGER, "\nName : \'%s\'\n\n", cur[0]);
tee_fprintf(PAGER, "Description : \n%s\n\n", cur[2]);
tee_fprintf(PAGER, "Examples : \n%s\n", cur[3]);
tee_fprintf(PAGER, "Name: \'%s\'\n\n", cur[0]);
tee_fprintf(PAGER, "Description:\n%s\n\n", cur[2]);
if (cur[3])
tee_fprintf(PAGER, "Examples:\n%s\n", cur[3]);
}
end_pager();
}
else if (num_rows > 1)
{
put_info("\nMany help items for your request exist", INFO_INFO);
put_info("For more specific request please type 'help <item>' where item is one of next :", INFO_INFO);
put_info("Many help items for your request exist", INFO_INFO);
put_info("For more specific request please type 'help <item>' where item is one of next:", INFO_INFO);
init_pager();
char last_char= '_';
@ -1506,8 +1508,8 @@ err:
}
static int
com_help (String *buffer __attribute__((unused)),
char *line __attribute__((unused)))
com_help(String *buffer __attribute__((unused)),
char *line __attribute__((unused)))
{
reg1 int i;
char * help_arg= strchr(line,' ');
@ -1530,13 +1532,9 @@ com_help (String *buffer __attribute__((unused)),
tee_fprintf(stdout, "%s\t(\\%c)\t%s\n", commands[i].name,
commands[i].cmd_char, commands[i].doc);
}
if (connected)
tee_fprintf(stdout,
"\nConnection id: %ld (Can be used with mysqladmin kill)\n\n",
mysql_thread_id(&mysql));
else
tee_fprintf(stdout, "Not connected! Reconnect with 'connect'!\n\n");
}
if (connected && mysql_get_server_version(&mysql) >= 40100)
put_info("\nFor server side help, type 'help all'\n", INFO_INFO);
return 0;
}
@ -2417,7 +2415,6 @@ com_use(String *buffer __attribute__((unused)), char *line)
}
/*
Gets argument from a command on the command line. If get_next_arg is
not defined, skips the command and returns the first argument. The

View file

@ -36,4 +36,8 @@
#endif
#endif
#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8)
#define __attribute__(A)
#endif
#endif

View file

@ -56,7 +56,8 @@ getline (char **lineptr, size_t *n, FILE *stream)
if (*n >= new_size) /* Overflowed size_t */
line = NULL;
else
line = (char *)*lineptr ? realloc (*lineptr, new_size) : malloc (new_size);
line = (char *) (*lineptr ? (char*) realloc(*lineptr, new_size) :
(char*) malloc(new_size));
if (line)
{

View file

@ -419,6 +419,7 @@ int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid);
int STDCALL mysql_ping(MYSQL *mysql);
const char * STDCALL mysql_stat(MYSQL *mysql);
const char * STDCALL mysql_get_server_info(MYSQL *mysql);
unsigned long STDCALL mysql_get_server_version(MYSQL *mysql);
const char * STDCALL mysql_get_client_info(void);
const char * STDCALL mysql_get_host_info(MYSQL *mysql);
unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql);

View file

@ -3402,6 +3402,35 @@ mysql_get_server_info(MYSQL *mysql)
}
/*
Get version number for server in a form easy to test on
SYNOPSIS
mysql_get_server_version()
mysql Connection
EXAMPLE
4.1.0-alfa -> 40100
NOTES
We will ensure that a newer server always has a bigger number.
RETURN
Signed number > 323000
*/
ulong STDCALL
mysql_get_server_version(MYSQL *mysql)
{
uint major, minor, version;
char *pos= mysql->server_version, *end_pos;
major= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1;
minor= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1;
version= (uint) strtoul(pos, &end_pos, 10);
return (ulong) major*10000L+(ulong) (minor*100+version);
}
const char * STDCALL
mysql_get_host_info(MYSQL *mysql)
{

View file

@ -386,7 +386,7 @@ mysql_init(MYSQL *mysql)
}
static void mysql_once_init()
void STDCALL mysql_once_init()
{
if (!mysql_client_init)
{

View file

@ -66,6 +66,9 @@ c_h="" i_h=""
c_u="" i_u=""
c_f="" i_f=""
c_t="" c_c=""
c_hl="" c_hl=""
c_hc="" c_hc=""
c_clr="" c_clr=""
# Check for old tables
if test ! -f $mdata/db.frm
@ -207,6 +210,42 @@ then
c_c="$c_c comment='Column privileges';"
fi
if test ! -f $mdata/help_topic.frm
then
c_hl="$c_hl CREATE TABLE help_topic ("
c_hl="$c_hl help_topic_id int unsigned not null auto_increment,"
c_hl="$c_hl name varchar(64) not null,"
c_hl="$c_hl description text not null,"
c_hl="$c_hl example text not null,"
c_hl="$c_hl url varchar(128) not null,"
c_hl="$c_hl primary key (help_topic_id),"
c_hl="$c_hl unique index (name)"
c_hl="$c_hl )"
c_hl="$c_hl comment='help topics';"
fi
if test ! -f $mdata/help_category.frm
then
c_clr="$c_clr CREATE TABLE help_category ("
c_clr="$c_clr help_category_id smallint unsigned not null auto_increment,"
c_clr="$c_clr name varchar(64) not null,"
c_clr="$c_clr url varchar(128) not null,"
c_clr="$c_clr primary key (help_category_id),"
c_clr="$c_clr unique index (name)"
c_clr="$c_clr )"
c_clr="$c_clr comment='help topics-categories relation';"
fi
if test ! -f $mdata/help_relation.frm
then
c_hc="$c_hc CREATE TABLE help_relation ("
c_hc="$c_hc help_topic_id int unsigned not null references help_topic,"
c_hc="$c_hc help_category_id smallint unsigned not null references help_category,"
c_hc="$c_hc primary key (help_category_id, help_topic_id),"
c_hc="$c_hc )"
c_hc="$c_hc comment='categories of help topics';"
fi
mysqld_boot=" $execdir/mysqld --no-defaults --bootstrap --skip-grant-tables \
--basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $EXTRA_ARG"
echo "running $mysqld_boot"
@ -227,6 +266,10 @@ $i_f
$c_t
$c_c
$c_hl
$c_hc
$c_clr
END_OF_DATA
then
exit 0

View file

@ -3,6 +3,9 @@ Tables_in_mysql
columns_priv
db
func
help_category
help_relation
help_topic
host
tables_priv
user
@ -15,6 +18,9 @@ Tables_in_mysql
columns_priv
db
func
help_category
help_relation
help_topic
host
tables_priv
user
@ -27,6 +33,9 @@ Tables_in_mysql
columns_priv
db
func
help_category
help_relation
help_topic
host
tables_priv
user

123
mysql-test/r/help.result Normal file
View file

@ -0,0 +1,123 @@
truncate mysql.help_topic;
truncate mysql.help_category;
truncate mysql.help_relation;
insert into mysql.help_topic(name,description,example)values('impossible_function_1','description of \n impossible_function1','example of \n impossible_function1');
SELECT @topic1_id:=LAST_INSERT_ID();
@topic1_id:=LAST_INSERT_ID()
1
insert into mysql.help_topic(name,description,example)values('impossible_function_2','description of \n impossible_function2','example of \n impossible_function2');
SELECT @topic2_id:=LAST_INSERT_ID();
@topic2_id:=LAST_INSERT_ID()
2
insert into mysql.help_topic(name,description,example)values('impossible_function_3','description of \n impossible_function3','example of \n impossible_function3');
SELECT @topic3_id:=LAST_INSERT_ID();
@topic3_id:=LAST_INSERT_ID()
3
insert into mysql.help_category(name)values('impossible_category_1');
SELECT @category1_id:=LAST_INSERT_ID();
@category1_id:=LAST_INSERT_ID()
1
insert into mysql.help_category(name)values('impossible_category_2');
SELECT @category2_id:=LAST_INSERT_ID();
@category2_id:=LAST_INSERT_ID()
2
insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic1_id);
insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic2_id);
insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic2_id);
insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic3_id);
help 'function_of_my_dream';
Name Category
impossible_category_1 Y
impossible_category_2 Y
help '%possible_f%';
Name Category
impossible_function_1 N
impossible_function_2 N
impossible_function_3 N
help 'impossible_func%';
Name Category
impossible_function_1 N
impossible_function_2 N
impossible_function_3 N
help 'impossible_category%';
Name Category
impossible_category_1 Y
impossible_category_2 Y
help 'impossible_%';
Name Category
impossible_function_1 N
impossible_function_2 N
impossible_function_3 N
impossible_category_1 Y
impossible_category_2 Y
help '%function_2';
Name Category Description Example
impossible_function_2 N description of
impossible_function2 example of
impossible_function2
help '%category_2';
Name Category Description Example
impossible_category_2 Y impossible_function_2
impossible_function_3
help 'impossible_function_1';
Name Category Description Example
impossible_function_1 N description of
impossible_function1 example of
impossible_function1
help 'impossible_category_1';
Name Category Description Example
impossible_category_1 Y impossible_function_1
impossible_function_2
alter table mysql.help_topic type=innodb;
alter table mysql.help_category type=innodb;
alter table mysql.help_relation type=innodb;
help 'function_of_my_dream';
Name Category
impossible_category_1 Y
impossible_category_2 Y
help '%ble_f%';
Name Category
impossible_function_1 N
impossible_function_2 N
impossible_function_3 N
help 'impossible_func%';
Name Category
impossible_function_1 N
impossible_function_2 N
impossible_function_3 N
help 'impossible_category%';
Name Category
impossible_category_1 Y
impossible_category_2 Y
help 'impossible_%';
Name Category
impossible_function_1 N
impossible_function_2 N
impossible_function_3 N
impossible_category_1 Y
impossible_category_2 Y
help '%function_2';
Name Category Description Example
impossible_function_2 N description of
impossible_function2 example of
impossible_function2
help '%category_2';
Name Category Description Example
impossible_category_2 Y impossible_function_2
impossible_function_3
help 'impossible_function_1';
Name Category Description Example
impossible_function_1 N description of
impossible_function1 example of
impossible_function1
help 'impossible_category_1';
Name Category Description Example
impossible_category_1 Y impossible_function_1
impossible_function_2
alter table mysql.help_topic type=myisam;
alter table mysql.help_category type=myisam;
alter table mysql.help_relation type=myisam;

View file

@ -364,3 +364,8 @@ explain select * from t1 use index() where c=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
drop table t1,t2;
CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) TYPE=MyISAM;
This version of MySQL doesn't yet support 'RTREE INDEX'
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'

View file

@ -85,7 +85,7 @@ CREATE INDEX test3 on t1 ( medium ) ;
DROP INDEX test ON t1;
insert into t1 values (10, 1,1,1,1,1,1,1,1,1,1,1,1,1,NULL,0,0,0,1,1,1,1,'one','one');
insert into t1 values (NULL,2,2,2,2,2,2,2,2,2,2,2,2,2,NULL,NULL,NULL,NULL,NULL,NULL,2,2,'two','two,one');
insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303 101010','','','','3',3,3);
insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303101010','','','','3',3,3);
insert into t1 values (0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,NULL,19970807,080706,19970403090807,-1,-1,-1,'-1',-1,-1);
insert into t1 values (0,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,NULL,0,0,0,-4294967295,-4294967295,-4294967295,'-4294967295',0,"one,two,tree");
insert into t1 values (0,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,NULL,0,0,0,4294967295,4294967295,4294967295,'4294967295',0,0);

50
mysql-test/t/help.test Normal file
View file

@ -0,0 +1,50 @@
-- source include/have_innodb.inc
truncate mysql.help_topic;
truncate mysql.help_category;
truncate mysql.help_relation;
insert into mysql.help_topic(name,description,example)values('impossible_function_1','description of \n impossible_function1','example of \n impossible_function1');
SELECT @topic1_id:=LAST_INSERT_ID();
insert into mysql.help_topic(name,description,example)values('impossible_function_2','description of \n impossible_function2','example of \n impossible_function2');
SELECT @topic2_id:=LAST_INSERT_ID();
insert into mysql.help_topic(name,description,example)values('impossible_function_3','description of \n impossible_function3','example of \n impossible_function3');
SELECT @topic3_id:=LAST_INSERT_ID();
insert into mysql.help_category(name)values('impossible_category_1');
SELECT @category1_id:=LAST_INSERT_ID();
insert into mysql.help_category(name)values('impossible_category_2');
SELECT @category2_id:=LAST_INSERT_ID();
insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic1_id);
insert into mysql.help_relation(help_category_id,help_topic_id)values(@category1_id,@topic2_id);
insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic2_id);
insert into mysql.help_relation(help_category_id,help_topic_id)values(@category2_id,@topic3_id);
help 'function_of_my_dream';
help '%possible_f%';
help 'impossible_func%';
help 'impossible_category%';
help 'impossible_%';
help '%function_2';
help '%category_2';
help 'impossible_function_1';
help 'impossible_category_1';
alter table mysql.help_topic type=innodb;
alter table mysql.help_category type=innodb;
alter table mysql.help_relation type=innodb;
help 'function_of_my_dream';
help '%ble_f%';
help 'impossible_func%';
help 'impossible_category%';
help 'impossible_%';
help '%function_2';
help '%category_2';
help 'impossible_function_1';
help 'impossible_category_1';
alter table mysql.help_topic type=myisam;
alter table mysql.help_category type=myisam;
alter table mysql.help_relation type=myisam;

View file

@ -352,3 +352,12 @@ explain select * from t1 force index (a) where a=0 or a=2;
explain select * from t1 where c=1;
explain select * from t1 use index() where c=1;
drop table t1,t2;
#
# Test RTREE index
#
--error 1235
CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) TYPE=MyISAM;
# INSERT INTO t1 VALUES (1,1),(1,1);
# DELETE FROM rt WHERE a<1;
DROP TABLE IF EXISTS t1;

View file

@ -55,7 +55,7 @@ DROP INDEX test ON t1;
insert into t1 values (10, 1,1,1,1,1,1,1,1,1,1,1,1,1,NULL,0,0,0,1,1,1,1,'one','one');
insert into t1 values (NULL,2,2,2,2,2,2,2,2,2,2,2,2,2,NULL,NULL,NULL,NULL,NULL,NULL,2,2,'two','two,one');
insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303 101010','','','','3',3,3);
insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303101010','','','','3',3,3);
insert into t1 values (0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,NULL,19970807,080706,19970403090807,-1,-1,-1,'-1',-1,-1);
insert into t1 values (0,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,NULL,0,0,0,-4294967295,-4294967295,-4294967295,'-4294967295',0,"one,two,tree");
insert into t1 values (0,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,NULL,0,0,0,4294967295,4294967295,4294967295,'4294967295',0,0);

View file

@ -324,7 +324,7 @@ CHARSET_INFO *system_charset_info = &my_charset_latin1;
#define MY_ADD_CHARSET(x) all_charsets[(x)->number]=(x)
static my_bool init_compiled_charsets(myf flags __attribute__((unused)))
static my_bool init_compiled_charsets(myf flags __attribute__((unused)))
{
CHARSET_INFO *cs;

View file

@ -103,7 +103,8 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags)
#define BUFF_LEN FN_LEN
#endif
int my_realpath(char *to, const char *filename, myf MyFlags)
int my_realpath(char *to, const char *filename,
myf MyFlags __attribute__((unused)))
{
#if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH)
int result=0;

View file

@ -111,12 +111,12 @@ sub flush_all
$example= prepare_example($example);
if ($func_name ne "" && $text ne "" && !($func_name =~ /[abcdefghikjlmnopqrstuvwxyz]/)){
print "INSERT INTO function (name,description,example) VALUES (";
print "INSERT INTO help_topic (name,description,example) VALUES (";
print "'$func_name',";
print "'$text',";
print "'$example'";
print ");\n";
print "INSERT INTO function_category (cat_id,func_id) VALUES (\@cur_category,LAST_INSERT_ID());\n";
print "INSERT INTO help_relation (help_category_id,help_topic_id) VALUES (\@cur_category,LAST_INSERT_ID());\n";
}
$func_name= "";
@ -131,50 +131,43 @@ sub new_category
$category= prepare_text($category);
print "INSERT INTO function_category_name (name) VALUES (\'$category\');\n";
print "SELECT \@cur_category:=LAST_INSERT_ID();\n";
print "INSERT INTO help_category (name) VALUES (\'$category\');\n";
print "SET \@cur_category=LAST_INSERT_ID();\n";
}
print "INSERT INTO db (Host,DB,User,Select_priv) VALUES ('%','mysql_help','','Y');\n";
print "CREATE DATABASE mysql_help;\n";
#print "INSERT INTO db (Host,DB,User,Select_priv) VALUES ('%','mysql_help','','Y');\n";
#print "CREATE DATABASE mysql_help;\n";
print "USE mysql_help;\n";
print "USE mysql;\n";
print "DROP TABLE IF EXISTS function;\n";
print "CREATE TABLE function (";
print " func_id int unsigned not null auto_increment,";
print "DROP TABLE IF EXISTS help_topic;\n";
print "CREATE TABLE help_topic (";
print " help_topic_id int unsigned not null auto_increment,";
print " name varchar(64) not null,";
print " url varchar(128) not null,";
print " description text not null,";
print " example text not null,";
print " min_args tinyint not null,";
print " max_args tinyint,";
print " date_created datetime not null,";
print " last_modified timestamp not null,";
print " primary key (func_id)";
print ") type=myisam;\n\n";
print "DROP TABLE IF EXISTS function_category_name;\n";
print "CREATE TABLE function_category_name (";
print " cat_id smallint unsigned not null auto_increment,";
print " name varchar(64) not null,";
print " url varchar(128) not null,";
print " date_created datetime not null,";
print " last_modified timestamp not null,";
print " primary key (cat_id)";
print " primary key (help_topic_id),";
print " uniuqe index(name)";
print ") type=myisam;\n\n";
print "DROP TABLE IF EXISTS function_category;\n";
print "CREATE TABLE function_category (";
print " cat_id smallint unsigned not null references function_category_name,";
print " func_id int unsigned not null references function,";
print " primary key (cat_id, func_id)";
print "DROP TABLE IF EXISTS help_category;\n";
print "CREATE TABLE help_category (";
print " help_category_id smallint unsigned not null auto_increment,";
print " name varchar(64) not null,";
print " url varchar(128) not null,";
print " primary key (help_category_id),";
print " unique index (name)";
print ") type=myisam;\n\n";
print "DELETE FROM function_category_name;\n";
print "DELETE FROM function_category;\n";
print "DELETE FROM function;\n";
print "SELECT \@cur_category:=null;\n\n";
print "DROP TABLE IF EXISTS help_relation;\n";
print "CREATE TABLE help_relation (";
print" help_topic_id int unsigned not null references help_topic,";
print" help_category_id smallint unsigned not null references help_category,";
print" primary key (help_category_id, help_topic_id),";
print ") type=myisam;\n\n";
print "SET \@cur_category=null;\n\n";
my $in_section_6_3= 0;
@ -239,8 +232,8 @@ for(<>)
}
print "DELETE function_category_name ";
print "FROM function_category_name ";
print "LEFT JOIN function_category ON function_category.cat_id=function_category_name.cat_id ";
print "WHERE function_category.cat_id is null;"
print "DELETE help_category ";
print "FROM help_category ";
print "LEFT JOIN help_relation ON help_category.help_category_id=help_relation.help_category_id ";
print "WHERE help_relation.help_category_id is null;"

View file

@ -4226,7 +4226,8 @@ uint Field_varstring::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length;
}
void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,imagetype type)
void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
imagetype type)
{
length-= HA_KEY_BLOB_LENGTH;
uint f_length=uint2korr(ptr);
@ -4478,7 +4479,7 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
/* The following is used only when comparing a key */
void Field_blob::get_key_image(char *buff,uint length,
CHARSET_INFO *cs,imagetype type)
CHARSET_INFO *cs, imagetype type)
{
length-= HA_KEY_BLOB_LENGTH;
uint32 blob_length= get_length(ptr);
@ -4522,7 +4523,8 @@ void Field_blob::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
}
void Field_geom::get_key_image(char *buff,uint length,CHARSET_INFO *cs, imagetype type)
void Field_geom::get_key_image(char *buff,uint length,CHARSET_INFO *cs,
imagetype type)
{
length-=HA_KEY_BLOB_LENGTH;
ulong blob_length=get_length(ptr);

View file

@ -49,7 +49,8 @@ static int merge_index(SORTPARAM *param,uchar *sort_buffer,
uint maxbuffer,IO_CACHE *tempfile,
IO_CACHE *outfile);
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
static uint sortlength(SORT_FIELD *sortorder,uint length);
static uint sortlength(SORT_FIELD *sortorder, uint s_length,
bool *multi_byte_charset);
/*
Creates a set of pointers that can be used to read the rows
@ -75,19 +76,13 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
uchar **sort_keys;
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
SORTPARAM param;
CHARSET_INFO *charset= &my_charset_bin;
bool multi_byte_charset;
DBUG_ENTER("filesort");
DBUG_EXECUTE("info",TEST_filesort(sortorder,s_length););
#ifdef SKIP_DBUG_IN_FILESORT
DBUG_PUSH(""); /* No DBUG here */
#endif
// BAR TODO: this is not absolutely correct, but OK for now
for (i=0;i<table->fields;i++)
if (!table->field[i]->binary())
charset=table->field[i]->charset();
// /BAR TODO
outfile= table->io_cache;
my_b_clear(&tempfile);
my_b_clear(&buffpek_pointers);
@ -96,7 +91,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
error= 1;
bzero((char*) &param,sizeof(param));
param.ref_length= table->file->ref_length;
param.sort_length=sortlength(sortorder,s_length)+ param.ref_length;
param.sort_length= (sortlength(sortorder,s_length, &multi_byte_charset)+
param.ref_length);
param.max_rows= max_rows;
if (select && select->quick)
@ -123,7 +119,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
if (param.sort_length == param.ref_length && records > param.max_rows)
records=param.max_rows; /* purecov: inspected */
if (use_strnxfrm(charset) &&
if (multi_byte_charset &&
!(param.tmp_buffer=my_malloc(param.sort_length,MYF(MY_WME))))
goto err;
@ -493,28 +489,19 @@ static void make_sortkey(register SORTPARAM *param,
diff=0; /* purecov: inspected */
length=sort_field->length;
}
if (use_strnxfrm(cs))
if (sort_field->need_strxnfrm)
{
if (item->binary())
{
if (res->ptr() != (char*) to)
memcpy(to,res->ptr(),length);
bzero((char*) to+length,diff);
}
else
{
char *from=(char*) res->ptr();
if ((unsigned char *)from == to)
{
set_if_smaller(length,sort_field->length);
memcpy(param->tmp_buffer,from,length);
from=param->tmp_buffer;
}
uint tmp_length=my_strnxfrm(cs,to,sort_field->length,
(unsigned char *) from, length);
if (tmp_length < sort_field->length)
bzero((char*) to+tmp_length,sort_field->length-tmp_length);
}
char *from=(char*) res->ptr();
if ((unsigned char *)from == to)
{
set_if_smaller(length,sort_field->length);
memcpy(param->tmp_buffer,from,length);
from=param->tmp_buffer;
}
uint tmp_length=my_strnxfrm(cs,to,sort_field->length,
(unsigned char *) from, length);
if (tmp_length < sort_field->length)
bzero((char*) to+tmp_length,sort_field->length-tmp_length);
}
else
{
@ -907,17 +894,36 @@ static int merge_index(SORTPARAM *param, uchar *sort_buffer,
} /* merge_index */
/* Calculate length of sort key */
/*
Calculate length of sort key
SYNOPSIS
sortlength()
sortorder Order of items to sort
uint s_length Number of items to sort
multi_byte_charset (out)
Set to 1 if we are using multi-byte charset
(In which case we have to use strxnfrm())
NOTES
sortorder->length is updated for each sort item
sortorder->need_strxnfrm is set 1 if we have to use strxnfrm
RETURN
Total length of sort buffer in bytes
*/
static uint
sortlength(SORT_FIELD *sortorder, uint s_length)
sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset)
{
reg2 uint length;
THD *thd= current_thd;
*multi_byte_charset= 0;
length=0;
for (; s_length-- ; sortorder++)
{
sortorder->need_strxnfrm= 0;
if (sortorder->field)
{
if (sortorder->field->type() == FIELD_TYPE_BLOB)
@ -929,7 +935,11 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
{
CHARSET_INFO *cs=sortorder->field->charset();
if (use_strnxfrm(cs))
{
sortorder->need_strxnfrm= 1;
*multi_byte_charset= 1;
sortorder->length= sortorder->length*cs->strxfrm_multiply;
}
}
}
if (sortorder->field->maybe_null())
@ -944,7 +954,11 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
{
CHARSET_INFO *cs=sortorder->item->charset();
if (use_strnxfrm(cs))
{
sortorder->length= sortorder->length*cs->strxfrm_multiply;
sortorder->need_strxnfrm= 1;
*multi_byte_charset= 1;
}
}
break;
case INT_RESULT:

View file

@ -125,8 +125,10 @@ void Item_bool_func2::fix_length_and_dec()
}
}
set_cmp_func();
binary_cmp= args[0]->binary() || args[1]->binary();
}
int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
{
owner= item;
@ -165,7 +167,7 @@ int Arg_comparator::compare_string()
if ((res2= (*b)->val_str(&owner->tmp_value2)))
{
owner->null_value= 0;
return owner->binary() ? stringcmp(res1,res2) : sortcmp(res1,res2);
return owner->binary_cmp ? stringcmp(res1,res2) : sortcmp(res1,res2);
}
}
owner->null_value= 1;
@ -179,7 +181,7 @@ int Arg_comparator::compare_e_string()
res2= (*b)->val_str(&owner->tmp_value2);
if (!res1 || !res2)
return test(res1 == res2);
return (owner->binary() ? test(stringcmp(res1, res2) == 0) :
return (owner->binary_cmp ? test(stringcmp(res1, res2) == 0) :
test(sortcmp(res1, res2) == 0));
}
@ -274,6 +276,7 @@ bool Item_in_optimizer::preallocate_row()
return (!(cache= Item_cache::get_cache(ROW_RESULT)));
}
bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
Item ** ref)
{
@ -281,8 +284,12 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
return 1;
if (args[0]->maybe_null)
maybe_null=1;
/*
TODO: Check if following is right
(set_charset set type of result, not how compare should be used)
*/
if (args[0]->binary())
set_charset(&my_charset_bin);
set_charset(&my_charset_bin);
with_sum_func= args[0]->with_sum_func;
used_tables_cache= args[0]->used_tables();
const_item_cache= args[0]->const_item();
@ -395,7 +402,7 @@ longlong Item_func_strcmp::val_int()
null_value=1;
return 0;
}
int value= binary() ? stringcmp(a,b) : sortcmp(a,b);
int value= binary_cmp ? stringcmp(a,b) : sortcmp(a,b);
null_value=0;
return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
}
@ -659,7 +666,7 @@ Item_func_if::fix_length_and_dec()
else if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT)
{
cached_result_type = STRING_RESULT;
set_charset( (args[1]->binary() || args[2]->binary()) ?
set_charset((args[1]->binary() || args[2]->binary()) ?
&my_charset_bin : args[1]->charset());
}
else
@ -802,7 +809,7 @@ Item *Item_func_case::find_item(String *str)
}
if ((tmp=args[i]->val_str(str))) // If not null
{
if (first_expr->binary() || args[i]->binary())
if (first_expr_is_binary || args[i]->binary())
{
if (stringcmp(tmp,first_expr_str)==0)
return args[i+1];
@ -912,6 +919,7 @@ Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
used_tables_cache|=(first_expr)->used_tables();
const_item_cache&= (first_expr)->const_item();
with_sum_func= with_sum_func || (first_expr)->with_sum_func;
first_expr_is_binary= first_expr->binary();
}
if (else_expr)
{
@ -1193,7 +1201,7 @@ byte *in_double::get_value(Item *item)
return (byte*) &tmp;
}
cmp_item* cmp_item::get_comparator (Item *item)
cmp_item* cmp_item::get_comparator(Item *item)
{
switch (item->result_type()) {
case STRING_RESULT:
@ -1368,7 +1376,7 @@ void Item_func_in::fix_length_and_dec()
}
else
{
in_item= cmp_item:: get_comparator(item);
in_item= cmp_item::get_comparator(item);
}
maybe_null= item->maybe_null;
max_length= 1;
@ -1690,13 +1698,6 @@ longlong Item_func_isnotnull::val_int()
}
void Item_func_like::fix_length_and_dec()
{
decimals= 0;
max_length= 1;
// cmp_type=STRING_RESULT; // For quick select
}
longlong Item_func_like::val_int()
{
String* res = args[0]->val_str(&tmp_value1);
@ -1740,6 +1741,7 @@ Item_func::optimize_type Item_func_like::select_optimize() const
return OPTIMIZE_NONE;
}
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{
if (Item_bool_func2::fix_fields(thd, tlist, ref))
@ -1800,8 +1802,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
max_length= 1;
decimals= 0;
if (args[0]->binary() || args[1]->binary())
set_charset(&my_charset_bin);
binary_cmp= (args[0]->binary() || args[1]->binary());
used_tables_cache=args[0]->used_tables() | args[1]->used_tables();
const_item_cache=args[0]->const_item() && args[1]->const_item();
@ -1817,7 +1818,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
int error;
if ((error=regcomp(&preg,res->c_ptr(),
binary() ? REG_EXTENDED | REG_NOSUB :
binary_cmp ? REG_EXTENDED | REG_NOSUB :
REG_EXTENDED | REG_NOSUB | REG_ICASE,
res->charset())))
{
@ -1834,6 +1835,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 0;
}
longlong Item_func_regex::val_int()
{
char buff[MAX_FIELD_WIDTH];
@ -1865,7 +1867,7 @@ longlong Item_func_regex::val_int()
regex_compiled=0;
}
if (regcomp(&preg,res2->c_ptr(),
binary() ? REG_EXTENDED | REG_NOSUB :
binary_cmp ? REG_EXTENDED | REG_NOSUB :
REG_EXTENDED | REG_NOSUB | REG_ICASE,
res->charset()))
@ -1915,7 +1917,7 @@ void Item_func_like::turboBM_compute_suffixes(int *suff)
*splm1 = pattern_len;
if (binary())
if (binary_cmp)
{
int i;
for (i = pattern_len - 2; i >= 0; i--)
@ -2018,7 +2020,7 @@ void Item_func_like::turboBM_compute_bad_character_shifts()
for (i = bmBc; i < end; i++)
*i = pattern_len;
if (binary())
if (binary_cmp)
{
for (j = 0; j < plm1; j++)
bmBc[(uint) (uchar) pattern[j]] = plm1 - j;
@ -2049,7 +2051,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
const int tlmpl= text_len - pattern_len;
/* Searching */
if (binary())
if (binary_cmp)
{
while (j <= tlmpl)
{

View file

@ -112,6 +112,8 @@ class Item_bool_func2 :public Item_int_func
protected:
Arg_comparator cmp;
String tmp_value1,tmp_value2;
bool binary_cmp;
public:
Item_bool_func2(Item *a,Item *b):
Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
@ -125,6 +127,7 @@ public:
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
void print(String *str) { Item_func::print_op(str); }
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
virtual bool binary() const { return binary_cmp; }
static Item_bool_func2* eq_creator(Item *a, Item *b);
static Item_bool_func2* ne_creator(Item *a, Item *b);
@ -156,7 +159,7 @@ public:
class Item_func_eq :public Item_bool_rowready_func2
{
public:
Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { };
Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
longlong val_int();
enum Functype functype() const { return EQ_FUNC; }
enum Functype rev_functype() const { return EQ_FUNC; }
@ -180,7 +183,7 @@ public:
class Item_func_ge :public Item_bool_rowready_func2
{
public:
Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { };
Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
longlong val_int();
enum Functype functype() const { return GE_FUNC; }
enum Functype rev_functype() const { return LE_FUNC; }
@ -192,7 +195,7 @@ public:
class Item_func_gt :public Item_bool_rowready_func2
{
public:
Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { };
Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
longlong val_int();
enum Functype functype() const { return GT_FUNC; }
enum Functype rev_functype() const { return LT_FUNC; }
@ -204,7 +207,7 @@ public:
class Item_func_le :public Item_bool_rowready_func2
{
public:
Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { };
Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
longlong val_int();
enum Functype functype() const { return LE_FUNC; }
enum Functype rev_functype() const { return GE_FUNC; }
@ -216,7 +219,7 @@ public:
class Item_func_lt :public Item_bool_rowready_func2
{
public:
Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }
Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
longlong val_int();
enum Functype functype() const { return LT_FUNC; }
enum Functype rev_functype() const { return GT_FUNC; }
@ -228,7 +231,7 @@ public:
class Item_func_ne :public Item_bool_rowready_func2
{
public:
Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }
Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
longlong val_int();
enum Functype functype() const { return NE_FUNC; }
cond_result eq_cmp_result() const { return COND_FALSE; }
@ -257,7 +260,11 @@ class Item_func_strcmp :public Item_bool_func2
public:
Item_func_strcmp(Item *a,Item *b) :Item_bool_func2(a,b) {}
longlong val_int();
void fix_length_and_dec() { max_length=2; }
void fix_length_and_dec()
{
max_length=2;
binary_cmp= args[0]->binary() || args[1]->binary();
}
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
const char *func_name() const { return "strcmp"; }
};
@ -280,7 +287,9 @@ class Item_func_ifnull :public Item_func
{
enum Item_result cached_result_type;
public:
Item_func_ifnull(Item *a,Item *b) :Item_func(a,b) { }
Item_func_ifnull(Item *a,Item *b)
:Item_func(a,b), cached_result_type(INT_RESULT)
{}
double val();
longlong val_int();
String *val_str(String *str);
@ -294,7 +303,9 @@ class Item_func_if :public Item_func
{
enum Item_result cached_result_type;
public:
Item_func_if(Item *a,Item *b,Item *c) :Item_func(a,b,c) { }
Item_func_if(Item *a,Item *b,Item *c)
:Item_func(a,b,c), cached_result_type(INT_RESULT)
{}
double val();
longlong val_int();
String *val_str(String *str);
@ -313,7 +324,9 @@ class Item_func_nullif :public Item_bool_func2
{
enum Item_result cached_result_type;
public:
Item_func_nullif(Item *a,Item *b) :Item_bool_func2(a,b) { }
Item_func_nullif(Item *a,Item *b)
:Item_bool_func2(a,b), cached_result_type(INT_RESULT)
{}
double val();
longlong val_int();
String *val_str(String *str);
@ -327,7 +340,9 @@ class Item_func_coalesce :public Item_func
{
enum Item_result cached_result_type;
public:
Item_func_coalesce(List<Item> &list) :Item_func(list) {}
Item_func_coalesce(List<Item> &list)
:Item_func(list),cached_result_type(INT_RESULT)
{}
double val();
longlong val_int();
String *val_str(String *);
@ -341,9 +356,12 @@ class Item_func_case :public Item_func
Item * first_expr, *else_expr;
enum Item_result cached_result_type;
String tmp_value;
bool first_expr_is_binary;
public:
Item_func_case(List<Item> &list, Item *first_expr_, Item *else_expr_)
:Item_func(list), first_expr(first_expr_), else_expr(else_expr_) {}
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
:Item_func(list), first_expr(first_expr_arg), else_expr(else_expr_arg),
cached_result_type(INT_RESULT)
{}
double val();
longlong val_int();
String *val_str(String *);
@ -723,7 +741,6 @@ public:
optimize_type select_optimize() const;
cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "like"; }
void fix_length_and_dec();
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
};
@ -737,6 +754,7 @@ class Item_func_regex :public Item_bool_func
bool regex_compiled;
bool regex_is_const;
String prev_regexp;
bool binary_cmp;
public:
Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
regex_compiled(0),regex_is_const(0) {}

View file

@ -80,6 +80,7 @@ Item_func::Item_func(List<Item> &list):
str_value.charset If this is a string function, set this to the
character set for the first argument.
If any argument is binary, this is set to binary
If for any item any of the defaults are wrong, then this can
be fixed in the fix_length_and_dec() function that is called
@ -96,6 +97,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
Item **arg,**arg_end;
char buff[STACK_BUFF_ALLOC]; // Max argument in function
used_tables_cache=0;
const_item_cache=1;
@ -103,6 +105,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 0; // Fatal error if flag is set!
if (arg_count)
{ // Print purify happy
CHARSET_INFO *charset= 0;
/*
Set return character set to first argument if we are returning a
string.
@ -115,15 +118,21 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if ((*arg)->maybe_null)
maybe_null=1;
if ((*arg)->binary())
set_charset(&my_charset_bin);
charset= &my_charset_bin;
else if (!charset && (*arg)->result_type() == STRING_RESULT)
charset= (*arg)->charset();
with_sum_func= with_sum_func || (*arg)->with_sum_func;
used_tables_cache|=(*arg)->used_tables();
const_item_cache&= (*arg)->const_item();
}
/*
We must set charset here as fix_length_and_dec() may want to change
charset
*/
if (charset && result_type() == STRING_RESULT)
set_charset(charset);
}
fix_length_and_dec();
if (result_type() == STRING_RESULT)
set_charset((*args)->charset());
fixed= 1;
return 0;
}
@ -847,6 +856,8 @@ void Item_func_min_max::fix_length_and_dec()
if (args[i]->binary())
set_charset(&my_charset_bin);
}
if (cmp_type == STRING_RESULT)
str_cmp_function= binary() ? stringcmp : sortcmp;
}
@ -891,7 +902,7 @@ String *Item_func_min_max::val_str(String *str)
res2= args[i]->val_str(res == str ? &tmp_value : str);
if (res2)
{
int cmp=binary() ? stringcmp(res,res2) : sortcmp(res,res2);
int cmp= (*str_cmp_function)(res,res2);
if ((cmp_sign < 0 ? cmp : -cmp) < 0)
res=res2;
}
@ -994,7 +1005,6 @@ longlong Item_func_locate::val_int()
{
String *a=args[0]->val_str(&value1);
String *b=args[1]->val_str(&value2);
bool binary_str = args[0]->binary() || args[1]->binary();
if (!a || !b)
{
null_value=1;
@ -1012,7 +1022,7 @@ longlong Item_func_locate::val_int()
if (use_mb(a->charset()))
{
start0=start;
if (!binary_str)
if (!binary_cmp)
start=a->charpos(start);
}
#endif
@ -1022,7 +1032,7 @@ longlong Item_func_locate::val_int()
if (!b->length()) // Found empty string at start
return (longlong) (start+1);
#ifdef USE_MB
if (use_mb(a->charset()) && !binary_str)
if (use_mb(a->charset()) && !binary_cmp)
{
const char *ptr=a->ptr()+start;
const char *search=b->ptr();
@ -1049,7 +1059,7 @@ longlong Item_func_locate::val_int()
return 0;
}
#endif /* USE_MB */
return (longlong) (binary() ? a->strstr(*b,start) :
return (longlong) (binary_cmp ? a->strstr(*b,start) :
(a->strstr_case(*b,start)))+1;
}
@ -1662,7 +1672,7 @@ longlong Item_master_pos_wait::val_int()
{
THD* thd = current_thd;
String *log_name = args[0]->val_str(&value);
int event_count;
int event_count= 0;
null_value=0;
if (thd->slave_thread || !log_name || !log_name->length())

View file

@ -524,9 +524,10 @@ class Item_func_min_max :public Item_func
Item_result cmp_type;
String tmp_value;
int cmp_sign;
int (*str_cmp_function)(const String *x,const String *y);
public:
Item_func_min_max(List<Item> &list,int cmp_sign_arg) :Item_func(list),
cmp_sign(cmp_sign_arg) {}
cmp_type(INT_RESULT), cmp_sign(cmp_sign_arg) {}
double val();
longlong val_int();
String *val_str(String *);
@ -590,12 +591,17 @@ public:
class Item_func_locate :public Item_int_func
{
String value1,value2;
bool binary_cmp;
public:
Item_func_locate(Item *a,Item *b) :Item_int_func(a,b) {}
Item_func_locate(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
const char *func_name() const { return "locate"; }
longlong val_int();
void fix_length_and_dec() { maybe_null=0; max_length=11; }
void fix_length_and_dec()
{
maybe_null=0; max_length=11;
binary_cmp = args[0]->binary() || args[1]->binary();
}
};

View file

@ -701,7 +701,7 @@ String *Item_func_replace::val_str(String *str)
#ifdef USE_MB
const char *ptr,*end,*strend,*search,*search_end;
register uint32 l;
bool binary_str;
bool binary_cmp;
#endif
null_value=0;
@ -713,7 +713,7 @@ String *Item_func_replace::val_str(String *str)
goto null;
#ifdef USE_MB
binary_str = (args[0]->binary() || args[1]->binary() || !use_mb(res->charset()));
binary_cmp = (args[0]->binary() || args[1]->binary() || !use_mb(res->charset()));
#endif
if (res2->length() == 0)
@ -723,7 +723,7 @@ String *Item_func_replace::val_str(String *str)
return res;
#else
offset=0;
if (binary_str && (offset=res->strstr(*res2)) < 0)
if (binary_cmp && (offset=res->strstr(*res2)) < 0)
return res;
#endif
if (!(res3=args[2]->val_str(&tmp_value2)))
@ -732,7 +732,7 @@ String *Item_func_replace::val_str(String *str)
to_length= res3->length();
#ifdef USE_MB
if (!binary_str)
if (!binary_cmp)
{
search=res2->ptr();
search_end=search+from_length;

View file

@ -187,7 +187,10 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
else if (hybrid_type == REAL_RESULT)
max_length=float_length(decimals);
else
{
str_cmp_function= binary() ? stringcmp : sortcmp;
max_length=item->max_length;
}
decimals=item->decimals;
maybe_null=item->maybe_null;
unsigned_flag=item->unsigned_flag;
@ -434,8 +437,7 @@ bool Item_sum_min::add()
{
String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value &&
(null_value ||
(binary() ? stringcmp(&value,result) : sortcmp(&value,result)) > 0))
(null_value || (*str_cmp_function)(&value,result) > 0))
{
value.copy(*result);
null_value=0;
@ -481,8 +483,7 @@ bool Item_sum_max::add()
{
String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value &&
(null_value ||
(binary() & MY_CS_BINSORT ? stringcmp(&value,result) : sortcmp(&value,result)) < 0))
(null_value || (*str_cmp_function)(&value,result) < 0))
{
value.copy(*result);
null_value=0;
@ -757,8 +758,7 @@ Item_sum_hybrid::min_max_update_str_field(int offset)
result_field->ptr-=offset;
if (result_field->is_null() ||
(cmp_sign * (binary() ? stringcmp(res_str,&tmp_value) :
sortcmp(res_str,&tmp_value)) < 0))
(cmp_sign * (*str_cmp_function)(res_str,&tmp_value)) < 0)
result_field->store(res_str->ptr(),res_str->length(),res_str->charset());
else
{ // Use old value

View file

@ -369,9 +369,11 @@ class Item_sum_hybrid :public Item_sum
enum_field_types hybrid_field_type;
int cmp_sign;
table_map used_table_cache;
int (*str_cmp_function)(const String *x,const String *y);
public:
Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign),
Item_sum_hybrid(Item *item_par,int sign)
:Item_sum(item_par), hybrid_type(INT_RESULT), cmp_sign(sign),
used_table_cache(~(table_map) 0)
{}
Item_sum_hybrid(THD *thd, Item_sum_hybrid &item):

View file

@ -194,7 +194,8 @@ int key_cmp(TABLE *table,const byte *key,uint idx,uint key_length)
{
if (my_strnncoll(key_part->field->charset(),
(const uchar*) key, length,
(const uchar*) table->record[0]+key_part->offset,length))
(const uchar*) table->record[0]+key_part->offset,
length))
return 1;
}
else if (memcmp(key,table->record[0]+key_part->offset,length))

View file

@ -180,7 +180,7 @@ static SYMBOL symbols[] = {
{ "HANDLER", SYM(HANDLER_SYM),0,0},
{ "HASH", SYM(HASH_SYM),0,0},
{ "HEAP", SYM(HEAP_SYM),0,0},
{ "HELP", SYM(HELP),0,0},
{ "HELP", SYM(HELP_SYM),0,0},
{ "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0},
{ "HOUR", SYM(HOUR_SYM),0,0},
{ "HOUR_MINUTE", SYM(HOUR_MINUTE_SYM),0,0},

View file

@ -854,7 +854,7 @@ int rename_file_ext(const char * from,const char * to,const char * ext);
bool check_db_name(char *db);
bool check_column_name(const char *name);
bool check_table_name(const char *name, uint length);
char *get_field(MEM_ROOT *mem,TABLE *table,uint fieldnr);
char *get_field(MEM_ROOT *mem, Field *field);
int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
/* from hostname.cc */

View file

@ -147,9 +147,9 @@ double rnd(struct rand_struct *rand_st)
none
*/
void create_random_string(int length,struct rand_struct *rand_st,char* target)
void create_random_string(int length,struct rand_struct *rand_st,char *target)
{
char* end=target+length;
char *end=target+length;
/* Use pointer arithmetics as it is faster way to do so. */
for (; target<end ; target++)
*target= (char) (rnd(rand_st)*94+33);
@ -171,7 +171,7 @@ void create_random_string(int length,struct rand_struct *rand_st,char* target)
none
*/
void password_crypt(const char* from,char* to, const char* password,int length)
void password_crypt(const char *from,char *to, const char *password,int length)
{
const char *from_end=from+length;
@ -252,7 +252,7 @@ void password_hash_stage1(char *to, const char *password)
none
*/
void password_hash_stage2(char *to,const char *salt)
void password_hash_stage2(char *to, const char *salt)
{
SHA1_CONTEXT context;
sha1_reset(&context);
@ -326,7 +326,7 @@ void make_scrambled_password(char *to,const char *password,
void get_salt_from_bin_password(ulong *res,unsigned char *password,ulong salt)
{
unsigned char* password_end=password+SCRAMBLE41_LENGTH;
unsigned char *password_end=password+SCRAMBLE41_LENGTH;
*res=salt;
res++;
@ -356,14 +356,14 @@ void get_salt_from_bin_password(ulong *res,unsigned char *password,ulong salt)
!0 for invalid password
*/
my_bool validate_password(const char* password, const char* message,
ulong* salt)
my_bool validate_password(const char *password, const char *message,
ulong *salt)
{
char buffer[SCRAMBLE41_LENGTH]; /* Used for password validation */
char tmpsalt[8]; /* Temporary value to convert salt to string form */
ulong salt_candidate[6]; /* Computed candidate salt */
ulong* sc=salt_candidate; /* we need to be able to increment */
ulong* salt_end;
ulong *sc=salt_candidate; /* we need to be able to increment */
ulong *salt_end;
/* Now we shall get stage1 encrypted password in buffer*/
password_crypt(password,buffer,message,SCRAMBLE41_LENGTH);
@ -414,7 +414,7 @@ int get_password_length(my_bool force_old_scramble)
!0 password version char for newer passwords
*/
char get_password_version(const char* password)
char get_password_version(const char *password)
{
if (password==NULL) return 0;
if (password[0]==PVERSION41_CHAR) return PVERSION41_CHAR;
@ -536,46 +536,47 @@ void make_password_from_salt(char *to, ulong *hash_res,uint8 password_version)
!0 password version char for newer passwords
*/
void get_hash_and_password(ulong* salt, uint8 pversion, char* hash, unsigned char* bin_password)
void get_hash_and_password(ulong *salt, uint8 pversion, char *hash,
unsigned char *bin_password)
{
int t;
ulong* salt_end;
ulong val;
SHA1_CONTEXT context;
unsigned char* bp; /* Binary password loop pointer */
if (pversion) /* New password version assumed */
if (pversion) /* New password version assumed */
{
salt_end=salt+5;
sprintf(hash,"%04x",(unsigned short)salt[0]);
while (salt<salt_end) /* Iterate over these elements*/
while (salt<salt_end)
{
val=*(++salt);
for (t=3; t>=0; t--)
{
bin_password[t]= (char) (val & 255);
val>>=8; /* Scroll 8 bits to get next part*/
val>>=8; /* Scroll 8 bits to get next part*/
}
bin_password+=4; /* Get to next 4 chars*/
bin_password+=4; /* Get to next 4 chars*/
}
}
else
{
unsigned char *bp= bin_password; /* Binary password loop pointer */
/* Use zero starting hash as an indication of old password */
hash[0]=0;
salt_end=salt+2;
bp=bin_password;
/* Encode salt using SHA1 here */
sha1_reset(&context);
while (salt<salt_end) /* Iterate over these elements*/
while (salt<salt_end) /* Iterate over these elements*/
{
val=*salt;
val= *salt;
for (t=3;t>=0;t--)
{
bp[t]= (uchar) (val & 255);
val>>=8; /* Scroll 8 bits to get next part*/
val>>=8; /* Scroll 8 bits to get next part*/
}
bp+=4; /* Get to next 4 chars*/
bp+= 4; /* Get to next 4 chars*/
salt++;
}
/* Use 8 bytes of binary password for hash */
@ -599,7 +600,7 @@ void get_hash_and_password(ulong* salt, uint8 pversion, char* hash, unsigned cha
*/
void create_key_from_old_password(const char* passwd, char* key)
void create_key_from_old_password(const char *passwd, char *key)
{
char buffer[SCRAMBLE41_LENGTH]; /* Buffer for various needs */
ulong salt[6]; /* Salt (large for safety) */
@ -633,7 +634,7 @@ char *scramble(char *to,const char *message,const char *password,
struct rand_struct rand_st;
ulong hash_pass[2],hash_message[2];
char message_buffer[9]; /* Real message buffer */
char* msg=message_buffer;
char *msg=message_buffer;
/* We use special message buffer now as new server can provide longer hash */

View file

@ -148,8 +148,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_HOST host;
update_hostname(&host.host,get_field(&mem, table,0));
host.db= get_field(&mem, table,1);
update_hostname(&host.host,get_field(&mem, table->field[0]));
host.db= get_field(&mem, table->field[1]);
host.access= get_access(table,2);
host.access= fix_rights_for_db(host.access);
host.sort= get_sort(2,host.host.hostname,host.db);
@ -190,9 +190,9 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
{
ACL_USER user;
uint length=0;
update_hostname(&user.host,get_field(&mem, table,0));
user.user=get_field(&mem, table,1);
user.password=get_field(&mem, table,2);
update_hostname(&user.host,get_field(&mem, table->field[0]));
user.user=get_field(&mem, table->field[1]);
user.password=get_field(&mem, table->field[2]);
if (user.password && (length=(uint) strlen(user.password)) == 8 &&
protocol_version == PROTOCOL_VERSION)
{
@ -220,7 +220,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
(uint) strlen(user.host.hostname) : 0);
if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
{
char *ssl_type=get_field(&mem, table, 24);
char *ssl_type=get_field(&mem, table->field[24]);
if (!ssl_type)
user.ssl_type=SSL_TYPE_NONE;
else if (!strcmp(ssl_type, "ANY"))
@ -230,15 +230,15 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
else /* !strcmp(ssl_type, "SPECIFIED") */
user.ssl_type=SSL_TYPE_SPECIFIED;
user.ssl_cipher= get_field(&mem, table, 25);
user.x509_issuer= get_field(&mem, table, 26);
user.x509_subject= get_field(&mem, table, 27);
user.ssl_cipher= get_field(&mem, table->field[25]);
user.x509_issuer= get_field(&mem, table->field[26]);
user.x509_subject= get_field(&mem, table->field[27]);
char *ptr = get_field(&mem, table, 28);
char *ptr = get_field(&mem, table->field[28]);
user.user_resource.questions=atoi(ptr);
ptr = get_field(&mem, table, 29);
ptr = get_field(&mem, table->field[29]);
user.user_resource.updates=atoi(ptr);
ptr = get_field(&mem, table, 30);
ptr = get_field(&mem, table->field[30]);
user.user_resource.connections=atoi(ptr);
if (user.user_resource.questions || user.user_resource.updates ||
user.user_resource.connections)
@ -277,14 +277,14 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_DB db;
update_hostname(&db.host,get_field(&mem, table,0));
db.db=get_field(&mem, table,1);
update_hostname(&db.host,get_field(&mem, table->field[0]));
db.db=get_field(&mem, table->field[1]);
if (!db.db)
{
sql_print_error("Found an entry in the 'db' table with empty database name; Skipped");
continue;
}
db.user=get_field(&mem, table,2);
db.user=get_field(&mem, table->field[2]);
db.access=get_access(table,3);
db.access=fix_rights_for_db(db.access);
db.sort=get_sort(3,db.host.hostname,db.db,db.user);
@ -457,8 +457,9 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
return 0;
}
/*
Prepare crypted scramble to be sent to the client
Prepare crypted scramble to be sent to the client
*/
void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
@ -469,18 +470,17 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
create_random_string(SCRAMBLE41_LENGTH,&thd->rand,thd->scramble);
thd->scramble[SCRAMBLE41_LENGTH]=0;
/* Get binary form, First 4 bytes of prepared scramble is salt */
get_hash_and_password(acl_user->salt,acl_user->pversion,prepared_scramble,(unsigned char*)bin_password);
get_hash_and_password(acl_user->salt,acl_user->pversion,prepared_scramble,
(unsigned char*) bin_password);
/* Store "*" as identifier for old passwords */
if (!acl_user->pversion)
prepared_scramble[0]='*';
/* Finally encrypt password to get prepared scramble */
password_crypt(thd->scramble,prepared_scramble+4,bin_password,SCRAMBLE41_LENGTH);
password_crypt(thd->scramble, prepared_scramble+4, bin_password,
SCRAMBLE41_LENGTH);
}
/*
Get master privilges for user (priviliges for all tables).
Required before connecting to MySQL
@ -493,7 +493,7 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
const char *password,const char *message,char **priv_user,
bool old_ver, USER_RESOURCES *mqh,char* prepared_scramble,
bool old_ver, USER_RESOURCES *mqh, char *prepared_scramble,
uint *cur_priv_version,ACL_USER** hint_user)
{
ulong user_access=NO_ACCESS;
@ -572,10 +572,11 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
if (!check_scramble(password,message,acl_user->salt,
(my_bool) old_ver))
password_correct=1;
else /* Password incorrect */
/* At the first stage - prepare scramble */
if (!stage)
prepare_scramble(thd,acl_user,prepared_scramble);
else if (!stage) /* Here if password incorrect */
{
/* At the first stage - prepare scramble */
prepare_scramble(thd,acl_user,prepared_scramble);
}
}
}
}
@ -1645,12 +1646,12 @@ public:
{
byte key[MAX_KEY_LENGTH];
host = get_field(&memex,form,0);
db = get_field(&memex,form,1);
user = get_field(&memex,form,2);
host = get_field(&memex,form->field[0]);
db = get_field(&memex,form->field[1]);
user = get_field(&memex,form->field[2]);
if (!user)
user=(char*) "";
tname = get_field(&memex,form,3);
tname = get_field(&memex,form->field[3]);
if (!host || !db || !tname)
{
/* Wrong table row; Ignore it */

View file

@ -1481,6 +1481,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
}
else
{
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
table= 0;
@ -1512,6 +1513,11 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
thd Thread handler
tables Tables to lock
NOTES
You can't call lock_tables twice, as this would break the dead-lock-free
handling thr_lock gives us. You most always get all needed locks at
once.
RETURN VALUES
0 ok
-1 Error
@ -1525,6 +1531,7 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
if (!thd->locked_tables)
{
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
uint count=0;
for (table = tables ; table ; table=table->next)
count++;
@ -1676,28 +1683,31 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
return field;
}
// Special Field pointer for find_field_in_tables returning
const Field *not_found_field= (Field*) 0x1;
/*
Find field in table list.
SYNOPSIS
find_field_in_tables()
thd - pointer to current thread structure
item - field item that should be found
tables - tables for scaning
where - table where field found will be returned via this parameter
report_error - if FALSE then do not report error if item not found and
return not_found_field;
thd Pointer to current thread structure
item Field item that should be found
tables Tables for scaning
where Table where field found will be returned via
this parameter
report_error If FALSE then do not report error if item not found
and return not_found_field
RETURN VALUES
0 - field is not found or field is not unique, error message is
reported
not_found_field - function was called with report_error == FALSE and
field if not found, no error message reported
0 Field is not found or field is not unique- error
message is reported
not_found_field Function was called with report_error == FALSE and
field was not found. no error message reported.
found field
*/
// Special Field pointer for find_field_in_tables returning
const Field *not_found_field= (Field*) 0x1;
Field *
find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
TABLE_LIST **where, bool report_error)
@ -1802,8 +1812,6 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
return (Field*) 0;
}
// Special Item pointer for find_item_in_list returning
const Item **not_found_item= (const Item**) 0x1;
/*
Find Item in list of items (find_field_in_tables analog)
@ -1813,24 +1821,29 @@ const Item **not_found_item= (const Item**) 0x1;
SYNOPSIS
find_item_in_list()
find - item to find
items - list of items
counter - to return number of found item
find Item to find
items List of items
counter To return number of found item
report_error
REPORT_ALL_ERRORS - report errors, return 0 if error
REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0
IGNORE_ERRORS - do not report errors, return 0 if error
REPORT_ALL_ERRORS report errors, return 0 if error
REPORT_EXCEPT_NOT_FOUND Do not report 'not found' error and
return not_found_item, report other errors,
return 0
IGNORE_ERRORS Do not report errors, return 0 if error
RETURN VALUES
0 - item is not found or item is not unique, error message is
reported
not_found_item - function was called with report_error ==
REPORT_EXCEPT_NOT_FOUND and item if not found, no error
message reported
0 Item is not found or item is not unique,
error message is reported
not_found_item Function was called with
report_error == REPORT_EXCEPT_NOT_FOUND and
item was not found. No error message was reported
found field
*/
// Special Item pointer for find_item_in_list returning
const Item **not_found_item= (const Item**) 0x1;
Item **
find_item_in_list(Item *find, List<Item> &items, uint *counter,
find_item_error_report_type report_error)
@ -1970,6 +1983,9 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
Remap table numbers if INSERT ... SELECT
Check also that the 'used keys' and 'ignored keys' exists and set up the
table structure accordingly
This has to be called for all tables that are used by items, as otherwise
table->map is not set and all Item_field will be regarded as const items.
*/
bool setup_tables(TABLE_LIST *tables)

View file

@ -857,6 +857,7 @@ end:
DBUG_VOID_RETURN;
}
/*
Check if the query is in the cache. If it was cached, send it
to the user.
@ -867,8 +868,6 @@ end:
-1 The query was cached but we didn't have rights to use it.
No error is sent to the client yet.
*/
int
Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)

View file

@ -882,8 +882,9 @@ typedef struct st_sort_field {
Field *field; /* Field to sort */
Item *item; /* Item if not sorting fields */
uint length; /* Length of sort field */
my_bool reverse; /* if descending sort */
Item_result result_type; /* Type of item */
bool reverse; /* if descending sort */
bool need_strxnfrm; /* If we have to use strxnfrm() */
} SORT_FIELD;
@ -898,7 +899,8 @@ typedef struct st_sort_buffer {
/* Structure for db & table in sql_yacc */
class Table_ident :public Sql_alloc {
class Table_ident :public Sql_alloc
{
public:
LEX_STRING db;
LEX_STRING table;

View file

@ -61,7 +61,8 @@ extern const char *any_db; // Special symbol for check_access
*/
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
TABLE_LIST *org_table_list)
{
SELECT_LEX *sl= unit->first_select();
List<Item> item_list;
@ -85,6 +86,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1))
DBUG_RETURN(-1);
/*
We have to do access checks here as this code is executed before any
sql command is started to execute.
*/
if (tables)
res= check_table_access(thd,SELECT_ACL, tables);
else
@ -173,10 +178,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
res= 1;
else
{
t->real_name=table->real_name;
t->table=table;
org_table_list->real_name=table->real_name;
org_table_list->table=table;
table->derived_select_number= sl->select_number;
table->tmp_table=TMP_TABLE;
table->tmp_table= TMP_TABLE;
if (lex->describe)
{
// to fix a problem in EXPLAIN
@ -185,8 +190,11 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
}
else
unit->exclude();
t->db= (char *)"";
t->derived=(SELECT_LEX *) 1; // just in case ...
org_table_list->db= (char *)"";
#ifndef DBUG_OFF
/* Try to catch errors if this is accessed */
org_table_list->derived=(SELECT_LEX_UNIT *) 1;
#endif
table->file->info(HA_STATUS_VARIABLE);
}
}
@ -196,6 +204,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
free_tmp_table(thd, table);
else
{
/* Add new temporary table to list of open derived tables */
table->next= thd->derived_tables;
thd->derived_tables= table;
}

View file

@ -15,288 +15,294 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h"
#include "sql_select.h" // For select_describe
#include "sql_acl.h"
/***************************************************************************
** Get help on string
***************************************************************************/
struct st_find_field
{
const char *table_name, *field_name;
Field *field;
};
/* Used fields */
static struct st_find_field init_used_fields[]=
{
{ "help_topic", "name", 0},
{ "help_topic","description", 0},
{ "help_topic","example", 0},
{ "help_topic", "help_topic_id", 0},
{ "help_category","name", 0},
{ "help_category","help_category_id", 0},
{ "help_relation","help_topic_id", 0},
{ "help_relation","help_category_id", 0}
};
enum enum_used_fields
{
help_topic_name=0, help_topic_description, help_topic_example,
help_topic_help_topic_id,
help_category_name, help_category_help_category_id,
help_relation_help_topic_id, help_relation_help_category_id
};
/*
Fill local used field structure with pointer to fields */
static bool init_fields(THD *thd, TABLE_LIST *tables,
struct st_find_field *find_field,
uint count)
{
for (; count-- ; find_field++)
{
TABLE_LIST *not_used;
/* We have to use 'new' here as field will be re_linked on free */
Item_field *field= new Item_field("mysql", find_field->table_name,
find_field->field_name);
if (!(find_field->field= find_field_in_tables(thd, field, tables,
&not_used,
TRUE)))
return 1;
}
return 0;
}
#define help_charset &my_charset_latin1
MI_INFO *open_help_file(THD *thd, const char *name)
{
char path[FN_REFLEN];
(void) sprintf(path,"%s/mysql_help/%s",mysql_data_home,name);
MI_INFO *res= 0;
if (!(res= mi_open(path,O_RDONLY,HA_OPEN_WAIT_IF_LOCKED)))
{
send_error(thd,ER_CORRUPT_HELP_DB);
return 0;
}
mi_extra(res,HA_EXTRA_WAIT_LOCK,0);
return res;
}
/*
Look for topics by mask
#define size_hf_func_id 4 /* func_id int unsigned, */
#define size_hf_name 64 /* name varchar(64), */
#define size_hf_url 128 /* url varchar(128), */
#define size_hf_description sizeof(char*) /* description text, */
#define size_hf_example sizeof(char*) /* example text, */
#define size_hf_min_args 16 /* min_args tinyint, */
#define size_hf_max_args 16 /* max_args tinyint, */
#define size_hf_date_created 8 /* date_created datetime, */
#define size_hf_last_modified 8 /* last_modified timestamp, */
SYNOPSIS
search_topics()
thd Thread handler
topics Table of topic
select Function to test for if matching help topic.
Normally 'help_topic.name like 'bit%'
pfname Pointer to Field structure for field "name"
names List of founded topic's names (out)
name Name of founded topic (out),
Only set if founded exactly one topic)
description Description of founded topic (out)
Only set if founded exactly one topic.
example Example for founded topic (out)
Only if founded exactly one topic.
RETURN VALUES
# number of topics founded
*/
#define offset_hf_func_id 1
#define offset_hf_name (offset_hf_func_id+size_hf_func_id)
#define offset_hf_url (offset_hf_name+size_hf_name)
#define offset_hf_description (offset_hf_url+size_hf_url)
#define offset_hf_example (offset_hf_description+size_hf_description)
#define offset_hf_min_args (offset_hf_example+size_hf_example)
#define offset_hf_max_args (offset_hf_min_args+size_hf_min_args)
#define offset_hf_date_created (offset_hf_max_args+size_hf_max_args)
#define offset_hf_last_modified (offset_hf_date_created+size_hf_date_created)
#define HELP_LEAF_SIZE (offset_hf_last_modified+size_hf_last_modified)
class help_leaf{
public:
char record[HELP_LEAF_SIZE];
inline const char *get_name()
{
return &record[offset_hf_name];
}
inline const char *get_description()
{
return *((char**)&record[199/*offset_hf_description*/]);
}
inline const char *get_example()
{
return *((char**)&record[209/*offset_hf_example*/]);
}
void prepare_fields()
{
const char *name= get_name();
const char *c= name + size_hf_name - 1;
while (*c==' ') c--;
int len= c-name+1;
((char*)name)[len]= '\0';
}
};
int search_functions(MI_INFO *file_leafs, const char *mask,
List<String> *names,
String **name, String **description, String **example)
int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_field,
SQL_SELECT *select, List<char> *names,
char **name, char **description, char **example)
{
DBUG_ENTER("search_functions");
int count= 0;
if (mi_scan_init(file_leafs))
DBUG_RETURN(-1);
help_leaf leaf;
while (!mi_scan(file_leafs,(byte*)&leaf))
READ_RECORD read_record_info;
init_read_record(&read_record_info, thd, topics, select,1,0);
while (!read_record_info.read_record(&read_record_info))
{
leaf.prepare_fields();
const char *lname= leaf.get_name();
if (wild_case_compare(help_charset,lname,mask))
if (!select->cond->val_int()) // Dosn't match like
continue;
count++;
if (count>2)
char *lname= get_field(&thd->mem_root, find_field[help_topic_name].field);
count++;
if (count > 2)
{
String *s= new String(lname,help_charset);
if (!s->copy())
names->push_back(s);
names->push_back(lname);
}
else if (count==1)
else if (count == 1)
{
*description= new String(leaf.get_description(),help_charset);
*example= new String(leaf.get_example(),help_charset);
*name= new String(lname,help_charset);
(*description)->copy();
(*example)->copy();
(*name)->copy();
*description= get_field(&thd->mem_root,
find_field[help_topic_description].field);
*example= get_field(&thd->mem_root,
find_field[help_topic_example].field);
*name= lname;
}
else
{
names->push_back(*name);
delete *description;
delete *example;
names->push_back(lname);
*name= 0;
*description= 0;
*example= 0;
String *s= new String(lname,help_charset);
if (!s->copy())
names->push_back(s);
}
}
end_read_record(&read_record_info);
DBUG_RETURN(count);
}
/*
Look for categories by mask
SYNOPSIS
search_categories()
thd THD for init_read_record
categories Table of categories
select Function to test for if matching help topic.
Normally 'help_topic.name like 'bit%'
names List of founded topic's names (out)
res_id Primary index of founded category (only if
founded exactly one category)
RETURN VALUES
# Number of categories founded
*/
int search_categories(THD *thd, TABLE *categories,
struct st_find_field *find_fields,
SQL_SELECT *select, List<char> *names, int16 *res_id)
{
Field *pfname= find_fields[help_category_name].field;
DBUG_ENTER("search_categories");
int count= 0;
READ_RECORD read_record_info;
init_read_record(&read_record_info, thd, categories, select,1,0);
while (!read_record_info.read_record(&read_record_info))
{
if (select && !select->cond->val_int())
continue;
char *lname= get_field(&thd->mem_root,pfname);
if (++count == 1 && res_id)
{
Field *pcat_id= find_fields[help_category_help_category_id].field;
*res_id= (int16) pcat_id->val_int();
}
names->push_back(lname);
}
end_read_record(&read_record_info);
DBUG_RETURN(count);
}
#define size_hc_cat_id 2 /* cat_id smallint, */
#define size_hc_name 64 /* name varchar(64), */
#define size_hc_url 128 /* url varchar(128), */
#define size_hc_date_created 8 /* date_created datetime, */
#define size_hc_last_modified 8 /* last_modified timestamp, */
#define offset_hc_cat_id 0
#define offset_hc_name (offset_hc_cat_id+size_hc_cat_id)
#define offset_hc_url (offset_hc_name+size_hc_name)
#define offset_hc_date_created (offset_hc_url+size_hc_url)
#define offset_hc_last_modified (offset_hc_date_created+size_hc_date_created)
/*
Send to client rows in format:
column1 : <name>
column2 : <is_it_category>
#define HELP_CATEGORY_SIZE (offset_hc_last_modified+size_hc_last_modified)
SYNOPSIS
send_variant_2_list()
protocol Protocol for sending
names List of names
cat Value of the column <is_it_category>
class help_category{
public:
char record[HELP_CATEGORY_SIZE];
RETURN VALUES
-1 Writing fail
0 Data was successefully send
*/
inline int16 get_cat_id()
{
return sint2korr(&record[offset_hc_cat_id]);
}
inline const char *get_name()
{
return &record[offset_hc_name];
}
void prepare_fields()
{
const char *name= get_name();
const char *c= name + size_hc_name - 1;
while (*c==' ') c--;
int len= c-name+1;
((char*)name)[len]= '\0';
}
};
int search_categories(THD *thd,
const char *mask, List<String> *names, int16 *res_id)
{
DBUG_ENTER("search_categories");
int count= 0;
MI_INFO *file_categories= 0;
if (!(file_categories= open_help_file(thd,"function_category_name")))
DBUG_RETURN(-1);
if (mi_scan_init(file_categories))
{
mi_close(file_categories);
DBUG_RETURN(-1);
}
help_category category;
while (!mi_scan(file_categories,(byte*)&category))
{
category.prepare_fields();
const char *lname= category.get_name();
if (mask && wild_case_compare(help_charset,lname,mask))
continue;
count++;
if (count==1 && res_id)
*res_id= category.get_cat_id();
String *s= new String(lname,help_charset);
if (!s->copy())
names->push_back(s);
}
mi_close(file_categories);
DBUG_RETURN(count);
}
int send_variant_2_list(Protocol *protocol, List<String> *names,
my_bool is_category)
int send_variant_2_list(Protocol *protocol, List<char> *names,
const char *cat)
{
DBUG_ENTER("send_names");
List_iterator<String> it(*names);
String *cur_name;
while ((cur_name = it++))
List_iterator<char> it(*names);
const char *cur_name;
while ((cur_name= it++))
{
protocol->prepare_for_resend();
protocol->store(cur_name->ptr());
protocol->store(is_category ? "Y" : "N");
protocol->store(cur_name);
protocol->store(cat);
if (protocol->write())
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
}
#define size_hcn_cat_id 2 /* cat_id smallint, */
#define size_hcn_func_id 4 /* func_id int, */
#define offset_hcn_cat_id 1
#define offset_hcn_func_id (offset_hcn_cat_id+size_hcn_cat_id)
/*
Look for all topics of category
#define HELP_CATEGORY_NAME_SIZE (offset_hcn_func_id + size_hcn_func_id)
SYNOPSIS
get_all_topics_for_category()
thd Thread handler
topics Table of topics
relations Table of m:m relation "topic/category"
cat_id Primary index looked for category
res List of founded topic's names (out)
class help_category_leaf{
public:
char record[HELP_CATEGORY_NAME_SIZE];
RETURN VALUES
-1 corrupt database
0 succesefull
*/
inline int16 get_cat_id()
{
return sint2korr(&record[offset_hcn_cat_id]);
}
inline int get_func_id()
{
return sint3korr(&record[offset_hcn_func_id]);
}
};
int get_all_names_for_category(THD *thd,MI_INFO *file_leafs,
int16 cat_id, List<String> *res)
int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
struct st_find_field *find_fields,
int16 cat_id, List<char> *res)
{
DBUG_ENTER("get_all_names_for_category");
MI_INFO *file_names_categories= 0;
if (!(file_names_categories= open_help_file(thd,"function_category")))
DBUG_RETURN(1);
help_category_leaf cat_leaf;
help_leaf leaf;
int key_res= mi_rkey(file_names_categories, (byte*)&cat_leaf, 0,
(const byte*)&cat_id,2,HA_READ_KEY_EXACT);
while (!key_res && cat_leaf.get_cat_id()==cat_id)
char buff[8]; // Max int length
DBUG_ENTER("get_all_topics_for_category");
int iindex_topic, iindex_relations;
Field *rtopic_id, *rcat_id;
if ((iindex_topic= find_type((char*) "PRIMARY",
&topics->keynames, 1+2)-1)<0 ||
(iindex_relations= find_type((char*) "PRIMARY",
&relations->keynames, 1+2)-1)<0)
{
int leaf_id= cat_leaf.get_func_id();
if (!mi_rkey(file_leafs, (byte*)&leaf, 0,
(const byte*)&leaf_id,4,HA_READ_KEY_EXACT))
{
leaf.prepare_fields();
String *s= new String(leaf.get_name(),help_charset);
if (!s->copy())
res->push_back(s);
}
key_res= mi_rnext(file_names_categories, (byte*)&cat_leaf, 0);
send_error(thd,ER_CORRUPT_HELP_DB);
DBUG_RETURN(-1);
}
rtopic_id= find_fields[help_relation_help_topic_id].field;
rcat_id= find_fields[help_relation_help_category_id].field;
topics->file->index_init(iindex_topic);
relations->file->index_init(iindex_relations);
rcat_id->store((longlong) cat_id);
rcat_id->get_key_image(buff, rcat_id->pack_length(), help_charset,
Field::itRAW);
int key_res= relations->file->index_read(relations->record[0],
buff, rcat_id->pack_length(),
HA_READ_KEY_EXACT);
for ( ; !key_res && cat_id == (int16) rcat_id->val_int() ;
key_res= relations->file->index_next(relations->record[0]))
{
char topic_id_buff[8];
longlong topic_id= rtopic_id->val_int();
Field *field= find_fields[help_topic_help_topic_id].field;
field->store((longlong) topic_id);
field->get_key_image(topic_id_buff, field->pack_length(), help_charset,
Field::itRAW);
mi_close(file_names_categories);
if (!topics->file->index_read(topics->record[0], topic_id_buff,
field->pack_length(),
HA_READ_KEY_EXACT))
res->push_back(get_field(&thd->mem_root,
find_fields[help_topic_name].field));
}
DBUG_RETURN(0);
}
/*
Send to client answer for help request
SYNOPSIS
send_answer_1()
protocol - protocol for sending
s1 - value of column "Name"
s2 - value of column "Category"
s3 - value of column "Description"
s4 - value of column "Example"
IMPLEMENTATION
Format used:
+----------+---------+------------+------------+
|Name: |Category |Description |Example |
+----------+---------+------------+------------+
|String(64)|String(1)|String(1000)|String(1000)|
+----------+---------+------------+------------+
with exactly one row!
RETURN VALUES
1 Writing of head failed
-1 Writing of row failed
0 Successeful send
*/
int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
const char *s3, const char *s4)
{
@ -306,10 +312,10 @@ int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
field_list.push_back(new Item_empty_string("Category",1));
field_list.push_back(new Item_empty_string("Description",1000));
field_list.push_back(new Item_empty_string("Example",1000));
if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
protocol->prepare_for_resend();
protocol->store(s1);
protocol->store(s2);
@ -317,11 +323,28 @@ int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
protocol->store(s4);
if (protocol->write())
DBUG_RETURN(-1);
DBUG_RETURN(0);
}
/*
Send to client help header
SYNOPSIS
send_header_2()
protocol - protocol for sending
IMPLEMENTATION
+----------+---------+
|Name: |Category |
+----------+---------+
|String(64)|String(1)|
+----------+---------+
RETURN VALUES
result of protocol->send_fields
*/
int send_header_2(Protocol *protocol)
{
DBUG_ENTER("send_header2");
@ -332,79 +355,165 @@ int send_header_2(Protocol *protocol)
}
/*
Server-side function 'help'
SYNOPSIS
mysqld_help()
thd Thread handler
RETURN VALUES
0 Success
1 Error and send_error already commited
-1 error && send_error should be issued (normal case)
*/
int mysqld_help(THD *thd, const char *mask)
{
Protocol *protocol= thd->protocol;
SQL_SELECT *select= 0, *select_cat= 0;
Item *cond_topic, *cond_cat;
st_find_field used_fields[array_elements(init_used_fields)];
DBUG_ENTER("mysqld_help");
MI_INFO *file_leafs= 0;
if (!(file_leafs= open_help_file(thd,"function")))
DBUG_RETURN(1);
List<String> function_list, categories_list;
String *name, *description, *example;
int res;
int count= search_functions(file_leafs, mask,
&function_list,&name,&description,&example);
if (count < 0)
TABLE_LIST tables[3];
bzero((gptr)tables,sizeof(tables));
tables[0].alias= tables[0].real_name= (char*) "help_topic";
tables[0].lock_type= TL_READ;
tables[0].db= (char*) "mysql";
tables[0].next= &tables[1];
tables[1].alias= tables[1].real_name= (char*) "help_category";
tables[1].lock_type= TL_READ;
tables[1].db= (char*) "mysql";
tables[1].next= &tables[2];
tables[2].alias= tables[2].real_name= (char*) "help_relation";
tables[2].lock_type= TL_READ;
tables[2].db= (char*) "mysql";
tables[2].next= 0;
List<char> function_list, categories_list;
char *name, *description, *example;
int res, count_topics, count_categories, error;
if (open_and_lock_tables(thd, tables))
{
res= 1;
res= -1;
goto end;
}
else if (count==0)
/* Init tables and fields to be usable from items */
setup_tables(tables);
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
{
res= -1;
goto end;
}
/* TODO: Find out why these are needed (should not be) */
tables[0].table->file->init_table_handle_for_HANDLER();
tables[1].table->file->init_table_handle_for_HANDLER();
tables[2].table->file->init_table_handle_for_HANDLER();
cond_topic= new Item_func_like(new Item_field(used_fields[help_topic_name].
field),
new Item_string(mask, strlen(mask),
help_charset),
(char*) "\\");
cond_topic->fix_fields(thd, tables, &cond_topic); // can never fail
select= make_select(tables[0].table,0,0,cond_topic,&error);
if (error || (select && select->check_quick(0, HA_POS_ERROR)))
{
res= -1;
goto end;
}
cond_cat= new Item_func_like(new Item_field(used_fields[help_category_name].
field),
new Item_string(mask, strlen(mask),
help_charset),
(char*) "\\");
cond_cat->fix_fields(thd, tables, &cond_topic); // can never fail
select_cat= make_select(tables[1].table,0,0,cond_cat,&error);
if (error || (select_cat && select_cat->check_quick(0, HA_POS_ERROR)))
{
res= -1;
goto end;
}
res= 1;
count_topics= search_topics(thd,tables[0].table, used_fields, select,
&function_list, &name, &description, &example);
if (count_topics == 0)
{
int16 category_id;
count= search_categories(thd, mask, &categories_list, &category_id);
if (count<0)
Item *cond=
new Item_func_like(new
Item_field(used_fields[help_category_name].field),
new Item_string(mask, strlen(mask),
help_charset),
(char*) "\\");
(void) cond->fix_fields(thd, tables, &cond); // can never fail
count_categories= search_categories(thd, tables[1].table, used_fields,
select_cat, &categories_list,
&category_id);
if (count_categories == 1)
{
res= 1;
goto end;
}
else if (count==1)
{
if ((res= get_all_names_for_category(thd, file_leafs,
category_id,&function_list)))
goto end;
List_iterator<String> it(function_list);
String *cur_leaf, example;
while ((cur_leaf = it++))
if (get_all_topics_for_category(thd,tables[0].table,
tables[2].table, used_fields,
category_id, &function_list))
{
example.append(*cur_leaf);
res= -1;
goto end;
}
List_iterator<char> it(function_list);
char *cur_topic;
char buff[1024];
String example(buff, sizeof(buff), help_charset);
example.length(0);
while ((cur_topic= it++))
{
example.append(cur_topic);
example.append("\n",1);
}
if ((res= send_answer_1(protocol, categories_list.head()->ptr(),
"Y","",example.ptr())))
if ((send_answer_1(protocol, categories_list.head(),
"Y","",example.ptr())))
goto end;
}
else
{
if ((res= send_header_2(protocol)) ||
(count==0 &&
(search_categories(thd, 0, &categories_list, 0)<0 &&
((res= 1)))) ||
(res= send_variant_2_list(protocol,&categories_list,true)))
if (send_header_2(protocol))
goto end;
if (count_categories == 0)
search_categories(thd,tables[1].table, used_fields, (SQL_SELECT *) 0,
&categories_list, 0);
if (send_variant_2_list(protocol,&categories_list,"Y"))
goto end;
}
}
else if (count==1)
else if (count_topics == 1)
{
if ((res= send_answer_1(protocol,name->ptr(),"N",
description->ptr(), example->ptr())))
if (send_answer_1(protocol,name,"N",description, example))
goto end;
}
else if ((res= send_header_2(protocol)) ||
(res= send_variant_2_list(protocol,&function_list,false)) ||
(search_categories(thd, mask, &categories_list, 0)<0 &&
((res=1))) ||
(res= send_variant_2_list(protocol,&categories_list,true)))
else
{
goto end;
/* First send header and functions */
if (send_header_2(protocol) ||
send_variant_2_list(protocol, &function_list, "N"))
goto end;
search_categories(thd, tables[1].table, used_fields, select_cat,
&categories_list, 0);
/* Then send categories */
if (send_variant_2_list(protocol, &categories_list, "Y"))
goto end;
}
res= 0;
send_eof(thd);
end:
mi_close(file_leafs);
delete select;
delete select_cat;
DBUG_RETURN(res);
}

View file

@ -147,6 +147,12 @@ void lex_free(void)
}
/*
This is called before every query that is to be parsed.
Because of this, it's critical to not do too much things here.
(We already do too much here)
*/
LEX *lex_start(THD *thd, uchar *buf,uint length)
{
LEX *lex= &thd->lex;
@ -164,10 +170,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->thd_charset= lex->thd->variables.thd_charset;
lex->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
lex->slave_thd_opt=0;
lex->sql_command=SQLCOM_END;
lex->safe_to_cache_query= 1;
bzero(&lex->mi,sizeof(lex->mi));
return lex;
}

View file

@ -472,7 +472,7 @@ typedef struct st_lex
uint param_count;
bool drop_primary, drop_if_exists, drop_temporary, local_file;
bool in_comment, ignore_space, verbose, simple_alter;
bool derived_tables, describe, olap;
bool derived_tables, describe;
bool safe_to_cache_query;
uint slave_thd_opt;
CHARSET_INFO *charset;

View file

@ -188,7 +188,7 @@ end:
static int check_user(THD *thd,enum_server_command command, const char *user,
const char *passwd, const char *db, bool check_count,
bool simple_connect, bool do_send_error,
char* crypted_scramble, bool had_password,
char *crypted_scramble, bool had_password,
uint *cur_priv_version, ACL_USER** hint_user)
{
thd->db=0;
@ -506,10 +506,10 @@ check_connections(THD *thd)
char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble&hash */
ACL_USER* cached_user=NULL; /* Initialise to NULL for first stage */
uint cur_priv_version;
DBUG_PRINT("info", (("check_connections called by thread %d"),
thd->thread_id));
DBUG_PRINT("info",("New connection received on %s",
vio_description(net->vio)));
/* Remove warning from valgrind. TODO: Fix it in password.c */
bzero((char*) prepared_scramble, sizeof(prepared_scramble));
if (!thd->host) // If TCP/IP connection
{
char ip[30];
@ -525,15 +525,17 @@ check_connections(THD *thd)
thd->host=(char*) localhost;
else
#endif
if (!(specialflag & SPECIAL_NO_RESOLVE))
{
vio_in_addr(net->vio,&thd->remote.sin_addr);
thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
/* Cut very long hostnames to avoid possible overflows */
if (thd->host)
thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
if (connect_errors > max_connect_errors)
return(ER_HOST_IS_BLOCKED);
if (!(specialflag & SPECIAL_NO_RESOLVE))
{
vio_in_addr(net->vio,&thd->remote.sin_addr);
thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
/* Cut very long hostnames to avoid possible overflows */
if (thd->host)
thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
if (connect_errors > max_connect_errors)
return(ER_HOST_IS_BLOCKED);
}
}
DBUG_PRINT("info",("Host: %s ip: %s",
thd->host ? thd->host : "unknown host",
@ -555,8 +557,8 @@ check_connections(THD *thd)
{
/* buff[] needs to big enough to hold the server_version variable */
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+64];
int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION;
int client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
if (opt_using_transactions)
client_flags|=CLIENT_TRANSACTIONS;
@ -582,7 +584,7 @@ check_connections(THD *thd)
// At this point we write connection message and read reply
if (net_write_command(net,(uchar) protocol_version, "", 0, buff,
(uint) (end-buff)) ||
(pkt_len= my_net_read(net)) == packet_error ||
(pkt_len= my_net_read(net)) == packet_error ||
pkt_len < MIN_HANDSHAKE_SIZE)
{
inc_host_errors(&thd->remote.sin_addr);
@ -647,17 +649,17 @@ check_connections(THD *thd)
passwd= strend(user)+1;
db=0;
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
db=strend(passwd)+1;
db=strend(passwd)+1;
/* We can get only old hash at this point */
if (passwd[0] && strlen(passwd)!=SCRAMBLE_LENGTH)
return ER_HANDSHAKE_ERROR;
return ER_HANDSHAKE_ERROR;
if (thd->client_capabilities & CLIENT_INTERACTIVE)
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
opt_using_transactions)
net->return_status= &thd->server_status;
opt_using_transactions)
net->return_status= &thd->server_status;
net->read_timeout=(uint) thd->variables.net_read_timeout;
/* Simple connect only for old clients. New clients always use secure auth */
@ -665,34 +667,34 @@ check_connections(THD *thd)
/* Store information if we used password. passwd will be dammaged */
bool using_password=test(passwd[0]);
/* Check user permissions. If password failure we'll get scramble back */
if (check_user(thd, COM_CONNECT, user, passwd, db, 1, simple_connect,
simple_connect, prepared_scramble, using_password, &cur_priv_version,
&cached_user)<0)
simple_connect, prepared_scramble, using_password,
&cur_priv_version,
&cached_user)<0)
{
/* Store current used and database as they are erased with next packet */
char tmp_user[USERNAME_LENGTH+1];
char tmp_db[NAME_LEN+1];
tmp_user[0]= tmp_db[0]= 0;
/* If The client is old we just have to return error */
if (simple_connect)
return -1;
tmp_user[0]=0;
if (user)
strmake(tmp_user,user,USERNAME_LENGTH);
tmp_db[0]=0;
if (db)
strmake(tmp_db,db,NAME_LEN);
/* Write hash and encrypted scramble to client */
if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) ||
net_flush(net))
{
inc_host_errors(&thd->remote.sin_addr);
return ER_HANDSHAKE_ERROR;
}
{
inc_host_errors(&thd->remote.sin_addr);
return ER_HANDSHAKE_ERROR;
}
/* Reading packet back */
if ((pkt_len= my_net_read(net)) == packet_error)
{
@ -707,8 +709,9 @@ check_connections(THD *thd)
}
/* Final attempt to check the user based on reply */
if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos,
tmp_db, 1, 0, 1, prepared_scramble, using_password, &cur_priv_version,
&cached_user))
tmp_db, 1, 0, 1, prepared_scramble, using_password,
&cur_priv_version,
&cached_user))
return -1;
}
thd->password=using_password;
@ -774,7 +777,7 @@ pthread_handler_decl(handle_one_connection,arg)
net_printf(thd,error,thd->host_or_ip);
#ifdef __NT__
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
sleep(1); /* must wait after eof() */
my_sleep(1000); /* must wait after eof() */
#endif
statistic_increment(aborted_connects,&LOCK_status);
goto end_thread;
@ -1123,22 +1126,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
*/
if (check_user(thd,COM_CHANGE_USER, user, passwd, db, 0, simple_connect,
simple_connect, prepared_scramble, using_password, &cur_priv_version,
&cached_user)<0)
&cached_user) < 0)
{
/* If The client is old we just have to have auth failure */
if (simple_connect)
goto restore_user; /* Error is already reported */
/* Store current used and database as they are erased with next packet */
tmp_user[0]=0;
tmp_user[0]= tmp_db[0]= 0;
if (user)
strmake(tmp_user,user,USERNAME_LENGTH);
tmp_db[0]=0;
if (db)
strmake(tmp_db,db,NAME_LEN);
/* Write hash and encrypted scramble to client */
if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) ||
net_flush(net))
@ -1589,7 +1589,6 @@ mysql_execute_command(THD *thd)
cursor= cursor->next)
{
if (cursor->derived && (res=mysql_derived(thd, lex,
(SELECT_LEX_UNIT *)
cursor->derived,
cursor)))
{
@ -1602,7 +1601,7 @@ mysql_execute_command(THD *thd)
}
if ((&lex->select_lex != lex->all_selects_list &&
lex->unit.create_total_list(thd, lex, &tables, 0))
#ifndef EMBEDDED_LIBRARY
#ifndef HAVE_REPLICATION
||
(table_rules_on && tables && thd->slave_thread &&
!tables_ok(thd,tables))
@ -3148,7 +3147,7 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, int *yystacksize)
/****************************************************************************
Initialize global thd variables needed for query
Initialize global thd variables needed for query
****************************************************************************/
void
@ -3170,10 +3169,11 @@ mysql_init_query(THD *thd)
lex->select_lex.prev= &lex->unit.slave;
lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
lex->olap=lex->describe= 0;
lex->derived_tables= false;
lex->describe= 0;
lex->derived_tables= FALSE;
lex->lock_option= TL_READ;
lex->found_colon= 0;
lex->safe_to_cache_query= 1;
thd->select_number= lex->select_lex.select_number= 1;
thd->free_list= 0;
thd->total_warn_count=0; // Warnings for this query
@ -3184,7 +3184,7 @@ mysql_init_query(THD *thd)
thd->tmp_table_used= 0;
if (opt_bin_log)
reset_dynamic(&thd->user_var_events);
thd->clear_error();
DBUG_VOID_RETURN;
}
@ -3283,8 +3283,6 @@ mysql_parse(THD *thd, char *inBuf, uint length)
DBUG_ENTER("mysql_parse");
mysql_init_query(thd);
thd->clear_error();
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
{
LEX *lex=lex_start(thd, (uchar*) inBuf, length);
@ -3787,10 +3785,10 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
my_casedn_str(files_charset_info,table->table.str);
ptr->real_name=table->table.str;
ptr->real_name_length=table->table.length;
ptr->lock_type= lock_type;
ptr->lock_type= lock_type;
ptr->updating= test(table_options & TL_OPTION_UPDATING);
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
ptr->derived= (SELECT_LEX_UNIT *) table->sel;
ptr->derived= table->sel;
if (use_index)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index,
sizeof(*use_index));

View file

@ -669,11 +669,10 @@ static bool parse_prepare_query(PREP_STMT *stmt,
mysql_log.write(thd,COM_PREPARE,"%s",packet);
mysql_init_query(thd);
thd->prepare_command=true;
thd->lex.param_count= 0;
LEX *lex=lex_start(thd, (uchar*) packet, length);
lex->safe_to_cache_query= 0;
thd->prepare_command= TRUE;
thd->lex.param_count= 0;
if (!yyparse((void *)thd) && !thd->is_fatal_error)
error= send_prepare_results(stmt);
lex_end(lex);

View file

@ -670,6 +670,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
DBUG_RETURN(-1);
}
/* TODO: To be deleted */
my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET),
MYF(0), "RTREE INDEX");
DBUG_RETURN(-1);
}
List_iterator<key_part_spec> cols(key->columns);

View file

@ -162,9 +162,9 @@ void udf_init()
{
DBUG_PRINT("info",("init udf record"));
LEX_STRING name;
name.str=get_field(&mem, table, 0);
name.str=get_field(&mem, table->field[0]);
name.length = strlen(name.str);
char *dl_name= get_field(&mem, table, 2);
char *dl_name= get_field(&mem, table->field[2]);
bool new_dl=0;
Item_udftype udftype=UDFTYPE_FUNCTION;
if (table->fields >= 4) // New func table

View file

@ -136,6 +136,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token EVENTS_SYM
%token EXECUTE_SYM
%token FLUSH_SYM
%token HELP_SYM
%token INSERT
%token IO_THREAD
%token KILL_SYM
@ -528,8 +529,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SUBJECT_SYM
%token CIPHER_SYM
%token HELP
%left SET_VAR
%left OR_OR_CONCAT OR
%left AND
@ -742,11 +741,11 @@ verb_clause:
/* help */
help:
HELP TEXT_STRING
HELP_SYM ident_or_text
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_HELP;
lex->help_arg= $2.str;
LEX *lex= Lex;
lex->sql_command= SQLCOM_HELP;
lex->help_arg= $2.str;
};
/* change master */
@ -1573,8 +1572,13 @@ start:
;
slave_thread_opts:
{ Lex->slave_thd_opt= 0; }
slave_thread_opt_list
slave_thread_opt_list:
slave_thread_opt
| slave_thread_opts ',' slave_thread_opt;
| slave_thread_opt_list ',' slave_thread_opt
;
slave_thread_opt:
/*empty*/ {}
@ -1720,7 +1724,8 @@ select_init:
send_error(lex->thd, ER_SYNTAX_ERROR);
YYABORT;
}
if (sel->linkage == UNION_TYPE && !sel->master_unit()->first_select()->braces)
if (sel->linkage == UNION_TYPE &&
!sel->master_unit()->first_select()->braces)
{
send_error(lex->thd, ER_SYNTAX_ERROR);
YYABORT;
@ -1740,7 +1745,8 @@ select_init2:
send_error(lex->thd, ER_SYNTAX_ERROR);
YYABORT;
}
if (sel->linkage == UNION_TYPE && sel->master_unit()->first_select()->braces)
if (sel->linkage == UNION_TYPE &&
sel->master_unit()->first_select()->braces)
{
send_error(lex->thd, ER_SYNTAX_ERROR);
YYABORT;
@ -2773,7 +2779,6 @@ olap_opt:
| WITH CUBE_SYM
{
LEX *lex=Lex;
lex->olap= 1;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
{
net_printf(lex->thd, ER_WRONG_USAGE, "WITH CUBE",
@ -2787,7 +2792,6 @@ olap_opt:
| WITH ROLLUP_SYM
{
LEX *lex= Lex;
lex->olap= 1;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
{
net_printf(lex->thd, ER_WRONG_USAGE, "WITH ROLLUP",
@ -2812,7 +2816,7 @@ order_clause:
ORDER_SYM BY
{
LEX *lex=Lex;
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE) &&
lex->current_select->select_lex()->olap !=
UNSPECIFIED_OLAP_TYPE)
{
@ -2835,11 +2839,21 @@ order_dir:
| DESC { $$ =0; };
opt_limit_clause:
/* empty */ {}
opt_limit_clause_init:
/* empty */
{
SELECT_LEX_NODE *sel= Select;
sel->offset_limit= 0L;
sel->select_limit= Lex->thd->variables.select_limit;
}
| limit_clause {}
;
opt_limit_clause:
/* empty */ {}
| limit_clause {}
;
limit_clause:
LIMIT
{
@ -3423,9 +3437,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
lex->select_lex.select_limit= lex->thd->variables.select_limit;
lex->select_lex.offset_limit= 0L;
} opt_limit_clause
} opt_limit_clause_init
| keys_or_index FROM table_ident opt_db
{
Lex->sql_command= SQLCOM_SHOW_KEYS;
@ -3453,9 +3465,9 @@ show_param:
{ (void) create_select_for_variable("warning_count"); }
| COUNT_SYM '(' '*' ')' ERRORS
{ (void) create_select_for_variable("error_count"); }
| WARNINGS {Select->offset_limit=0L;} opt_limit_clause
| WARNINGS opt_limit_clause_init
{ Lex->sql_command = SQLCOM_SHOW_WARNS;}
| ERRORS {Select->offset_limit=0L;} opt_limit_clause
| ERRORS opt_limit_clause_init
{ Lex->sql_command = SQLCOM_SHOW_ERRORS;}
| STATUS_SYM wild
{ Lex->sql_command= SQLCOM_SHOW_STATUS; }
@ -3729,18 +3741,24 @@ opt_ignore_lines:
/* Common definitions */
text_literal:
TEXT_STRING { $$ = new Item_string($1.str,$1.length,YYTHD->variables.thd_charset); }
| UNDERSCORE_CHARSET TEXT_STRING { $$ = new Item_string($2.str,$2.length,Lex->charset); }
TEXT_STRING
{ $$ = new Item_string($1.str,$1.length,
YYTHD->variables.thd_charset); }
| UNDERSCORE_CHARSET TEXT_STRING
{ $$ = new Item_string($2.str,$2.length,Lex->charset); }
| text_literal TEXT_STRING
{ ((Item_string*) $1)->append($2.str,$2.length); };
{ ((Item_string*) $1)->append($2.str,$2.length); };
text_string:
TEXT_STRING { $$= new String($1.str,$1.length,YYTHD->variables.thd_charset); }
TEXT_STRING
{ $$= new String($1.str,$1.length,YYTHD->variables.thd_charset); }
| HEX_NUM
{
Item *tmp = new Item_varbinary($1.str,$1.length);
$$= tmp ? tmp->val_str((String*) 0) : (String*) 0;
};
}
;
param_marker:
'?'
{
@ -3755,7 +3773,9 @@ param_marker:
yyerror("You have an error in your SQL syntax");
YYABORT;
}
};
}
;
literal:
text_literal { $$ = $1; }
| NUM { $$ = new Item_int($1.str, (longlong) strtol($1.str, NULL, 10),$1.length); }
@ -3948,8 +3968,9 @@ keyword:
| FLUSH_SYM {}
| GRANTS {}
| GLOBAL_SYM {}
| HEAP_SYM {}
| HANDLER_SYM {}
| HEAP_SYM {}
| HELP_SYM {}
| HOSTS_SYM {}
| HOUR_SYM {}
| IDENTIFIED_SYM {}
@ -4255,7 +4276,7 @@ handler:
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
YYABORT;
}
handler_read_or_scan where_clause opt_limit_clause { }
handler_read_or_scan where_clause opt_limit_clause {}
;
handler_read_or_scan:
@ -4633,8 +4654,6 @@ optional_order_or_limit:
sel->master_unit()->global_parameters=
sel->master_unit();
lex->current_select= sel->master_unit();
lex->current_select->select_limit=
lex->thd->variables.select_limit;
lex->current_select->no_table_names_allowed= 1;
thd->where= "global ORDER clause";
}
@ -4647,9 +4666,8 @@ optional_order_or_limit:
;
order_or_limit:
order_clause opt_limit_clause
|
limit_clause
order_clause opt_limit_clause_init
| limit_clause
;
union_option:

View file

@ -37,7 +37,27 @@ static byte* get_field_name(Field *buff,uint *length,
return (byte*) buff->field_name;
}
/* Open a .frm file */
/*
Open a .frm file
SYNOPSIS
openfrm()
name path to table-file "db/name"
alias alias for table
db_stat open flags (for example HA_OPEN_KEYFILE|HA_OPEN_RNDFILE..)
can be 0 (example in ha_example_table)
prgflag READ_ALL etc..
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
outparam result table
RETURN VALUES
0 ok
1 Error (see frm_error)
2 Error (see frm_error)
3 Wrong data in .frm file
4 Error (see frm_error)
*/
int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
uint ha_open_flags, TABLE *outparam)
@ -1127,13 +1147,20 @@ rename_file_ext(const char * from,const char * to,const char * ext)
/*
Alloc a value as a string and return it
If field is empty, return NULL
Allocate string field in MEM_ROOT and return it as NULL-terminated string
SYNOPSIS
get_field()
mem MEM_ROOT for allocating
field Field for retrieving of string
RETURN VALUES
NullS string is empty
# pointer to NULL-terminated string value of field
*/
char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr)
char *get_field(MEM_ROOT *mem, Field *field)
{
Field *field=table->field[fieldnr];
char buff[MAX_FIELD_WIDTH];
String str(buff,sizeof(buff),default_charset_info);
field->val_str(&str,&str);

View file

@ -19,6 +19,7 @@
class Item; /* Needed by ORDER */
class GRANT_TABLE;
class st_select_lex_unit;
/* Order clause list element */
@ -161,7 +162,7 @@ typedef struct st_table_list
TABLE *table; /* opened table */
st_table_list *table_list; /* pointer to node of list of all tables */
};
void *derived; /* SELECT_LEX_UNIT of derived table */
class st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
GRANT_INFO grant;
thr_lock_type lock_type;
uint outer_join; /* Which join type */

View file

@ -436,7 +436,8 @@ ulong convert_month_to_period(ulong month)
Also dates where all parts are zero are allowed
RETURN VALUES
TIMESTAMP_NONE String wasn't a timestamp
TIMESTAMP_NONE String wasn't a timestamp, like
[DD [HH:[MM:[SS]]]].fraction
TIMESTAMP_DATE DATE string (YY MM and DD parts ok)
TIMESTAMP_FULL Full timestamp
*/
@ -448,6 +449,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
uint not_zero_date;
const char *pos;
const char *end=str+length;
bool found_delimitier= 0;
DBUG_ENTER("str_to_TIME");
DBUG_PRINT("enter",("str: %.*s",length,str));
@ -456,7 +458,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
if (str == end)
DBUG_RETURN(TIMESTAMP_NONE);
/*
calculate first number of digits.
Calculate first number of digits.
If length= 8 or >= 14 then year is of format YYYY.
(YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS)
*/
@ -474,6 +476,11 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
str++;
}
if (found_delimitier && (int) field_length < 0)
{
/* The number can't match any valid date or datetime string */
DBUG_RETURN(TIMESTAMP_NONE);
}
date[i]=tmp_value;
not_zero_date|= tmp_value;
if (i == 2 && str != end && *str == 'T')
@ -488,6 +495,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
if (my_isspace(&my_charset_latin1,*str) && i != 2)
DBUG_RETURN(TIMESTAMP_NONE);
str++;
found_delimitier=1; // Should be a 'normal' date
}
}
field_length=1; // Rest fields can only be 2
@ -498,7 +506,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
{
str++;
uint tmp_value=(uint) (uchar) (*str - '0');
field_length=3;
field_length=5;
while (str++ != end && my_isdigit(&my_charset_latin1,str[0]) &&
field_length--)
tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
@ -583,12 +591,22 @@ longlong str_to_datetime(const char *str,uint length,bool fuzzy_date)
}
/*****************************************************************************
** convert a time string to a (ulong) value.
** Can use all full timestamp formats and
** [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS, [M]MSS or [S]S
** There may be an optional [.second_part] after seconds
*****************************************************************************/
/*
Convert a time string to a TIME struct.
SYNOPSIS
str_to_time()
str A string in full TIMESTAMP format or
[-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS,
[M]MSS or [S]S
There may be an optional [.second_part] after seconds
length Length of str
l_time Store result here
RETURN
0 ok
1 error
*/
bool str_to_time(const char *str,uint length,TIME *l_time)
{

View file

@ -22,24 +22,48 @@
#include "m_string.h"
#include "m_ctype.h"
static uchar ctype_bin[] = {
0,
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
static uchar ctype_bin[]=
{
0,
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
};
/* Dummy array for toupper / tolower / sortorder */
static uchar bin_char_array[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
};
@ -277,9 +301,9 @@ CHARSET_INFO my_charset_bin =
"binary", /* name */
"", /* comment */
ctype_bin, /* ctype */
NULL, /* to_lower */
NULL, /* to_upper */
NULL, /* sort_order */
bin_char_array, /* to_lower */
bin_char_array, /* to_upper */
bin_char_array, /* sort_order */
NULL, /* tab_to_uni */
NULL, /* tab_from_uni */
0, /* strxfrm_multiply */