mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
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:
parent
363fd89b92
commit
fcb61f5917
48 changed files with 1200 additions and 650 deletions
|
@ -596,3 +596,4 @@ vio/test-ssl
|
|||
vio/test-sslclient
|
||||
vio/test-sslserver
|
||||
vio/viotest-ssl
|
||||
scripts/fill_help_tables.sql
|
||||
|
|
|
@ -1398,8 +1398,8 @@ int mysql_real_query_for_lazy(const char *buf, int length)
|
|||
if (!mysql_real_query(&mysql,buf,length))
|
||||
return 0;
|
||||
uint error=put_info(mysql_error(&mysql),INFO_ERROR, mysql_errno(&mysql));
|
||||
if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1
|
||||
|| status.batch)
|
||||
if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 ||
|
||||
status.batch)
|
||||
return error;
|
||||
if (reconnect())
|
||||
return error;
|
||||
|
@ -1417,8 +1417,9 @@ int mysql_store_result_for_lazy(MYSQL_RES **result)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int com_server_help(String *buffer __attribute__((unused)),
|
||||
char *line __attribute__((unused)), char *help_arg)
|
||||
char *line __attribute__((unused)), char *help_arg)
|
||||
{
|
||||
MYSQL_ROW cur;
|
||||
const char *server_cmd= buffer->ptr();
|
||||
|
@ -1460,22 +1461,23 @@ static int com_server_help(String *buffer __attribute__((unused)),
|
|||
init_pager();
|
||||
if (cur[1][0] == 'Y')
|
||||
{
|
||||
tee_fprintf(PAGER, "\nHelp topic \'%s\'\n", cur[0]);
|
||||
tee_fprintf(PAGER, "Help topic \'%s\'\n", cur[0]);
|
||||
tee_fprintf(PAGER, "%s\n", cur[2]);
|
||||
tee_fprintf(PAGER, "For help on specific function please type 'help <function>' where function is one of next :\n%s\n", cur[3]);
|
||||
tee_fprintf(PAGER, "For help on specific function please type 'help <function>'\nwhere function is one of next:\n%s\n", cur[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
tee_fprintf(PAGER, "\nName : \'%s\'\n\n", cur[0]);
|
||||
tee_fprintf(PAGER, "Description : \n%s\n\n", cur[2]);
|
||||
tee_fprintf(PAGER, "Examples : \n%s\n", cur[3]);
|
||||
tee_fprintf(PAGER, "Name: \'%s\'\n\n", cur[0]);
|
||||
tee_fprintf(PAGER, "Description:\n%s\n\n", cur[2]);
|
||||
if (cur[3])
|
||||
tee_fprintf(PAGER, "Examples:\n%s\n", cur[3]);
|
||||
}
|
||||
end_pager();
|
||||
}
|
||||
else if (num_rows > 1)
|
||||
{
|
||||
put_info("\nMany help items for your request exist", INFO_INFO);
|
||||
put_info("For more specific request please type 'help <item>' where item is one of next :", INFO_INFO);
|
||||
put_info("Many help items for your request exist", INFO_INFO);
|
||||
put_info("For more specific request please type 'help <item>' where item is one of next:", INFO_INFO);
|
||||
|
||||
init_pager();
|
||||
char last_char= '_';
|
||||
|
@ -1506,8 +1508,8 @@ err:
|
|||
}
|
||||
|
||||
static int
|
||||
com_help (String *buffer __attribute__((unused)),
|
||||
char *line __attribute__((unused)))
|
||||
com_help(String *buffer __attribute__((unused)),
|
||||
char *line __attribute__((unused)))
|
||||
{
|
||||
reg1 int i;
|
||||
char * help_arg= strchr(line,' ');
|
||||
|
@ -1530,13 +1532,9 @@ com_help (String *buffer __attribute__((unused)),
|
|||
tee_fprintf(stdout, "%s\t(\\%c)\t%s\n", commands[i].name,
|
||||
commands[i].cmd_char, commands[i].doc);
|
||||
}
|
||||
if (connected)
|
||||
tee_fprintf(stdout,
|
||||
"\nConnection id: %ld (Can be used with mysqladmin kill)\n\n",
|
||||
mysql_thread_id(&mysql));
|
||||
else
|
||||
tee_fprintf(stdout, "Not connected! Reconnect with 'connect'!\n\n");
|
||||
}
|
||||
if (connected && mysql_get_server_version(&mysql) >= 40100)
|
||||
put_info("\nFor server side help, type 'help all'\n", INFO_INFO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2417,7 +2415,6 @@ com_use(String *buffer __attribute__((unused)), char *line)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Gets argument from a command on the command line. If get_next_arg is
|
||||
not defined, skips the command and returns the first argument. The
|
||||
|
|
|
@ -36,4 +36,8 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8)
|
||||
#define __attribute__(A)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -56,7 +56,8 @@ getline (char **lineptr, size_t *n, FILE *stream)
|
|||
if (*n >= new_size) /* Overflowed size_t */
|
||||
line = NULL;
|
||||
else
|
||||
line = (char *)*lineptr ? realloc (*lineptr, new_size) : malloc (new_size);
|
||||
line = (char *) (*lineptr ? (char*) realloc(*lineptr, new_size) :
|
||||
(char*) malloc(new_size));
|
||||
|
||||
if (line)
|
||||
{
|
||||
|
|
|
@ -419,6 +419,7 @@ int STDCALL mysql_kill(MYSQL *mysql,unsigned long pid);
|
|||
int STDCALL mysql_ping(MYSQL *mysql);
|
||||
const char * STDCALL mysql_stat(MYSQL *mysql);
|
||||
const char * STDCALL mysql_get_server_info(MYSQL *mysql);
|
||||
unsigned long STDCALL mysql_get_server_version(MYSQL *mysql);
|
||||
const char * STDCALL mysql_get_client_info(void);
|
||||
const char * STDCALL mysql_get_host_info(MYSQL *mysql);
|
||||
unsigned int STDCALL mysql_get_proto_info(MYSQL *mysql);
|
||||
|
|
|
@ -3402,6 +3402,35 @@ mysql_get_server_info(MYSQL *mysql)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Get version number for server in a form easy to test on
|
||||
|
||||
SYNOPSIS
|
||||
mysql_get_server_version()
|
||||
mysql Connection
|
||||
|
||||
EXAMPLE
|
||||
4.1.0-alfa -> 40100
|
||||
|
||||
NOTES
|
||||
We will ensure that a newer server always has a bigger number.
|
||||
|
||||
RETURN
|
||||
Signed number > 323000
|
||||
*/
|
||||
|
||||
ulong STDCALL
|
||||
mysql_get_server_version(MYSQL *mysql)
|
||||
{
|
||||
uint major, minor, version;
|
||||
char *pos= mysql->server_version, *end_pos;
|
||||
major= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1;
|
||||
minor= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1;
|
||||
version= (uint) strtoul(pos, &end_pos, 10);
|
||||
return (ulong) major*10000L+(ulong) (minor*100+version);
|
||||
}
|
||||
|
||||
|
||||
const char * STDCALL
|
||||
mysql_get_host_info(MYSQL *mysql)
|
||||
{
|
||||
|
|
|
@ -386,7 +386,7 @@ mysql_init(MYSQL *mysql)
|
|||
}
|
||||
|
||||
|
||||
static void mysql_once_init()
|
||||
void STDCALL mysql_once_init()
|
||||
{
|
||||
if (!mysql_client_init)
|
||||
{
|
||||
|
|
|
@ -66,6 +66,9 @@ c_h="" i_h=""
|
|||
c_u="" i_u=""
|
||||
c_f="" i_f=""
|
||||
c_t="" c_c=""
|
||||
c_hl="" c_hl=""
|
||||
c_hc="" c_hc=""
|
||||
c_clr="" c_clr=""
|
||||
|
||||
# Check for old tables
|
||||
if test ! -f $mdata/db.frm
|
||||
|
@ -207,6 +210,42 @@ then
|
|||
c_c="$c_c comment='Column privileges';"
|
||||
fi
|
||||
|
||||
if test ! -f $mdata/help_topic.frm
|
||||
then
|
||||
c_hl="$c_hl CREATE TABLE help_topic ("
|
||||
c_hl="$c_hl help_topic_id int unsigned not null auto_increment,"
|
||||
c_hl="$c_hl name varchar(64) not null,"
|
||||
c_hl="$c_hl description text not null,"
|
||||
c_hl="$c_hl example text not null,"
|
||||
c_hl="$c_hl url varchar(128) not null,"
|
||||
c_hl="$c_hl primary key (help_topic_id),"
|
||||
c_hl="$c_hl unique index (name)"
|
||||
c_hl="$c_hl )"
|
||||
c_hl="$c_hl comment='help topics';"
|
||||
fi
|
||||
|
||||
if test ! -f $mdata/help_category.frm
|
||||
then
|
||||
c_clr="$c_clr CREATE TABLE help_category ("
|
||||
c_clr="$c_clr help_category_id smallint unsigned not null auto_increment,"
|
||||
c_clr="$c_clr name varchar(64) not null,"
|
||||
c_clr="$c_clr url varchar(128) not null,"
|
||||
c_clr="$c_clr primary key (help_category_id),"
|
||||
c_clr="$c_clr unique index (name)"
|
||||
c_clr="$c_clr )"
|
||||
c_clr="$c_clr comment='help topics-categories relation';"
|
||||
fi
|
||||
|
||||
if test ! -f $mdata/help_relation.frm
|
||||
then
|
||||
c_hc="$c_hc CREATE TABLE help_relation ("
|
||||
c_hc="$c_hc help_topic_id int unsigned not null references help_topic,"
|
||||
c_hc="$c_hc help_category_id smallint unsigned not null references help_category,"
|
||||
c_hc="$c_hc primary key (help_category_id, help_topic_id),"
|
||||
c_hc="$c_hc )"
|
||||
c_hc="$c_hc comment='categories of help topics';"
|
||||
fi
|
||||
|
||||
mysqld_boot=" $execdir/mysqld --no-defaults --bootstrap --skip-grant-tables \
|
||||
--basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $EXTRA_ARG"
|
||||
echo "running $mysqld_boot"
|
||||
|
@ -227,6 +266,10 @@ $i_f
|
|||
|
||||
$c_t
|
||||
$c_c
|
||||
|
||||
$c_hl
|
||||
$c_hc
|
||||
$c_clr
|
||||
END_OF_DATA
|
||||
then
|
||||
exit 0
|
||||
|
|
|
@ -3,6 +3,9 @@ Tables_in_mysql
|
|||
columns_priv
|
||||
db
|
||||
func
|
||||
help_category
|
||||
help_relation
|
||||
help_topic
|
||||
host
|
||||
tables_priv
|
||||
user
|
||||
|
@ -15,6 +18,9 @@ Tables_in_mysql
|
|||
columns_priv
|
||||
db
|
||||
func
|
||||
help_category
|
||||
help_relation
|
||||
help_topic
|
||||
host
|
||||
tables_priv
|
||||
user
|
||||
|
@ -27,6 +33,9 @@ Tables_in_mysql
|
|||
columns_priv
|
||||
db
|
||||
func
|
||||
help_category
|
||||
help_relation
|
||||
help_topic
|
||||
host
|
||||
tables_priv
|
||||
user
|
||||
|
|
123
mysql-test/r/help.result
Normal file
123
mysql-test/r/help.result
Normal 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;
|
|
@ -364,3 +364,8 @@ explain select * from t1 use index() where c=1;
|
|||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
|
||||
drop table t1,t2;
|
||||
CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) TYPE=MyISAM;
|
||||
This version of MySQL doesn't yet support 'RTREE INDEX'
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
|
|
|
@ -85,7 +85,7 @@ CREATE INDEX test3 on t1 ( medium ) ;
|
|||
DROP INDEX test ON t1;
|
||||
insert into t1 values (10, 1,1,1,1,1,1,1,1,1,1,1,1,1,NULL,0,0,0,1,1,1,1,'one','one');
|
||||
insert into t1 values (NULL,2,2,2,2,2,2,2,2,2,2,2,2,2,NULL,NULL,NULL,NULL,NULL,NULL,2,2,'two','two,one');
|
||||
insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303 101010','','','','3',3,3);
|
||||
insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303101010','','','','3',3,3);
|
||||
insert into t1 values (0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,NULL,19970807,080706,19970403090807,-1,-1,-1,'-1',-1,-1);
|
||||
insert into t1 values (0,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,NULL,0,0,0,-4294967295,-4294967295,-4294967295,'-4294967295',0,"one,two,tree");
|
||||
insert into t1 values (0,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,NULL,0,0,0,4294967295,4294967295,4294967295,'4294967295',0,0);
|
||||
|
|
50
mysql-test/t/help.test
Normal file
50
mysql-test/t/help.test
Normal 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;
|
|
@ -352,3 +352,12 @@ explain select * from t1 force index (a) where a=0 or a=2;
|
|||
explain select * from t1 where c=1;
|
||||
explain select * from t1 use index() where c=1;
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# Test RTREE index
|
||||
#
|
||||
--error 1235
|
||||
CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) TYPE=MyISAM;
|
||||
# INSERT INTO t1 VALUES (1,1),(1,1);
|
||||
# DELETE FROM rt WHERE a<1;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
|
|
|
@ -55,7 +55,7 @@ DROP INDEX test ON t1;
|
|||
|
||||
insert into t1 values (10, 1,1,1,1,1,1,1,1,1,1,1,1,1,NULL,0,0,0,1,1,1,1,'one','one');
|
||||
insert into t1 values (NULL,2,2,2,2,2,2,2,2,2,2,2,2,2,NULL,NULL,NULL,NULL,NULL,NULL,2,2,'two','two,one');
|
||||
insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303 101010','','','','3',3,3);
|
||||
insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303101010','','','','3',3,3);
|
||||
insert into t1 values (0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,NULL,19970807,080706,19970403090807,-1,-1,-1,'-1',-1,-1);
|
||||
insert into t1 values (0,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,NULL,0,0,0,-4294967295,-4294967295,-4294967295,'-4294967295',0,"one,two,tree");
|
||||
insert into t1 values (0,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,NULL,0,0,0,4294967295,4294967295,4294967295,'4294967295',0,0);
|
||||
|
|
|
@ -324,7 +324,7 @@ CHARSET_INFO *system_charset_info = &my_charset_latin1;
|
|||
#define MY_ADD_CHARSET(x) all_charsets[(x)->number]=(x)
|
||||
|
||||
|
||||
static my_bool init_compiled_charsets(myf flags __attribute__((unused)))
|
||||
static my_bool init_compiled_charsets(myf flags __attribute__((unused)))
|
||||
{
|
||||
CHARSET_INFO *cs;
|
||||
|
||||
|
|
|
@ -103,7 +103,8 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags)
|
|||
#define BUFF_LEN FN_LEN
|
||||
#endif
|
||||
|
||||
int my_realpath(char *to, const char *filename, myf MyFlags)
|
||||
int my_realpath(char *to, const char *filename,
|
||||
myf MyFlags __attribute__((unused)))
|
||||
{
|
||||
#if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH)
|
||||
int result=0;
|
||||
|
|
|
@ -111,12 +111,12 @@ sub flush_all
|
|||
$example= prepare_example($example);
|
||||
|
||||
if ($func_name ne "" && $text ne "" && !($func_name =~ /[abcdefghikjlmnopqrstuvwxyz]/)){
|
||||
print "INSERT INTO function (name,description,example) VALUES (";
|
||||
print "INSERT INTO help_topic (name,description,example) VALUES (";
|
||||
print "'$func_name',";
|
||||
print "'$text',";
|
||||
print "'$example'";
|
||||
print ");\n";
|
||||
print "INSERT INTO function_category (cat_id,func_id) VALUES (\@cur_category,LAST_INSERT_ID());\n";
|
||||
print "INSERT INTO help_relation (help_category_id,help_topic_id) VALUES (\@cur_category,LAST_INSERT_ID());\n";
|
||||
}
|
||||
|
||||
$func_name= "";
|
||||
|
@ -131,50 +131,43 @@ sub new_category
|
|||
|
||||
$category= prepare_text($category);
|
||||
|
||||
print "INSERT INTO function_category_name (name) VALUES (\'$category\');\n";
|
||||
print "SELECT \@cur_category:=LAST_INSERT_ID();\n";
|
||||
print "INSERT INTO help_category (name) VALUES (\'$category\');\n";
|
||||
print "SET \@cur_category=LAST_INSERT_ID();\n";
|
||||
}
|
||||
|
||||
print "INSERT INTO db (Host,DB,User,Select_priv) VALUES ('%','mysql_help','','Y');\n";
|
||||
print "CREATE DATABASE mysql_help;\n";
|
||||
#print "INSERT INTO db (Host,DB,User,Select_priv) VALUES ('%','mysql_help','','Y');\n";
|
||||
#print "CREATE DATABASE mysql_help;\n";
|
||||
|
||||
print "USE mysql_help;\n";
|
||||
print "USE mysql;\n";
|
||||
|
||||
print "DROP TABLE IF EXISTS function;\n";
|
||||
print "CREATE TABLE function (";
|
||||
print " func_id int unsigned not null auto_increment,";
|
||||
print "DROP TABLE IF EXISTS help_topic;\n";
|
||||
print "CREATE TABLE help_topic (";
|
||||
print " help_topic_id int unsigned not null auto_increment,";
|
||||
print " name varchar(64) not null,";
|
||||
print " url varchar(128) not null,";
|
||||
print " description text not null,";
|
||||
print " example text not null,";
|
||||
print " min_args tinyint not null,";
|
||||
print " max_args tinyint,";
|
||||
print " date_created datetime not null,";
|
||||
print " last_modified timestamp not null,";
|
||||
print " primary key (func_id)";
|
||||
print ") type=myisam;\n\n";
|
||||
|
||||
print "DROP TABLE IF EXISTS function_category_name;\n";
|
||||
print "CREATE TABLE function_category_name (";
|
||||
print " cat_id smallint unsigned not null auto_increment,";
|
||||
print " name varchar(64) not null,";
|
||||
print " url varchar(128) not null,";
|
||||
print " date_created datetime not null,";
|
||||
print " last_modified timestamp not null,";
|
||||
print " primary key (cat_id)";
|
||||
print " primary key (help_topic_id),";
|
||||
print " uniuqe index(name)";
|
||||
print ") type=myisam;\n\n";
|
||||
|
||||
print "DROP TABLE IF EXISTS function_category;\n";
|
||||
print "CREATE TABLE function_category (";
|
||||
print " cat_id smallint unsigned not null references function_category_name,";
|
||||
print " func_id int unsigned not null references function,";
|
||||
print " primary key (cat_id, func_id)";
|
||||
print "DROP TABLE IF EXISTS help_category;\n";
|
||||
print "CREATE TABLE help_category (";
|
||||
print " help_category_id smallint unsigned not null auto_increment,";
|
||||
print " name varchar(64) not null,";
|
||||
print " url varchar(128) not null,";
|
||||
print " primary key (help_category_id),";
|
||||
print " unique index (name)";
|
||||
print ") type=myisam;\n\n";
|
||||
|
||||
print "DELETE FROM function_category_name;\n";
|
||||
print "DELETE FROM function_category;\n";
|
||||
print "DELETE FROM function;\n";
|
||||
print "SELECT \@cur_category:=null;\n\n";
|
||||
print "DROP TABLE IF EXISTS help_relation;\n";
|
||||
print "CREATE TABLE help_relation (";
|
||||
print" help_topic_id int unsigned not null references help_topic,";
|
||||
print" help_category_id smallint unsigned not null references help_category,";
|
||||
print" primary key (help_category_id, help_topic_id),";
|
||||
print ") type=myisam;\n\n";
|
||||
|
||||
print "SET \@cur_category=null;\n\n";
|
||||
|
||||
my $in_section_6_3= 0;
|
||||
|
||||
|
@ -239,8 +232,8 @@ for(<>)
|
|||
}
|
||||
|
||||
|
||||
print "DELETE function_category_name ";
|
||||
print "FROM function_category_name ";
|
||||
print "LEFT JOIN function_category ON function_category.cat_id=function_category_name.cat_id ";
|
||||
print "WHERE function_category.cat_id is null;"
|
||||
print "DELETE help_category ";
|
||||
print "FROM help_category ";
|
||||
print "LEFT JOIN help_relation ON help_category.help_category_id=help_relation.help_category_id ";
|
||||
print "WHERE help_relation.help_category_id is null;"
|
||||
|
||||
|
|
|
@ -4226,7 +4226,8 @@ uint Field_varstring::max_packed_col_length(uint max_length)
|
|||
return (max_length > 255 ? 2 : 1)+max_length;
|
||||
}
|
||||
|
||||
void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,imagetype type)
|
||||
void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
|
||||
imagetype type)
|
||||
{
|
||||
length-= HA_KEY_BLOB_LENGTH;
|
||||
uint f_length=uint2korr(ptr);
|
||||
|
@ -4478,7 +4479,7 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
|
|||
/* The following is used only when comparing a key */
|
||||
|
||||
void Field_blob::get_key_image(char *buff,uint length,
|
||||
CHARSET_INFO *cs,imagetype type)
|
||||
CHARSET_INFO *cs, imagetype type)
|
||||
{
|
||||
length-= HA_KEY_BLOB_LENGTH;
|
||||
uint32 blob_length= get_length(ptr);
|
||||
|
@ -4522,7 +4523,8 @@ void Field_blob::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
|
|||
}
|
||||
|
||||
|
||||
void Field_geom::get_key_image(char *buff,uint length,CHARSET_INFO *cs, imagetype type)
|
||||
void Field_geom::get_key_image(char *buff,uint length,CHARSET_INFO *cs,
|
||||
imagetype type)
|
||||
{
|
||||
length-=HA_KEY_BLOB_LENGTH;
|
||||
ulong blob_length=get_length(ptr);
|
||||
|
|
|
@ -49,7 +49,8 @@ static int merge_index(SORTPARAM *param,uchar *sort_buffer,
|
|||
uint maxbuffer,IO_CACHE *tempfile,
|
||||
IO_CACHE *outfile);
|
||||
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
|
||||
static uint sortlength(SORT_FIELD *sortorder,uint length);
|
||||
static uint sortlength(SORT_FIELD *sortorder, uint s_length,
|
||||
bool *multi_byte_charset);
|
||||
|
||||
/*
|
||||
Creates a set of pointers that can be used to read the rows
|
||||
|
@ -75,19 +76,13 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
|
|||
uchar **sort_keys;
|
||||
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
|
||||
SORTPARAM param;
|
||||
CHARSET_INFO *charset= &my_charset_bin;
|
||||
bool multi_byte_charset;
|
||||
DBUG_ENTER("filesort");
|
||||
DBUG_EXECUTE("info",TEST_filesort(sortorder,s_length););
|
||||
#ifdef SKIP_DBUG_IN_FILESORT
|
||||
DBUG_PUSH(""); /* No DBUG here */
|
||||
#endif
|
||||
|
||||
// BAR TODO: this is not absolutely correct, but OK for now
|
||||
for (i=0;i<table->fields;i++)
|
||||
if (!table->field[i]->binary())
|
||||
charset=table->field[i]->charset();
|
||||
// /BAR TODO
|
||||
|
||||
outfile= table->io_cache;
|
||||
my_b_clear(&tempfile);
|
||||
my_b_clear(&buffpek_pointers);
|
||||
|
@ -96,7 +91,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
|
|||
error= 1;
|
||||
bzero((char*) ¶m,sizeof(param));
|
||||
param.ref_length= table->file->ref_length;
|
||||
param.sort_length=sortlength(sortorder,s_length)+ param.ref_length;
|
||||
param.sort_length= (sortlength(sortorder,s_length, &multi_byte_charset)+
|
||||
param.ref_length);
|
||||
param.max_rows= max_rows;
|
||||
|
||||
if (select && select->quick)
|
||||
|
@ -123,7 +119,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
|
|||
if (param.sort_length == param.ref_length && records > param.max_rows)
|
||||
records=param.max_rows; /* purecov: inspected */
|
||||
|
||||
if (use_strnxfrm(charset) &&
|
||||
if (multi_byte_charset &&
|
||||
!(param.tmp_buffer=my_malloc(param.sort_length,MYF(MY_WME))))
|
||||
goto err;
|
||||
|
||||
|
@ -493,28 +489,19 @@ static void make_sortkey(register SORTPARAM *param,
|
|||
diff=0; /* purecov: inspected */
|
||||
length=sort_field->length;
|
||||
}
|
||||
if (use_strnxfrm(cs))
|
||||
if (sort_field->need_strxnfrm)
|
||||
{
|
||||
if (item->binary())
|
||||
{
|
||||
if (res->ptr() != (char*) to)
|
||||
memcpy(to,res->ptr(),length);
|
||||
bzero((char*) to+length,diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *from=(char*) res->ptr();
|
||||
if ((unsigned char *)from == to)
|
||||
{
|
||||
set_if_smaller(length,sort_field->length);
|
||||
memcpy(param->tmp_buffer,from,length);
|
||||
from=param->tmp_buffer;
|
||||
}
|
||||
uint tmp_length=my_strnxfrm(cs,to,sort_field->length,
|
||||
(unsigned char *) from, length);
|
||||
if (tmp_length < sort_field->length)
|
||||
bzero((char*) to+tmp_length,sort_field->length-tmp_length);
|
||||
}
|
||||
char *from=(char*) res->ptr();
|
||||
if ((unsigned char *)from == to)
|
||||
{
|
||||
set_if_smaller(length,sort_field->length);
|
||||
memcpy(param->tmp_buffer,from,length);
|
||||
from=param->tmp_buffer;
|
||||
}
|
||||
uint tmp_length=my_strnxfrm(cs,to,sort_field->length,
|
||||
(unsigned char *) from, length);
|
||||
if (tmp_length < sort_field->length)
|
||||
bzero((char*) to+tmp_length,sort_field->length-tmp_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -907,17 +894,36 @@ static int merge_index(SORTPARAM *param, uchar *sort_buffer,
|
|||
} /* merge_index */
|
||||
|
||||
|
||||
/* Calculate length of sort key */
|
||||
/*
|
||||
Calculate length of sort key
|
||||
|
||||
SYNOPSIS
|
||||
sortlength()
|
||||
sortorder Order of items to sort
|
||||
uint s_length Number of items to sort
|
||||
multi_byte_charset (out)
|
||||
Set to 1 if we are using multi-byte charset
|
||||
(In which case we have to use strxnfrm())
|
||||
|
||||
NOTES
|
||||
sortorder->length is updated for each sort item
|
||||
sortorder->need_strxnfrm is set 1 if we have to use strxnfrm
|
||||
|
||||
RETURN
|
||||
Total length of sort buffer in bytes
|
||||
*/
|
||||
|
||||
static uint
|
||||
sortlength(SORT_FIELD *sortorder, uint s_length)
|
||||
sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset)
|
||||
{
|
||||
reg2 uint length;
|
||||
THD *thd= current_thd;
|
||||
*multi_byte_charset= 0;
|
||||
|
||||
length=0;
|
||||
for (; s_length-- ; sortorder++)
|
||||
{
|
||||
sortorder->need_strxnfrm= 0;
|
||||
if (sortorder->field)
|
||||
{
|
||||
if (sortorder->field->type() == FIELD_TYPE_BLOB)
|
||||
|
@ -929,7 +935,11 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
|
|||
{
|
||||
CHARSET_INFO *cs=sortorder->field->charset();
|
||||
if (use_strnxfrm(cs))
|
||||
{
|
||||
sortorder->need_strxnfrm= 1;
|
||||
*multi_byte_charset= 1;
|
||||
sortorder->length= sortorder->length*cs->strxfrm_multiply;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sortorder->field->maybe_null())
|
||||
|
@ -944,7 +954,11 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
|
|||
{
|
||||
CHARSET_INFO *cs=sortorder->item->charset();
|
||||
if (use_strnxfrm(cs))
|
||||
{
|
||||
sortorder->length= sortorder->length*cs->strxfrm_multiply;
|
||||
sortorder->need_strxnfrm= 1;
|
||||
*multi_byte_charset= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case INT_RESULT:
|
||||
|
|
|
@ -125,8 +125,10 @@ void Item_bool_func2::fix_length_and_dec()
|
|||
}
|
||||
}
|
||||
set_cmp_func();
|
||||
binary_cmp= args[0]->binary() || args[1]->binary();
|
||||
}
|
||||
|
||||
|
||||
int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
|
||||
{
|
||||
owner= item;
|
||||
|
@ -165,7 +167,7 @@ int Arg_comparator::compare_string()
|
|||
if ((res2= (*b)->val_str(&owner->tmp_value2)))
|
||||
{
|
||||
owner->null_value= 0;
|
||||
return owner->binary() ? stringcmp(res1,res2) : sortcmp(res1,res2);
|
||||
return owner->binary_cmp ? stringcmp(res1,res2) : sortcmp(res1,res2);
|
||||
}
|
||||
}
|
||||
owner->null_value= 1;
|
||||
|
@ -179,7 +181,7 @@ int Arg_comparator::compare_e_string()
|
|||
res2= (*b)->val_str(&owner->tmp_value2);
|
||||
if (!res1 || !res2)
|
||||
return test(res1 == res2);
|
||||
return (owner->binary() ? test(stringcmp(res1, res2) == 0) :
|
||||
return (owner->binary_cmp ? test(stringcmp(res1, res2) == 0) :
|
||||
test(sortcmp(res1, res2) == 0));
|
||||
}
|
||||
|
||||
|
@ -274,6 +276,7 @@ bool Item_in_optimizer::preallocate_row()
|
|||
return (!(cache= Item_cache::get_cache(ROW_RESULT)));
|
||||
}
|
||||
|
||||
|
||||
bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
|
||||
Item ** ref)
|
||||
{
|
||||
|
@ -281,8 +284,12 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
|
|||
return 1;
|
||||
if (args[0]->maybe_null)
|
||||
maybe_null=1;
|
||||
/*
|
||||
TODO: Check if following is right
|
||||
(set_charset set type of result, not how compare should be used)
|
||||
*/
|
||||
if (args[0]->binary())
|
||||
set_charset(&my_charset_bin);
|
||||
set_charset(&my_charset_bin);
|
||||
with_sum_func= args[0]->with_sum_func;
|
||||
used_tables_cache= args[0]->used_tables();
|
||||
const_item_cache= args[0]->const_item();
|
||||
|
@ -395,7 +402,7 @@ longlong Item_func_strcmp::val_int()
|
|||
null_value=1;
|
||||
return 0;
|
||||
}
|
||||
int value= binary() ? stringcmp(a,b) : sortcmp(a,b);
|
||||
int value= binary_cmp ? stringcmp(a,b) : sortcmp(a,b);
|
||||
null_value=0;
|
||||
return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
|
||||
}
|
||||
|
@ -659,7 +666,7 @@ Item_func_if::fix_length_and_dec()
|
|||
else if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT)
|
||||
{
|
||||
cached_result_type = STRING_RESULT;
|
||||
set_charset( (args[1]->binary() || args[2]->binary()) ?
|
||||
set_charset((args[1]->binary() || args[2]->binary()) ?
|
||||
&my_charset_bin : args[1]->charset());
|
||||
}
|
||||
else
|
||||
|
@ -802,7 +809,7 @@ Item *Item_func_case::find_item(String *str)
|
|||
}
|
||||
if ((tmp=args[i]->val_str(str))) // If not null
|
||||
{
|
||||
if (first_expr->binary() || args[i]->binary())
|
||||
if (first_expr_is_binary || args[i]->binary())
|
||||
{
|
||||
if (stringcmp(tmp,first_expr_str)==0)
|
||||
return args[i+1];
|
||||
|
@ -912,6 +919,7 @@ Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
used_tables_cache|=(first_expr)->used_tables();
|
||||
const_item_cache&= (first_expr)->const_item();
|
||||
with_sum_func= with_sum_func || (first_expr)->with_sum_func;
|
||||
first_expr_is_binary= first_expr->binary();
|
||||
}
|
||||
if (else_expr)
|
||||
{
|
||||
|
@ -1193,7 +1201,7 @@ byte *in_double::get_value(Item *item)
|
|||
return (byte*) &tmp;
|
||||
}
|
||||
|
||||
cmp_item* cmp_item::get_comparator (Item *item)
|
||||
cmp_item* cmp_item::get_comparator(Item *item)
|
||||
{
|
||||
switch (item->result_type()) {
|
||||
case STRING_RESULT:
|
||||
|
@ -1368,7 +1376,7 @@ void Item_func_in::fix_length_and_dec()
|
|||
}
|
||||
else
|
||||
{
|
||||
in_item= cmp_item:: get_comparator(item);
|
||||
in_item= cmp_item::get_comparator(item);
|
||||
}
|
||||
maybe_null= item->maybe_null;
|
||||
max_length= 1;
|
||||
|
@ -1690,13 +1698,6 @@ longlong Item_func_isnotnull::val_int()
|
|||
}
|
||||
|
||||
|
||||
void Item_func_like::fix_length_and_dec()
|
||||
{
|
||||
decimals= 0;
|
||||
max_length= 1;
|
||||
// cmp_type=STRING_RESULT; // For quick select
|
||||
}
|
||||
|
||||
longlong Item_func_like::val_int()
|
||||
{
|
||||
String* res = args[0]->val_str(&tmp_value1);
|
||||
|
@ -1740,6 +1741,7 @@ Item_func::optimize_type Item_func_like::select_optimize() const
|
|||
return OPTIMIZE_NONE;
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
|
||||
{
|
||||
if (Item_bool_func2::fix_fields(thd, tlist, ref))
|
||||
|
@ -1800,8 +1802,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
|
||||
max_length= 1;
|
||||
decimals= 0;
|
||||
if (args[0]->binary() || args[1]->binary())
|
||||
set_charset(&my_charset_bin);
|
||||
binary_cmp= (args[0]->binary() || args[1]->binary());
|
||||
|
||||
used_tables_cache=args[0]->used_tables() | args[1]->used_tables();
|
||||
const_item_cache=args[0]->const_item() && args[1]->const_item();
|
||||
|
@ -1817,7 +1818,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
}
|
||||
int error;
|
||||
if ((error=regcomp(&preg,res->c_ptr(),
|
||||
binary() ? REG_EXTENDED | REG_NOSUB :
|
||||
binary_cmp ? REG_EXTENDED | REG_NOSUB :
|
||||
REG_EXTENDED | REG_NOSUB | REG_ICASE,
|
||||
res->charset())))
|
||||
{
|
||||
|
@ -1834,6 +1835,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
longlong Item_func_regex::val_int()
|
||||
{
|
||||
char buff[MAX_FIELD_WIDTH];
|
||||
|
@ -1865,7 +1867,7 @@ longlong Item_func_regex::val_int()
|
|||
regex_compiled=0;
|
||||
}
|
||||
if (regcomp(&preg,res2->c_ptr(),
|
||||
binary() ? REG_EXTENDED | REG_NOSUB :
|
||||
binary_cmp ? REG_EXTENDED | REG_NOSUB :
|
||||
REG_EXTENDED | REG_NOSUB | REG_ICASE,
|
||||
res->charset()))
|
||||
|
||||
|
@ -1915,7 +1917,7 @@ void Item_func_like::turboBM_compute_suffixes(int *suff)
|
|||
|
||||
*splm1 = pattern_len;
|
||||
|
||||
if (binary())
|
||||
if (binary_cmp)
|
||||
{
|
||||
int i;
|
||||
for (i = pattern_len - 2; i >= 0; i--)
|
||||
|
@ -2018,7 +2020,7 @@ void Item_func_like::turboBM_compute_bad_character_shifts()
|
|||
for (i = bmBc; i < end; i++)
|
||||
*i = pattern_len;
|
||||
|
||||
if (binary())
|
||||
if (binary_cmp)
|
||||
{
|
||||
for (j = 0; j < plm1; j++)
|
||||
bmBc[(uint) (uchar) pattern[j]] = plm1 - j;
|
||||
|
@ -2049,7 +2051,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
|
|||
const int tlmpl= text_len - pattern_len;
|
||||
|
||||
/* Searching */
|
||||
if (binary())
|
||||
if (binary_cmp)
|
||||
{
|
||||
while (j <= tlmpl)
|
||||
{
|
||||
|
|
|
@ -112,6 +112,8 @@ class Item_bool_func2 :public Item_int_func
|
|||
protected:
|
||||
Arg_comparator cmp;
|
||||
String tmp_value1,tmp_value2;
|
||||
bool binary_cmp;
|
||||
|
||||
public:
|
||||
Item_bool_func2(Item *a,Item *b):
|
||||
Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
|
||||
|
@ -125,6 +127,7 @@ public:
|
|||
bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
|
||||
void print(String *str) { Item_func::print_op(str); }
|
||||
bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
|
||||
virtual bool binary() const { return binary_cmp; }
|
||||
|
||||
static Item_bool_func2* eq_creator(Item *a, Item *b);
|
||||
static Item_bool_func2* ne_creator(Item *a, Item *b);
|
||||
|
@ -156,7 +159,7 @@ public:
|
|||
class Item_func_eq :public Item_bool_rowready_func2
|
||||
{
|
||||
public:
|
||||
Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { };
|
||||
Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
|
||||
longlong val_int();
|
||||
enum Functype functype() const { return EQ_FUNC; }
|
||||
enum Functype rev_functype() const { return EQ_FUNC; }
|
||||
|
@ -180,7 +183,7 @@ public:
|
|||
class Item_func_ge :public Item_bool_rowready_func2
|
||||
{
|
||||
public:
|
||||
Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { };
|
||||
Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
|
||||
longlong val_int();
|
||||
enum Functype functype() const { return GE_FUNC; }
|
||||
enum Functype rev_functype() const { return LE_FUNC; }
|
||||
|
@ -192,7 +195,7 @@ public:
|
|||
class Item_func_gt :public Item_bool_rowready_func2
|
||||
{
|
||||
public:
|
||||
Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { };
|
||||
Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
|
||||
longlong val_int();
|
||||
enum Functype functype() const { return GT_FUNC; }
|
||||
enum Functype rev_functype() const { return LT_FUNC; }
|
||||
|
@ -204,7 +207,7 @@ public:
|
|||
class Item_func_le :public Item_bool_rowready_func2
|
||||
{
|
||||
public:
|
||||
Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { };
|
||||
Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
|
||||
longlong val_int();
|
||||
enum Functype functype() const { return LE_FUNC; }
|
||||
enum Functype rev_functype() const { return GE_FUNC; }
|
||||
|
@ -216,7 +219,7 @@ public:
|
|||
class Item_func_lt :public Item_bool_rowready_func2
|
||||
{
|
||||
public:
|
||||
Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }
|
||||
Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
|
||||
longlong val_int();
|
||||
enum Functype functype() const { return LT_FUNC; }
|
||||
enum Functype rev_functype() const { return GT_FUNC; }
|
||||
|
@ -228,7 +231,7 @@ public:
|
|||
class Item_func_ne :public Item_bool_rowready_func2
|
||||
{
|
||||
public:
|
||||
Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }
|
||||
Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
|
||||
longlong val_int();
|
||||
enum Functype functype() const { return NE_FUNC; }
|
||||
cond_result eq_cmp_result() const { return COND_FALSE; }
|
||||
|
@ -257,7 +260,11 @@ class Item_func_strcmp :public Item_bool_func2
|
|||
public:
|
||||
Item_func_strcmp(Item *a,Item *b) :Item_bool_func2(a,b) {}
|
||||
longlong val_int();
|
||||
void fix_length_and_dec() { max_length=2; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
max_length=2;
|
||||
binary_cmp= args[0]->binary() || args[1]->binary();
|
||||
}
|
||||
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
|
||||
const char *func_name() const { return "strcmp"; }
|
||||
};
|
||||
|
@ -280,7 +287,9 @@ class Item_func_ifnull :public Item_func
|
|||
{
|
||||
enum Item_result cached_result_type;
|
||||
public:
|
||||
Item_func_ifnull(Item *a,Item *b) :Item_func(a,b) { }
|
||||
Item_func_ifnull(Item *a,Item *b)
|
||||
:Item_func(a,b), cached_result_type(INT_RESULT)
|
||||
{}
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String *str);
|
||||
|
@ -294,7 +303,9 @@ class Item_func_if :public Item_func
|
|||
{
|
||||
enum Item_result cached_result_type;
|
||||
public:
|
||||
Item_func_if(Item *a,Item *b,Item *c) :Item_func(a,b,c) { }
|
||||
Item_func_if(Item *a,Item *b,Item *c)
|
||||
:Item_func(a,b,c), cached_result_type(INT_RESULT)
|
||||
{}
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String *str);
|
||||
|
@ -313,7 +324,9 @@ class Item_func_nullif :public Item_bool_func2
|
|||
{
|
||||
enum Item_result cached_result_type;
|
||||
public:
|
||||
Item_func_nullif(Item *a,Item *b) :Item_bool_func2(a,b) { }
|
||||
Item_func_nullif(Item *a,Item *b)
|
||||
:Item_bool_func2(a,b), cached_result_type(INT_RESULT)
|
||||
{}
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String *str);
|
||||
|
@ -327,7 +340,9 @@ class Item_func_coalesce :public Item_func
|
|||
{
|
||||
enum Item_result cached_result_type;
|
||||
public:
|
||||
Item_func_coalesce(List<Item> &list) :Item_func(list) {}
|
||||
Item_func_coalesce(List<Item> &list)
|
||||
:Item_func(list),cached_result_type(INT_RESULT)
|
||||
{}
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String *);
|
||||
|
@ -341,9 +356,12 @@ class Item_func_case :public Item_func
|
|||
Item * first_expr, *else_expr;
|
||||
enum Item_result cached_result_type;
|
||||
String tmp_value;
|
||||
bool first_expr_is_binary;
|
||||
public:
|
||||
Item_func_case(List<Item> &list, Item *first_expr_, Item *else_expr_)
|
||||
:Item_func(list), first_expr(first_expr_), else_expr(else_expr_) {}
|
||||
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
|
||||
:Item_func(list), first_expr(first_expr_arg), else_expr(else_expr_arg),
|
||||
cached_result_type(INT_RESULT)
|
||||
{}
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String *);
|
||||
|
@ -723,7 +741,6 @@ public:
|
|||
optimize_type select_optimize() const;
|
||||
cond_result eq_cmp_result() const { return COND_TRUE; }
|
||||
const char *func_name() const { return "like"; }
|
||||
void fix_length_and_dec();
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
||||
};
|
||||
|
||||
|
@ -737,6 +754,7 @@ class Item_func_regex :public Item_bool_func
|
|||
bool regex_compiled;
|
||||
bool regex_is_const;
|
||||
String prev_regexp;
|
||||
bool binary_cmp;
|
||||
public:
|
||||
Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
|
||||
regex_compiled(0),regex_is_const(0) {}
|
||||
|
|
|
@ -80,6 +80,7 @@ Item_func::Item_func(List<Item> &list):
|
|||
|
||||
str_value.charset If this is a string function, set this to the
|
||||
character set for the first argument.
|
||||
If any argument is binary, this is set to binary
|
||||
|
||||
If for any item any of the defaults are wrong, then this can
|
||||
be fixed in the fix_length_and_dec() function that is called
|
||||
|
@ -96,6 +97,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
{
|
||||
Item **arg,**arg_end;
|
||||
char buff[STACK_BUFF_ALLOC]; // Max argument in function
|
||||
|
||||
used_tables_cache=0;
|
||||
const_item_cache=1;
|
||||
|
||||
|
@ -103,6 +105,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
return 0; // Fatal error if flag is set!
|
||||
if (arg_count)
|
||||
{ // Print purify happy
|
||||
CHARSET_INFO *charset= 0;
|
||||
/*
|
||||
Set return character set to first argument if we are returning a
|
||||
string.
|
||||
|
@ -115,15 +118,21 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
if ((*arg)->maybe_null)
|
||||
maybe_null=1;
|
||||
if ((*arg)->binary())
|
||||
set_charset(&my_charset_bin);
|
||||
charset= &my_charset_bin;
|
||||
else if (!charset && (*arg)->result_type() == STRING_RESULT)
|
||||
charset= (*arg)->charset();
|
||||
with_sum_func= with_sum_func || (*arg)->with_sum_func;
|
||||
used_tables_cache|=(*arg)->used_tables();
|
||||
const_item_cache&= (*arg)->const_item();
|
||||
}
|
||||
/*
|
||||
We must set charset here as fix_length_and_dec() may want to change
|
||||
charset
|
||||
*/
|
||||
if (charset && result_type() == STRING_RESULT)
|
||||
set_charset(charset);
|
||||
}
|
||||
fix_length_and_dec();
|
||||
if (result_type() == STRING_RESULT)
|
||||
set_charset((*args)->charset());
|
||||
fixed= 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -847,6 +856,8 @@ void Item_func_min_max::fix_length_and_dec()
|
|||
if (args[i]->binary())
|
||||
set_charset(&my_charset_bin);
|
||||
}
|
||||
if (cmp_type == STRING_RESULT)
|
||||
str_cmp_function= binary() ? stringcmp : sortcmp;
|
||||
}
|
||||
|
||||
|
||||
|
@ -891,7 +902,7 @@ String *Item_func_min_max::val_str(String *str)
|
|||
res2= args[i]->val_str(res == str ? &tmp_value : str);
|
||||
if (res2)
|
||||
{
|
||||
int cmp=binary() ? stringcmp(res,res2) : sortcmp(res,res2);
|
||||
int cmp= (*str_cmp_function)(res,res2);
|
||||
if ((cmp_sign < 0 ? cmp : -cmp) < 0)
|
||||
res=res2;
|
||||
}
|
||||
|
@ -994,7 +1005,6 @@ longlong Item_func_locate::val_int()
|
|||
{
|
||||
String *a=args[0]->val_str(&value1);
|
||||
String *b=args[1]->val_str(&value2);
|
||||
bool binary_str = args[0]->binary() || args[1]->binary();
|
||||
if (!a || !b)
|
||||
{
|
||||
null_value=1;
|
||||
|
@ -1012,7 +1022,7 @@ longlong Item_func_locate::val_int()
|
|||
if (use_mb(a->charset()))
|
||||
{
|
||||
start0=start;
|
||||
if (!binary_str)
|
||||
if (!binary_cmp)
|
||||
start=a->charpos(start);
|
||||
}
|
||||
#endif
|
||||
|
@ -1022,7 +1032,7 @@ longlong Item_func_locate::val_int()
|
|||
if (!b->length()) // Found empty string at start
|
||||
return (longlong) (start+1);
|
||||
#ifdef USE_MB
|
||||
if (use_mb(a->charset()) && !binary_str)
|
||||
if (use_mb(a->charset()) && !binary_cmp)
|
||||
{
|
||||
const char *ptr=a->ptr()+start;
|
||||
const char *search=b->ptr();
|
||||
|
@ -1049,7 +1059,7 @@ longlong Item_func_locate::val_int()
|
|||
return 0;
|
||||
}
|
||||
#endif /* USE_MB */
|
||||
return (longlong) (binary() ? a->strstr(*b,start) :
|
||||
return (longlong) (binary_cmp ? a->strstr(*b,start) :
|
||||
(a->strstr_case(*b,start)))+1;
|
||||
}
|
||||
|
||||
|
@ -1662,7 +1672,7 @@ longlong Item_master_pos_wait::val_int()
|
|||
{
|
||||
THD* thd = current_thd;
|
||||
String *log_name = args[0]->val_str(&value);
|
||||
int event_count;
|
||||
int event_count= 0;
|
||||
|
||||
null_value=0;
|
||||
if (thd->slave_thread || !log_name || !log_name->length())
|
||||
|
|
|
@ -524,9 +524,10 @@ class Item_func_min_max :public Item_func
|
|||
Item_result cmp_type;
|
||||
String tmp_value;
|
||||
int cmp_sign;
|
||||
int (*str_cmp_function)(const String *x,const String *y);
|
||||
public:
|
||||
Item_func_min_max(List<Item> &list,int cmp_sign_arg) :Item_func(list),
|
||||
cmp_sign(cmp_sign_arg) {}
|
||||
cmp_type(INT_RESULT), cmp_sign(cmp_sign_arg) {}
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String *);
|
||||
|
@ -590,12 +591,17 @@ public:
|
|||
class Item_func_locate :public Item_int_func
|
||||
{
|
||||
String value1,value2;
|
||||
bool binary_cmp;
|
||||
public:
|
||||
Item_func_locate(Item *a,Item *b) :Item_int_func(a,b) {}
|
||||
Item_func_locate(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
|
||||
const char *func_name() const { return "locate"; }
|
||||
longlong val_int();
|
||||
void fix_length_and_dec() { maybe_null=0; max_length=11; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
maybe_null=0; max_length=11;
|
||||
binary_cmp = args[0]->binary() || args[1]->binary();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -701,7 +701,7 @@ String *Item_func_replace::val_str(String *str)
|
|||
#ifdef USE_MB
|
||||
const char *ptr,*end,*strend,*search,*search_end;
|
||||
register uint32 l;
|
||||
bool binary_str;
|
||||
bool binary_cmp;
|
||||
#endif
|
||||
|
||||
null_value=0;
|
||||
|
@ -713,7 +713,7 @@ String *Item_func_replace::val_str(String *str)
|
|||
goto null;
|
||||
|
||||
#ifdef USE_MB
|
||||
binary_str = (args[0]->binary() || args[1]->binary() || !use_mb(res->charset()));
|
||||
binary_cmp = (args[0]->binary() || args[1]->binary() || !use_mb(res->charset()));
|
||||
#endif
|
||||
|
||||
if (res2->length() == 0)
|
||||
|
@ -723,7 +723,7 @@ String *Item_func_replace::val_str(String *str)
|
|||
return res;
|
||||
#else
|
||||
offset=0;
|
||||
if (binary_str && (offset=res->strstr(*res2)) < 0)
|
||||
if (binary_cmp && (offset=res->strstr(*res2)) < 0)
|
||||
return res;
|
||||
#endif
|
||||
if (!(res3=args[2]->val_str(&tmp_value2)))
|
||||
|
@ -732,7 +732,7 @@ String *Item_func_replace::val_str(String *str)
|
|||
to_length= res3->length();
|
||||
|
||||
#ifdef USE_MB
|
||||
if (!binary_str)
|
||||
if (!binary_cmp)
|
||||
{
|
||||
search=res2->ptr();
|
||||
search_end=search+from_length;
|
||||
|
|
|
@ -187,7 +187,10 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
else if (hybrid_type == REAL_RESULT)
|
||||
max_length=float_length(decimals);
|
||||
else
|
||||
{
|
||||
str_cmp_function= binary() ? stringcmp : sortcmp;
|
||||
max_length=item->max_length;
|
||||
}
|
||||
decimals=item->decimals;
|
||||
maybe_null=item->maybe_null;
|
||||
unsigned_flag=item->unsigned_flag;
|
||||
|
@ -434,8 +437,7 @@ bool Item_sum_min::add()
|
|||
{
|
||||
String *result=args[0]->val_str(&tmp_value);
|
||||
if (!args[0]->null_value &&
|
||||
(null_value ||
|
||||
(binary() ? stringcmp(&value,result) : sortcmp(&value,result)) > 0))
|
||||
(null_value || (*str_cmp_function)(&value,result) > 0))
|
||||
{
|
||||
value.copy(*result);
|
||||
null_value=0;
|
||||
|
@ -481,8 +483,7 @@ bool Item_sum_max::add()
|
|||
{
|
||||
String *result=args[0]->val_str(&tmp_value);
|
||||
if (!args[0]->null_value &&
|
||||
(null_value ||
|
||||
(binary() & MY_CS_BINSORT ? stringcmp(&value,result) : sortcmp(&value,result)) < 0))
|
||||
(null_value || (*str_cmp_function)(&value,result) < 0))
|
||||
{
|
||||
value.copy(*result);
|
||||
null_value=0;
|
||||
|
@ -757,8 +758,7 @@ Item_sum_hybrid::min_max_update_str_field(int offset)
|
|||
result_field->ptr-=offset;
|
||||
|
||||
if (result_field->is_null() ||
|
||||
(cmp_sign * (binary() ? stringcmp(res_str,&tmp_value) :
|
||||
sortcmp(res_str,&tmp_value)) < 0))
|
||||
(cmp_sign * (*str_cmp_function)(res_str,&tmp_value)) < 0)
|
||||
result_field->store(res_str->ptr(),res_str->length(),res_str->charset());
|
||||
else
|
||||
{ // Use old value
|
||||
|
|
|
@ -369,9 +369,11 @@ class Item_sum_hybrid :public Item_sum
|
|||
enum_field_types hybrid_field_type;
|
||||
int cmp_sign;
|
||||
table_map used_table_cache;
|
||||
int (*str_cmp_function)(const String *x,const String *y);
|
||||
|
||||
public:
|
||||
Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign),
|
||||
Item_sum_hybrid(Item *item_par,int sign)
|
||||
:Item_sum(item_par), hybrid_type(INT_RESULT), cmp_sign(sign),
|
||||
used_table_cache(~(table_map) 0)
|
||||
{}
|
||||
Item_sum_hybrid(THD *thd, Item_sum_hybrid &item):
|
||||
|
|
|
@ -194,7 +194,8 @@ int key_cmp(TABLE *table,const byte *key,uint idx,uint key_length)
|
|||
{
|
||||
if (my_strnncoll(key_part->field->charset(),
|
||||
(const uchar*) key, length,
|
||||
(const uchar*) table->record[0]+key_part->offset,length))
|
||||
(const uchar*) table->record[0]+key_part->offset,
|
||||
length))
|
||||
return 1;
|
||||
}
|
||||
else if (memcmp(key,table->record[0]+key_part->offset,length))
|
||||
|
|
|
@ -180,7 +180,7 @@ static SYMBOL symbols[] = {
|
|||
{ "HANDLER", SYM(HANDLER_SYM),0,0},
|
||||
{ "HASH", SYM(HASH_SYM),0,0},
|
||||
{ "HEAP", SYM(HEAP_SYM),0,0},
|
||||
{ "HELP", SYM(HELP),0,0},
|
||||
{ "HELP", SYM(HELP_SYM),0,0},
|
||||
{ "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0},
|
||||
{ "HOUR", SYM(HOUR_SYM),0,0},
|
||||
{ "HOUR_MINUTE", SYM(HOUR_MINUTE_SYM),0,0},
|
||||
|
|
|
@ -854,7 +854,7 @@ int rename_file_ext(const char * from,const char * to,const char * ext);
|
|||
bool check_db_name(char *db);
|
||||
bool check_column_name(const char *name);
|
||||
bool check_table_name(const char *name, uint length);
|
||||
char *get_field(MEM_ROOT *mem,TABLE *table,uint fieldnr);
|
||||
char *get_field(MEM_ROOT *mem, Field *field);
|
||||
int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
|
||||
|
||||
/* from hostname.cc */
|
||||
|
|
|
@ -147,9 +147,9 @@ double rnd(struct rand_struct *rand_st)
|
|||
none
|
||||
*/
|
||||
|
||||
void create_random_string(int length,struct rand_struct *rand_st,char* target)
|
||||
void create_random_string(int length,struct rand_struct *rand_st,char *target)
|
||||
{
|
||||
char* end=target+length;
|
||||
char *end=target+length;
|
||||
/* Use pointer arithmetics as it is faster way to do so. */
|
||||
for (; target<end ; target++)
|
||||
*target= (char) (rnd(rand_st)*94+33);
|
||||
|
@ -171,7 +171,7 @@ void create_random_string(int length,struct rand_struct *rand_st,char* target)
|
|||
none
|
||||
*/
|
||||
|
||||
void password_crypt(const char* from,char* to, const char* password,int length)
|
||||
void password_crypt(const char *from,char *to, const char *password,int length)
|
||||
{
|
||||
const char *from_end=from+length;
|
||||
|
||||
|
@ -252,7 +252,7 @@ void password_hash_stage1(char *to, const char *password)
|
|||
none
|
||||
*/
|
||||
|
||||
void password_hash_stage2(char *to,const char *salt)
|
||||
void password_hash_stage2(char *to, const char *salt)
|
||||
{
|
||||
SHA1_CONTEXT context;
|
||||
sha1_reset(&context);
|
||||
|
@ -326,7 +326,7 @@ void make_scrambled_password(char *to,const char *password,
|
|||
|
||||
void get_salt_from_bin_password(ulong *res,unsigned char *password,ulong salt)
|
||||
{
|
||||
unsigned char* password_end=password+SCRAMBLE41_LENGTH;
|
||||
unsigned char *password_end=password+SCRAMBLE41_LENGTH;
|
||||
*res=salt;
|
||||
res++;
|
||||
|
||||
|
@ -356,14 +356,14 @@ void get_salt_from_bin_password(ulong *res,unsigned char *password,ulong salt)
|
|||
!0 for invalid password
|
||||
*/
|
||||
|
||||
my_bool validate_password(const char* password, const char* message,
|
||||
ulong* salt)
|
||||
my_bool validate_password(const char *password, const char *message,
|
||||
ulong *salt)
|
||||
{
|
||||
char buffer[SCRAMBLE41_LENGTH]; /* Used for password validation */
|
||||
char tmpsalt[8]; /* Temporary value to convert salt to string form */
|
||||
ulong salt_candidate[6]; /* Computed candidate salt */
|
||||
ulong* sc=salt_candidate; /* we need to be able to increment */
|
||||
ulong* salt_end;
|
||||
ulong *sc=salt_candidate; /* we need to be able to increment */
|
||||
ulong *salt_end;
|
||||
|
||||
/* Now we shall get stage1 encrypted password in buffer*/
|
||||
password_crypt(password,buffer,message,SCRAMBLE41_LENGTH);
|
||||
|
@ -414,7 +414,7 @@ int get_password_length(my_bool force_old_scramble)
|
|||
!0 password version char for newer passwords
|
||||
*/
|
||||
|
||||
char get_password_version(const char* password)
|
||||
char get_password_version(const char *password)
|
||||
{
|
||||
if (password==NULL) return 0;
|
||||
if (password[0]==PVERSION41_CHAR) return PVERSION41_CHAR;
|
||||
|
@ -536,46 +536,47 @@ void make_password_from_salt(char *to, ulong *hash_res,uint8 password_version)
|
|||
!0 password version char for newer passwords
|
||||
*/
|
||||
|
||||
void get_hash_and_password(ulong* salt, uint8 pversion, char* hash, unsigned char* bin_password)
|
||||
void get_hash_and_password(ulong *salt, uint8 pversion, char *hash,
|
||||
unsigned char *bin_password)
|
||||
{
|
||||
int t;
|
||||
ulong* salt_end;
|
||||
ulong val;
|
||||
SHA1_CONTEXT context;
|
||||
unsigned char* bp; /* Binary password loop pointer */
|
||||
|
||||
if (pversion) /* New password version assumed */
|
||||
if (pversion) /* New password version assumed */
|
||||
{
|
||||
salt_end=salt+5;
|
||||
sprintf(hash,"%04x",(unsigned short)salt[0]);
|
||||
while (salt<salt_end) /* Iterate over these elements*/
|
||||
while (salt<salt_end)
|
||||
{
|
||||
val=*(++salt);
|
||||
for (t=3; t>=0; t--)
|
||||
{
|
||||
bin_password[t]= (char) (val & 255);
|
||||
val>>=8; /* Scroll 8 bits to get next part*/
|
||||
val>>=8; /* Scroll 8 bits to get next part*/
|
||||
}
|
||||
bin_password+=4; /* Get to next 4 chars*/
|
||||
bin_password+=4; /* Get to next 4 chars*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char *bp= bin_password; /* Binary password loop pointer */
|
||||
|
||||
/* Use zero starting hash as an indication of old password */
|
||||
hash[0]=0;
|
||||
salt_end=salt+2;
|
||||
bp=bin_password;
|
||||
/* Encode salt using SHA1 here */
|
||||
sha1_reset(&context);
|
||||
while (salt<salt_end) /* Iterate over these elements*/
|
||||
while (salt<salt_end) /* Iterate over these elements*/
|
||||
{
|
||||
val=*salt;
|
||||
val= *salt;
|
||||
for (t=3;t>=0;t--)
|
||||
{
|
||||
bp[t]= (uchar) (val & 255);
|
||||
val>>=8; /* Scroll 8 bits to get next part*/
|
||||
val>>=8; /* Scroll 8 bits to get next part*/
|
||||
}
|
||||
bp+=4; /* Get to next 4 chars*/
|
||||
bp+= 4; /* Get to next 4 chars*/
|
||||
salt++;
|
||||
}
|
||||
/* Use 8 bytes of binary password for hash */
|
||||
|
@ -599,7 +600,7 @@ void get_hash_and_password(ulong* salt, uint8 pversion, char* hash, unsigned cha
|
|||
*/
|
||||
|
||||
|
||||
void create_key_from_old_password(const char* passwd, char* key)
|
||||
void create_key_from_old_password(const char *passwd, char *key)
|
||||
{
|
||||
char buffer[SCRAMBLE41_LENGTH]; /* Buffer for various needs */
|
||||
ulong salt[6]; /* Salt (large for safety) */
|
||||
|
@ -633,7 +634,7 @@ char *scramble(char *to,const char *message,const char *password,
|
|||
struct rand_struct rand_st;
|
||||
ulong hash_pass[2],hash_message[2];
|
||||
char message_buffer[9]; /* Real message buffer */
|
||||
char* msg=message_buffer;
|
||||
char *msg=message_buffer;
|
||||
|
||||
/* We use special message buffer now as new server can provide longer hash */
|
||||
|
||||
|
|
|
@ -148,8 +148,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
|
|||
while (!(read_record_info.read_record(&read_record_info)))
|
||||
{
|
||||
ACL_HOST host;
|
||||
update_hostname(&host.host,get_field(&mem, table,0));
|
||||
host.db= get_field(&mem, table,1);
|
||||
update_hostname(&host.host,get_field(&mem, table->field[0]));
|
||||
host.db= get_field(&mem, table->field[1]);
|
||||
host.access= get_access(table,2);
|
||||
host.access= fix_rights_for_db(host.access);
|
||||
host.sort= get_sort(2,host.host.hostname,host.db);
|
||||
|
@ -190,9 +190,9 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
|
|||
{
|
||||
ACL_USER user;
|
||||
uint length=0;
|
||||
update_hostname(&user.host,get_field(&mem, table,0));
|
||||
user.user=get_field(&mem, table,1);
|
||||
user.password=get_field(&mem, table,2);
|
||||
update_hostname(&user.host,get_field(&mem, table->field[0]));
|
||||
user.user=get_field(&mem, table->field[1]);
|
||||
user.password=get_field(&mem, table->field[2]);
|
||||
if (user.password && (length=(uint) strlen(user.password)) == 8 &&
|
||||
protocol_version == PROTOCOL_VERSION)
|
||||
{
|
||||
|
@ -220,7 +220,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
|
|||
(uint) strlen(user.host.hostname) : 0);
|
||||
if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
|
||||
{
|
||||
char *ssl_type=get_field(&mem, table, 24);
|
||||
char *ssl_type=get_field(&mem, table->field[24]);
|
||||
if (!ssl_type)
|
||||
user.ssl_type=SSL_TYPE_NONE;
|
||||
else if (!strcmp(ssl_type, "ANY"))
|
||||
|
@ -230,15 +230,15 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
|
|||
else /* !strcmp(ssl_type, "SPECIFIED") */
|
||||
user.ssl_type=SSL_TYPE_SPECIFIED;
|
||||
|
||||
user.ssl_cipher= get_field(&mem, table, 25);
|
||||
user.x509_issuer= get_field(&mem, table, 26);
|
||||
user.x509_subject= get_field(&mem, table, 27);
|
||||
user.ssl_cipher= get_field(&mem, table->field[25]);
|
||||
user.x509_issuer= get_field(&mem, table->field[26]);
|
||||
user.x509_subject= get_field(&mem, table->field[27]);
|
||||
|
||||
char *ptr = get_field(&mem, table, 28);
|
||||
char *ptr = get_field(&mem, table->field[28]);
|
||||
user.user_resource.questions=atoi(ptr);
|
||||
ptr = get_field(&mem, table, 29);
|
||||
ptr = get_field(&mem, table->field[29]);
|
||||
user.user_resource.updates=atoi(ptr);
|
||||
ptr = get_field(&mem, table, 30);
|
||||
ptr = get_field(&mem, table->field[30]);
|
||||
user.user_resource.connections=atoi(ptr);
|
||||
if (user.user_resource.questions || user.user_resource.updates ||
|
||||
user.user_resource.connections)
|
||||
|
@ -277,14 +277,14 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
|
|||
while (!(read_record_info.read_record(&read_record_info)))
|
||||
{
|
||||
ACL_DB db;
|
||||
update_hostname(&db.host,get_field(&mem, table,0));
|
||||
db.db=get_field(&mem, table,1);
|
||||
update_hostname(&db.host,get_field(&mem, table->field[0]));
|
||||
db.db=get_field(&mem, table->field[1]);
|
||||
if (!db.db)
|
||||
{
|
||||
sql_print_error("Found an entry in the 'db' table with empty database name; Skipped");
|
||||
continue;
|
||||
}
|
||||
db.user=get_field(&mem, table,2);
|
||||
db.user=get_field(&mem, table->field[2]);
|
||||
db.access=get_access(table,3);
|
||||
db.access=fix_rights_for_db(db.access);
|
||||
db.sort=get_sort(3,db.host.hostname,db.db,db.user);
|
||||
|
@ -457,8 +457,9 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Prepare crypted scramble to be sent to the client
|
||||
Prepare crypted scramble to be sent to the client
|
||||
*/
|
||||
|
||||
void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
|
||||
|
@ -469,18 +470,17 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
|
|||
create_random_string(SCRAMBLE41_LENGTH,&thd->rand,thd->scramble);
|
||||
thd->scramble[SCRAMBLE41_LENGTH]=0;
|
||||
/* Get binary form, First 4 bytes of prepared scramble is salt */
|
||||
get_hash_and_password(acl_user->salt,acl_user->pversion,prepared_scramble,(unsigned char*)bin_password);
|
||||
get_hash_and_password(acl_user->salt,acl_user->pversion,prepared_scramble,
|
||||
(unsigned char*) bin_password);
|
||||
/* Store "*" as identifier for old passwords */
|
||||
if (!acl_user->pversion)
|
||||
prepared_scramble[0]='*';
|
||||
/* Finally encrypt password to get prepared scramble */
|
||||
password_crypt(thd->scramble,prepared_scramble+4,bin_password,SCRAMBLE41_LENGTH);
|
||||
password_crypt(thd->scramble, prepared_scramble+4, bin_password,
|
||||
SCRAMBLE41_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Get master privilges for user (priviliges for all tables).
|
||||
Required before connecting to MySQL
|
||||
|
@ -493,7 +493,7 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
|
|||
|
||||
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
|
||||
const char *password,const char *message,char **priv_user,
|
||||
bool old_ver, USER_RESOURCES *mqh,char* prepared_scramble,
|
||||
bool old_ver, USER_RESOURCES *mqh, char *prepared_scramble,
|
||||
uint *cur_priv_version,ACL_USER** hint_user)
|
||||
{
|
||||
ulong user_access=NO_ACCESS;
|
||||
|
@ -572,10 +572,11 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
|
|||
if (!check_scramble(password,message,acl_user->salt,
|
||||
(my_bool) old_ver))
|
||||
password_correct=1;
|
||||
else /* Password incorrect */
|
||||
/* At the first stage - prepare scramble */
|
||||
if (!stage)
|
||||
prepare_scramble(thd,acl_user,prepared_scramble);
|
||||
else if (!stage) /* Here if password incorrect */
|
||||
{
|
||||
/* At the first stage - prepare scramble */
|
||||
prepare_scramble(thd,acl_user,prepared_scramble);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1645,12 +1646,12 @@ public:
|
|||
{
|
||||
byte key[MAX_KEY_LENGTH];
|
||||
|
||||
host = get_field(&memex,form,0);
|
||||
db = get_field(&memex,form,1);
|
||||
user = get_field(&memex,form,2);
|
||||
host = get_field(&memex,form->field[0]);
|
||||
db = get_field(&memex,form->field[1]);
|
||||
user = get_field(&memex,form->field[2]);
|
||||
if (!user)
|
||||
user=(char*) "";
|
||||
tname = get_field(&memex,form,3);
|
||||
tname = get_field(&memex,form->field[3]);
|
||||
if (!host || !db || !tname)
|
||||
{
|
||||
/* Wrong table row; Ignore it */
|
||||
|
|
|
@ -1481,6 +1481,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
|
|||
}
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
|
||||
if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
|
||||
if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
|
||||
table= 0;
|
||||
|
@ -1512,6 +1513,11 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
|
|||
thd Thread handler
|
||||
tables Tables to lock
|
||||
|
||||
NOTES
|
||||
You can't call lock_tables twice, as this would break the dead-lock-free
|
||||
handling thr_lock gives us. You most always get all needed locks at
|
||||
once.
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
-1 Error
|
||||
|
@ -1525,6 +1531,7 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
|
|||
|
||||
if (!thd->locked_tables)
|
||||
{
|
||||
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
|
||||
uint count=0;
|
||||
for (table = tables ; table ; table=table->next)
|
||||
count++;
|
||||
|
@ -1676,28 +1683,31 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
|
|||
return field;
|
||||
}
|
||||
|
||||
// Special Field pointer for find_field_in_tables returning
|
||||
const Field *not_found_field= (Field*) 0x1;
|
||||
|
||||
/*
|
||||
Find field in table list.
|
||||
|
||||
SYNOPSIS
|
||||
find_field_in_tables()
|
||||
thd - pointer to current thread structure
|
||||
item - field item that should be found
|
||||
tables - tables for scaning
|
||||
where - table where field found will be returned via this parameter
|
||||
report_error - if FALSE then do not report error if item not found and
|
||||
return not_found_field;
|
||||
thd Pointer to current thread structure
|
||||
item Field item that should be found
|
||||
tables Tables for scaning
|
||||
where Table where field found will be returned via
|
||||
this parameter
|
||||
report_error If FALSE then do not report error if item not found
|
||||
and return not_found_field
|
||||
|
||||
RETURN VALUES
|
||||
0 - field is not found or field is not unique, error message is
|
||||
reported
|
||||
not_found_field - function was called with report_error == FALSE and
|
||||
field if not found, no error message reported
|
||||
0 Field is not found or field is not unique- error
|
||||
message is reported
|
||||
not_found_field Function was called with report_error == FALSE and
|
||||
field was not found. no error message reported.
|
||||
found field
|
||||
*/
|
||||
|
||||
// Special Field pointer for find_field_in_tables returning
|
||||
const Field *not_found_field= (Field*) 0x1;
|
||||
|
||||
Field *
|
||||
find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
||||
TABLE_LIST **where, bool report_error)
|
||||
|
@ -1802,8 +1812,6 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||
return (Field*) 0;
|
||||
}
|
||||
|
||||
// Special Item pointer for find_item_in_list returning
|
||||
const Item **not_found_item= (const Item**) 0x1;
|
||||
|
||||
/*
|
||||
Find Item in list of items (find_field_in_tables analog)
|
||||
|
@ -1813,24 +1821,29 @@ const Item **not_found_item= (const Item**) 0x1;
|
|||
|
||||
SYNOPSIS
|
||||
find_item_in_list()
|
||||
find - item to find
|
||||
items - list of items
|
||||
counter - to return number of found item
|
||||
find Item to find
|
||||
items List of items
|
||||
counter To return number of found item
|
||||
report_error
|
||||
REPORT_ALL_ERRORS - report errors, return 0 if error
|
||||
REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0
|
||||
IGNORE_ERRORS - do not report errors, return 0 if error
|
||||
REPORT_ALL_ERRORS report errors, return 0 if error
|
||||
REPORT_EXCEPT_NOT_FOUND Do not report 'not found' error and
|
||||
return not_found_item, report other errors,
|
||||
return 0
|
||||
IGNORE_ERRORS Do not report errors, return 0 if error
|
||||
|
||||
RETURN VALUES
|
||||
0 - item is not found or item is not unique, error message is
|
||||
reported
|
||||
not_found_item - function was called with report_error ==
|
||||
REPORT_EXCEPT_NOT_FOUND and item if not found, no error
|
||||
message reported
|
||||
0 Item is not found or item is not unique,
|
||||
error message is reported
|
||||
not_found_item Function was called with
|
||||
report_error == REPORT_EXCEPT_NOT_FOUND and
|
||||
item was not found. No error message was reported
|
||||
found field
|
||||
|
||||
*/
|
||||
|
||||
// Special Item pointer for find_item_in_list returning
|
||||
const Item **not_found_item= (const Item**) 0x1;
|
||||
|
||||
|
||||
Item **
|
||||
find_item_in_list(Item *find, List<Item> &items, uint *counter,
|
||||
find_item_error_report_type report_error)
|
||||
|
@ -1970,6 +1983,9 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
|||
Remap table numbers if INSERT ... SELECT
|
||||
Check also that the 'used keys' and 'ignored keys' exists and set up the
|
||||
table structure accordingly
|
||||
|
||||
This has to be called for all tables that are used by items, as otherwise
|
||||
table->map is not set and all Item_field will be regarded as const items.
|
||||
*/
|
||||
|
||||
bool setup_tables(TABLE_LIST *tables)
|
||||
|
|
|
@ -857,6 +857,7 @@ end:
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check if the query is in the cache. If it was cached, send it
|
||||
to the user.
|
||||
|
@ -867,8 +868,6 @@ end:
|
|||
-1 The query was cached but we didn't have rights to use it.
|
||||
No error is sent to the client yet.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
int
|
||||
Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
|
||||
|
|
|
@ -882,8 +882,9 @@ typedef struct st_sort_field {
|
|||
Field *field; /* Field to sort */
|
||||
Item *item; /* Item if not sorting fields */
|
||||
uint length; /* Length of sort field */
|
||||
my_bool reverse; /* if descending sort */
|
||||
Item_result result_type; /* Type of item */
|
||||
bool reverse; /* if descending sort */
|
||||
bool need_strxnfrm; /* If we have to use strxnfrm() */
|
||||
} SORT_FIELD;
|
||||
|
||||
|
||||
|
@ -898,7 +899,8 @@ typedef struct st_sort_buffer {
|
|||
|
||||
/* Structure for db & table in sql_yacc */
|
||||
|
||||
class Table_ident :public Sql_alloc {
|
||||
class Table_ident :public Sql_alloc
|
||||
{
|
||||
public:
|
||||
LEX_STRING db;
|
||||
LEX_STRING table;
|
||||
|
|
|
@ -61,7 +61,8 @@ extern const char *any_db; // Special symbol for check_access
|
|||
*/
|
||||
|
||||
|
||||
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
|
||||
TABLE_LIST *org_table_list)
|
||||
{
|
||||
SELECT_LEX *sl= unit->first_select();
|
||||
List<Item> item_list;
|
||||
|
@ -85,6 +86,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
|||
if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
/*
|
||||
We have to do access checks here as this code is executed before any
|
||||
sql command is started to execute.
|
||||
*/
|
||||
if (tables)
|
||||
res= check_table_access(thd,SELECT_ACL, tables);
|
||||
else
|
||||
|
@ -173,10 +178,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
|||
res= 1;
|
||||
else
|
||||
{
|
||||
t->real_name=table->real_name;
|
||||
t->table=table;
|
||||
org_table_list->real_name=table->real_name;
|
||||
org_table_list->table=table;
|
||||
table->derived_select_number= sl->select_number;
|
||||
table->tmp_table=TMP_TABLE;
|
||||
table->tmp_table= TMP_TABLE;
|
||||
if (lex->describe)
|
||||
{
|
||||
// to fix a problem in EXPLAIN
|
||||
|
@ -185,8 +190,11 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
|||
}
|
||||
else
|
||||
unit->exclude();
|
||||
t->db= (char *)"";
|
||||
t->derived=(SELECT_LEX *) 1; // just in case ...
|
||||
org_table_list->db= (char *)"";
|
||||
#ifndef DBUG_OFF
|
||||
/* Try to catch errors if this is accessed */
|
||||
org_table_list->derived=(SELECT_LEX_UNIT *) 1;
|
||||
#endif
|
||||
table->file->info(HA_STATUS_VARIABLE);
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +204,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
|||
free_tmp_table(thd, table);
|
||||
else
|
||||
{
|
||||
/* Add new temporary table to list of open derived tables */
|
||||
table->next= thd->derived_tables;
|
||||
thd->derived_tables= table;
|
||||
}
|
||||
|
|
667
sql/sql_help.cc
667
sql/sql_help.cc
|
@ -15,288 +15,294 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "mysql_priv.h"
|
||||
#include "sql_select.h" // For select_describe
|
||||
#include "sql_acl.h"
|
||||
|
||||
/***************************************************************************
|
||||
** Get help on string
|
||||
***************************************************************************/
|
||||
struct st_find_field
|
||||
{
|
||||
const char *table_name, *field_name;
|
||||
Field *field;
|
||||
};
|
||||
|
||||
/* Used fields */
|
||||
|
||||
static struct st_find_field init_used_fields[]=
|
||||
{
|
||||
{ "help_topic", "name", 0},
|
||||
{ "help_topic","description", 0},
|
||||
{ "help_topic","example", 0},
|
||||
{ "help_topic", "help_topic_id", 0},
|
||||
{ "help_category","name", 0},
|
||||
{ "help_category","help_category_id", 0},
|
||||
{ "help_relation","help_topic_id", 0},
|
||||
{ "help_relation","help_category_id", 0}
|
||||
};
|
||||
|
||||
enum enum_used_fields
|
||||
{
|
||||
help_topic_name=0, help_topic_description, help_topic_example,
|
||||
help_topic_help_topic_id,
|
||||
help_category_name, help_category_help_category_id,
|
||||
help_relation_help_topic_id, help_relation_help_category_id
|
||||
};
|
||||
|
||||
/*
|
||||
Fill local used field structure with pointer to fields */
|
||||
|
||||
static bool init_fields(THD *thd, TABLE_LIST *tables,
|
||||
struct st_find_field *find_field,
|
||||
uint count)
|
||||
{
|
||||
for (; count-- ; find_field++)
|
||||
{
|
||||
TABLE_LIST *not_used;
|
||||
/* We have to use 'new' here as field will be re_linked on free */
|
||||
Item_field *field= new Item_field("mysql", find_field->table_name,
|
||||
find_field->field_name);
|
||||
if (!(find_field->field= find_field_in_tables(thd, field, tables,
|
||||
¬_used,
|
||||
TRUE)))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define help_charset &my_charset_latin1
|
||||
|
||||
MI_INFO *open_help_file(THD *thd, const char *name)
|
||||
{
|
||||
char path[FN_REFLEN];
|
||||
(void) sprintf(path,"%s/mysql_help/%s",mysql_data_home,name);
|
||||
MI_INFO *res= 0;
|
||||
if (!(res= mi_open(path,O_RDONLY,HA_OPEN_WAIT_IF_LOCKED)))
|
||||
{
|
||||
send_error(thd,ER_CORRUPT_HELP_DB);
|
||||
return 0;
|
||||
}
|
||||
mi_extra(res,HA_EXTRA_WAIT_LOCK,0);
|
||||
return res;
|
||||
}
|
||||
/*
|
||||
Look for topics by mask
|
||||
|
||||
#define size_hf_func_id 4 /* func_id int unsigned, */
|
||||
#define size_hf_name 64 /* name varchar(64), */
|
||||
#define size_hf_url 128 /* url varchar(128), */
|
||||
#define size_hf_description sizeof(char*) /* description text, */
|
||||
#define size_hf_example sizeof(char*) /* example text, */
|
||||
#define size_hf_min_args 16 /* min_args tinyint, */
|
||||
#define size_hf_max_args 16 /* max_args tinyint, */
|
||||
#define size_hf_date_created 8 /* date_created datetime, */
|
||||
#define size_hf_last_modified 8 /* last_modified timestamp, */
|
||||
SYNOPSIS
|
||||
search_topics()
|
||||
thd Thread handler
|
||||
topics Table of topic
|
||||
select Function to test for if matching help topic.
|
||||
Normally 'help_topic.name like 'bit%'
|
||||
pfname Pointer to Field structure for field "name"
|
||||
names List of founded topic's names (out)
|
||||
name Name of founded topic (out),
|
||||
Only set if founded exactly one topic)
|
||||
description Description of founded topic (out)
|
||||
Only set if founded exactly one topic.
|
||||
example Example for founded topic (out)
|
||||
Only if founded exactly one topic.
|
||||
RETURN VALUES
|
||||
# number of topics founded
|
||||
*/
|
||||
|
||||
#define offset_hf_func_id 1
|
||||
#define offset_hf_name (offset_hf_func_id+size_hf_func_id)
|
||||
#define offset_hf_url (offset_hf_name+size_hf_name)
|
||||
#define offset_hf_description (offset_hf_url+size_hf_url)
|
||||
#define offset_hf_example (offset_hf_description+size_hf_description)
|
||||
#define offset_hf_min_args (offset_hf_example+size_hf_example)
|
||||
#define offset_hf_max_args (offset_hf_min_args+size_hf_min_args)
|
||||
#define offset_hf_date_created (offset_hf_max_args+size_hf_max_args)
|
||||
#define offset_hf_last_modified (offset_hf_date_created+size_hf_date_created)
|
||||
|
||||
#define HELP_LEAF_SIZE (offset_hf_last_modified+size_hf_last_modified)
|
||||
|
||||
class help_leaf{
|
||||
public:
|
||||
char record[HELP_LEAF_SIZE];
|
||||
|
||||
inline const char *get_name()
|
||||
{
|
||||
return &record[offset_hf_name];
|
||||
}
|
||||
|
||||
inline const char *get_description()
|
||||
{
|
||||
return *((char**)&record[199/*offset_hf_description*/]);
|
||||
}
|
||||
|
||||
inline const char *get_example()
|
||||
{
|
||||
return *((char**)&record[209/*offset_hf_example*/]);
|
||||
}
|
||||
|
||||
void prepare_fields()
|
||||
{
|
||||
const char *name= get_name();
|
||||
const char *c= name + size_hf_name - 1;
|
||||
while (*c==' ') c--;
|
||||
int len= c-name+1;
|
||||
((char*)name)[len]= '\0';
|
||||
}
|
||||
};
|
||||
|
||||
int search_functions(MI_INFO *file_leafs, const char *mask,
|
||||
List<String> *names,
|
||||
String **name, String **description, String **example)
|
||||
int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_field,
|
||||
SQL_SELECT *select, List<char> *names,
|
||||
char **name, char **description, char **example)
|
||||
{
|
||||
DBUG_ENTER("search_functions");
|
||||
int count= 0;
|
||||
|
||||
if (mi_scan_init(file_leafs))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
help_leaf leaf;
|
||||
|
||||
while (!mi_scan(file_leafs,(byte*)&leaf))
|
||||
|
||||
READ_RECORD read_record_info;
|
||||
init_read_record(&read_record_info, thd, topics, select,1,0);
|
||||
while (!read_record_info.read_record(&read_record_info))
|
||||
{
|
||||
leaf.prepare_fields();
|
||||
|
||||
const char *lname= leaf.get_name();
|
||||
if (wild_case_compare(help_charset,lname,mask))
|
||||
if (!select->cond->val_int()) // Dosn't match like
|
||||
continue;
|
||||
count++;
|
||||
|
||||
if (count>2)
|
||||
char *lname= get_field(&thd->mem_root, find_field[help_topic_name].field);
|
||||
count++;
|
||||
if (count > 2)
|
||||
{
|
||||
String *s= new String(lname,help_charset);
|
||||
if (!s->copy())
|
||||
names->push_back(s);
|
||||
names->push_back(lname);
|
||||
}
|
||||
else if (count==1)
|
||||
else if (count == 1)
|
||||
{
|
||||
*description= new String(leaf.get_description(),help_charset);
|
||||
*example= new String(leaf.get_example(),help_charset);
|
||||
*name= new String(lname,help_charset);
|
||||
(*description)->copy();
|
||||
(*example)->copy();
|
||||
(*name)->copy();
|
||||
*description= get_field(&thd->mem_root,
|
||||
find_field[help_topic_description].field);
|
||||
*example= get_field(&thd->mem_root,
|
||||
find_field[help_topic_example].field);
|
||||
*name= lname;
|
||||
}
|
||||
else
|
||||
{
|
||||
names->push_back(*name);
|
||||
delete *description;
|
||||
delete *example;
|
||||
names->push_back(lname);
|
||||
*name= 0;
|
||||
*description= 0;
|
||||
*example= 0;
|
||||
|
||||
String *s= new String(lname,help_charset);
|
||||
if (!s->copy())
|
||||
names->push_back(s);
|
||||
}
|
||||
}
|
||||
end_read_record(&read_record_info);
|
||||
DBUG_RETURN(count);
|
||||
}
|
||||
|
||||
/*
|
||||
Look for categories by mask
|
||||
|
||||
SYNOPSIS
|
||||
search_categories()
|
||||
thd THD for init_read_record
|
||||
categories Table of categories
|
||||
select Function to test for if matching help topic.
|
||||
Normally 'help_topic.name like 'bit%'
|
||||
names List of founded topic's names (out)
|
||||
res_id Primary index of founded category (only if
|
||||
founded exactly one category)
|
||||
|
||||
RETURN VALUES
|
||||
# Number of categories founded
|
||||
*/
|
||||
|
||||
int search_categories(THD *thd, TABLE *categories,
|
||||
struct st_find_field *find_fields,
|
||||
SQL_SELECT *select, List<char> *names, int16 *res_id)
|
||||
{
|
||||
Field *pfname= find_fields[help_category_name].field;
|
||||
DBUG_ENTER("search_categories");
|
||||
int count= 0;
|
||||
|
||||
READ_RECORD read_record_info;
|
||||
init_read_record(&read_record_info, thd, categories, select,1,0);
|
||||
while (!read_record_info.read_record(&read_record_info))
|
||||
{
|
||||
if (select && !select->cond->val_int())
|
||||
continue;
|
||||
char *lname= get_field(&thd->mem_root,pfname);
|
||||
if (++count == 1 && res_id)
|
||||
{
|
||||
Field *pcat_id= find_fields[help_category_help_category_id].field;
|
||||
*res_id= (int16) pcat_id->val_int();
|
||||
}
|
||||
names->push_back(lname);
|
||||
}
|
||||
end_read_record(&read_record_info);
|
||||
|
||||
DBUG_RETURN(count);
|
||||
}
|
||||
|
||||
#define size_hc_cat_id 2 /* cat_id smallint, */
|
||||
#define size_hc_name 64 /* name varchar(64), */
|
||||
#define size_hc_url 128 /* url varchar(128), */
|
||||
#define size_hc_date_created 8 /* date_created datetime, */
|
||||
#define size_hc_last_modified 8 /* last_modified timestamp, */
|
||||
|
||||
#define offset_hc_cat_id 0
|
||||
#define offset_hc_name (offset_hc_cat_id+size_hc_cat_id)
|
||||
#define offset_hc_url (offset_hc_name+size_hc_name)
|
||||
#define offset_hc_date_created (offset_hc_url+size_hc_url)
|
||||
#define offset_hc_last_modified (offset_hc_date_created+size_hc_date_created)
|
||||
/*
|
||||
Send to client rows in format:
|
||||
column1 : <name>
|
||||
column2 : <is_it_category>
|
||||
|
||||
#define HELP_CATEGORY_SIZE (offset_hc_last_modified+size_hc_last_modified)
|
||||
SYNOPSIS
|
||||
send_variant_2_list()
|
||||
protocol Protocol for sending
|
||||
names List of names
|
||||
cat Value of the column <is_it_category>
|
||||
|
||||
class help_category{
|
||||
public:
|
||||
char record[HELP_CATEGORY_SIZE];
|
||||
RETURN VALUES
|
||||
-1 Writing fail
|
||||
0 Data was successefully send
|
||||
*/
|
||||
|
||||
inline int16 get_cat_id()
|
||||
{
|
||||
return sint2korr(&record[offset_hc_cat_id]);
|
||||
}
|
||||
|
||||
inline const char *get_name()
|
||||
{
|
||||
return &record[offset_hc_name];
|
||||
}
|
||||
|
||||
void prepare_fields()
|
||||
{
|
||||
const char *name= get_name();
|
||||
const char *c= name + size_hc_name - 1;
|
||||
while (*c==' ') c--;
|
||||
int len= c-name+1;
|
||||
((char*)name)[len]= '\0';
|
||||
}
|
||||
};
|
||||
|
||||
int search_categories(THD *thd,
|
||||
const char *mask, List<String> *names, int16 *res_id)
|
||||
{
|
||||
DBUG_ENTER("search_categories");
|
||||
int count= 0;
|
||||
|
||||
MI_INFO *file_categories= 0;
|
||||
if (!(file_categories= open_help_file(thd,"function_category_name")))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
if (mi_scan_init(file_categories))
|
||||
{
|
||||
mi_close(file_categories);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
help_category category;
|
||||
|
||||
|
||||
while (!mi_scan(file_categories,(byte*)&category))
|
||||
{
|
||||
category.prepare_fields();
|
||||
|
||||
const char *lname= category.get_name();
|
||||
if (mask && wild_case_compare(help_charset,lname,mask))
|
||||
continue;
|
||||
count++;
|
||||
|
||||
if (count==1 && res_id)
|
||||
*res_id= category.get_cat_id();
|
||||
|
||||
String *s= new String(lname,help_charset);
|
||||
if (!s->copy())
|
||||
names->push_back(s);
|
||||
}
|
||||
|
||||
mi_close(file_categories);
|
||||
DBUG_RETURN(count);
|
||||
}
|
||||
|
||||
int send_variant_2_list(Protocol *protocol, List<String> *names,
|
||||
my_bool is_category)
|
||||
int send_variant_2_list(Protocol *protocol, List<char> *names,
|
||||
const char *cat)
|
||||
{
|
||||
DBUG_ENTER("send_names");
|
||||
|
||||
List_iterator<String> it(*names);
|
||||
String *cur_name;
|
||||
while ((cur_name = it++))
|
||||
|
||||
List_iterator<char> it(*names);
|
||||
const char *cur_name;
|
||||
while ((cur_name= it++))
|
||||
{
|
||||
protocol->prepare_for_resend();
|
||||
protocol->store(cur_name->ptr());
|
||||
protocol->store(is_category ? "Y" : "N");
|
||||
protocol->store(cur_name);
|
||||
protocol->store(cat);
|
||||
if (protocol->write())
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
#define size_hcn_cat_id 2 /* cat_id smallint, */
|
||||
#define size_hcn_func_id 4 /* func_id int, */
|
||||
|
||||
#define offset_hcn_cat_id 1
|
||||
#define offset_hcn_func_id (offset_hcn_cat_id+size_hcn_cat_id)
|
||||
/*
|
||||
Look for all topics of category
|
||||
|
||||
#define HELP_CATEGORY_NAME_SIZE (offset_hcn_func_id + size_hcn_func_id)
|
||||
SYNOPSIS
|
||||
get_all_topics_for_category()
|
||||
thd Thread handler
|
||||
topics Table of topics
|
||||
relations Table of m:m relation "topic/category"
|
||||
cat_id Primary index looked for category
|
||||
res List of founded topic's names (out)
|
||||
|
||||
class help_category_leaf{
|
||||
public:
|
||||
char record[HELP_CATEGORY_NAME_SIZE];
|
||||
RETURN VALUES
|
||||
-1 corrupt database
|
||||
0 succesefull
|
||||
*/
|
||||
|
||||
inline int16 get_cat_id()
|
||||
{
|
||||
return sint2korr(&record[offset_hcn_cat_id]);
|
||||
}
|
||||
|
||||
inline int get_func_id()
|
||||
{
|
||||
return sint3korr(&record[offset_hcn_func_id]);
|
||||
}
|
||||
};
|
||||
|
||||
int get_all_names_for_category(THD *thd,MI_INFO *file_leafs,
|
||||
int16 cat_id, List<String> *res)
|
||||
int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
|
||||
struct st_find_field *find_fields,
|
||||
int16 cat_id, List<char> *res)
|
||||
{
|
||||
DBUG_ENTER("get_all_names_for_category");
|
||||
|
||||
MI_INFO *file_names_categories= 0;
|
||||
if (!(file_names_categories= open_help_file(thd,"function_category")))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
help_category_leaf cat_leaf;
|
||||
help_leaf leaf;
|
||||
int key_res= mi_rkey(file_names_categories, (byte*)&cat_leaf, 0,
|
||||
(const byte*)&cat_id,2,HA_READ_KEY_EXACT);
|
||||
|
||||
while (!key_res && cat_leaf.get_cat_id()==cat_id)
|
||||
char buff[8]; // Max int length
|
||||
DBUG_ENTER("get_all_topics_for_category");
|
||||
|
||||
int iindex_topic, iindex_relations;
|
||||
Field *rtopic_id, *rcat_id;
|
||||
|
||||
if ((iindex_topic= find_type((char*) "PRIMARY",
|
||||
&topics->keynames, 1+2)-1)<0 ||
|
||||
(iindex_relations= find_type((char*) "PRIMARY",
|
||||
&relations->keynames, 1+2)-1)<0)
|
||||
{
|
||||
int leaf_id= cat_leaf.get_func_id();
|
||||
|
||||
if (!mi_rkey(file_leafs, (byte*)&leaf, 0,
|
||||
(const byte*)&leaf_id,4,HA_READ_KEY_EXACT))
|
||||
{
|
||||
leaf.prepare_fields();
|
||||
String *s= new String(leaf.get_name(),help_charset);
|
||||
if (!s->copy())
|
||||
res->push_back(s);
|
||||
}
|
||||
|
||||
key_res= mi_rnext(file_names_categories, (byte*)&cat_leaf, 0);
|
||||
send_error(thd,ER_CORRUPT_HELP_DB);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
rtopic_id= find_fields[help_relation_help_topic_id].field;
|
||||
rcat_id= find_fields[help_relation_help_category_id].field;
|
||||
|
||||
topics->file->index_init(iindex_topic);
|
||||
relations->file->index_init(iindex_relations);
|
||||
|
||||
rcat_id->store((longlong) cat_id);
|
||||
rcat_id->get_key_image(buff, rcat_id->pack_length(), help_charset,
|
||||
Field::itRAW);
|
||||
int key_res= relations->file->index_read(relations->record[0],
|
||||
buff, rcat_id->pack_length(),
|
||||
HA_READ_KEY_EXACT);
|
||||
|
||||
for ( ; !key_res && cat_id == (int16) rcat_id->val_int() ;
|
||||
key_res= relations->file->index_next(relations->record[0]))
|
||||
{
|
||||
char topic_id_buff[8];
|
||||
longlong topic_id= rtopic_id->val_int();
|
||||
Field *field= find_fields[help_topic_help_topic_id].field;
|
||||
field->store((longlong) topic_id);
|
||||
field->get_key_image(topic_id_buff, field->pack_length(), help_charset,
|
||||
Field::itRAW);
|
||||
|
||||
mi_close(file_names_categories);
|
||||
|
||||
if (!topics->file->index_read(topics->record[0], topic_id_buff,
|
||||
field->pack_length(),
|
||||
HA_READ_KEY_EXACT))
|
||||
res->push_back(get_field(&thd->mem_root,
|
||||
find_fields[help_topic_name].field));
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Send to client answer for help request
|
||||
|
||||
SYNOPSIS
|
||||
send_answer_1()
|
||||
protocol - protocol for sending
|
||||
s1 - value of column "Name"
|
||||
s2 - value of column "Category"
|
||||
s3 - value of column "Description"
|
||||
s4 - value of column "Example"
|
||||
|
||||
IMPLEMENTATION
|
||||
Format used:
|
||||
+----------+---------+------------+------------+
|
||||
|Name: |Category |Description |Example |
|
||||
+----------+---------+------------+------------+
|
||||
|String(64)|String(1)|String(1000)|String(1000)|
|
||||
+----------+---------+------------+------------+
|
||||
with exactly one row!
|
||||
|
||||
RETURN VALUES
|
||||
1 Writing of head failed
|
||||
-1 Writing of row failed
|
||||
0 Successeful send
|
||||
*/
|
||||
|
||||
int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
|
||||
const char *s3, const char *s4)
|
||||
{
|
||||
|
@ -306,10 +312,10 @@ int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
|
|||
field_list.push_back(new Item_empty_string("Category",1));
|
||||
field_list.push_back(new Item_empty_string("Description",1000));
|
||||
field_list.push_back(new Item_empty_string("Example",1000));
|
||||
|
||||
|
||||
if (protocol->send_fields(&field_list,1))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
|
||||
protocol->prepare_for_resend();
|
||||
protocol->store(s1);
|
||||
protocol->store(s2);
|
||||
|
@ -317,11 +323,28 @@ int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
|
|||
protocol->store(s4);
|
||||
if (protocol->write())
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Send to client help header
|
||||
|
||||
SYNOPSIS
|
||||
send_header_2()
|
||||
protocol - protocol for sending
|
||||
|
||||
IMPLEMENTATION
|
||||
+----------+---------+
|
||||
|Name: |Category |
|
||||
+----------+---------+
|
||||
|String(64)|String(1)|
|
||||
+----------+---------+
|
||||
|
||||
RETURN VALUES
|
||||
result of protocol->send_fields
|
||||
*/
|
||||
|
||||
int send_header_2(Protocol *protocol)
|
||||
{
|
||||
DBUG_ENTER("send_header2");
|
||||
|
@ -332,79 +355,165 @@ int send_header_2(Protocol *protocol)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Server-side function 'help'
|
||||
|
||||
SYNOPSIS
|
||||
mysqld_help()
|
||||
thd Thread handler
|
||||
|
||||
RETURN VALUES
|
||||
0 Success
|
||||
1 Error and send_error already commited
|
||||
-1 error && send_error should be issued (normal case)
|
||||
*/
|
||||
|
||||
int mysqld_help(THD *thd, const char *mask)
|
||||
{
|
||||
Protocol *protocol= thd->protocol;
|
||||
SQL_SELECT *select= 0, *select_cat= 0;
|
||||
Item *cond_topic, *cond_cat;
|
||||
st_find_field used_fields[array_elements(init_used_fields)];
|
||||
DBUG_ENTER("mysqld_help");
|
||||
|
||||
MI_INFO *file_leafs= 0;
|
||||
if (!(file_leafs= open_help_file(thd,"function")))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
List<String> function_list, categories_list;
|
||||
String *name, *description, *example;
|
||||
int res;
|
||||
|
||||
int count= search_functions(file_leafs, mask,
|
||||
&function_list,&name,&description,&example);
|
||||
if (count < 0)
|
||||
|
||||
TABLE_LIST tables[3];
|
||||
bzero((gptr)tables,sizeof(tables));
|
||||
tables[0].alias= tables[0].real_name= (char*) "help_topic";
|
||||
tables[0].lock_type= TL_READ;
|
||||
tables[0].db= (char*) "mysql";
|
||||
tables[0].next= &tables[1];
|
||||
tables[1].alias= tables[1].real_name= (char*) "help_category";
|
||||
tables[1].lock_type= TL_READ;
|
||||
tables[1].db= (char*) "mysql";
|
||||
tables[1].next= &tables[2];
|
||||
tables[2].alias= tables[2].real_name= (char*) "help_relation";
|
||||
tables[2].lock_type= TL_READ;
|
||||
tables[2].db= (char*) "mysql";
|
||||
tables[2].next= 0;
|
||||
|
||||
List<char> function_list, categories_list;
|
||||
char *name, *description, *example;
|
||||
int res, count_topics, count_categories, error;
|
||||
|
||||
if (open_and_lock_tables(thd, tables))
|
||||
{
|
||||
res= 1;
|
||||
res= -1;
|
||||
goto end;
|
||||
}
|
||||
else if (count==0)
|
||||
/* Init tables and fields to be usable from items */
|
||||
setup_tables(tables);
|
||||
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
|
||||
if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
|
||||
{
|
||||
res= -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* TODO: Find out why these are needed (should not be) */
|
||||
tables[0].table->file->init_table_handle_for_HANDLER();
|
||||
tables[1].table->file->init_table_handle_for_HANDLER();
|
||||
tables[2].table->file->init_table_handle_for_HANDLER();
|
||||
|
||||
cond_topic= new Item_func_like(new Item_field(used_fields[help_topic_name].
|
||||
field),
|
||||
new Item_string(mask, strlen(mask),
|
||||
help_charset),
|
||||
(char*) "\\");
|
||||
cond_topic->fix_fields(thd, tables, &cond_topic); // can never fail
|
||||
select= make_select(tables[0].table,0,0,cond_topic,&error);
|
||||
if (error || (select && select->check_quick(0, HA_POS_ERROR)))
|
||||
{
|
||||
res= -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
cond_cat= new Item_func_like(new Item_field(used_fields[help_category_name].
|
||||
field),
|
||||
new Item_string(mask, strlen(mask),
|
||||
help_charset),
|
||||
(char*) "\\");
|
||||
cond_cat->fix_fields(thd, tables, &cond_topic); // can never fail
|
||||
select_cat= make_select(tables[1].table,0,0,cond_cat,&error);
|
||||
if (error || (select_cat && select_cat->check_quick(0, HA_POS_ERROR)))
|
||||
{
|
||||
res= -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
res= 1;
|
||||
count_topics= search_topics(thd,tables[0].table, used_fields, select,
|
||||
&function_list, &name, &description, &example);
|
||||
if (count_topics == 0)
|
||||
{
|
||||
int16 category_id;
|
||||
count= search_categories(thd, mask, &categories_list, &category_id);
|
||||
if (count<0)
|
||||
Item *cond=
|
||||
new Item_func_like(new
|
||||
Item_field(used_fields[help_category_name].field),
|
||||
new Item_string(mask, strlen(mask),
|
||||
help_charset),
|
||||
(char*) "\\");
|
||||
(void) cond->fix_fields(thd, tables, &cond); // can never fail
|
||||
|
||||
count_categories= search_categories(thd, tables[1].table, used_fields,
|
||||
select_cat, &categories_list,
|
||||
&category_id);
|
||||
if (count_categories == 1)
|
||||
{
|
||||
res= 1;
|
||||
goto end;
|
||||
}
|
||||
else if (count==1)
|
||||
{
|
||||
if ((res= get_all_names_for_category(thd, file_leafs,
|
||||
category_id,&function_list)))
|
||||
goto end;
|
||||
List_iterator<String> it(function_list);
|
||||
String *cur_leaf, example;
|
||||
while ((cur_leaf = it++))
|
||||
if (get_all_topics_for_category(thd,tables[0].table,
|
||||
tables[2].table, used_fields,
|
||||
category_id, &function_list))
|
||||
{
|
||||
example.append(*cur_leaf);
|
||||
res= -1;
|
||||
goto end;
|
||||
}
|
||||
List_iterator<char> it(function_list);
|
||||
char *cur_topic;
|
||||
char buff[1024];
|
||||
String example(buff, sizeof(buff), help_charset);
|
||||
example.length(0);
|
||||
|
||||
while ((cur_topic= it++))
|
||||
{
|
||||
example.append(cur_topic);
|
||||
example.append("\n",1);
|
||||
}
|
||||
if ((res= send_answer_1(protocol, categories_list.head()->ptr(),
|
||||
"Y","",example.ptr())))
|
||||
if ((send_answer_1(protocol, categories_list.head(),
|
||||
"Y","",example.ptr())))
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((res= send_header_2(protocol)) ||
|
||||
(count==0 &&
|
||||
(search_categories(thd, 0, &categories_list, 0)<0 &&
|
||||
((res= 1)))) ||
|
||||
(res= send_variant_2_list(protocol,&categories_list,true)))
|
||||
if (send_header_2(protocol))
|
||||
goto end;
|
||||
if (count_categories == 0)
|
||||
search_categories(thd,tables[1].table, used_fields, (SQL_SELECT *) 0,
|
||||
&categories_list, 0);
|
||||
if (send_variant_2_list(protocol,&categories_list,"Y"))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else if (count==1)
|
||||
else if (count_topics == 1)
|
||||
{
|
||||
if ((res= send_answer_1(protocol,name->ptr(),"N",
|
||||
description->ptr(), example->ptr())))
|
||||
if (send_answer_1(protocol,name,"N",description, example))
|
||||
goto end;
|
||||
}
|
||||
else if ((res= send_header_2(protocol)) ||
|
||||
(res= send_variant_2_list(protocol,&function_list,false)) ||
|
||||
(search_categories(thd, mask, &categories_list, 0)<0 &&
|
||||
((res=1))) ||
|
||||
(res= send_variant_2_list(protocol,&categories_list,true)))
|
||||
else
|
||||
{
|
||||
goto end;
|
||||
/* First send header and functions */
|
||||
if (send_header_2(protocol) ||
|
||||
send_variant_2_list(protocol, &function_list, "N"))
|
||||
goto end;
|
||||
search_categories(thd, tables[1].table, used_fields, select_cat,
|
||||
&categories_list, 0);
|
||||
/* Then send categories */
|
||||
if (send_variant_2_list(protocol, &categories_list, "Y"))
|
||||
goto end;
|
||||
}
|
||||
|
||||
res= 0;
|
||||
|
||||
send_eof(thd);
|
||||
|
||||
end:
|
||||
mi_close(file_leafs);
|
||||
delete select;
|
||||
delete select_cat;
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
|
|
@ -147,6 +147,12 @@ void lex_free(void)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
This is called before every query that is to be parsed.
|
||||
Because of this, it's critical to not do too much things here.
|
||||
(We already do too much here)
|
||||
*/
|
||||
|
||||
LEX *lex_start(THD *thd, uchar *buf,uint length)
|
||||
{
|
||||
LEX *lex= &thd->lex;
|
||||
|
@ -164,10 +170,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
|
|||
lex->thd_charset= lex->thd->variables.thd_charset;
|
||||
lex->yacc_yyss=lex->yacc_yyvs=0;
|
||||
lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
|
||||
lex->slave_thd_opt=0;
|
||||
lex->sql_command=SQLCOM_END;
|
||||
lex->safe_to_cache_query= 1;
|
||||
bzero(&lex->mi,sizeof(lex->mi));
|
||||
return lex;
|
||||
}
|
||||
|
||||
|
|
|
@ -472,7 +472,7 @@ typedef struct st_lex
|
|||
uint param_count;
|
||||
bool drop_primary, drop_if_exists, drop_temporary, local_file;
|
||||
bool in_comment, ignore_space, verbose, simple_alter;
|
||||
bool derived_tables, describe, olap;
|
||||
bool derived_tables, describe;
|
||||
bool safe_to_cache_query;
|
||||
uint slave_thd_opt;
|
||||
CHARSET_INFO *charset;
|
||||
|
|
|
@ -188,7 +188,7 @@ end:
|
|||
static int check_user(THD *thd,enum_server_command command, const char *user,
|
||||
const char *passwd, const char *db, bool check_count,
|
||||
bool simple_connect, bool do_send_error,
|
||||
char* crypted_scramble, bool had_password,
|
||||
char *crypted_scramble, bool had_password,
|
||||
uint *cur_priv_version, ACL_USER** hint_user)
|
||||
{
|
||||
thd->db=0;
|
||||
|
@ -506,10 +506,10 @@ check_connections(THD *thd)
|
|||
char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble&hash */
|
||||
ACL_USER* cached_user=NULL; /* Initialise to NULL for first stage */
|
||||
uint cur_priv_version;
|
||||
DBUG_PRINT("info", (("check_connections called by thread %d"),
|
||||
thd->thread_id));
|
||||
DBUG_PRINT("info",("New connection received on %s",
|
||||
vio_description(net->vio)));
|
||||
/* Remove warning from valgrind. TODO: Fix it in password.c */
|
||||
bzero((char*) prepared_scramble, sizeof(prepared_scramble));
|
||||
if (!thd->host) // If TCP/IP connection
|
||||
{
|
||||
char ip[30];
|
||||
|
@ -525,15 +525,17 @@ check_connections(THD *thd)
|
|||
thd->host=(char*) localhost;
|
||||
else
|
||||
#endif
|
||||
if (!(specialflag & SPECIAL_NO_RESOLVE))
|
||||
{
|
||||
vio_in_addr(net->vio,&thd->remote.sin_addr);
|
||||
thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
|
||||
/* Cut very long hostnames to avoid possible overflows */
|
||||
if (thd->host)
|
||||
thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
|
||||
if (connect_errors > max_connect_errors)
|
||||
return(ER_HOST_IS_BLOCKED);
|
||||
if (!(specialflag & SPECIAL_NO_RESOLVE))
|
||||
{
|
||||
vio_in_addr(net->vio,&thd->remote.sin_addr);
|
||||
thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
|
||||
/* Cut very long hostnames to avoid possible overflows */
|
||||
if (thd->host)
|
||||
thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
|
||||
if (connect_errors > max_connect_errors)
|
||||
return(ER_HOST_IS_BLOCKED);
|
||||
}
|
||||
}
|
||||
DBUG_PRINT("info",("Host: %s ip: %s",
|
||||
thd->host ? thd->host : "unknown host",
|
||||
|
@ -555,8 +557,8 @@ check_connections(THD *thd)
|
|||
{
|
||||
/* buff[] needs to big enough to hold the server_version variable */
|
||||
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+64];
|
||||
int client_flags = CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
|
||||
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION;
|
||||
int client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
|
||||
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
|
||||
|
||||
if (opt_using_transactions)
|
||||
client_flags|=CLIENT_TRANSACTIONS;
|
||||
|
@ -582,7 +584,7 @@ check_connections(THD *thd)
|
|||
// At this point we write connection message and read reply
|
||||
if (net_write_command(net,(uchar) protocol_version, "", 0, buff,
|
||||
(uint) (end-buff)) ||
|
||||
(pkt_len= my_net_read(net)) == packet_error ||
|
||||
(pkt_len= my_net_read(net)) == packet_error ||
|
||||
pkt_len < MIN_HANDSHAKE_SIZE)
|
||||
{
|
||||
inc_host_errors(&thd->remote.sin_addr);
|
||||
|
@ -647,17 +649,17 @@ check_connections(THD *thd)
|
|||
passwd= strend(user)+1;
|
||||
db=0;
|
||||
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
|
||||
db=strend(passwd)+1;
|
||||
db=strend(passwd)+1;
|
||||
|
||||
/* We can get only old hash at this point */
|
||||
if (passwd[0] && strlen(passwd)!=SCRAMBLE_LENGTH)
|
||||
return ER_HANDSHAKE_ERROR;
|
||||
return ER_HANDSHAKE_ERROR;
|
||||
|
||||
if (thd->client_capabilities & CLIENT_INTERACTIVE)
|
||||
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
|
||||
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
|
||||
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
|
||||
opt_using_transactions)
|
||||
net->return_status= &thd->server_status;
|
||||
opt_using_transactions)
|
||||
net->return_status= &thd->server_status;
|
||||
net->read_timeout=(uint) thd->variables.net_read_timeout;
|
||||
|
||||
/* Simple connect only for old clients. New clients always use secure auth */
|
||||
|
@ -665,34 +667,34 @@ check_connections(THD *thd)
|
|||
|
||||
/* Store information if we used password. passwd will be dammaged */
|
||||
bool using_password=test(passwd[0]);
|
||||
|
||||
/* Check user permissions. If password failure we'll get scramble back */
|
||||
if (check_user(thd, COM_CONNECT, user, passwd, db, 1, simple_connect,
|
||||
simple_connect, prepared_scramble, using_password, &cur_priv_version,
|
||||
&cached_user)<0)
|
||||
simple_connect, prepared_scramble, using_password,
|
||||
&cur_priv_version,
|
||||
&cached_user)<0)
|
||||
{
|
||||
/* Store current used and database as they are erased with next packet */
|
||||
char tmp_user[USERNAME_LENGTH+1];
|
||||
char tmp_db[NAME_LEN+1];
|
||||
|
||||
tmp_user[0]= tmp_db[0]= 0;
|
||||
/* If The client is old we just have to return error */
|
||||
if (simple_connect)
|
||||
return -1;
|
||||
|
||||
tmp_user[0]=0;
|
||||
if (user)
|
||||
strmake(tmp_user,user,USERNAME_LENGTH);
|
||||
|
||||
tmp_db[0]=0;
|
||||
if (db)
|
||||
strmake(tmp_db,db,NAME_LEN);
|
||||
|
||||
/* Write hash and encrypted scramble to client */
|
||||
if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) ||
|
||||
net_flush(net))
|
||||
{
|
||||
inc_host_errors(&thd->remote.sin_addr);
|
||||
return ER_HANDSHAKE_ERROR;
|
||||
}
|
||||
{
|
||||
inc_host_errors(&thd->remote.sin_addr);
|
||||
return ER_HANDSHAKE_ERROR;
|
||||
}
|
||||
/* Reading packet back */
|
||||
if ((pkt_len= my_net_read(net)) == packet_error)
|
||||
{
|
||||
|
@ -707,8 +709,9 @@ check_connections(THD *thd)
|
|||
}
|
||||
/* Final attempt to check the user based on reply */
|
||||
if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos,
|
||||
tmp_db, 1, 0, 1, prepared_scramble, using_password, &cur_priv_version,
|
||||
&cached_user))
|
||||
tmp_db, 1, 0, 1, prepared_scramble, using_password,
|
||||
&cur_priv_version,
|
||||
&cached_user))
|
||||
return -1;
|
||||
}
|
||||
thd->password=using_password;
|
||||
|
@ -774,7 +777,7 @@ pthread_handler_decl(handle_one_connection,arg)
|
|||
net_printf(thd,error,thd->host_or_ip);
|
||||
#ifdef __NT__
|
||||
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
|
||||
sleep(1); /* must wait after eof() */
|
||||
my_sleep(1000); /* must wait after eof() */
|
||||
#endif
|
||||
statistic_increment(aborted_connects,&LOCK_status);
|
||||
goto end_thread;
|
||||
|
@ -1123,22 +1126,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||
*/
|
||||
if (check_user(thd,COM_CHANGE_USER, user, passwd, db, 0, simple_connect,
|
||||
simple_connect, prepared_scramble, using_password, &cur_priv_version,
|
||||
&cached_user)<0)
|
||||
&cached_user) < 0)
|
||||
{
|
||||
/* If The client is old we just have to have auth failure */
|
||||
if (simple_connect)
|
||||
goto restore_user; /* Error is already reported */
|
||||
|
||||
/* Store current used and database as they are erased with next packet */
|
||||
tmp_user[0]=0;
|
||||
tmp_user[0]= tmp_db[0]= 0;
|
||||
if (user)
|
||||
strmake(tmp_user,user,USERNAME_LENGTH);
|
||||
|
||||
tmp_db[0]=0;
|
||||
if (db)
|
||||
strmake(tmp_db,db,NAME_LEN);
|
||||
|
||||
|
||||
/* Write hash and encrypted scramble to client */
|
||||
if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) ||
|
||||
net_flush(net))
|
||||
|
@ -1589,7 +1589,6 @@ mysql_execute_command(THD *thd)
|
|||
cursor= cursor->next)
|
||||
{
|
||||
if (cursor->derived && (res=mysql_derived(thd, lex,
|
||||
(SELECT_LEX_UNIT *)
|
||||
cursor->derived,
|
||||
cursor)))
|
||||
{
|
||||
|
@ -1602,7 +1601,7 @@ mysql_execute_command(THD *thd)
|
|||
}
|
||||
if ((&lex->select_lex != lex->all_selects_list &&
|
||||
lex->unit.create_total_list(thd, lex, &tables, 0))
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
#ifndef HAVE_REPLICATION
|
||||
||
|
||||
(table_rules_on && tables && thd->slave_thread &&
|
||||
!tables_ok(thd,tables))
|
||||
|
@ -3148,7 +3147,7 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, int *yystacksize)
|
|||
|
||||
|
||||
/****************************************************************************
|
||||
Initialize global thd variables needed for query
|
||||
Initialize global thd variables needed for query
|
||||
****************************************************************************/
|
||||
|
||||
void
|
||||
|
@ -3170,10 +3169,11 @@ mysql_init_query(THD *thd)
|
|||
lex->select_lex.prev= &lex->unit.slave;
|
||||
lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
|
||||
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
|
||||
lex->olap=lex->describe= 0;
|
||||
lex->derived_tables= false;
|
||||
lex->describe= 0;
|
||||
lex->derived_tables= FALSE;
|
||||
lex->lock_option= TL_READ;
|
||||
lex->found_colon= 0;
|
||||
lex->safe_to_cache_query= 1;
|
||||
thd->select_number= lex->select_lex.select_number= 1;
|
||||
thd->free_list= 0;
|
||||
thd->total_warn_count=0; // Warnings for this query
|
||||
|
@ -3184,7 +3184,7 @@ mysql_init_query(THD *thd)
|
|||
thd->tmp_table_used= 0;
|
||||
if (opt_bin_log)
|
||||
reset_dynamic(&thd->user_var_events);
|
||||
|
||||
thd->clear_error();
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -3283,8 +3283,6 @@ mysql_parse(THD *thd, char *inBuf, uint length)
|
|||
DBUG_ENTER("mysql_parse");
|
||||
|
||||
mysql_init_query(thd);
|
||||
thd->clear_error();
|
||||
|
||||
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
|
||||
{
|
||||
LEX *lex=lex_start(thd, (uchar*) inBuf, length);
|
||||
|
@ -3787,10 +3785,10 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
|||
my_casedn_str(files_charset_info,table->table.str);
|
||||
ptr->real_name=table->table.str;
|
||||
ptr->real_name_length=table->table.length;
|
||||
ptr->lock_type= lock_type;
|
||||
ptr->lock_type= lock_type;
|
||||
ptr->updating= test(table_options & TL_OPTION_UPDATING);
|
||||
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
|
||||
ptr->derived= (SELECT_LEX_UNIT *) table->sel;
|
||||
ptr->derived= table->sel;
|
||||
if (use_index)
|
||||
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index,
|
||||
sizeof(*use_index));
|
||||
|
|
|
@ -669,11 +669,10 @@ static bool parse_prepare_query(PREP_STMT *stmt,
|
|||
|
||||
mysql_log.write(thd,COM_PREPARE,"%s",packet);
|
||||
mysql_init_query(thd);
|
||||
thd->prepare_command=true;
|
||||
thd->lex.param_count= 0;
|
||||
|
||||
LEX *lex=lex_start(thd, (uchar*) packet, length);
|
||||
lex->safe_to_cache_query= 0;
|
||||
thd->prepare_command= TRUE;
|
||||
thd->lex.param_count= 0;
|
||||
if (!yyparse((void *)thd) && !thd->is_fatal_error)
|
||||
error= send_prepare_results(stmt);
|
||||
lex_end(lex);
|
||||
|
|
|
@ -670,6 +670,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
|||
ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
/* TODO: To be deleted */
|
||||
my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET),
|
||||
MYF(0), "RTREE INDEX");
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
List_iterator<key_part_spec> cols(key->columns);
|
||||
|
|
|
@ -162,9 +162,9 @@ void udf_init()
|
|||
{
|
||||
DBUG_PRINT("info",("init udf record"));
|
||||
LEX_STRING name;
|
||||
name.str=get_field(&mem, table, 0);
|
||||
name.str=get_field(&mem, table->field[0]);
|
||||
name.length = strlen(name.str);
|
||||
char *dl_name= get_field(&mem, table, 2);
|
||||
char *dl_name= get_field(&mem, table->field[2]);
|
||||
bool new_dl=0;
|
||||
Item_udftype udftype=UDFTYPE_FUNCTION;
|
||||
if (table->fields >= 4) // New func table
|
||||
|
|
|
@ -136,6 +136,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
|||
%token EVENTS_SYM
|
||||
%token EXECUTE_SYM
|
||||
%token FLUSH_SYM
|
||||
%token HELP_SYM
|
||||
%token INSERT
|
||||
%token IO_THREAD
|
||||
%token KILL_SYM
|
||||
|
@ -528,8 +529,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
|||
%token SUBJECT_SYM
|
||||
%token CIPHER_SYM
|
||||
|
||||
%token HELP
|
||||
|
||||
%left SET_VAR
|
||||
%left OR_OR_CONCAT OR
|
||||
%left AND
|
||||
|
@ -742,11 +741,11 @@ verb_clause:
|
|||
/* help */
|
||||
|
||||
help:
|
||||
HELP TEXT_STRING
|
||||
HELP_SYM ident_or_text
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
lex->sql_command= SQLCOM_HELP;
|
||||
lex->help_arg= $2.str;
|
||||
LEX *lex= Lex;
|
||||
lex->sql_command= SQLCOM_HELP;
|
||||
lex->help_arg= $2.str;
|
||||
};
|
||||
|
||||
/* change master */
|
||||
|
@ -1573,8 +1572,13 @@ start:
|
|||
;
|
||||
|
||||
slave_thread_opts:
|
||||
{ Lex->slave_thd_opt= 0; }
|
||||
slave_thread_opt_list
|
||||
|
||||
slave_thread_opt_list:
|
||||
slave_thread_opt
|
||||
| slave_thread_opts ',' slave_thread_opt;
|
||||
| slave_thread_opt_list ',' slave_thread_opt
|
||||
;
|
||||
|
||||
slave_thread_opt:
|
||||
/*empty*/ {}
|
||||
|
@ -1720,7 +1724,8 @@ select_init:
|
|||
send_error(lex->thd, ER_SYNTAX_ERROR);
|
||||
YYABORT;
|
||||
}
|
||||
if (sel->linkage == UNION_TYPE && !sel->master_unit()->first_select()->braces)
|
||||
if (sel->linkage == UNION_TYPE &&
|
||||
!sel->master_unit()->first_select()->braces)
|
||||
{
|
||||
send_error(lex->thd, ER_SYNTAX_ERROR);
|
||||
YYABORT;
|
||||
|
@ -1740,7 +1745,8 @@ select_init2:
|
|||
send_error(lex->thd, ER_SYNTAX_ERROR);
|
||||
YYABORT;
|
||||
}
|
||||
if (sel->linkage == UNION_TYPE && sel->master_unit()->first_select()->braces)
|
||||
if (sel->linkage == UNION_TYPE &&
|
||||
sel->master_unit()->first_select()->braces)
|
||||
{
|
||||
send_error(lex->thd, ER_SYNTAX_ERROR);
|
||||
YYABORT;
|
||||
|
@ -2773,7 +2779,6 @@ olap_opt:
|
|||
| WITH CUBE_SYM
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->olap= 1;
|
||||
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
|
||||
{
|
||||
net_printf(lex->thd, ER_WRONG_USAGE, "WITH CUBE",
|
||||
|
@ -2787,7 +2792,6 @@ olap_opt:
|
|||
| WITH ROLLUP_SYM
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
lex->olap= 1;
|
||||
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
|
||||
{
|
||||
net_printf(lex->thd, ER_WRONG_USAGE, "WITH ROLLUP",
|
||||
|
@ -2812,7 +2816,7 @@ order_clause:
|
|||
ORDER_SYM BY
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
|
||||
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE) &&
|
||||
lex->current_select->select_lex()->olap !=
|
||||
UNSPECIFIED_OLAP_TYPE)
|
||||
{
|
||||
|
@ -2835,11 +2839,21 @@ order_dir:
|
|||
| DESC { $$ =0; };
|
||||
|
||||
|
||||
opt_limit_clause:
|
||||
/* empty */ {}
|
||||
opt_limit_clause_init:
|
||||
/* empty */
|
||||
{
|
||||
SELECT_LEX_NODE *sel= Select;
|
||||
sel->offset_limit= 0L;
|
||||
sel->select_limit= Lex->thd->variables.select_limit;
|
||||
}
|
||||
| limit_clause {}
|
||||
;
|
||||
|
||||
opt_limit_clause:
|
||||
/* empty */ {}
|
||||
| limit_clause {}
|
||||
;
|
||||
|
||||
limit_clause:
|
||||
LIMIT
|
||||
{
|
||||
|
@ -3423,9 +3437,7 @@ show_param:
|
|||
{
|
||||
LEX *lex= Lex;
|
||||
lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
|
||||
lex->select_lex.select_limit= lex->thd->variables.select_limit;
|
||||
lex->select_lex.offset_limit= 0L;
|
||||
} opt_limit_clause
|
||||
} opt_limit_clause_init
|
||||
| keys_or_index FROM table_ident opt_db
|
||||
{
|
||||
Lex->sql_command= SQLCOM_SHOW_KEYS;
|
||||
|
@ -3453,9 +3465,9 @@ show_param:
|
|||
{ (void) create_select_for_variable("warning_count"); }
|
||||
| COUNT_SYM '(' '*' ')' ERRORS
|
||||
{ (void) create_select_for_variable("error_count"); }
|
||||
| WARNINGS {Select->offset_limit=0L;} opt_limit_clause
|
||||
| WARNINGS opt_limit_clause_init
|
||||
{ Lex->sql_command = SQLCOM_SHOW_WARNS;}
|
||||
| ERRORS {Select->offset_limit=0L;} opt_limit_clause
|
||||
| ERRORS opt_limit_clause_init
|
||||
{ Lex->sql_command = SQLCOM_SHOW_ERRORS;}
|
||||
| STATUS_SYM wild
|
||||
{ Lex->sql_command= SQLCOM_SHOW_STATUS; }
|
||||
|
@ -3729,18 +3741,24 @@ opt_ignore_lines:
|
|||
/* Common definitions */
|
||||
|
||||
text_literal:
|
||||
TEXT_STRING { $$ = new Item_string($1.str,$1.length,YYTHD->variables.thd_charset); }
|
||||
| UNDERSCORE_CHARSET TEXT_STRING { $$ = new Item_string($2.str,$2.length,Lex->charset); }
|
||||
TEXT_STRING
|
||||
{ $$ = new Item_string($1.str,$1.length,
|
||||
YYTHD->variables.thd_charset); }
|
||||
| UNDERSCORE_CHARSET TEXT_STRING
|
||||
{ $$ = new Item_string($2.str,$2.length,Lex->charset); }
|
||||
| text_literal TEXT_STRING
|
||||
{ ((Item_string*) $1)->append($2.str,$2.length); };
|
||||
{ ((Item_string*) $1)->append($2.str,$2.length); };
|
||||
|
||||
text_string:
|
||||
TEXT_STRING { $$= new String($1.str,$1.length,YYTHD->variables.thd_charset); }
|
||||
TEXT_STRING
|
||||
{ $$= new String($1.str,$1.length,YYTHD->variables.thd_charset); }
|
||||
| HEX_NUM
|
||||
{
|
||||
Item *tmp = new Item_varbinary($1.str,$1.length);
|
||||
$$= tmp ? tmp->val_str((String*) 0) : (String*) 0;
|
||||
};
|
||||
}
|
||||
;
|
||||
|
||||
param_marker:
|
||||
'?'
|
||||
{
|
||||
|
@ -3755,7 +3773,9 @@ param_marker:
|
|||
yyerror("You have an error in your SQL syntax");
|
||||
YYABORT;
|
||||
}
|
||||
};
|
||||
}
|
||||
;
|
||||
|
||||
literal:
|
||||
text_literal { $$ = $1; }
|
||||
| NUM { $$ = new Item_int($1.str, (longlong) strtol($1.str, NULL, 10),$1.length); }
|
||||
|
@ -3948,8 +3968,9 @@ keyword:
|
|||
| FLUSH_SYM {}
|
||||
| GRANTS {}
|
||||
| GLOBAL_SYM {}
|
||||
| HEAP_SYM {}
|
||||
| HANDLER_SYM {}
|
||||
| HEAP_SYM {}
|
||||
| HELP_SYM {}
|
||||
| HOSTS_SYM {}
|
||||
| HOUR_SYM {}
|
||||
| IDENTIFIED_SYM {}
|
||||
|
@ -4255,7 +4276,7 @@ handler:
|
|||
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
|
||||
YYABORT;
|
||||
}
|
||||
handler_read_or_scan where_clause opt_limit_clause { }
|
||||
handler_read_or_scan where_clause opt_limit_clause {}
|
||||
;
|
||||
|
||||
handler_read_or_scan:
|
||||
|
@ -4633,8 +4654,6 @@ optional_order_or_limit:
|
|||
sel->master_unit()->global_parameters=
|
||||
sel->master_unit();
|
||||
lex->current_select= sel->master_unit();
|
||||
lex->current_select->select_limit=
|
||||
lex->thd->variables.select_limit;
|
||||
lex->current_select->no_table_names_allowed= 1;
|
||||
thd->where= "global ORDER clause";
|
||||
}
|
||||
|
@ -4647,9 +4666,8 @@ optional_order_or_limit:
|
|||
;
|
||||
|
||||
order_or_limit:
|
||||
order_clause opt_limit_clause
|
||||
|
|
||||
limit_clause
|
||||
order_clause opt_limit_clause_init
|
||||
| limit_clause
|
||||
;
|
||||
|
||||
union_option:
|
||||
|
|
37
sql/table.cc
37
sql/table.cc
|
@ -37,7 +37,27 @@ static byte* get_field_name(Field *buff,uint *length,
|
|||
return (byte*) buff->field_name;
|
||||
}
|
||||
|
||||
/* Open a .frm file */
|
||||
/*
|
||||
Open a .frm file
|
||||
|
||||
SYNOPSIS
|
||||
openfrm()
|
||||
|
||||
name path to table-file "db/name"
|
||||
alias alias for table
|
||||
db_stat open flags (for example HA_OPEN_KEYFILE|HA_OPEN_RNDFILE..)
|
||||
can be 0 (example in ha_example_table)
|
||||
prgflag READ_ALL etc..
|
||||
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
|
||||
outparam result table
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
1 Error (see frm_error)
|
||||
2 Error (see frm_error)
|
||||
3 Wrong data in .frm file
|
||||
4 Error (see frm_error)
|
||||
*/
|
||||
|
||||
int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
|
||||
uint ha_open_flags, TABLE *outparam)
|
||||
|
@ -1127,13 +1147,20 @@ rename_file_ext(const char * from,const char * to,const char * ext)
|
|||
|
||||
|
||||
/*
|
||||
Alloc a value as a string and return it
|
||||
If field is empty, return NULL
|
||||
Allocate string field in MEM_ROOT and return it as NULL-terminated string
|
||||
|
||||
SYNOPSIS
|
||||
get_field()
|
||||
mem MEM_ROOT for allocating
|
||||
field Field for retrieving of string
|
||||
|
||||
RETURN VALUES
|
||||
NullS string is empty
|
||||
# pointer to NULL-terminated string value of field
|
||||
*/
|
||||
|
||||
char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr)
|
||||
char *get_field(MEM_ROOT *mem, Field *field)
|
||||
{
|
||||
Field *field=table->field[fieldnr];
|
||||
char buff[MAX_FIELD_WIDTH];
|
||||
String str(buff,sizeof(buff),default_charset_info);
|
||||
field->val_str(&str,&str);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
class Item; /* Needed by ORDER */
|
||||
class GRANT_TABLE;
|
||||
class st_select_lex_unit;
|
||||
|
||||
/* Order clause list element */
|
||||
|
||||
|
@ -161,7 +162,7 @@ typedef struct st_table_list
|
|||
TABLE *table; /* opened table */
|
||||
st_table_list *table_list; /* pointer to node of list of all tables */
|
||||
};
|
||||
void *derived; /* SELECT_LEX_UNIT of derived table */
|
||||
class st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
|
||||
GRANT_INFO grant;
|
||||
thr_lock_type lock_type;
|
||||
uint outer_join; /* Which join type */
|
||||
|
|
36
sql/time.cc
36
sql/time.cc
|
@ -436,7 +436,8 @@ ulong convert_month_to_period(ulong month)
|
|||
Also dates where all parts are zero are allowed
|
||||
|
||||
RETURN VALUES
|
||||
TIMESTAMP_NONE String wasn't a timestamp
|
||||
TIMESTAMP_NONE String wasn't a timestamp, like
|
||||
[DD [HH:[MM:[SS]]]].fraction
|
||||
TIMESTAMP_DATE DATE string (YY MM and DD parts ok)
|
||||
TIMESTAMP_FULL Full timestamp
|
||||
*/
|
||||
|
@ -448,6 +449,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
|
|||
uint not_zero_date;
|
||||
const char *pos;
|
||||
const char *end=str+length;
|
||||
bool found_delimitier= 0;
|
||||
DBUG_ENTER("str_to_TIME");
|
||||
DBUG_PRINT("enter",("str: %.*s",length,str));
|
||||
|
||||
|
@ -456,7 +458,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
|
|||
if (str == end)
|
||||
DBUG_RETURN(TIMESTAMP_NONE);
|
||||
/*
|
||||
calculate first number of digits.
|
||||
Calculate first number of digits.
|
||||
If length= 8 or >= 14 then year is of format YYYY.
|
||||
(YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS)
|
||||
*/
|
||||
|
@ -474,6 +476,11 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
|
|||
tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
|
||||
str++;
|
||||
}
|
||||
if (found_delimitier && (int) field_length < 0)
|
||||
{
|
||||
/* The number can't match any valid date or datetime string */
|
||||
DBUG_RETURN(TIMESTAMP_NONE);
|
||||
}
|
||||
date[i]=tmp_value;
|
||||
not_zero_date|= tmp_value;
|
||||
if (i == 2 && str != end && *str == 'T')
|
||||
|
@ -488,6 +495,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
|
|||
if (my_isspace(&my_charset_latin1,*str) && i != 2)
|
||||
DBUG_RETURN(TIMESTAMP_NONE);
|
||||
str++;
|
||||
found_delimitier=1; // Should be a 'normal' date
|
||||
}
|
||||
}
|
||||
field_length=1; // Rest fields can only be 2
|
||||
|
@ -498,7 +506,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
|
|||
{
|
||||
str++;
|
||||
uint tmp_value=(uint) (uchar) (*str - '0');
|
||||
field_length=3;
|
||||
field_length=5;
|
||||
while (str++ != end && my_isdigit(&my_charset_latin1,str[0]) &&
|
||||
field_length--)
|
||||
tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0');
|
||||
|
@ -583,12 +591,22 @@ longlong str_to_datetime(const char *str,uint length,bool fuzzy_date)
|
|||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
** convert a time string to a (ulong) value.
|
||||
** Can use all full timestamp formats and
|
||||
** [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS, [M]MSS or [S]S
|
||||
** There may be an optional [.second_part] after seconds
|
||||
*****************************************************************************/
|
||||
/*
|
||||
Convert a time string to a TIME struct.
|
||||
|
||||
SYNOPSIS
|
||||
str_to_time()
|
||||
str A string in full TIMESTAMP format or
|
||||
[-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS,
|
||||
[M]MSS or [S]S
|
||||
There may be an optional [.second_part] after seconds
|
||||
length Length of str
|
||||
l_time Store result here
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
|
||||
bool str_to_time(const char *str,uint length,TIME *l_time)
|
||||
{
|
||||
|
|
|
@ -22,24 +22,48 @@
|
|||
#include "m_string.h"
|
||||
#include "m_ctype.h"
|
||||
|
||||
static uchar ctype_bin[] = {
|
||||
0,
|
||||
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
|
||||
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
|
||||
72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
static uchar ctype_bin[]=
|
||||
{
|
||||
0,
|
||||
32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32,
|
||||
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
|
||||
72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
132,132,132,132,132,132,132,132,132,132, 16, 16, 16, 16, 16, 16,
|
||||
16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
|
||||
16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
|
||||
16,129,129,129,129,129,129, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 16,
|
||||
16,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 16, 16, 16, 32,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
72, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1, 1, 1, 1, 1, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 16, 2, 2, 2, 2, 2, 2, 2, 2
|
||||
};
|
||||
|
||||
|
||||
/* Dummy array for toupper / tolower / sortorder */
|
||||
|
||||
static uchar bin_char_array[] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
||||
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
|
||||
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
|
||||
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
|
||||
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
|
||||
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
|
||||
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
|
||||
};
|
||||
|
||||
|
||||
|
@ -277,9 +301,9 @@ CHARSET_INFO my_charset_bin =
|
|||
"binary", /* name */
|
||||
"", /* comment */
|
||||
ctype_bin, /* ctype */
|
||||
NULL, /* to_lower */
|
||||
NULL, /* to_upper */
|
||||
NULL, /* sort_order */
|
||||
bin_char_array, /* to_lower */
|
||||
bin_char_array, /* to_upper */
|
||||
bin_char_array, /* sort_order */
|
||||
NULL, /* tab_to_uni */
|
||||
NULL, /* tab_from_uni */
|
||||
0, /* strxfrm_multiply */
|
||||
|
|
Loading…
Reference in a new issue