Commit fc8f92ca authored by unknown's avatar unknown

New myisamchk option --sort-recover

Allow delete of crashed MyISAM tables
Fixed bug when BLOB was first part of key
Fixed bug when using result from CASE in GROUP BY
Fixed core-dump bug in monthname()
Optimized calling of check_db_name()


Docs/manual.texi:
  Added more information about myisamchk
client/mysqladmin.c:
  Added error message for CREATE database and fixed possible overflow bug
include/myisam.h:
  New myisamchk option --sort-recover
libmysql/libmysql.c:
  Removed commented code
  Don't define getpwuid (breaks on SCO 3.2)
myisam/mi_check.c:
  Fixed (new) bug when using --recover --optimize
myisam/mi_delete_table.c:
  Allow delete of crashed tables
myisam/mi_key.c:
  Fixed bug when BLOB was first part of key
myisam/myisamchk.c:
  New myisamchk option --sort-recover
mysql-test/r/case.result:
  New test cases to check for reported bugs
mysql-test/r/func_time.result:
  New test cases to check for reported bugs
mysql-test/r/type_blob.result:
  New test cases to check for reported bugs
mysql-test/r/type_datetime.result:
  New test cases to check for reported bugs
mysql-test/t/case.test:
  New test cases to check for reported bugs
mysql-test/t/func_time.test:
  New test cases to check for reported bugs
mysql-test/t/type_blob.test:
  New test cases to check for reported bugs
mysql-test/t/type_datetime.test:
  New test cases to check for reported bugs
mysys/my_bitmap.c:
  Optimize
sql-bench/limits/ms-sql.cfg:
  Updated limits
sql/item_cmpfunc.cc:
  Fixed bug when using result from CASE in GROUP BY
sql/item_cmpfunc.h:
  Fixed bug when using result from CASE in GROUP BY
sql/item_timefunc.cc:
  Fixed core-dump bug in monthname()
sql/sql_db.cc:
  Optimized calling of check_db_name()
sql/sql_parse.cc:
  Optimized calling of check_db_name()
sql/table.cc:
  Fixed typo
