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-sslclient
vio/test-sslserver vio/test-sslserver
vio/viotest-ssl 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)) if (!mysql_real_query(&mysql,buf,length))
return 0; return 0;
uint error=put_info(mysql_error(&mysql),INFO_ERROR, mysql_errno(&mysql)); uint error=put_info(mysql_error(&mysql),INFO_ERROR, mysql_errno(&mysql));
if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 ||
|| status.batch) status.batch)
return error; return error;
if (reconnect()) if (reconnect())
return error; return error;
@ -1417,6 +1417,7 @@ int mysql_store_result_for_lazy(MYSQL_RES **result)
return 0; return 0;
} }
static int com_server_help(String *buffer __attribute__((unused)), static int com_server_help(String *buffer __attribute__((unused)),
char *line __attribute__((unused)), char *help_arg) char *line __attribute__((unused)), char *help_arg)
{ {
@ -1460,22 +1461,23 @@ static int com_server_help(String *buffer __attribute__((unused)),
init_pager(); init_pager();
if (cur[1][0] == 'Y') 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, "%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 else
{ {
tee_fprintf(PAGER, "\nName : \'%s\'\n\n", cur[0]); tee_fprintf(PAGER, "Name: \'%s\'\n\n", cur[0]);
tee_fprintf(PAGER, "Description : \n%s\n\n", cur[2]); tee_fprintf(PAGER, "Description:\n%s\n\n", cur[2]);
tee_fprintf(PAGER, "Examples : \n%s\n", cur[3]); if (cur[3])
tee_fprintf(PAGER, "Examples:\n%s\n", cur[3]);
} }
end_pager(); end_pager();
} }
else if (num_rows > 1) else if (num_rows > 1)
{ {
put_info("\nMany help items for your request exist", 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); put_info("For more specific request please type 'help <item>' where item is one of next:", INFO_INFO);
init_pager(); init_pager();
char last_char= '_'; char last_char= '_';
@ -1506,7 +1508,7 @@ err:
} }
static int static int
com_help (String *buffer __attribute__((unused)), com_help(String *buffer __attribute__((unused)),
char *line __attribute__((unused))) char *line __attribute__((unused)))
{ {
reg1 int i; reg1 int i;
@ -1530,13 +1532,9 @@ com_help (String *buffer __attribute__((unused)),
tee_fprintf(stdout, "%s\t(\\%c)\t%s\n", commands[i].name, tee_fprintf(stdout, "%s\t(\\%c)\t%s\n", commands[i].name,
commands[i].cmd_char, commands[i].doc); 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; 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 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 not defined, skips the command and returns the first argument. The

View File

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

View File

@ -56,7 +56,8 @@ getline (char **lineptr, size_t *n, FILE *stream)
if (*n >= new_size) /* Overflowed size_t */ if (*n >= new_size) /* Overflowed size_t */
line = NULL; line = NULL;
else 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) if (line)
{ {

View File

@ -419,6 +419,7 @@ int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid);
int STDCALL mysql_ping(MYSQL *mysql); int STDCALL mysql_ping(MYSQL *mysql);
const char * STDCALL mysql_stat(MYSQL *mysql); const char * STDCALL mysql_stat(MYSQL *mysql);
const char * STDCALL mysql_get_server_info(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_client_info(void);
const char * STDCALL mysql_get_host_info(MYSQL *mysql); const char * STDCALL mysql_get_host_info(MYSQL *mysql);
unsigned int STDCALL mysql_get_proto_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 const char * STDCALL
mysql_get_host_info(MYSQL *mysql) 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) if (!mysql_client_init)
{ {

View File

@ -66,6 +66,9 @@ c_h="" i_h=""
c_u="" i_u="" c_u="" i_u=""
c_f="" i_f="" c_f="" i_f=""
c_t="" c_c="" c_t="" c_c=""
c_hl="" c_hl=""
c_hc="" c_hc=""
c_clr="" c_clr=""
# Check for old tables # Check for old tables
if test ! -f $mdata/db.frm if test ! -f $mdata/db.frm
@ -207,6 +210,42 @@ then
c_c="$c_c comment='Column privileges';" c_c="$c_c comment='Column privileges';"
fi 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 \ mysqld_boot=" $execdir/mysqld --no-defaults --bootstrap --skip-grant-tables \
--basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $EXTRA_ARG" --basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $EXTRA_ARG"
echo "running $mysqld_boot" echo "running $mysqld_boot"
@ -227,6 +266,10 @@ $i_f
$c_t $c_t
$c_c $c_c
$c_hl
$c_hc
$c_clr
END_OF_DATA END_OF_DATA
then then
exit 0 exit 0

View File

@ -3,6 +3,9 @@ Tables_in_mysql
columns_priv columns_priv
db db
func func
help_category
help_relation
help_topic
host host
tables_priv tables_priv
user user
@ -15,6 +18,9 @@ Tables_in_mysql
columns_priv columns_priv
db db
func func
help_category
help_relation
help_topic
host host
tables_priv tables_priv
user user
@ -27,6 +33,9 @@ Tables_in_mysql
columns_priv columns_priv
db db
func func
help_category
help_relation
help_topic
host host
tables_priv tables_priv
user 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 id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where 1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
drop table t1,t2; 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; 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 (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 (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,-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,"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); 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 where c=1;
explain select * from t1 use index() where c=1; explain select * from t1 use index() where c=1;
drop table t1,t2; 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 (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 (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,-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,"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); 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

@ -103,7 +103,8 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags)
#define BUFF_LEN FN_LEN #define BUFF_LEN FN_LEN
#endif #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) #if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH)
int result=0; int result=0;

View File

@ -111,12 +111,12 @@ sub flush_all
$example= prepare_example($example); $example= prepare_example($example);
if ($func_name ne "" && $text ne "" && !($func_name =~ /[abcdefghikjlmnopqrstuvwxyz]/)){ 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 "'$func_name',";
print "'$text',"; print "'$text',";
print "'$example'"; print "'$example'";
print ");\n"; 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= ""; $func_name= "";
@ -131,50 +131,43 @@ sub new_category
$category= prepare_text($category); $category= prepare_text($category);
print "INSERT INTO function_category_name (name) VALUES (\'$category\');\n"; print "INSERT INTO help_category (name) VALUES (\'$category\');\n";
print "SELECT \@cur_category:=LAST_INSERT_ID();\n"; print "SET \@cur_category=LAST_INSERT_ID();\n";
} }
print "INSERT INTO db (Host,DB,User,Select_priv) VALUES ('%','mysql_help','','Y');\n"; #print "INSERT INTO db (Host,DB,User,Select_priv) VALUES ('%','mysql_help','','Y');\n";
print "CREATE DATABASE mysql_help;\n"; #print "CREATE DATABASE mysql_help;\n";
print "USE mysql_help;\n"; print "USE mysql;\n";
print "DROP TABLE IF EXISTS function;\n"; print "DROP TABLE IF EXISTS help_topic;\n";
print "CREATE TABLE function ("; print "CREATE TABLE help_topic (";
print " func_id int unsigned not null auto_increment,"; print " help_topic_id int unsigned not null auto_increment,";
print " name varchar(64) not null,"; print " name varchar(64) not null,";
print " url varchar(128) not null,";
print " description text not null,"; print " description text not null,";
print " example text not null,"; print " example text not null,";
print " min_args tinyint not null,"; print " url varchar(128) not null,";
print " max_args tinyint,"; print " primary key (help_topic_id),";
print " date_created datetime not null,"; print " uniuqe index(name)";
print " last_modified timestamp not null,";
print " primary key (func_id)";
print ") type=myisam;\n\n"; print ") type=myisam;\n\n";
print "DROP TABLE IF EXISTS function_category_name;\n"; print "DROP TABLE IF EXISTS help_category;\n";
print "CREATE TABLE function_category_name ("; print "CREATE TABLE help_category (";
print " cat_id smallint unsigned not null auto_increment,"; print " help_category_id smallint unsigned not null auto_increment,";
print " name varchar(64) not null,"; print " name varchar(64) not null,";
print " url varchar(128) not null,"; print " url varchar(128) not null,";
print " date_created datetime not null,"; print " primary key (help_category_id),";
print " last_modified timestamp not null,"; print " unique index (name)";
print " primary key (cat_id)";
print ") type=myisam;\n\n"; print ") type=myisam;\n\n";
print "DROP TABLE IF EXISTS function_category;\n"; print "DROP TABLE IF EXISTS help_relation;\n";
print "CREATE TABLE function_category ("; print "CREATE TABLE help_relation (";
print " cat_id smallint unsigned not null references function_category_name,"; print" help_topic_id int unsigned not null references help_topic,";
print " func_id int unsigned not null references function,"; print" help_category_id smallint unsigned not null references help_category,";
print " primary key (cat_id, func_id)"; print" primary key (help_category_id, help_topic_id),";
print ") type=myisam;\n\n"; print ") type=myisam;\n\n";
print "DELETE FROM function_category_name;\n"; print "SET \@cur_category=null;\n\n";
print "DELETE FROM function_category;\n";
print "DELETE FROM function;\n";
print "SELECT \@cur_category:=null;\n\n";
my $in_section_6_3= 0; my $in_section_6_3= 0;
@ -239,8 +232,8 @@ for(<>)
} }
print "DELETE function_category_name "; print "DELETE help_category ";
print "FROM function_category_name "; print "FROM help_category ";
print "LEFT JOIN function_category ON function_category.cat_id=function_category_name.cat_id "; print "LEFT JOIN help_relation ON help_category.help_category_id=help_relation.help_category_id ";
print "WHERE function_category.cat_id is null;" 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; 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; length-= HA_KEY_BLOB_LENGTH;
uint f_length=uint2korr(ptr); 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 */ /* The following is used only when comparing a key */
void Field_blob::get_key_image(char *buff,uint length, 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; length-= HA_KEY_BLOB_LENGTH;
uint32 blob_length= get_length(ptr); 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; length-=HA_KEY_BLOB_LENGTH;
ulong blob_length=get_length(ptr); 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, uint maxbuffer,IO_CACHE *tempfile,
IO_CACHE *outfile); IO_CACHE *outfile);
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count); 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 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; uchar **sort_keys;
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile; IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
SORTPARAM param; SORTPARAM param;
CHARSET_INFO *charset= &my_charset_bin; bool multi_byte_charset;
DBUG_ENTER("filesort"); DBUG_ENTER("filesort");
DBUG_EXECUTE("info",TEST_filesort(sortorder,s_length);); DBUG_EXECUTE("info",TEST_filesort(sortorder,s_length););
#ifdef SKIP_DBUG_IN_FILESORT #ifdef SKIP_DBUG_IN_FILESORT
DBUG_PUSH(""); /* No DBUG here */ DBUG_PUSH(""); /* No DBUG here */
#endif #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; outfile= table->io_cache;
my_b_clear(&tempfile); my_b_clear(&tempfile);
my_b_clear(&buffpek_pointers); my_b_clear(&buffpek_pointers);
@ -96,7 +91,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
error= 1; error= 1;
bzero((char*) &param,sizeof(param)); bzero((char*) &param,sizeof(param));
param.ref_length= table->file->ref_length; 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; param.max_rows= max_rows;
if (select && select->quick) 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) if (param.sort_length == param.ref_length && records > param.max_rows)
records=param.max_rows; /* purecov: inspected */ 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)))) !(param.tmp_buffer=my_malloc(param.sort_length,MYF(MY_WME))))
goto err; goto err;
@ -493,15 +489,7 @@ static void make_sortkey(register SORTPARAM *param,
diff=0; /* purecov: inspected */ diff=0; /* purecov: inspected */
length=sort_field->length; 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(); char *from=(char*) res->ptr();
if ((unsigned char *)from == to) if ((unsigned char *)from == to)
@ -515,7 +503,6 @@ static void make_sortkey(register SORTPARAM *param,
if (tmp_length < sort_field->length) if (tmp_length < sort_field->length)
bzero((char*) to+tmp_length,sort_field->length-tmp_length); bzero((char*) to+tmp_length,sort_field->length-tmp_length);
} }
}
else else
{ {
if (res->ptr() != (char*) to) if (res->ptr() != (char*) to)
@ -907,17 +894,36 @@ static int merge_index(SORTPARAM *param, uchar *sort_buffer,
} /* merge_index */ } /* 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 static uint
sortlength(SORT_FIELD *sortorder, uint s_length) sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset)
{ {
reg2 uint length; reg2 uint length;
THD *thd= current_thd; THD *thd= current_thd;
*multi_byte_charset= 0;
length=0; length=0;
for (; s_length-- ; sortorder++) for (; s_length-- ; sortorder++)
{ {
sortorder->need_strxnfrm= 0;
if (sortorder->field) if (sortorder->field)
{ {
if (sortorder->field->type() == FIELD_TYPE_BLOB) if (sortorder->field->type() == FIELD_TYPE_BLOB)
@ -929,9 +935,13 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
{ {
CHARSET_INFO *cs=sortorder->field->charset(); CHARSET_INFO *cs=sortorder->field->charset();
if (use_strnxfrm(cs)) if (use_strnxfrm(cs))
{
sortorder->need_strxnfrm= 1;
*multi_byte_charset= 1;
sortorder->length= sortorder->length*cs->strxfrm_multiply; sortorder->length= sortorder->length*cs->strxfrm_multiply;
} }
} }
}
if (sortorder->field->maybe_null()) if (sortorder->field->maybe_null())
length++; // Place for NULL marker length++; // Place for NULL marker
} }
@ -944,7 +954,11 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
{ {
CHARSET_INFO *cs=sortorder->item->charset(); CHARSET_INFO *cs=sortorder->item->charset();
if (use_strnxfrm(cs)) if (use_strnxfrm(cs))
{
sortorder->length= sortorder->length*cs->strxfrm_multiply; sortorder->length= sortorder->length*cs->strxfrm_multiply;
sortorder->need_strxnfrm= 1;
*multi_byte_charset= 1;
}
} }
break; break;
case INT_RESULT: case INT_RESULT:

View File

@ -125,8 +125,10 @@ void Item_bool_func2::fix_length_and_dec()
} }
} }
set_cmp_func(); set_cmp_func();
binary_cmp= args[0]->binary() || args[1]->binary();
} }
int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
{ {
owner= item; owner= item;
@ -165,7 +167,7 @@ int Arg_comparator::compare_string()
if ((res2= (*b)->val_str(&owner->tmp_value2))) if ((res2= (*b)->val_str(&owner->tmp_value2)))
{ {
owner->null_value= 0; 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; owner->null_value= 1;
@ -179,7 +181,7 @@ int Arg_comparator::compare_e_string()
res2= (*b)->val_str(&owner->tmp_value2); res2= (*b)->val_str(&owner->tmp_value2);
if (!res1 || !res2) if (!res1 || !res2)
return test(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)); test(sortcmp(res1, res2) == 0));
} }
@ -274,6 +276,7 @@ bool Item_in_optimizer::preallocate_row()
return (!(cache= Item_cache::get_cache(ROW_RESULT))); return (!(cache= Item_cache::get_cache(ROW_RESULT)));
} }
bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables, bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
Item ** ref) Item ** ref)
{ {
@ -281,6 +284,10 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
return 1; return 1;
if (args[0]->maybe_null) if (args[0]->maybe_null)
maybe_null=1; 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()) if (args[0]->binary())
set_charset(&my_charset_bin); set_charset(&my_charset_bin);
with_sum_func= args[0]->with_sum_func; with_sum_func= args[0]->with_sum_func;
@ -395,7 +402,7 @@ longlong Item_func_strcmp::val_int()
null_value=1; null_value=1;
return 0; return 0;
} }
int value= binary() ? stringcmp(a,b) : sortcmp(a,b); int value= binary_cmp ? stringcmp(a,b) : sortcmp(a,b);
null_value=0; null_value=0;
return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1); 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) else if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT)
{ {
cached_result_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()); &my_charset_bin : args[1]->charset());
} }
else else
@ -802,7 +809,7 @@ Item *Item_func_case::find_item(String *str)
} }
if ((tmp=args[i]->val_str(str))) // If not null 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) if (stringcmp(tmp,first_expr_str)==0)
return args[i+1]; 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(); used_tables_cache|=(first_expr)->used_tables();
const_item_cache&= (first_expr)->const_item(); const_item_cache&= (first_expr)->const_item();
with_sum_func= with_sum_func || (first_expr)->with_sum_func; with_sum_func= with_sum_func || (first_expr)->with_sum_func;
first_expr_is_binary= first_expr->binary();
} }
if (else_expr) if (else_expr)
{ {
@ -1193,7 +1201,7 @@ byte *in_double::get_value(Item *item)
return (byte*) &tmp; return (byte*) &tmp;
} }
cmp_item* cmp_item::get_comparator (Item *item) cmp_item* cmp_item::get_comparator(Item *item)
{ {
switch (item->result_type()) { switch (item->result_type()) {
case STRING_RESULT: case STRING_RESULT:
@ -1368,7 +1376,7 @@ void Item_func_in::fix_length_and_dec()
} }
else else
{ {
in_item= cmp_item:: get_comparator(item); in_item= cmp_item::get_comparator(item);
} }
maybe_null= item->maybe_null; maybe_null= item->maybe_null;
max_length= 1; 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() longlong Item_func_like::val_int()
{ {
String* res = args[0]->val_str(&tmp_value1); 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; return OPTIMIZE_NONE;
} }
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{ {
if (Item_bool_func2::fix_fields(thd, tlist, 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; with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
max_length= 1; max_length= 1;
decimals= 0; decimals= 0;
if (args[0]->binary() || args[1]->binary()) binary_cmp= (args[0]->binary() || args[1]->binary());
set_charset(&my_charset_bin);
used_tables_cache=args[0]->used_tables() | args[1]->used_tables(); used_tables_cache=args[0]->used_tables() | args[1]->used_tables();
const_item_cache=args[0]->const_item() && args[1]->const_item(); 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; int error;
if ((error=regcomp(&preg,res->c_ptr(), if ((error=regcomp(&preg,res->c_ptr(),
binary() ? REG_EXTENDED | REG_NOSUB : binary_cmp ? REG_EXTENDED | REG_NOSUB :
REG_EXTENDED | REG_NOSUB | REG_ICASE, REG_EXTENDED | REG_NOSUB | REG_ICASE,
res->charset()))) res->charset())))
{ {
@ -1834,6 +1835,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 0; return 0;
} }
longlong Item_func_regex::val_int() longlong Item_func_regex::val_int()
{ {
char buff[MAX_FIELD_WIDTH]; char buff[MAX_FIELD_WIDTH];
@ -1865,7 +1867,7 @@ longlong Item_func_regex::val_int()
regex_compiled=0; regex_compiled=0;
} }
if (regcomp(&preg,res2->c_ptr(), if (regcomp(&preg,res2->c_ptr(),
binary() ? REG_EXTENDED | REG_NOSUB : binary_cmp ? REG_EXTENDED | REG_NOSUB :
REG_EXTENDED | REG_NOSUB | REG_ICASE, REG_EXTENDED | REG_NOSUB | REG_ICASE,
res->charset())) res->charset()))
@ -1915,7 +1917,7 @@ void Item_func_like::turboBM_compute_suffixes(int *suff)
*splm1 = pattern_len; *splm1 = pattern_len;
if (binary()) if (binary_cmp)
{ {
int i; int i;
for (i = pattern_len - 2; i >= 0; 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++) for (i = bmBc; i < end; i++)
*i = pattern_len; *i = pattern_len;
if (binary()) if (binary_cmp)
{ {
for (j = 0; j < plm1; j++) for (j = 0; j < plm1; j++)
bmBc[(uint) (uchar) pattern[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; const int tlmpl= text_len - pattern_len;
/* Searching */ /* Searching */
if (binary()) if (binary_cmp)
{ {
while (j <= tlmpl) while (j <= tlmpl)
{ {

View File

@ -112,6 +112,8 @@ class Item_bool_func2 :public Item_int_func
protected: protected:
Arg_comparator cmp; Arg_comparator cmp;
String tmp_value1,tmp_value2; String tmp_value1,tmp_value2;
bool binary_cmp;
public: public:
Item_bool_func2(Item *a,Item *b): Item_bool_func2(Item *a,Item *b):
Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {} 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; } bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
void print(String *str) { Item_func::print_op(str); } void print(String *str) { Item_func::print_op(str); }
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); } 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* eq_creator(Item *a, Item *b);
static Item_bool_func2* ne_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 class Item_func_eq :public Item_bool_rowready_func2
{ {
public: 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(); longlong val_int();
enum Functype functype() const { return EQ_FUNC; } enum Functype functype() const { return EQ_FUNC; }
enum Functype rev_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 class Item_func_ge :public Item_bool_rowready_func2
{ {
public: 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(); longlong val_int();
enum Functype functype() const { return GE_FUNC; } enum Functype functype() const { return GE_FUNC; }
enum Functype rev_functype() const { return LE_FUNC; } enum Functype rev_functype() const { return LE_FUNC; }
@ -192,7 +195,7 @@ public:
class Item_func_gt :public Item_bool_rowready_func2 class Item_func_gt :public Item_bool_rowready_func2
{ {
public: 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(); longlong val_int();
enum Functype functype() const { return GT_FUNC; } enum Functype functype() const { return GT_FUNC; }
enum Functype rev_functype() const { return LT_FUNC; } enum Functype rev_functype() const { return LT_FUNC; }
@ -204,7 +207,7 @@ public:
class Item_func_le :public Item_bool_rowready_func2 class Item_func_le :public Item_bool_rowready_func2
{ {
public: 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(); longlong val_int();
enum Functype functype() const { return LE_FUNC; } enum Functype functype() const { return LE_FUNC; }
enum Functype rev_functype() const { return GE_FUNC; } enum Functype rev_functype() const { return GE_FUNC; }
@ -216,7 +219,7 @@ public:
class Item_func_lt :public Item_bool_rowready_func2 class Item_func_lt :public Item_bool_rowready_func2
{ {
public: 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(); longlong val_int();
enum Functype functype() const { return LT_FUNC; } enum Functype functype() const { return LT_FUNC; }
enum Functype rev_functype() const { return GT_FUNC; } enum Functype rev_functype() const { return GT_FUNC; }
@ -228,7 +231,7 @@ public:
class Item_func_ne :public Item_bool_rowready_func2 class Item_func_ne :public Item_bool_rowready_func2
{ {
public: 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(); longlong val_int();
enum Functype functype() const { return NE_FUNC; } enum Functype functype() const { return NE_FUNC; }
cond_result eq_cmp_result() const { return COND_FALSE; } cond_result eq_cmp_result() const { return COND_FALSE; }
@ -257,7 +260,11 @@ class Item_func_strcmp :public Item_bool_func2
public: public:
Item_func_strcmp(Item *a,Item *b) :Item_bool_func2(a,b) {} Item_func_strcmp(Item *a,Item *b) :Item_bool_func2(a,b) {}
longlong val_int(); 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; } optimize_type select_optimize() const { return OPTIMIZE_NONE; }
const char *func_name() const { return "strcmp"; } const char *func_name() const { return "strcmp"; }
}; };
@ -280,7 +287,9 @@ class Item_func_ifnull :public Item_func
{ {
enum Item_result cached_result_type; enum Item_result cached_result_type;
public: 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(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *str); String *val_str(String *str);
@ -294,7 +303,9 @@ class Item_func_if :public Item_func
{ {
enum Item_result cached_result_type; enum Item_result cached_result_type;
public: 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(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *str); String *val_str(String *str);
@ -313,7 +324,9 @@ class Item_func_nullif :public Item_bool_func2
{ {
enum Item_result cached_result_type; enum Item_result cached_result_type;
public: 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(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *str); String *val_str(String *str);
@ -327,7 +340,9 @@ class Item_func_coalesce :public Item_func
{ {
enum Item_result cached_result_type; enum Item_result cached_result_type;
public: 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(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *); String *val_str(String *);
@ -341,9 +356,12 @@ class Item_func_case :public Item_func
Item * first_expr, *else_expr; Item * first_expr, *else_expr;
enum Item_result cached_result_type; enum Item_result cached_result_type;
String tmp_value; String tmp_value;
bool first_expr_is_binary;
public: public:
Item_func_case(List<Item> &list, Item *first_expr_, Item *else_expr_) Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
:Item_func(list), first_expr(first_expr_), else_expr(else_expr_) {} :Item_func(list), first_expr(first_expr_arg), else_expr(else_expr_arg),
cached_result_type(INT_RESULT)
{}
double val(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *); String *val_str(String *);
@ -723,7 +741,6 @@ public:
optimize_type select_optimize() const; optimize_type select_optimize() const;
cond_result eq_cmp_result() const { return COND_TRUE; } cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "like"; } const char *func_name() const { return "like"; }
void fix_length_and_dec();
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); 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_compiled;
bool regex_is_const; bool regex_is_const;
String prev_regexp; String prev_regexp;
bool binary_cmp;
public: public:
Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b), Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
regex_compiled(0),regex_is_const(0) {} 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 str_value.charset If this is a string function, set this to the
character set for the first argument. 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 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 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; Item **arg,**arg_end;
char buff[STACK_BUFF_ALLOC]; // Max argument in function char buff[STACK_BUFF_ALLOC]; // Max argument in function
used_tables_cache=0; used_tables_cache=0;
const_item_cache=1; 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! return 0; // Fatal error if flag is set!
if (arg_count) if (arg_count)
{ // Print purify happy { // Print purify happy
CHARSET_INFO *charset= 0;
/* /*
Set return character set to first argument if we are returning a Set return character set to first argument if we are returning a
string. string.
@ -115,15 +118,21 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if ((*arg)->maybe_null) if ((*arg)->maybe_null)
maybe_null=1; maybe_null=1;
if ((*arg)->binary()) 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; with_sum_func= with_sum_func || (*arg)->with_sum_func;
used_tables_cache|=(*arg)->used_tables(); used_tables_cache|=(*arg)->used_tables();
const_item_cache&= (*arg)->const_item(); 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(); fix_length_and_dec();
if (result_type() == STRING_RESULT)
set_charset((*args)->charset());
fixed= 1; fixed= 1;
return 0; return 0;
} }
@ -847,6 +856,8 @@ void Item_func_min_max::fix_length_and_dec()
if (args[i]->binary()) if (args[i]->binary())
set_charset(&my_charset_bin); 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); res2= args[i]->val_str(res == str ? &tmp_value : str);
if (res2) 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) if ((cmp_sign < 0 ? cmp : -cmp) < 0)
res=res2; res=res2;
} }
@ -994,7 +1005,6 @@ longlong Item_func_locate::val_int()
{ {
String *a=args[0]->val_str(&value1); String *a=args[0]->val_str(&value1);
String *b=args[1]->val_str(&value2); String *b=args[1]->val_str(&value2);
bool binary_str = args[0]->binary() || args[1]->binary();
if (!a || !b) if (!a || !b)
{ {
null_value=1; null_value=1;
@ -1012,7 +1022,7 @@ longlong Item_func_locate::val_int()
if (use_mb(a->charset())) if (use_mb(a->charset()))
{ {
start0=start; start0=start;
if (!binary_str) if (!binary_cmp)
start=a->charpos(start); start=a->charpos(start);
} }
#endif #endif
@ -1022,7 +1032,7 @@ longlong Item_func_locate::val_int()
if (!b->length()) // Found empty string at start if (!b->length()) // Found empty string at start
return (longlong) (start+1); return (longlong) (start+1);
#ifdef USE_MB #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 *ptr=a->ptr()+start;
const char *search=b->ptr(); const char *search=b->ptr();
@ -1049,7 +1059,7 @@ longlong Item_func_locate::val_int()
return 0; return 0;
} }
#endif /* USE_MB */ #endif /* USE_MB */
return (longlong) (binary() ? a->strstr(*b,start) : return (longlong) (binary_cmp ? a->strstr(*b,start) :
(a->strstr_case(*b,start)))+1; (a->strstr_case(*b,start)))+1;
} }
@ -1662,7 +1672,7 @@ longlong Item_master_pos_wait::val_int()
{ {
THD* thd = current_thd; THD* thd = current_thd;
String *log_name = args[0]->val_str(&value); String *log_name = args[0]->val_str(&value);
int event_count; int event_count= 0;
null_value=0; null_value=0;
if (thd->slave_thread || !log_name || !log_name->length()) 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; Item_result cmp_type;
String tmp_value; String tmp_value;
int cmp_sign; int cmp_sign;
int (*str_cmp_function)(const String *x,const String *y);
public: public:
Item_func_min_max(List<Item> &list,int cmp_sign_arg) :Item_func(list), 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(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *); String *val_str(String *);
@ -590,12 +591,17 @@ public:
class Item_func_locate :public Item_int_func class Item_func_locate :public Item_int_func
{ {
String value1,value2; String value1,value2;
bool binary_cmp;
public: public:
Item_func_locate(Item *a,Item *b) :Item_int_func(a,b) {} 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) {} Item_func_locate(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
const char *func_name() const { return "locate"; } const char *func_name() const { return "locate"; }
longlong val_int(); 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 #ifdef USE_MB
const char *ptr,*end,*strend,*search,*search_end; const char *ptr,*end,*strend,*search,*search_end;
register uint32 l; register uint32 l;
bool binary_str; bool binary_cmp;
#endif #endif
null_value=0; null_value=0;
@ -713,7 +713,7 @@ String *Item_func_replace::val_str(String *str)
goto null; goto null;
#ifdef USE_MB #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 #endif
if (res2->length() == 0) if (res2->length() == 0)
@ -723,7 +723,7 @@ String *Item_func_replace::val_str(String *str)
return res; return res;
#else #else
offset=0; offset=0;
if (binary_str && (offset=res->strstr(*res2)) < 0) if (binary_cmp && (offset=res->strstr(*res2)) < 0)
return res; return res;
#endif #endif
if (!(res3=args[2]->val_str(&tmp_value2))) if (!(res3=args[2]->val_str(&tmp_value2)))
@ -732,7 +732,7 @@ String *Item_func_replace::val_str(String *str)
to_length= res3->length(); to_length= res3->length();
#ifdef USE_MB #ifdef USE_MB
if (!binary_str) if (!binary_cmp)
{ {
search=res2->ptr(); search=res2->ptr();
search_end=search+from_length; 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) else if (hybrid_type == REAL_RESULT)
max_length=float_length(decimals); max_length=float_length(decimals);
else else
{
str_cmp_function= binary() ? stringcmp : sortcmp;
max_length=item->max_length; max_length=item->max_length;
}
decimals=item->decimals; decimals=item->decimals;
maybe_null=item->maybe_null; maybe_null=item->maybe_null;
unsigned_flag=item->unsigned_flag; unsigned_flag=item->unsigned_flag;
@ -434,8 +437,7 @@ bool Item_sum_min::add()
{ {
String *result=args[0]->val_str(&tmp_value); String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value && if (!args[0]->null_value &&
(null_value || (null_value || (*str_cmp_function)(&value,result) > 0))
(binary() ? stringcmp(&value,result) : sortcmp(&value,result)) > 0))
{ {
value.copy(*result); value.copy(*result);
null_value=0; null_value=0;
@ -481,8 +483,7 @@ bool Item_sum_max::add()
{ {
String *result=args[0]->val_str(&tmp_value); String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value && if (!args[0]->null_value &&
(null_value || (null_value || (*str_cmp_function)(&value,result) < 0))
(binary() & MY_CS_BINSORT ? stringcmp(&value,result) : sortcmp(&value,result)) < 0))
{ {
value.copy(*result); value.copy(*result);
null_value=0; null_value=0;
@ -757,8 +758,7 @@ Item_sum_hybrid::min_max_update_str_field(int offset)
result_field->ptr-=offset; result_field->ptr-=offset;
if (result_field->is_null() || if (result_field->is_null() ||
(cmp_sign * (binary() ? stringcmp(res_str,&tmp_value) : (cmp_sign * (*str_cmp_function)(res_str,&tmp_value)) < 0)
sortcmp(res_str,&tmp_value)) < 0))
result_field->store(res_str->ptr(),res_str->length(),res_str->charset()); result_field->store(res_str->ptr(),res_str->length(),res_str->charset());
else else
{ // Use old value { // Use old value

View File

@ -369,9 +369,11 @@ class Item_sum_hybrid :public Item_sum
enum_field_types hybrid_field_type; enum_field_types hybrid_field_type;
int cmp_sign; int cmp_sign;
table_map used_table_cache; table_map used_table_cache;
int (*str_cmp_function)(const String *x,const String *y);
public: 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) used_table_cache(~(table_map) 0)
{} {}
Item_sum_hybrid(THD *thd, Item_sum_hybrid &item): 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(), if (my_strnncoll(key_part->field->charset(),
(const uchar*) key, length, (const uchar*) key, length,
(const uchar*) table->record[0]+key_part->offset,length)) (const uchar*) table->record[0]+key_part->offset,
length))
return 1; return 1;
} }
else if (memcmp(key,table->record[0]+key_part->offset,length)) 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}, { "HANDLER", SYM(HANDLER_SYM),0,0},
{ "HASH", SYM(HASH_SYM),0,0}, { "HASH", SYM(HASH_SYM),0,0},
{ "HEAP", SYM(HEAP_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}, { "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0},
{ "HOUR", SYM(HOUR_SYM),0,0}, { "HOUR", SYM(HOUR_SYM),0,0},
{ "HOUR_MINUTE", SYM(HOUR_MINUTE_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_db_name(char *db);
bool check_column_name(const char *name); bool check_column_name(const char *name);
bool check_table_name(const char *name, uint length); 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); int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
/* from hostname.cc */ /* from hostname.cc */

View File

@ -147,9 +147,9 @@ double rnd(struct rand_struct *rand_st)
none 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. */ /* Use pointer arithmetics as it is faster way to do so. */
for (; target<end ; target++) for (; target<end ; target++)
*target= (char) (rnd(rand_st)*94+33); *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 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; const char *from_end=from+length;
@ -252,7 +252,7 @@ void password_hash_stage1(char *to, const char *password)
none none
*/ */
void password_hash_stage2(char *to,const char *salt) void password_hash_stage2(char *to, const char *salt)
{ {
SHA1_CONTEXT context; SHA1_CONTEXT context;
sha1_reset(&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) 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=salt;
res++; res++;
@ -356,14 +356,14 @@ void get_salt_from_bin_password(ulong *res,unsigned char *password,ulong salt)
!0 for invalid password !0 for invalid password
*/ */
my_bool validate_password(const char* password, const char* message, my_bool validate_password(const char *password, const char *message,
ulong* salt) ulong *salt)
{ {
char buffer[SCRAMBLE41_LENGTH]; /* Used for password validation */ char buffer[SCRAMBLE41_LENGTH]; /* Used for password validation */
char tmpsalt[8]; /* Temporary value to convert salt to string form */ char tmpsalt[8]; /* Temporary value to convert salt to string form */
ulong salt_candidate[6]; /* Computed candidate salt */ ulong salt_candidate[6]; /* Computed candidate salt */
ulong* sc=salt_candidate; /* we need to be able to increment */ ulong *sc=salt_candidate; /* we need to be able to increment */
ulong* salt_end; ulong *salt_end;
/* Now we shall get stage1 encrypted password in buffer*/ /* Now we shall get stage1 encrypted password in buffer*/
password_crypt(password,buffer,message,SCRAMBLE41_LENGTH); 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 !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==NULL) return 0;
if (password[0]==PVERSION41_CHAR) return PVERSION41_CHAR; if (password[0]==PVERSION41_CHAR) return PVERSION41_CHAR;
@ -536,19 +536,19 @@ void make_password_from_salt(char *to, ulong *hash_res,uint8 password_version)
!0 password version char for newer passwords !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; int t;
ulong* salt_end; ulong* salt_end;
ulong val; ulong val;
SHA1_CONTEXT context; 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; salt_end=salt+5;
sprintf(hash,"%04x",(unsigned short)salt[0]); sprintf(hash,"%04x",(unsigned short)salt[0]);
while (salt<salt_end) /* Iterate over these elements*/ while (salt<salt_end)
{ {
val=*(++salt); val=*(++salt);
for (t=3; t>=0; t--) for (t=3; t>=0; t--)
@ -561,21 +561,22 @@ void get_hash_and_password(ulong* salt, uint8 pversion, char* hash, unsigned cha
} }
else else
{ {
unsigned char *bp= bin_password; /* Binary password loop pointer */
/* Use zero starting hash as an indication of old password */ /* Use zero starting hash as an indication of old password */
hash[0]=0; hash[0]=0;
salt_end=salt+2; salt_end=salt+2;
bp=bin_password;
/* Encode salt using SHA1 here */ /* Encode salt using SHA1 here */
sha1_reset(&context); 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--) for (t=3;t>=0;t--)
{ {
bp[t]= (uchar) (val & 255); 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++; salt++;
} }
/* Use 8 bytes of binary password for hash */ /* 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 */ char buffer[SCRAMBLE41_LENGTH]; /* Buffer for various needs */
ulong salt[6]; /* Salt (large for safety) */ 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; struct rand_struct rand_st;
ulong hash_pass[2],hash_message[2]; ulong hash_pass[2],hash_message[2];
char message_buffer[9]; /* Real message buffer */ 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 */ /* 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))) while (!(read_record_info.read_record(&read_record_info)))
{ {
ACL_HOST host; ACL_HOST host;
update_hostname(&host.host,get_field(&mem, table,0)); update_hostname(&host.host,get_field(&mem, table->field[0]));
host.db= get_field(&mem, table,1); host.db= get_field(&mem, table->field[1]);
host.access= get_access(table,2); host.access= get_access(table,2);
host.access= fix_rights_for_db(host.access); host.access= fix_rights_for_db(host.access);
host.sort= get_sort(2,host.host.hostname,host.db); 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; ACL_USER user;
uint length=0; uint length=0;
update_hostname(&user.host,get_field(&mem, table,0)); update_hostname(&user.host,get_field(&mem, table->field[0]));
user.user=get_field(&mem, table,1); user.user=get_field(&mem, table->field[1]);
user.password=get_field(&mem, table,2); user.password=get_field(&mem, table->field[2]);
if (user.password && (length=(uint) strlen(user.password)) == 8 && if (user.password && (length=(uint) strlen(user.password)) == 8 &&
protocol_version == PROTOCOL_VERSION) 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); (uint) strlen(user.host.hostname) : 0);
if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */ 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) if (!ssl_type)
user.ssl_type=SSL_TYPE_NONE; user.ssl_type=SSL_TYPE_NONE;
else if (!strcmp(ssl_type, "ANY")) 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") */ else /* !strcmp(ssl_type, "SPECIFIED") */
user.ssl_type=SSL_TYPE_SPECIFIED; user.ssl_type=SSL_TYPE_SPECIFIED;
user.ssl_cipher= get_field(&mem, table, 25); user.ssl_cipher= get_field(&mem, table->field[25]);
user.x509_issuer= get_field(&mem, table, 26); user.x509_issuer= get_field(&mem, table->field[26]);
user.x509_subject= get_field(&mem, table, 27); 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); 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); 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); user.user_resource.connections=atoi(ptr);
if (user.user_resource.questions || user.user_resource.updates || if (user.user_resource.questions || user.user_resource.updates ||
user.user_resource.connections) 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))) while (!(read_record_info.read_record(&read_record_info)))
{ {
ACL_DB db; ACL_DB db;
update_hostname(&db.host,get_field(&mem, table,0)); update_hostname(&db.host,get_field(&mem, table->field[0]));
db.db=get_field(&mem, table,1); db.db=get_field(&mem, table->field[1]);
if (!db.db) if (!db.db)
{ {
sql_print_error("Found an entry in the 'db' table with empty database name; Skipped"); sql_print_error("Found an entry in the 'db' table with empty database name; Skipped");
continue; continue;
} }
db.user=get_field(&mem, table,2); db.user=get_field(&mem, table->field[2]);
db.access=get_access(table,3); db.access=get_access(table,3);
db.access=fix_rights_for_db(db.access); db.access=fix_rights_for_db(db.access);
db.sort=get_sort(3,db.host.hostname,db.db,db.user); db.sort=get_sort(3,db.host.hostname,db.db,db.user);
@ -457,6 +457,7 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
return 0; return 0;
} }
/* /*
Prepare crypted scramble to be sent to the client Prepare crypted scramble to be sent to the client
*/ */
@ -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); create_random_string(SCRAMBLE41_LENGTH,&thd->rand,thd->scramble);
thd->scramble[SCRAMBLE41_LENGTH]=0; thd->scramble[SCRAMBLE41_LENGTH]=0;
/* Get binary form, First 4 bytes of prepared scramble is salt */ /* 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 */ /* Store "*" as identifier for old passwords */
if (!acl_user->pversion) if (!acl_user->pversion)
prepared_scramble[0]='*'; prepared_scramble[0]='*';
/* Finally encrypt password to get prepared scramble */ /* 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). Get master privilges for user (priviliges for all tables).
Required before connecting to MySQL 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, ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
const char *password,const char *message,char **priv_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) uint *cur_priv_version,ACL_USER** hint_user)
{ {
ulong user_access=NO_ACCESS; ulong user_access=NO_ACCESS;
@ -572,14 +572,15 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
if (!check_scramble(password,message,acl_user->salt, if (!check_scramble(password,message,acl_user->salt,
(my_bool) old_ver)) (my_bool) old_ver))
password_correct=1; password_correct=1;
else /* Password incorrect */ else if (!stage) /* Here if password incorrect */
{
/* At the first stage - prepare scramble */ /* At the first stage - prepare scramble */
if (!stage)
prepare_scramble(thd,acl_user,prepared_scramble); prepare_scramble(thd,acl_user,prepared_scramble);
} }
} }
} }
} }
}
/* If user not found password_correct will also be zero */ /* If user not found password_correct will also be zero */
if (!password_correct) if (!password_correct)
@ -1645,12 +1646,12 @@ public:
{ {
byte key[MAX_KEY_LENGTH]; byte key[MAX_KEY_LENGTH];
host = get_field(&memex,form,0); host = get_field(&memex,form->field[0]);
db = get_field(&memex,form,1); db = get_field(&memex,form->field[1]);
user = get_field(&memex,form,2); user = get_field(&memex,form->field[2]);
if (!user) if (!user)
user=(char*) ""; user=(char*) "";
tname = get_field(&memex,form,3); tname = get_field(&memex,form->field[3]);
if (!host || !db || !tname) if (!host || !db || !tname)
{ {
/* Wrong table row; Ignore it */ /* 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 else
{ {
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK) if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1))) if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
table= 0; table= 0;
@ -1512,6 +1513,11 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
thd Thread handler thd Thread handler
tables Tables to lock 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 RETURN VALUES
0 ok 0 ok
-1 Error -1 Error
@ -1525,6 +1531,7 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
if (!thd->locked_tables) if (!thd->locked_tables)
{ {
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
uint count=0; uint count=0;
for (table = tables ; table ; table=table->next) for (table = tables ; table ; table=table->next)
count++; count++;
@ -1676,28 +1683,31 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
return field; return field;
} }
// Special Field pointer for find_field_in_tables returning
const Field *not_found_field= (Field*) 0x1;
/* /*
Find field in table list. Find field in table list.
SYNOPSIS SYNOPSIS
find_field_in_tables() find_field_in_tables()
thd - pointer to current thread structure thd Pointer to current thread structure
item - field item that should be found item Field item that should be found
tables - tables for scaning tables Tables for scaning
where - table where field found will be returned via this parameter where Table where field found will be returned via
report_error - if FALSE then do not report error if item not found and this parameter
return not_found_field; report_error If FALSE then do not report error if item not found
and return not_found_field
RETURN VALUES RETURN VALUES
0 - field is not found or field is not unique, error message is 0 Field is not found or field is not unique- error
reported message is reported
not_found_field - function was called with report_error == FALSE and not_found_field Function was called with report_error == FALSE and
field if not found, no error message reported field was not found. no error message reported.
found field found field
*/ */
// Special Field pointer for find_field_in_tables returning
const Field *not_found_field= (Field*) 0x1;
Field * Field *
find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
TABLE_LIST **where, bool report_error) 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; 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) Find Item in list of items (find_field_in_tables analog)
@ -1813,24 +1821,29 @@ const Item **not_found_item= (const Item**) 0x1;
SYNOPSIS SYNOPSIS
find_item_in_list() find_item_in_list()
find - item to find find Item to find
items - list of items items List of items
counter - to return number of found item counter To return number of found item
report_error report_error
REPORT_ALL_ERRORS - 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 REPORT_EXCEPT_NOT_FOUND Do not report 'not found' error and
IGNORE_ERRORS - do not report errors, return 0 if error return not_found_item, report other errors,
return 0
IGNORE_ERRORS Do not report errors, return 0 if error
RETURN VALUES RETURN VALUES
0 - item is not found or item is not unique, error message is 0 Item is not found or item is not unique,
reported error message is reported
not_found_item - function was called with report_error == not_found_item Function was called with
REPORT_EXCEPT_NOT_FOUND and item if not found, no error report_error == REPORT_EXCEPT_NOT_FOUND and
message reported item was not found. No error message was reported
found field found field
*/ */
// Special Item pointer for find_item_in_list returning
const Item **not_found_item= (const Item**) 0x1;
Item ** Item **
find_item_in_list(Item *find, List<Item> &items, uint *counter, find_item_in_list(Item *find, List<Item> &items, uint *counter,
find_item_error_report_type report_error) 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 Remap table numbers if INSERT ... SELECT
Check also that the 'used keys' and 'ignored keys' exists and set up the Check also that the 'used keys' and 'ignored keys' exists and set up the
table structure accordingly 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) bool setup_tables(TABLE_LIST *tables)

View File

@ -857,6 +857,7 @@ end:
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/* /*
Check if the query is in the cache. If it was cached, send it Check if the query is in the cache. If it was cached, send it
to the user. to the user.
@ -868,8 +869,6 @@ end:
No error is sent to the client yet. No error is sent to the client yet.
*/ */
int int
Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) 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 */ Field *field; /* Field to sort */
Item *item; /* Item if not sorting fields */ Item *item; /* Item if not sorting fields */
uint length; /* Length of sort field */ uint length; /* Length of sort field */
my_bool reverse; /* if descending sort */
Item_result result_type; /* Type of item */ Item_result result_type; /* Type of item */
bool reverse; /* if descending sort */
bool need_strxnfrm; /* If we have to use strxnfrm() */
} SORT_FIELD; } SORT_FIELD;
@ -898,7 +899,8 @@ typedef struct st_sort_buffer {
/* Structure for db & table in sql_yacc */ /* Structure for db & table in sql_yacc */
class Table_ident :public Sql_alloc { class Table_ident :public Sql_alloc
{
public: public:
LEX_STRING db; LEX_STRING db;
LEX_STRING table; 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(); SELECT_LEX *sl= unit->first_select();
List<Item> item_list; 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)) if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1))
DBUG_RETURN(-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) if (tables)
res= check_table_access(thd,SELECT_ACL, tables); res= check_table_access(thd,SELECT_ACL, tables);
else else
@ -173,10 +178,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
res= 1; res= 1;
else else
{ {
t->real_name=table->real_name; org_table_list->real_name=table->real_name;
t->table=table; org_table_list->table=table;
table->derived_select_number= sl->select_number; table->derived_select_number= sl->select_number;
table->tmp_table=TMP_TABLE; table->tmp_table= TMP_TABLE;
if (lex->describe) if (lex->describe)
{ {
// to fix a problem in EXPLAIN // 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 else
unit->exclude(); unit->exclude();
t->db= (char *)""; org_table_list->db= (char *)"";
t->derived=(SELECT_LEX *) 1; // just in case ... #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); 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); free_tmp_table(thd, table);
else else
{ {
/* Add new temporary table to list of open derived tables */
table->next= thd->derived_tables; table->next= thd->derived_tables;
thd->derived_tables= table; thd->derived_tables= table;
} }

View File

@ -15,288 +15,294 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h" #include "mysql_priv.h"
#include "sql_select.h" // For select_describe
#include "sql_acl.h"
/*************************************************************************** struct st_find_field
** Get help on string {
***************************************************************************/ 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 #define help_charset &my_charset_latin1
MI_INFO *open_help_file(THD *thd, const char *name) /*
{ Look for topics by mask
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;
}
#define size_hf_func_id 4 /* func_id int unsigned, */ SYNOPSIS
#define size_hf_name 64 /* name varchar(64), */ search_topics()
#define size_hf_url 128 /* url varchar(128), */ thd Thread handler
#define size_hf_description sizeof(char*) /* description text, */ topics Table of topic
#define size_hf_example sizeof(char*) /* example text, */ select Function to test for if matching help topic.
#define size_hf_min_args 16 /* min_args tinyint, */ Normally 'help_topic.name like 'bit%'
#define size_hf_max_args 16 /* max_args tinyint, */ pfname Pointer to Field structure for field "name"
#define size_hf_date_created 8 /* date_created datetime, */ names List of founded topic's names (out)
#define size_hf_last_modified 8 /* last_modified timestamp, */ 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 int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_field,
#define offset_hf_name (offset_hf_func_id+size_hf_func_id) SQL_SELECT *select, List<char> *names,
#define offset_hf_url (offset_hf_name+size_hf_name) char **name, char **description, char **example)
#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)
{ {
DBUG_ENTER("search_functions"); DBUG_ENTER("search_functions");
int count= 0; int count= 0;
if (mi_scan_init(file_leafs)) READ_RECORD read_record_info;
DBUG_RETURN(-1); init_read_record(&read_record_info, thd, topics, select,1,0);
while (!read_record_info.read_record(&read_record_info))
help_leaf leaf;
while (!mi_scan(file_leafs,(byte*)&leaf))
{ {
leaf.prepare_fields(); if (!select->cond->val_int()) // Dosn't match like
const char *lname= leaf.get_name();
if (wild_case_compare(help_charset,lname,mask))
continue; 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); names->push_back(lname);
if (!s->copy())
names->push_back(s);
} }
else if (count==1) else if (count == 1)
{ {
*description= new String(leaf.get_description(),help_charset); *description= get_field(&thd->mem_root,
*example= new String(leaf.get_example(),help_charset); find_field[help_topic_description].field);
*name= new String(lname,help_charset); *example= get_field(&thd->mem_root,
(*description)->copy(); find_field[help_topic_example].field);
(*example)->copy(); *name= lname;
(*name)->copy();
} }
else else
{ {
names->push_back(*name); names->push_back(*name);
delete *description; names->push_back(lname);
delete *example;
*name= 0; *name= 0;
*description= 0; *description= 0;
*example= 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); DBUG_RETURN(count);
} }
#define size_hc_cat_id 2 /* cat_id smallint, */ /*
#define size_hc_name 64 /* name varchar(64), */ Look for categories by mask
#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 SYNOPSIS
#define offset_hc_name (offset_hc_cat_id+size_hc_cat_id) search_categories()
#define offset_hc_url (offset_hc_name+size_hc_name) thd THD for init_read_record
#define offset_hc_date_created (offset_hc_url+size_hc_url) categories Table of categories
#define offset_hc_last_modified (offset_hc_date_created+size_hc_date_created) 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)
#define HELP_CATEGORY_SIZE (offset_hc_last_modified+size_hc_last_modified) RETURN VALUES
# Number of categories founded
*/
class help_category{ int search_categories(THD *thd, TABLE *categories,
public: struct st_find_field *find_fields,
char record[HELP_CATEGORY_SIZE]; SQL_SELECT *select, List<char> *names, int16 *res_id)
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)
{ {
Field *pfname= find_fields[help_category_name].field;
DBUG_ENTER("search_categories"); DBUG_ENTER("search_categories");
int count= 0; int count= 0;
MI_INFO *file_categories= 0; READ_RECORD read_record_info;
if (!(file_categories= open_help_file(thd,"function_category_name"))) init_read_record(&read_record_info, thd, categories, select,1,0);
DBUG_RETURN(-1); while (!read_record_info.read_record(&read_record_info))
if (mi_scan_init(file_categories))
{ {
mi_close(file_categories); if (select && !select->cond->val_int())
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; continue;
count++; char *lname= get_field(&thd->mem_root,pfname);
if (++count == 1 && res_id)
if (count==1 && res_id) {
*res_id= category.get_cat_id(); Field *pcat_id= find_fields[help_category_help_category_id].field;
*res_id= (int16) pcat_id->val_int();
String *s= new String(lname,help_charset);
if (!s->copy())
names->push_back(s);
} }
names->push_back(lname);
}
end_read_record(&read_record_info);
mi_close(file_categories);
DBUG_RETURN(count); DBUG_RETURN(count);
} }
int send_variant_2_list(Protocol *protocol, List<String> *names,
my_bool is_category) /*
Send to client rows in format:
column1 : <name>
column2 : <is_it_category>
SYNOPSIS
send_variant_2_list()
protocol Protocol for sending
names List of names
cat Value of the column <is_it_category>
RETURN VALUES
-1 Writing fail
0 Data was successefully send
*/
int send_variant_2_list(Protocol *protocol, List<char> *names,
const char *cat)
{ {
DBUG_ENTER("send_names"); DBUG_ENTER("send_names");
List_iterator<String> it(*names); List_iterator<char> it(*names);
String *cur_name; const char *cur_name;
while ((cur_name = it++)) while ((cur_name= it++))
{ {
protocol->prepare_for_resend(); protocol->prepare_for_resend();
protocol->store(cur_name->ptr()); protocol->store(cur_name);
protocol->store(is_category ? "Y" : "N"); protocol->store(cat);
if (protocol->write()) if (protocol->write())
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
DBUG_RETURN(0); 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{ RETURN VALUES
public: -1 corrupt database
char record[HELP_CATEGORY_NAME_SIZE]; 0 succesefull
*/
inline int16 get_cat_id() int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
{ struct st_find_field *find_fields,
return sint2korr(&record[offset_hcn_cat_id]); int16 cat_id, List<char> *res)
}
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)
{ {
DBUG_ENTER("get_all_names_for_category"); char buff[8]; // Max int length
DBUG_ENTER("get_all_topics_for_category");
MI_INFO *file_names_categories= 0; int iindex_topic, iindex_relations;
if (!(file_names_categories= open_help_file(thd,"function_category"))) Field *rtopic_id, *rcat_id;
DBUG_RETURN(1);
help_category_leaf cat_leaf; if ((iindex_topic= find_type((char*) "PRIMARY",
help_leaf leaf; &topics->keynames, 1+2)-1)<0 ||
int key_res= mi_rkey(file_names_categories, (byte*)&cat_leaf, 0, (iindex_relations= find_type((char*) "PRIMARY",
(const byte*)&cat_id,2,HA_READ_KEY_EXACT); &relations->keynames, 1+2)-1)<0)
while (!key_res && cat_leaf.get_cat_id()==cat_id)
{ {
int leaf_id= cat_leaf.get_func_id(); 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;
if (!mi_rkey(file_leafs, (byte*)&leaf, 0, topics->file->index_init(iindex_topic);
(const byte*)&leaf_id,4,HA_READ_KEY_EXACT)) 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]))
{ {
leaf.prepare_fields(); char topic_id_buff[8];
String *s= new String(leaf.get_name(),help_charset); longlong topic_id= rtopic_id->val_int();
if (!s->copy()) Field *field= find_fields[help_topic_help_topic_id].field;
res->push_back(s); field->store((longlong) topic_id);
field->get_key_image(topic_id_buff, field->pack_length(), help_charset,
Field::itRAW);
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));
} }
key_res= mi_rnext(file_names_categories, (byte*)&cat_leaf, 0);
}
mi_close(file_names_categories);
DBUG_RETURN(0); 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, int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
const char *s3, const char *s4) const char *s3, const char *s4)
{ {
@ -317,11 +323,28 @@ int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
protocol->store(s4); protocol->store(s4);
if (protocol->write()) if (protocol->write())
DBUG_RETURN(-1); DBUG_RETURN(-1);
DBUG_RETURN(0); 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) int send_header_2(Protocol *protocol)
{ {
DBUG_ENTER("send_header2"); 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) int mysqld_help(THD *thd, const char *mask)
{ {
Protocol *protocol= thd->protocol; 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"); DBUG_ENTER("mysqld_help");
MI_INFO *file_leafs= 0; TABLE_LIST tables[3];
if (!(file_leafs= open_help_file(thd,"function"))) bzero((gptr)tables,sizeof(tables));
DBUG_RETURN(1); 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<String> function_list, categories_list; List<char> function_list, categories_list;
String *name, *description, *example; char *name, *description, *example;
int res; int res, count_topics, count_categories, error;
int count= search_functions(file_leafs, mask, if (open_and_lock_tables(thd, tables))
&function_list,&name,&description,&example);
if (count < 0)
{ {
res= 1; res= -1;
goto end; 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; int16 category_id;
count= search_categories(thd, mask, &categories_list, &category_id); Item *cond=
if (count<0) 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; if (get_all_topics_for_category(thd,tables[0].table,
tables[2].table, used_fields,
category_id, &function_list))
{
res= -1;
goto end; goto end;
} }
else if (count==1) 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++))
{ {
if ((res= get_all_names_for_category(thd, file_leafs, example.append(cur_topic);
category_id,&function_list)))
goto end;
List_iterator<String> it(function_list);
String *cur_leaf, example;
while ((cur_leaf = it++))
{
example.append(*cur_leaf);
example.append("\n",1); example.append("\n",1);
} }
if ((res= send_answer_1(protocol, categories_list.head()->ptr(), if ((send_answer_1(protocol, categories_list.head(),
"Y","",example.ptr()))) "Y","",example.ptr())))
goto end; goto end;
} }
else else
{ {
if ((res= send_header_2(protocol)) || if (send_header_2(protocol))
(count==0 && goto end;
(search_categories(thd, 0, &categories_list, 0)<0 && if (count_categories == 0)
((res= 1)))) || search_categories(thd,tables[1].table, used_fields, (SQL_SELECT *) 0,
(res= send_variant_2_list(protocol,&categories_list,true))) &categories_list, 0);
if (send_variant_2_list(protocol,&categories_list,"Y"))
goto end; goto end;
} }
} }
else if (count==1) else if (count_topics == 1)
{ {
if ((res= send_answer_1(protocol,name->ptr(),"N", if (send_answer_1(protocol,name,"N",description, example))
description->ptr(), example->ptr())))
goto end; goto end;
} }
else if ((res= send_header_2(protocol)) || else
(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)))
{ {
/* 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; goto end;
} }
res= 0;
send_eof(thd); send_eof(thd);
end: end:
mi_close(file_leafs); delete select;
delete select_cat;
DBUG_RETURN(res); 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_start(THD *thd, uchar *buf,uint length)
{ {
LEX *lex= &thd->lex; 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->thd_charset= lex->thd->variables.thd_charset;
lex->yacc_yyss=lex->yacc_yyvs=0; lex->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE); lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
lex->slave_thd_opt=0;
lex->sql_command=SQLCOM_END; lex->sql_command=SQLCOM_END;
lex->safe_to_cache_query= 1;
bzero(&lex->mi,sizeof(lex->mi));
return lex; return lex;
} }

View File

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

View File

@ -188,7 +188,7 @@ end:
static int check_user(THD *thd,enum_server_command command, const char *user, static int check_user(THD *thd,enum_server_command command, const char *user,
const char *passwd, const char *db, bool check_count, const char *passwd, const char *db, bool check_count,
bool simple_connect, bool do_send_error, 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) uint *cur_priv_version, ACL_USER** hint_user)
{ {
thd->db=0; thd->db=0;
@ -506,10 +506,10 @@ check_connections(THD *thd)
char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble&hash */ char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble&hash */
ACL_USER* cached_user=NULL; /* Initialise to NULL for first stage */ ACL_USER* cached_user=NULL; /* Initialise to NULL for first stage */
uint cur_priv_version; uint cur_priv_version;
DBUG_PRINT("info", (("check_connections called by thread %d"),
thd->thread_id));
DBUG_PRINT("info",("New connection received on %s", DBUG_PRINT("info",("New connection received on %s",
vio_description(net->vio))); 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 if (!thd->host) // If TCP/IP connection
{ {
char ip[30]; char ip[30];
@ -525,6 +525,7 @@ check_connections(THD *thd)
thd->host=(char*) localhost; thd->host=(char*) localhost;
else else
#endif #endif
{
if (!(specialflag & SPECIAL_NO_RESOLVE)) if (!(specialflag & SPECIAL_NO_RESOLVE))
{ {
vio_in_addr(net->vio,&thd->remote.sin_addr); vio_in_addr(net->vio,&thd->remote.sin_addr);
@ -535,6 +536,7 @@ check_connections(THD *thd)
if (connect_errors > max_connect_errors) if (connect_errors > max_connect_errors)
return(ER_HOST_IS_BLOCKED); return(ER_HOST_IS_BLOCKED);
} }
}
DBUG_PRINT("info",("Host: %s ip: %s", DBUG_PRINT("info",("Host: %s ip: %s",
thd->host ? thd->host : "unknown host", thd->host ? thd->host : "unknown host",
thd->ip ? thd->ip : "unknown ip")); thd->ip ? thd->ip : "unknown ip"));
@ -555,8 +557,8 @@ check_connections(THD *thd)
{ {
/* buff[] needs to big enough to hold the server_version variable */ /* buff[] needs to big enough to hold the server_version variable */
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+64]; char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+64];
int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | int client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION; CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
if (opt_using_transactions) if (opt_using_transactions)
client_flags|=CLIENT_TRANSACTIONS; client_flags|=CLIENT_TRANSACTIONS;
@ -665,24 +667,24 @@ check_connections(THD *thd)
/* Store information if we used password. passwd will be dammaged */ /* Store information if we used password. passwd will be dammaged */
bool using_password=test(passwd[0]); bool using_password=test(passwd[0]);
/* Check user permissions. If password failure we'll get scramble back */ /* Check user permissions. If password failure we'll get scramble back */
if (check_user(thd, COM_CONNECT, user, passwd, db, 1, simple_connect, if (check_user(thd, COM_CONNECT, user, passwd, db, 1, simple_connect,
simple_connect, prepared_scramble, using_password, &cur_priv_version, simple_connect, prepared_scramble, using_password,
&cur_priv_version,
&cached_user)<0) &cached_user)<0)
{ {
/* Store current used and database as they are erased with next packet */ /* Store current used and database as they are erased with next packet */
char tmp_user[USERNAME_LENGTH+1]; char tmp_user[USERNAME_LENGTH+1];
char tmp_db[NAME_LEN+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 The client is old we just have to return error */
if (simple_connect) if (simple_connect)
return -1; return -1;
tmp_user[0]=0;
if (user) if (user)
strmake(tmp_user,user,USERNAME_LENGTH); strmake(tmp_user,user,USERNAME_LENGTH);
tmp_db[0]=0;
if (db) if (db)
strmake(tmp_db,db,NAME_LEN); strmake(tmp_db,db,NAME_LEN);
@ -707,7 +709,8 @@ check_connections(THD *thd)
} }
/* Final attempt to check the user based on reply */ /* Final attempt to check the user based on reply */
if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos, if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos,
tmp_db, 1, 0, 1, prepared_scramble, using_password, &cur_priv_version, tmp_db, 1, 0, 1, prepared_scramble, using_password,
&cur_priv_version,
&cached_user)) &cached_user))
return -1; return -1;
} }
@ -774,7 +777,7 @@ pthread_handler_decl(handle_one_connection,arg)
net_printf(thd,error,thd->host_or_ip); net_printf(thd,error,thd->host_or_ip);
#ifdef __NT__ #ifdef __NT__
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE) if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
sleep(1); /* must wait after eof() */ my_sleep(1000); /* must wait after eof() */
#endif #endif
statistic_increment(aborted_connects,&LOCK_status); statistic_increment(aborted_connects,&LOCK_status);
goto end_thread; 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, if (check_user(thd,COM_CHANGE_USER, user, passwd, db, 0, simple_connect,
simple_connect, prepared_scramble, using_password, &cur_priv_version, 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 The client is old we just have to have auth failure */
if (simple_connect) if (simple_connect)
goto restore_user; /* Error is already reported */ goto restore_user; /* Error is already reported */
/* Store current used and database as they are erased with next packet */ /* 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) if (user)
strmake(tmp_user,user,USERNAME_LENGTH); strmake(tmp_user,user,USERNAME_LENGTH);
tmp_db[0]=0;
if (db) if (db)
strmake(tmp_db,db,NAME_LEN); strmake(tmp_db,db,NAME_LEN);
/* Write hash and encrypted scramble to client */ /* Write hash and encrypted scramble to client */
if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) || if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) ||
net_flush(net)) net_flush(net))
@ -1589,7 +1589,6 @@ mysql_execute_command(THD *thd)
cursor= cursor->next) cursor= cursor->next)
{ {
if (cursor->derived && (res=mysql_derived(thd, lex, if (cursor->derived && (res=mysql_derived(thd, lex,
(SELECT_LEX_UNIT *)
cursor->derived, cursor->derived,
cursor))) cursor)))
{ {
@ -1602,7 +1601,7 @@ mysql_execute_command(THD *thd)
} }
if ((&lex->select_lex != lex->all_selects_list && if ((&lex->select_lex != lex->all_selects_list &&
lex->unit.create_total_list(thd, lex, &tables, 0)) lex->unit.create_total_list(thd, lex, &tables, 0))
#ifndef EMBEDDED_LIBRARY #ifndef HAVE_REPLICATION
|| ||
(table_rules_on && tables && thd->slave_thread && (table_rules_on && tables && thd->slave_thread &&
!tables_ok(thd,tables)) !tables_ok(thd,tables))
@ -3170,10 +3169,11 @@ mysql_init_query(THD *thd)
lex->select_lex.prev= &lex->unit.slave; 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_next= lex->select_lex.slave= lex->select_lex.next= 0;
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list); lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
lex->olap=lex->describe= 0; lex->describe= 0;
lex->derived_tables= false; lex->derived_tables= FALSE;
lex->lock_option= TL_READ; lex->lock_option= TL_READ;
lex->found_colon= 0; lex->found_colon= 0;
lex->safe_to_cache_query= 1;
thd->select_number= lex->select_lex.select_number= 1; thd->select_number= lex->select_lex.select_number= 1;
thd->free_list= 0; thd->free_list= 0;
thd->total_warn_count=0; // Warnings for this query thd->total_warn_count=0; // Warnings for this query
@ -3184,7 +3184,7 @@ mysql_init_query(THD *thd)
thd->tmp_table_used= 0; thd->tmp_table_used= 0;
if (opt_bin_log) if (opt_bin_log)
reset_dynamic(&thd->user_var_events); reset_dynamic(&thd->user_var_events);
thd->clear_error();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -3283,8 +3283,6 @@ mysql_parse(THD *thd, char *inBuf, uint length)
DBUG_ENTER("mysql_parse"); DBUG_ENTER("mysql_parse");
mysql_init_query(thd); mysql_init_query(thd);
thd->clear_error();
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
{ {
LEX *lex=lex_start(thd, (uchar*) inBuf, length); LEX *lex=lex_start(thd, (uchar*) inBuf, length);
@ -3790,7 +3788,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->lock_type= lock_type; ptr->lock_type= lock_type;
ptr->updating= test(table_options & TL_OPTION_UPDATING); ptr->updating= test(table_options & TL_OPTION_UPDATING);
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX); ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
ptr->derived= (SELECT_LEX_UNIT *) table->sel; ptr->derived= table->sel;
if (use_index) if (use_index)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index, ptr->use_index=(List<String> *) thd->memdup((gptr) use_index,
sizeof(*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_log.write(thd,COM_PREPARE,"%s",packet);
mysql_init_query(thd); mysql_init_query(thd);
thd->prepare_command=true;
thd->lex.param_count= 0;
LEX *lex=lex_start(thd, (uchar*) packet, length); LEX *lex=lex_start(thd, (uchar*) packet, length);
lex->safe_to_cache_query= 0; lex->safe_to_cache_query= 0;
thd->prepare_command= TRUE;
thd->lex.param_count= 0;
if (!yyparse((void *)thd) && !thd->is_fatal_error) if (!yyparse((void *)thd) && !thd->is_fatal_error)
error= send_prepare_results(stmt); error= send_prepare_results(stmt);
lex_end(lex); 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"); ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
DBUG_RETURN(-1); 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); List_iterator<key_part_spec> cols(key->columns);

View File

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

View File

@ -37,7 +37,27 @@ static byte* get_field_name(Field *buff,uint *length,
return (byte*) buff->field_name; 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, int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
uint ha_open_flags, TABLE *outparam) 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 Allocate string field in MEM_ROOT and return it as NULL-terminated string
If field is empty, return NULL
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]; char buff[MAX_FIELD_WIDTH];
String str(buff,sizeof(buff),default_charset_info); String str(buff,sizeof(buff),default_charset_info);
field->val_str(&str,&str); field->val_str(&str,&str);

View File

@ -19,6 +19,7 @@
class Item; /* Needed by ORDER */ class Item; /* Needed by ORDER */
class GRANT_TABLE; class GRANT_TABLE;
class st_select_lex_unit;
/* Order clause list element */ /* Order clause list element */
@ -161,7 +162,7 @@ typedef struct st_table_list
TABLE *table; /* opened table */ TABLE *table; /* opened table */
st_table_list *table_list; /* pointer to node of list of all tables */ 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; GRANT_INFO grant;
thr_lock_type lock_type; thr_lock_type lock_type;
uint outer_join; /* Which join 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 Also dates where all parts are zero are allowed
RETURN VALUES 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_DATE DATE string (YY MM and DD parts ok)
TIMESTAMP_FULL Full timestamp 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; uint not_zero_date;
const char *pos; const char *pos;
const char *end=str+length; const char *end=str+length;
bool found_delimitier= 0;
DBUG_ENTER("str_to_TIME"); DBUG_ENTER("str_to_TIME");
DBUG_PRINT("enter",("str: %.*s",length,str)); 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) if (str == end)
DBUG_RETURN(TIMESTAMP_NONE); 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. If length= 8 or >= 14 then year is of format YYYY.
(YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS) (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'); tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
str++; 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; date[i]=tmp_value;
not_zero_date|= tmp_value; not_zero_date|= tmp_value;
if (i == 2 && str != end && *str == 'T') 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) if (my_isspace(&my_charset_latin1,*str) && i != 2)
DBUG_RETURN(TIMESTAMP_NONE); DBUG_RETURN(TIMESTAMP_NONE);
str++; str++;
found_delimitier=1; // Should be a 'normal' date
} }
} }
field_length=1; // Rest fields can only be 2 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++; str++;
uint tmp_value=(uint) (uchar) (*str - '0'); uint tmp_value=(uint) (uchar) (*str - '0');
field_length=3; field_length=5;
while (str++ != end && my_isdigit(&my_charset_latin1,str[0]) && while (str++ != end && my_isdigit(&my_charset_latin1,str[0]) &&
field_length--) field_length--)
tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0'); 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. Convert a time string to a TIME struct.
** 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 SYNOPSIS
** There may be an optional [.second_part] after seconds 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) bool str_to_time(const char *str,uint length,TIME *l_time)
{ {

View File

@ -22,7 +22,8 @@
#include "m_string.h" #include "m_string.h"
#include "m_ctype.h" #include "m_ctype.h"
static uchar ctype_bin[] = { static uchar ctype_bin[]=
{
0, 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, 40, 40, 40, 40, 40, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
@ -43,6 +44,29 @@ static uchar ctype_bin[] = {
}; };
/* 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
};
static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)), static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
const uchar *s, uint slen, const uchar *s, uint slen,
const uchar *t, uint tlen) const uchar *t, uint tlen)
@ -277,9 +301,9 @@ CHARSET_INFO my_charset_bin =
"binary", /* name */ "binary", /* name */
"", /* comment */ "", /* comment */
ctype_bin, /* ctype */ ctype_bin, /* ctype */
NULL, /* to_lower */ bin_char_array, /* to_lower */
NULL, /* to_upper */ bin_char_array, /* to_upper */
NULL, /* sort_order */ bin_char_array, /* sort_order */
NULL, /* tab_to_uni */ NULL, /* tab_to_uni */
NULL, /* tab_from_uni */ NULL, /* tab_from_uni */
0, /* strxfrm_multiply */ 0, /* strxfrm_multiply */