Commit 0fb07014 authored by paul@teton.kitebird.com's avatar paul@teton.kitebird.com

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

into teton.kitebird.com:/home/paul/mysql-4.1
parents 882fad23 d3f2ad20
......@@ -28,6 +28,11 @@
#include <my_sys.h>
#include <m_string.h>
#include <errno.h>
#ifndef EOVERFLOW
#define EOVERFLOW 84
#endif
#ifdef MSDOS
#include <share.h> /* Neaded for sopen() */
#endif
......
......@@ -60,6 +60,7 @@ log. */
#define OS_FILE_CREATE 52
#define OS_FILE_OVERWRITE 53
#define OS_FILE_OPEN_RAW 54
#define OS_FILE_CREATE_PATH 55
#define OS_FILE_READ_ONLY 333
#define OS_FILE_READ_WRITE 444
......@@ -228,7 +229,9 @@ os_file_create_simple(
string */
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
(if does not exist, error), or OS_FILE_CREATE if a new
file is created (if exists, error) */
file is created (if exists, error), or
OS_FILE_CREATE_PATH if new file (if exists, error) and
subdirectories along its path are created (if needed)*/
ulint access_type,/* in: OS_FILE_READ_ONLY or OS_FILE_READ_WRITE */
ibool* success);/* out: TRUE if succeed, FALSE if error */
/********************************************************************
......@@ -421,6 +424,59 @@ os_file_write(
ulint offset_high,/* in: most significant 32 bits of
offset */
ulint n); /* in: number of bytes to write */
/***********************************************************************
Check the existence and type of the given file. */
ibool
os_file_status(
/*===========*/
/* out: TRUE if call succeeded */
char * path, /* in: pathname of the file */
ibool * exists, /* out: TRUE if file exists */
os_file_type_t* type); /* out: type of the file (if it exists) */
/********************************************************************
The function os_file_dirname returns a directory component of a
null-terminated pathname string. In the usual case, dirname returns
the string up to, but not including, the final '/', and basename
is the component following the final '/'. Trailing '/' charac­
ters are not counted as part of the pathname.
If path does not contain a slash, dirname returns the string ".".
Concatenating the string returned by dirname, a "/", and the basename
yields a complete pathname.
The return value is a copy of the directory component of the pathname.
The copy is allocated from heap. It is the caller responsibility
to free it after it is no longer needed.
The following list of examples (taken from SUSv2) shows the strings
returned by dirname and basename for different paths:
path dirname basename
"/usr/lib" "/usr" "lib"
"/usr/" "/" "usr"
"usr" "." "usr"
"/" "/" "/"
"." "." "."
".." "." ".."
*/
char*
os_file_dirname(
/*============*/
/* out, own: directory component of the
pathname */
char* path); /* in: pathname */
/********************************************************************
Creates all missing subdirectories along the given path. */
ibool
os_file_create_subdirs_if_needed(
/*=============================*/
/* out: TRUE if call succeeded
FALSE otherwise */
char* path); /* in: path name */
/****************************************************************************
Initializes the asynchronous io system. Creates separate aio array for
non-ibuf read and write, a third aio array for the ibuf i/o, with just one
......
......@@ -96,6 +96,15 @@ ut_str_catenate(
char* str1, /* in: null-terminated string */
char* str2); /* in: null-terminated string */
/**************************************************************************
Return a copy of the given string. The returned string must be freed
using mem_free. */
char*
ut_strdup(
/*======*/
/* out, own: cnull-terminated string */
char* str); /* in: null-terminated string */
/**************************************************************************
Checks if a null-terminated string contains a certain character. */
ibool
......
......@@ -6,6 +6,8 @@ The interface to the operating system file i/o primitives
Created 10/21/1995 Heikki Tuuri
*******************************************************/
#include <sys/stat.h>
#include "os0file.h"
#include "os0sync.h"
#include "os0thread.h"
......@@ -716,7 +718,9 @@ os_file_create_simple(
string */
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
(if does not exist, error), or OS_FILE_CREATE if a new
file is created (if exists, error) */
file is created (if exists, error), or
OS_FILE_CREATE_PATH if new file (if exists, error) and
subdirectories along its path are created (if needed)*/
ulint access_type,/* in: OS_FILE_READ_ONLY or OS_FILE_READ_WRITE */
ibool* success)/* out: TRUE if succeed, FALSE if error */
{
......@@ -734,6 +738,14 @@ os_file_create_simple(
create_flag = OPEN_EXISTING;
} else if (create_mode == OS_FILE_CREATE) {
create_flag = CREATE_NEW;
} else if (create_mode == OS_FILE_CREATE_PATH) {
/* create subdirs along the path if needed */
*success = os_file_create_subdirs_if_needed(name);
if (!*success) {
ut_error;
}
create_flag = CREATE_NEW;
create_mode = OS_FILE_CREATE;
} else {
create_flag = 0;
ut_error;
......@@ -787,6 +799,14 @@ os_file_create_simple(
}
} else if (create_mode == OS_FILE_CREATE) {
create_flag = O_RDWR | O_CREAT | O_EXCL;
} else if (create_mode == OS_FILE_CREATE_PATH) {
/* create subdirs along the path if needed */
*success = os_file_create_subdirs_if_needed(name);
if (!*success) {
return (-1);
}
create_flag = O_RDWR | O_CREAT | O_EXCL;
create_mode = OS_FILE_CREATE;
} else {
create_flag = 0;
ut_error;
......@@ -2114,6 +2134,185 @@ os_file_write(
#endif
}
/***********************************************************************
Check the existence and type of the given file. */
ibool
os_file_status(
/*===========*/
/* out: TRUE if call succeeded */
char* path, /* in: pathname of the file */
ibool* exists, /* out: TRUE if file exists */
os_file_type_t* type) /* out: type of the file (if it exists) */
{
#ifdef __WIN__
int ret;
struct _stat statinfo;
ret = _stat(path, &statinfo);
if (ret && (errno == ENOENT || errno == ENOTDIR)) {
/* file does not exist */
*exists = FALSE;
return(TRUE);
} else if (ret) {
/* file exists, but stat call failed */
os_file_handle_error_no_exit(0, path, "stat");
return(FALSE);
}
if (_S_IFDIR & statinfo.st_mode) {
*type = OS_FILE_TYPE_DIR;
} else if (_S_IFREG & statinfo.st_mode) {
*type = OS_FILE_TYPE_FILE;
} else {
*type = OS_FILE_TYPE_UNKNOWN;
}
*exists = TRUE;
return(TRUE);
#else
int ret;
struct stat statinfo;
ret = stat(path, &statinfo);
if (ret && (errno == ENOENT || errno == ENOTDIR)) {
/* file does not exist */
*exists = FALSE;
return(TRUE);
} else if (ret) {
/* file exists, but stat call failed */
os_file_handle_error_no_exit(0, path, "stat");
return(FALSE);
}
if (S_ISDIR(statinfo.st_mode)) {
*type = OS_FILE_TYPE_DIR;
} else if (S_ISLNK(statinfo.st_mode)) {
*type = OS_FILE_TYPE_LINK;
} else if (S_ISREG(statinfo.st_mode)) {
*type = OS_FILE_TYPE_FILE;
} else {
*type = OS_FILE_TYPE_UNKNOWN;
}
*exists = TRUE;
return(TRUE);
#endif
}
/* path name separator character */
#ifdef __WIN__
# define OS_FILE_PATH_SEPARATOR '\\'
#else
# define OS_FILE_PATH_SEPARATOR '/'
#endif
/********************************************************************
The function os_file_dirname returns a directory component of a
null-terminated pathname string. In the usual case, dirname returns
the string up to, but not including, the final '/', and basename
is the component following the final '/'. Trailing '/' charac­
ters are not counted as part of the pathname.
If path does not contain a slash, dirname returns the string ".".
Concatenating the string returned by dirname, a "/", and the basename
yields a complete pathname.
The return value is a copy of the directory component of the pathname.
The copy is allocated from heap. It is the caller responsibility
to free it after it is no longer needed.
The following list of examples (taken from SUSv2) shows the strings
returned by dirname and basename for different paths:
path dirname basename
"/usr/lib" "/usr" "lib"
"/usr/" "/" "usr"
"usr" "." "usr"
"/" "/" "/"
"." "." "."
".." "." ".."
*/
char*
os_file_dirname(
/*============*/
/* out, own: directory component of the
pathname */
char* path) /* in: pathname */
{
char* dir;
int i, length, last_slash;
/* find the offset of the last slash */
length = ut_strlen(path);
for (i = length - 1; i >= 0 && path[i] != OS_FILE_PATH_SEPARATOR; i++);
last_slash = i;
if (last_slash < 0) {
/* no slash in the path, return "." */
return(ut_strdup((char*)"."));
}
/* ok, there is a slash */
if (last_slash == 0) {
/* last slash is the first char of the path */
return(ut_strdup((char*)"/"));
}
/* non-trivial directory component */
dir = ut_strdup(path);
dir[last_slash] = 0;
return(dir);
}
/********************************************************************
Creates all missing subdirectories along the given path. */
ibool
os_file_create_subdirs_if_needed(
/*=============================*/
/* out: TRUE if call succeeded
FALSE otherwise */
char* path) /* in: path name */
{
char* subdir;
static char rootdir[2] = { OS_FILE_PATH_SEPARATOR, 0 };
ibool success, subdir_exists;
os_file_type_t type;
subdir = os_file_dirname(path);
if (0 == strcmp(subdir, rootdir) || 0 == strcmp(subdir, ".")) {
/* subdir is root or cwd, nothing to do */
ut_free(subdir);
return(TRUE);
}
/* test if subdir exists */
success = os_file_status(subdir, &subdir_exists, &type);
if (success && !subdir_exists) {
/* subdir does not exist, create it */
success = os_file_create_subdirs_if_needed(subdir);
if (!success) {
ut_free(subdir);
return(FALSE);
}
success = os_file_create_directory(subdir, FALSE);
}
ut_free(subdir);
return(success);
}
/********************************************************************
Returns a pointer to the nth slot in the aio array. */
static
......
......@@ -282,3 +282,27 @@ ut_str_contains(
return(FALSE);
}
/**************************************************************************
Return a copy of the given string. The returned string must be freed
using mem_free. */
char*
ut_strdup(
/*======*/
/* out, own: cnull-terminated string */
char* str) /* in: null-terminated string */
{
ulint len;
char* copy;
len = ut_strlen(str);
copy = mem_alloc(len + 1);
ut_memcpy(copy, str, len);
copy[len] = 0;
return(copy);
}
......@@ -33,8 +33,8 @@ EXPORTS
myodbc_remove_escape
mysql_affected_rows
mysql_autocommit
mysql_bind_param
mysql_bind_result
mysql_stmt_bind_param
mysql_stmt_bind_result
mysql_change_user
mysql_character_set_name
mysql_close
......@@ -46,9 +46,9 @@ EXPORTS
mysql_errno
mysql_error
mysql_escape_string
mysql_execute
mysql_fetch
mysql_fetch_column
mysql_stmt_execute
mysql_stmt_fetch
mysql_stmt_fetch_column
mysql_fetch_field
mysql_fetch_field_direct
mysql_fetch_fields
......@@ -78,11 +78,11 @@ EXPORTS
mysql_num_rows
mysql_odbc_escape_string
mysql_options
mysql_param_count
mysql_param_result
mysql_stmt_param_count
mysql_stmt_param_metadata
mysql_ping
mysql_prepare
mysql_get_metadata
mysql_stmt_result_metadata
mysql_query
mysql_read_query_result
mysql_real_connect
......@@ -93,7 +93,7 @@ EXPORTS
mysql_row_seek
mysql_row_tell
mysql_select_db
mysql_send_long_data
mysql_stmt_send_long_data
mysql_send_query
mysql_shutdown
mysql_ssl_set
......
......@@ -19,6 +19,9 @@ hex(inet_aton('127.1'))
select hex(inet_aton('127.1.1'));
hex(inet_aton('127.1.1'))
7F010001
select length(uuid()), charset(uuid()), length(unhex(replace(uuid(),_utf8'-',_utf8'')));
length(uuid()) charset(uuid()) length(unhex(replace(uuid(),_utf8'-',_utf8'')))
36 utf8 16
select length(format('nan', 2)) > 0;
length(format('nan', 2)) > 0
1
......
......@@ -1686,3 +1686,10 @@ id select_type table type possible_keys key key_len ref rows Extra
Warnings:
Note 1003 select high_priority test.a.id AS `id`,test.a.text AS `text`,test.b.id AS `id`,test.b.text AS `text`,test.c.id AS `id`,test.c.text AS `text` from test.t1 a left join test.t2 b on(((test.a.id = test.b.id) or isnull(test.b.id))) join test.t1 c where (if(isnull(test.b.id),1000,test.b.id) = test.c.id)
drop table t1,t2;
create table t1 (a int);
insert into t1 values (1);
explain select benchmark(1000, (select a from t1 where a=sha(rand())));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 1
drop table t1;
......@@ -407,12 +407,12 @@ select @a, @b;
@a @b
2 1
set @@global.global.key_buffer_size= 1;
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size= 1' at line 1
set GLOBAL global.key_buffer_size= 1;
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size= 1' at line 1
SELECT @@global.global.key_buffer_size;
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
SELECT @@global.session.key_buffer_size;
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
SELECT @@global.local.key_buffer_size;
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'key_buffer_size' at line 1
......@@ -12,6 +12,8 @@ select hex(inet_aton('127'));
select hex(inet_aton('127.1'));
select hex(inet_aton('127.1.1'));
select length(uuid()), charset(uuid()), length(unhex(replace(uuid(),_utf8'-',_utf8'')));
#
# Test for core dump with nan
#
......
......@@ -1089,3 +1089,11 @@ insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, '
select * from t1 a left join t2 b on (a.id=b.id or b.id is null) join t1 c on (if(isnull(b.id), 1000, b.id)=c.id);
explain extended select * from t1 a left join t2 b on (a.id=b.id or b.id is null) join t1 c on (if(isnull(b.id), 1000, b.id)=c.id);
drop table t1,t2;
#
# Static tables & rund() in subqueries
#
create table t1 (a int);
insert into t1 values (1);
explain select benchmark(1000, (select a from t1 where a=sha(rand())));
drop table t1;
......@@ -289,13 +289,13 @@ select @a, @b;
#
# Bug#2586:Disallow global/session/local as structured var. instance names
#
--error 1149
--error 1064
set @@global.global.key_buffer_size= 1;
--error 1149
--error 1064
set GLOBAL global.key_buffer_size= 1;
--error 1149
--error 1064
SELECT @@global.global.key_buffer_size;
--error 1149
--error 1064
SELECT @@global.session.key_buffer_size;
--error 1149
--error 1064
SELECT @@global.local.key_buffer_size;
......@@ -107,7 +107,7 @@ bool test_if_int(const char *str, int length, const char *int_end,
return 1;
}
#ifdef NOT_USED
static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
{
cs= system_charset_info; // QQ move test_if_real into CHARSET_INFO struct
......@@ -159,7 +159,7 @@ static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
}
return 1;
}
#endif
static inline uint field_length_without_space(const char *ptr, uint length)
{
......@@ -2273,7 +2273,7 @@ int Field_float::store(const char *from,uint len,CHARSET_INFO *cs)
int err;
char *end;
double nr= my_strntod(cs,(char*) from,len,&end,&err);
if (!err && (!current_thd->count_cuted_fields || end-from==len))
if (!err && (!current_thd->count_cuted_fields || end-from==(int)len))
{
return Field_float::store(nr);
}
......@@ -2570,8 +2570,8 @@ int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
{
int err;
char *end;
double nr= my_strntod(cs,(char*) from,len,&end,&err);
if (!err && (!current_thd->count_cuted_fields || end-from==len))
double nr= my_strntod(cs,(char*) from,len,&end,&err);
if (!err && (!current_thd->count_cuted_fields || end-from==(int)len))
{
return Field_double::store(nr);
}
......
......@@ -964,6 +964,7 @@ void Item_func_rand::fix_length_and_dec()
{
decimals=NOT_FIXED_DEC;
max_length=float_length(decimals);
used_tables_cache|= RAND_TABLE_BIT;
if (arg_count)
{ // Only use argument once in query
uint32 tmp= (uint32) (args[0]->val_int());
......@@ -989,6 +990,12 @@ void Item_func_rand::fix_length_and_dec()
}
}
void Item_func_rand::update_used_tables()
{
Item_real_func::update_used_tables();
used_tables_cache|= RAND_TABLE_BIT;
}
double Item_func_rand::val()
{
......@@ -2967,12 +2974,6 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
(uint) strlen(server_version),
system_charset_info);
if (name.str && component.str && check_reserved_words(&name))
{
net_printf(thd, ER_SYNTAX_ERROR);
return 0;
}
Item *item;
sys_var *var;
char buff[MAX_SYS_VAR_LENGTH*2+4+8], *pos;
......
......@@ -512,7 +512,7 @@ class Item_func_rand :public Item_real_func
double val();
const char *func_name() const { return "rand"; }
bool const_item() const { return 0; }
table_map used_tables() const { return RAND_TABLE_BIT; }
void update_used_tables();
void fix_length_and_dec();
};
......
......@@ -2642,7 +2642,7 @@ Create_file_log_event::Create_file_log_event(const char* buf, int len,
We must make copy of 'buf' as this event may have to live over a
rotate log entry when used in mysqlbinlog
*/
if (!(event_buf= my_memdup(buf, len, MYF(MY_WME))) ||
if (!(event_buf= my_memdup((byte*)buf, len, MYF(MY_WME))) ||
(copy_log_event(event_buf, len, old_format)))
DBUG_VOID_RETURN;
......
......@@ -2560,8 +2560,8 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
QUICK_RANGE *null_range;
*ref->null_ref_key= 1; // Set null byte then create a range
if (!(null_range= new QUICK_RANGE(ref->key_buff, ref->key_length,
ref->key_buff, ref->key_length,
if (!(null_range= new QUICK_RANGE((char*)ref->key_buff, ref->key_length,
(char*)ref->key_buff, ref->key_length,
EQ_RANGE)))
goto err;
*ref->null_ref_key= 0; // Clear null byte
......
......@@ -584,7 +584,10 @@ JOIN::optimize()
DBUG_RETURN(1); // error == -1
}
if (const_table_map != found_const_table_map &&
!(select_options & SELECT_DESCRIBE))
!(select_options & SELECT_DESCRIBE) &&
(!conds ||
!(conds->used_tables() & RAND_TABLE_BIT) ||
select_lex->master_unit() == &thd->lex->unit)) // upper level SELECT
{
zero_result_cause= "no matching row in const table";
DBUG_PRINT("error",("Error: %s", zero_result_cause));
......@@ -3411,7 +3414,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
table_map used_tables;
if (join->tables > 1)
cond->update_used_tables(); // Tablenr may have changed
if (join->const_tables == join->tables)
if (join->const_tables == join->tables &&
join->thd->lex->current_select->master_unit() ==
&join->thd->lex->unit) // not upper level SELECT
join->const_table_map|=RAND_TABLE_BIT;
{ // Check const tables
COND *const_cond=
......
......@@ -2508,7 +2508,7 @@ simple_expr:
$$= new Item_func_set_collation($1,
new Item_string($3.str,
$3.length,
YYTHD->charset()));
YYTHD->charset()));
}
| literal
| param_marker
......@@ -2524,6 +2524,12 @@ simple_expr:
}
| '@' '@' opt_var_ident_type ident_or_text opt_component
{
if ($4.str && $5.str && check_reserved_words(&$4))
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
if (!($$= get_system_var(YYTHD, (enum_var_type) $3, $4, $5)))
YYABORT;
}
......@@ -5041,7 +5047,7 @@ internal_variable_name:
{
if (check_reserved_words(&$1))
{
net_printf(YYTHD, ER_SYNTAX_ERROR);
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
sys_var *tmp=find_sys_var($3.str, $3.length);
......
......@@ -29,10 +29,6 @@
#include "my_base.h" /* Includes errno.h */
#include "m_ctype.h"
#ifndef EOVERFLOW
#define EOVERFLOW 84
#endif
static double scaler10[] = {
1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90
};
......
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