parent 040f0c0d
......@@ -9952,7 +9952,7 @@ for this is that negative numbers caused problems when wrapping from -1 to 0.
@code{AUTO_INCREMENT} is now for MyISAM tables handled at a lower level and
is much faster than before. For MyISAM tables old numbers are also not reused
anymore, even if you delete some rows from the table.
@item @code{INNER}, @code{DELAYED}, @code{RIGHT}, @code{CASE}, @code{THEN}, @code{WHEN}, @code{ELSE}, @code{END} and @code{WHEN} are now reserved words.
@item @code{CASE}, @code{DELAYED}, @code{ELSE}, @code{END}, @code{FULLTEXT}, @code{INNER}, @code{RIGHT}, @code{THEN} and @code{WHEN} are now reserved words.
@item @code{FLOAT(X)} is now a true floating-point type and not a value with
a fixed number of decimals.
@item When declaring @code{DECIMAL(length,dec)} the length argument no
......@@ -15814,6 +15814,10 @@ mysql> SELECT CASE BINARY "B" when "a" then 1 when "b" then 2 END;
@end example
@end table
The type of the return value (@code{INTEGER}, @code{DOUBLE} or
@code{STRING}) is the same as the type of the first returned value (the
expression after the first @code{THEN}).
@findex mathematical functions
@findex functions, mathematical
@node Mathematical functions, String functions, Control flow functions, Functions
......@@ -30619,11 +30623,11 @@ utility. @xref{Table types}.
In the following text we will talk about @code{myisamchk}, but everything
also applies to the old @code{isamchk}.
You can use the @code{myisamchk} utility to get information about your database
tables, check and repair them, or optimize them. The following sections
describe how to invoke @code{myisamchk} (including a description of its
options), how to set up a table maintenance schedule, and how to use
@code{myisamchk} to perform its various functions.
You can use the @code{myisamchk} utility to get information about your
database tables, check and repair them, or optimize them. The following
sections describe how to invoke @code{myisamchk} (including a
description of its options), how to set up a table maintenance schedule,
and how to use @code{myisamchk} to perform its various functions.
You can, in most cases, also use the command @code{OPTIMIZE TABLES} to
optimize and repair tables, but this is not as fast or reliable (in case
......@@ -30713,9 +30717,9 @@ the file or that has died without closing the file properly.
If you @code{mysqld} is running, you must force a sync/close of all
tables with @code{FLUSH TABLES} and ensure that no one is using the
tables while you are running @code{myisamchk}. In MySQL Version 3.23 the easiest
way to avoid this problem is to use @code{CHECK TABLE} instead of
@code{myisamchk} to check tables.
tables while you are running @code{myisamchk}. In @strong{MySQL} Version 3.23
the easiest way to avoid this problem is to use @code{CHECK TABLE}
instead of @code{myisamchk} to check tables.
@cindex options, @code{myisamchk}
@cindex @code{myisamchk}, options
......@@ -30740,9 +30744,30 @@ for myisamchk can be examined with @code{myisamchk --help}:
@item decode_bits @tab 9
@end multitable
@code{key_buffer_size} is only used when you check the table with @code{-e} or
repair it with @code{-o}.
@code{sort_buffer_size} is used when you repair the table with @code{-r}.
@code{sort_buffer_size} is used when the keys are reparied by sorting
keys, which is the normal case when you use @code{--recover}.
@code{key_buffer_size} is used when you are checking the table with
@code{--extended-check} or when the keys are repaired by inserting key
row by row in to the table (like when doing normal inserts). Repairing
through the key buffer is used in the following cases:
@itemize @bullet
@item
If you use @code{--safe-recover}.
@item
If you are using a @code{FULLTEXT} index.
@item
If the temporary files needed to sort the keys would be more than twice
as big as when creating the key file directly. This is often the case
when you have big @code{CHAR}, @code{VARCHAR} or @code{TEXT} keys as the
sort needs to store the whole keys during sorting. If you have lots
of temporary space and you can force @code{myisamchk} to repair by sorting
you can use the @code{--sort-recover} option.
@end itemize
Reparing through the key buffer takes much less disk space than using
sorting, but is also much slower.
If you want a faster repair, set the above variables to about 1/4 of your
available memory. You can set both variables to big values, as only one
......@@ -30851,6 +30876,11 @@ space than @code{-r}. Normally one should always first repair with
If you have lots of memory, you should increase the size of
@code{key_buffer_size}!
@item -n or --sort-recover
Force @code{myisamchk} to use sorting to resolve the keys even if the
temporary files should be very big. This will not have any effect if you have
fulltext keys in the table.
@item --character-sets-dir=...
Directory where character sets are stored.
@item --set-character-set=name
......@@ -30933,8 +30963,9 @@ Space for the new index file that replaces the old one. The old
index file is truncated at start, so one usually ignore this space.
This space is needed on the same disk as the original index file!
@item
When using @code{--repair} (but not when using @code{--safe-repair}, you
will need space for a sort buffer for:
When using @code{--recover} or @code{--sort-recover}
(but not when using @code{--safe-recover}, you will need space for a
sort buffer for:
@code{(largest_key + row_pointer_length)*number_of_rows * 2}.
You can check the length of the keys and the row_pointer_length with
@code{myisamchk -dv table}.
......@@ -30943,7 +30974,7 @@ This space is allocated on the temporary disk (specified by @code{TMPDIR} or
@end itemize
If you have a problem with disk space during repair, you can try to use
@code{--safe-repair} instead of @code{--repair}.
@code{--safe-recover} instead of @code{--recover}.
@cindex maintaining, tables
@cindex tables, maintenance regimen
......@@ -39486,6 +39517,8 @@ javascript, 2d/3d graphics, and PHP3/MySQL. All pages are generated from
a database.
@c Added 990614; EMAIL: downey@image.dk (Rune Madsen)
@item @uref{http://www.softwarezrus.com/, Softwarezrus.com}
Ecommerce site that is selling computers.
@end itemize
@cindex consultants, list of
......@@ -39782,6 +39815,10 @@ OLEDB handler for @code{MySQL}. By SWsoft.
Examples and documentation for MyOLEDB. By SWsoft.
@item @uref{http://www.mysql.com/Downloads/Win32/Myoledb.zip, Myoledb.zip}
Source for MyOLEDB. By SWsoft.
@item @uref{http://www.mysql.com/Downloads/Win32/MyOLEDB.chm, MyOLEDB.chm}
Help files for MyOLEDB.
@item @uref{http://www.mysql.com/Downloads/Win32/libmyodbc.zip, libmyodbc.zip}
Static MyODBC library used for build MyOLEDB. Based on MyODBC code.
@end itemize
@cindex C++
......@@ -40950,6 +40987,13 @@ not yet 100 % confident in this code.
@appendixsubsec Changes in release 3.23.33
@itemize bullet
@item
Fixed 'no found rows' bug in @code{MyISAM} tables when a @code{BLOB} was
first part of a multi-part key.
@item
Fixed bug where @code{CASE} didn't work with @code{GROUP BY}.
@item
Added option @code{--sort-recover} to @code{myisamchk}.
@item
@code{myisamchk -S} and @code{OPTIMIZE TABLE} now works on Windows.
@item
Fixed bug when using @code{DISTINCT} on results from functions that refered to
......@@ -28,7 +28,7 @@
#include <my_pthread.h> /* because of signal() */
#endif
#define ADMIN_VERSION "8.14"
#define ADMIN_VERSION "8.15"
#define MAX_MYSQL_VAR 64
#define MAX_TIME_TO_WAIT 3600 /* Wait for shutdown */
#define MAX_TRUNC_LENGTH 3
......@@ -404,7 +404,11 @@ static my_bool execute_commands(MYSQL *mysql,int argc, char **argv)
}
sprintf(buff,"create database %.*s",FN_REFLEN,argv[1]);
if (mysql_query(mysql,buff))
{
my_printf_error(0,"Create failed; error: '%-.200s'",MYF(ME_BELL),
mysql_error(mysql));
return 1;
}
else
{
argc--; argv++;
......@@ -762,7 +766,7 @@ static my_bool execute_commands(MYSQL *mysql,int argc, char **argv)
mysql->reconnect=1; /* Automatic reconnect is default */
break;
default:
my_printf_error(0,"Unknown command: '%s'",MYF(ME_BELL),argv[0]);
my_printf_error(0,"Unknown command: '%-.60s'",MYF(ME_BELL),argv[0]);
return 1;
}
}
......
......@@ -324,7 +324,7 @@ typedef struct st_mi_check_param
uint testflag;
uint8 language;
my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
my_bool retry_repair,retry_without_quick;
my_bool retry_repair,retry_without_quick, force_sort;
char temp_filename[FN_REFLEN],*isam_file_name,*tmpdir;
int tmpfile_createflag;
myf myf_rw;
......
......@@ -485,7 +485,7 @@ static void free_old_query(MYSQL *mysql)
DBUG_VOID_RETURN;
}
#ifdef HAVE_GETPWUID
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
struct passwd *getpwuid(uid_t);
char* getlogin(void);
#endif
......@@ -501,14 +501,6 @@ static void read_user_name(char *name)
#ifdef HAVE_GETPWUID
struct passwd *skr;
const char *str;
/*#ifdef __cplusplus
extern "C" struct passwd *getpwuid(uid_t);
extern "C" { char* getlogin(void); }
#else
char * getlogin();
struct passwd *getpwuid(uid_t);
#endif
*/
if ((str=getlogin()) == NULL)
{
if ((skr=getpwuid(geteuid())) != NULL)
......
......@@ -1464,6 +1464,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
my_off_t index_pos[MI_MAX_POSSIBLE_KEY];
uint r_locks,w_locks;
MYISAM_SHARE *share=info->s;
MI_STATE_INFO old_state;
DBUG_ENTER("sort_index");
if (!(param->testflag & T_SILENT))
......@@ -1502,9 +1503,10 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
/* Flush key cache for this file if we are calling this outside myisamchk */
flush_key_blocks(share->kfile, FLUSH_IGNORE_CHANGED);
/* Put same locks as old file */
share->state.version=(ulong) time((time_t*) 0);
old_state=share->state; /* save state if not stored */
r_locks=share->r_locks; w_locks=share->w_locks;
/* Put same locks as old file */
share->r_locks=share->w_locks=0;
(void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
VOID(my_close(share->kfile,MYF(MY_WME)));
......@@ -1518,6 +1520,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
_mi_readinfo(info,F_WRLCK,0); /* Will lock the table */
info->lock_type=F_WRLCK;
share->r_locks=r_locks; share->w_locks=w_locks;
share->state=old_state; /* Restore old state */
info->state->key_file_length=param->new_file_pos;
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
......@@ -3144,7 +3147,7 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows)
*/
my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
my_bool force __attribute__((unused)))
my_bool force)
{
MYISAM_SHARE *share=info->s;
uint i;
......@@ -3160,7 +3163,8 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
is very time-consuming process, it's better to leave it to repair stage
but this repair shouldn't be repair_by_sort (serg)
*/
if (mi_too_big_key_for_sort(key,rows) || (key->flag & HA_FULLTEXT))
if (!force && mi_too_big_key_for_sort(key,rows) ||
(key->flag & HA_FULLTEXT))
return FALSE;
}
return TRUE;
......
......@@ -37,7 +37,8 @@ int mi_delete_table(const char *name)
#ifdef USE_RAID
{
MI_INFO *info;
if (!(info=mi_open(name, O_RDONLY, 0)))
/* we use 'open_for_repair' to be able to delete a crashed table */
if (!(info=mi_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR)))
DBUG_RETURN(my_errno);
raid_type = info->s->base.raid_type;
raid_chunks = info->s->base.raid_chunks;
......
......@@ -184,8 +184,9 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
/* Length of key-part used with mi_rkey() always 2 */
uint tmp_length=uint2korr(pos);
k_length-= 2+length;
set_if_smaller(length,tmp_length);
set_if_smaller(length,tmp_length); /* Safety */
store_key_length_inc(key,length);
old+=2; /* Skipp length */
memcpy((byte*) key, pos+2,(size_t) length);
key+= length;
continue;
......
......@@ -189,6 +189,7 @@ static struct option long_options[] =
{"silent", no_argument, 0, 's'},
{"sort-index", no_argument, 0, 'S'},
{"sort-records", required_argument, 0, 'R'},
{"sort-recover", no_argument, 0, 'n'},
{"tmpdir", required_argument, 0, 't'},
{"update-state", no_argument, 0, 'U'},
{"unpack", no_argument, 0, 'u'},
......@@ -200,7 +201,7 @@ static struct option long_options[] =
static void print_version(void)
{
printf("%s Ver 1.41 for %s at %s\n",my_progname,SYSTEM_TYPE,
printf("%s Ver 1.42 for %s at %s\n",my_progname,SYSTEM_TYPE,
MACHINE_TYPE);
}
......@@ -255,9 +256,11 @@ static void usage(void)
myisamchk repairs the table a symlink points at.\n\
-r, --recover Can fix almost anything except unique keys that aren't\n\
unique.\n\
-n, --sort-recover Force recovering with sorting even if the temporary\n\
file would be very big.\n\
-o, --safe-recover Uses old recovery method; Slower than '-r' but can\n\
handle a couple of cases where '-r' reports that it can't\n\
fix the data file.\n\
handle a couple of cases where '-r' reports that it\n\
can't fix the data file.\n\
--character-sets-dir=...\n\
Directory where character sets are\n\
--set-character-set=name\n\
......@@ -306,7 +309,8 @@ static void get_options(register int *argc,register char ***argv)
set_all_changeable_vars(changeable_vars);
if (isatty(fileno(stdout)))
check_param.testflag|=T_WRITE_LOOP;
while ((c=getopt_long(*argc,*argv,"aBcCdeifF?lqrmosSTuUvVw#:b:D:k:O:R:A::t:",
while ((c=getopt_long(*argc,*argv,
"aBcCdeifF?lqrmnosSTuUvVw#:b:D:k:O:R:A::t:",
long_options, &option_index)) != EOF)
{
switch(c) {
......@@ -374,8 +378,13 @@ static void get_options(register int *argc,register char ***argv)
break;
case 'o':
check_param.testflag= (check_param.testflag & ~T_REP_BY_SORT) | T_REP;
check_param.force_sort=0;
my_disable_async_io=1; /* More safety */
break;
case 'n':
check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT;
check_param.force_sort=1;
break;
case 'q':
check_param.opt_rep_quick++;
break;
......@@ -683,7 +692,8 @@ static int myisamchk(MI_CHECK *param, my_string filename)
if ((param->testflag & T_REP_BY_SORT) &&
(share->state.key_map ||
(rep_quick && !param->keys_in_use && !recreate)) &&
mi_test_if_sort_rep(info, info->state->records, 1))
mi_test_if_sort_rep(info, info->state->records,
check_param.force_sort))
{
error=mi_repair_by_sort(&check_param,info,fixed_name,rep_quick);
state_updated=1;
......
......@@ -32,3 +32,11 @@ case when 1>0 then "TRUE" else "FALSE" END
TRUE
case when 1<0 then "TRUE" else "FALSE" END
FALSE
fcase count(*)
0 2
2 1
3 1
fcase count(*)
nothing 2
one 1
two 1
......@@ -186,3 +186,9 @@ extract(SECOND FROM "1999-01-02 10:11:12")
12
ctime hour(ctime)
2001-01-12 12:23:40 12
monthname(date)
NULL
January
monthname(date)
NULL
January
......@@ -257,3 +257,7 @@ hello
hello word
count(*)
2
foobar boggle
fish 10
foobar boggle
fish 10
......@@ -13,6 +13,8 @@ t
9999-12-31 23:59:59
Table Op Msg_type Msg_text
test.t1 optimize status OK
Table Op Msg_type Msg_text
test.t1 check status OK
t
2000-01-01 00:00:00
2069-12-31 00:00:00
......
......@@ -2,6 +2,8 @@
# Testing of CASE
#
drop table if exists t1;
select CASE "b" when "a" then 1 when "b" then 2 END;
select CASE "c" when "a" then 1 when "b" then 2 END;
select CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END;
......@@ -19,3 +21,12 @@ select (case 1/0 when "a" then "true" END) | 0;
select (case 1/0 when "a" then "true" END) + 0.0;
select case when 1>0 then "TRUE" else "FALSE" END;
select case when 1<0 then "TRUE" else "FALSE" END;
#
# Test bug when using GROUP BY on CASE
#
create table t1 (a int);
insert into t1 values(1),(2),(3),(4);
select case a when 1 then 2 when 2 then 3 else 0 end as fcase, count(*) from t1 group by fcase;
select case a when 1 then "one" when 2 then "two" else "nothing" end as fcase, count(*) from t1 group by fcase;
drop table t1;
#
# time functions
#
drop table if exists t1,t2;
select from_days(to_days("960101")),to_days(960201)-to_days("19960101"),to_days(date_add(curdate(), interval 1 day))-to_days(curdate()),weekday("1997-11-29");
select period_add("9602",-12),period_diff(199505,"9404") ;
select now()-now(),weekday(curdate())-weekday(now()),unix_timestamp()-unix_timestamp(now());
......@@ -99,9 +101,21 @@ select extract(MINUTE FROM "10:11:12");
select extract(MINUTE_SECOND FROM "10:11:12");
select extract(SECOND FROM "1999-01-02 10:11:12");
drop table if exists t1;
create table t1 (ctime varchar(20));
insert into t1 values ('2001-01-12 12:23:40');
select ctime, hour(ctime) from t1;
drop table t1;
#
# Test bug with monthname() and NULL
#
create table t1 (id int);
create table t2 (id int, date date);
insert into t1 values (1);
insert into t2 values (1, "0000-00-00");
insert into t1 values (2);
insert into t2 values (2, "2000-01-01");
select monthname(date) from t1 inner join t2 on t1.id = t2.id;
select monthname(date) from t1 inner join t2 on t1.id = t2.id order by t1.id;
drop table t1,t2;
......@@ -239,3 +239,13 @@ INSERT INTO t1 VALUES (0,'traktor','1111111111111');
INSERT INTO t1 VALUES (1,'traktor','1111111111111111111111111');
select count(*) from t1 where f2='traktor';
drop table t1;
#
# Test of found bug when blob is first key part
#
create table t1 (foobar tinyblob not null, boggle smallint not null, key (foobar(32), boggle));
insert into t1 values ('fish', 10),('bear', 20);
select foobar, boggle from t1 where foobar = 'fish';
select foobar, boggle from t1 where foobar = 'fish' and boggle = 10;
drop table t1;
#
# testing different DATETIME ranges
#
drop table if exists t1;
create table t1 (t datetime);
insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959);
select * from t1;
delete from t1 where t > 0;
optimize table t1;
check table t1;
insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959");
select * from t1;
drop table t1;
......
......@@ -17,6 +17,13 @@
/*
Handling of uchar arrays as large bitmaps.
We assume that the size of the used bitmap is less than ~(uint) 0
TODO:
create an unique structure for this that includes the mutex and bitmap size
make a init function that will allocate the bitmap and init the mutex
make an end function that will free everything
*/
#include "mysys_priv.h"
......@@ -24,37 +31,51 @@
pthread_mutex_t LOCK_bitmap;
void bitmap_set_bit(uchar *bitmap, uint bitmap_size, uint bitmap_bit) {
if((bitmap_bit != MY_BIT_NONE) && (bitmap_bit < bitmap_size*8)) {
void bitmap_set_bit(uchar *bitmap, uint bitmap_size, uint bitmap_bit)
{
if (bitmap_bit < bitmap_size*8)
{
pthread_mutex_lock(&LOCK_bitmap);
bitmap[bitmap_bit / 8] |= (1 << bitmap_bit % 8);
bitmap[bitmap_bit / 8] |= (1 << (bitmap_bit & 7));
pthread_mutex_unlock(&LOCK_bitmap);
};
};
}
}
uint bitmap_set_next(uchar *bitmap, uint bitmap_size) {
uint bitmap_set_next(uchar *bitmap, uint bitmap_size)
{
uint bit_found = MY_BIT_NONE;
int i, b;
uint i;
pthread_mutex_lock(&LOCK_bitmap);
for(i=0; (i<bitmap_size) && (bit_found==MY_BIT_NONE); i++) {
if(bitmap[i] == 0xff) continue;
for(b=0; (b<8) && (bit_found==MY_BIT_NONE); b++)
if((bitmap[i] & 1<<b) == 0) {
bit_found = (i*8)+b;
bitmap[i] |= 1<<b;
};
};
for (i=0; i < bitmap_size ; i++, bitmap++)
{
if (*bitmap != 0xff)
{ /* Found slot with free bit */
uint b;
for (b=0; ; b++)
{
if (!(*bitmap & (1 << b)))
{
*bitmap |= 1<<b;
bit_found = (i*8)+b;
break;
}
}
break; /* Found bit */
}
}
pthread_mutex_unlock(&LOCK_bitmap);
return bit_found;
};
}
void bitmap_clear_bit(uchar *bitmap, uint bitmap_size, uint bitmap_bit) {
if((bitmap_bit != MY_BIT_NONE) && (bitmap_bit < bitmap_size*8)) {
void bitmap_clear_bit(uchar *bitmap, uint bitmap_size, uint bitmap_bit)
{
if (bitmap_bit < bitmap_size*8)
{
pthread_mutex_lock(&LOCK_bitmap);
bitmap[bitmap_bit / 8] &= ~(1 << bitmap_bit % 8);
bitmap[bitmap_bit / 8] &= ~ (1 << (bitmap_bit & 7));
pthread_mutex_unlock(&LOCK_bitmap);
};
};
}
}
This diff is collapsed.
......@@ -721,17 +721,41 @@ double Item_func_case::val()
bool
Item_func_case::fix_fields(THD *thd,TABLE_LIST *tables)
{
if (first_expr && first_expr->fix_fields(thd,tables) ||
else_expr && else_expr->fix_fields(thd,tables))
return 1;
if (Item_func::fix_fields(thd,tables))
return 1;
if (first_expr)
{
used_tables_cache|=(first_expr)->used_tables();
const_item_cache&= (first_expr)->const_item();
}
if (else_expr)
{
used_tables_cache|=(else_expr)->used_tables();
const_item_cache&= (else_expr)->const_item();
}
if (!else_expr || else_expr->maybe_null)
maybe_null=1; // The result may be NULL
return 0;
}
void Item_func_case::update_used_tables()
{
Item_func::update_used_tables();
if (first_expr)
{
used_tables_cache|=(first_expr)->used_tables();
const_item_cache&= (first_expr)->const_item();
}
if (else_expr)
{
used_tables_cache|=(else_expr)->used_tables();
const_item_cache&= (else_expr)->const_item();
}
}
void Item_func_case::fix_length_and_dec()
{
......@@ -750,6 +774,7 @@ void Item_func_case::fix_length_and_dec()
}
}
/* TODO: Fix this so that it prints the whole CASE expression */
void Item_func_case::print(String *str)
{
......
......@@ -254,6 +254,7 @@ class Item_func_case :public Item_func
longlong val_int();
String *val_str(String *);
void fix_length_and_dec();
void update_used_tables();
enum Item_result result_type () const { return cached_result_type; }
const char *func_name() const { return "case"; }
void print(String *str);
......
......@@ -135,7 +135,11 @@ String* Item_func_monthname::val_str(String* str)
{
uint month=(uint) Item_func_month::val_int();
if (!month) // This is also true for NULL
{
null_value=1;
return (String*) 0;
}
null_value=0;
return &month_names[month-1];
}
......
......@@ -28,6 +28,8 @@
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *path,
uint level);
/* db-name is already validated when we come here */
void mysql_create_db(THD *thd, char *db, uint create_options)
{
char path[FN_REFLEN+16];
......@@ -35,11 +37,6 @@ void mysql_create_db(THD *thd, char *db, uint create_options)
long result=1;
DBUG_ENTER("mysql_create_db");
if (!stripp_sp(db) || check_db_name(db))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, db);
DBUG_VOID_RETURN;
}
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
/* Check directory */
......@@ -96,6 +93,8 @@ static TYPELIB deletable_extentions=
{array_elements(del_exts)-1,"del_exts", del_exts};
/* db-name is already validated when we come here */
void mysql_rm_db(THD *thd,char *db,bool if_exists)
{
long deleted=0;
......@@ -103,12 +102,6 @@ void mysql_rm_db(THD *thd,char *db,bool if_exists)
MY_DIR *dirp;
DBUG_ENTER("mysql_rm_db");
if (!stripp_sp(db) || check_db_name(db))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, db);
DBUG_VOID_RETURN;
}
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
VOID(pthread_mutex_lock(&LOCK_open));
......
......@@ -510,7 +510,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
int error = 0;
DBUG_ENTER("mysql_table_dump");
db = (db && db[0]) ? db : thd->db;
if(!(table_list = (TABLE_LIST*) sql_calloc(sizeof(TABLE_LIST))))
if (!(table_list = (TABLE_LIST*) sql_calloc(sizeof(TABLE_LIST))))
DBUG_RETURN(1); // out of memory
table_list->db = db;
table_list->real_name = table_list->name = tbl_name;
......@@ -518,9 +518,14 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
table_list->next = 0;
remove_escape(table_list->real_name);
if(!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT)))
if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT)))
DBUG_RETURN(1);
if (!db || check_db_name(db))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL");
goto err;
}
if (check_access(thd, SELECT_ACL, db, &table_list->grant.privilege))
goto err;
if (grant_option && check_grant(thd, SELECT_ACL, table_list))
......@@ -710,6 +715,12 @@ bool do_command(THD *thd)
case COM_CREATE_DB:
{
char *db=thd->strdup(packet+1);
// null test to handle EOM
if (!db || !stripp_sp(db) || check_db_name(db))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
}
if (check_access(thd,CREATE_ACL,db,0,1))
break;
mysql_log.write(thd,command,packet+1);
......@@ -719,6 +730,12 @@ bool do_command(THD *thd)
case COM_DROP_DB:
{
char *db=thd->strdup(packet+1);
// null test to handle EOM
if (!db || !stripp_sp(db) || check_db_name(db))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
}
if (check_access(thd,DROP_ACL,db,0,1) || end_active_trans(thd))
break;
mysql_log.write(thd,command,db);
......@@ -1503,10 +1520,10 @@ mysql_execute_command(void)
goto error; /* purecov: inspected */
}
remove_escape(db); // Fix escaped '_'
if (strlen(db) > NAME_LEN)
if (check_db_name(db))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, db);
goto error;
net_printf(&thd->net,ER_WRONG_DB_NAME, db);
goto error;
}
if (check_access(thd,SELECT_ACL,db,&thd->col_access))
goto error; /* purecov: inspected */
......@@ -1666,6 +1683,11 @@ mysql_execute_command(void)
break;
case SQLCOM_CREATE_DB:
{
if (!stripp_sp(lex->name) || check_db_name(lex->name))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
break;
}
if (check_access(thd,CREATE_ACL,lex->name,0,1))
break;
mysql_create_db(thd,lex->name,lex->create_info.options);
......@@ -1673,6 +1695,11 @@ mysql_execute_command(void)
}
case SQLCOM_DROP_DB:
{
if (!stripp_sp(lex->name) || check_db_name(lex->name))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
break;
}
if (check_access(thd,DROP_ACL,lex->name,0,1) ||
end_active_trans(thd))
break;
......@@ -1887,12 +1914,6 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
if (db == any_db)
return FALSE; // Allow select on anything
if (strlen(db) > NAME_LEN || check_db_name(db))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, db);
return TRUE;
}
if (db && (!thd->db || strcmp(db,thd->db)))
db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
thd->priv_user, db); /* purecov: inspected */
......@@ -1970,7 +1991,8 @@ static bool check_db_used(THD *thd,TABLE_LIST *tables)
}
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list)
static bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list)
{
int error=0;
if (table_list)
......@@ -2463,8 +2485,8 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
DBUG_RETURN(0); // End of memory
alias_str= alias ? alias->str : table->table.str;
if (table->table.length > NAME_LEN ||
table->db.str && table->db.length > NAME_LEN ||
check_table_name(table->table.str,table->table.length))
check_table_name(table->table.str,table->table.length) ||
table->db.str && check_db_name(table->db.str))
{
net_printf(&thd->net,ER_WRONG_TABLE_NAME,table->table.str);
DBUG_RETURN(0);
......
......@@ -1033,7 +1033,7 @@ char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr)
bool check_db_name(const char *name)
{
const char *start=end;
const char *start=name;
while (*name)
{
#if defined(USE_MB) && defined(USE_MB_IDENT)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment